It is pretty common knowledge that custom meta fields can be added to posts, pages and custom post types, but did you know that you can add custom meta fields to post tags, categories, and custom taxonomies as well? It’s actually pretty simple, though relatively undocumented. So in this quick tutorial I’m going to walk you through the process of added some custom meta fields to taxonomy. These meta fields can be used for a variety of purposes, but one of my favorites is the Taxonomy Images plugin by Michael Fields.
With WordPress 4.4, there will be a native “terms metadata” table in WordPress, so this is no longer a necessary or valid method of adding customer metadata to terms.
See here for more information: https://make.wordpress.org/core/2015/09/04/taxonomy-term-metadata-proposal/
Adding custom meta fields to a taxonomy requires three separate functions: one to add the field to the Add New page; one to add the field to the Edit Term page; and one to save the values of the custom field from both pages. This first function will add a custom field to the Add New page for the default Category taxonomy.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php // Add term page function pippin_taxonomy_add_new_meta_field() { // this will add the custom meta field to the add new term page ?> <div class="form-field"> <label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label> <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value=""> <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p> </div> <?php } add_action( 'category_add_form_fields', 'pippin_taxonomy_add_new_meta_field', 10, 2 ); |
There is nothing special about this function. It’s just an HTML form that uses the same layout as the default WordPress add new term page fields. One thing to note, however, is that I have setup the name of the input to be an array. This is important for our save function. If the field name was not an array, then we’d have to save each field individually in the save function, but as an array, we can simply loop through the fields and save each one automatically.
Also take note of the add_action():
add_action( 'category_add_form_fields', 'pippin_taxonomy_add_new_meta_field', 10, 2 ); |
The first parameter is what determines the taxonomy that this field gets added to. It uses this format: {$taxonomy_name}_add_form_fields. So if you wanted to add the field to your “genres” taxonomy, you would use:
add_action( 'genres_add_form_fields', 'pippin_taxonomy_add_new_meta_field', 10, 2 ); |
You will now have a field that looks like this on the Add New term page:
The second function we need is the one that adds the HTML to our taxonomy Edit Term page. It looks very similar, though the HTML layout is a little different, and we also have to do a check to see if the meta field has any data saved already, so that we can populate the field on load.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php // Edit term page function pippin_taxonomy_edit_meta_field($term) { // put the term ID into a variable $t_id = $term->term_id; // retrieve the existing value(s) for this meta field. This returns an array $term_meta = get_option( "taxonomy_$t_id" ); ?> <tr class="form-field"> <th scope="row" valign="top"><label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label></th> <td> <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>"> <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p> </td> </tr> <?php } add_action( 'category_edit_form_fields', 'pippin_taxonomy_edit_meta_field', 10, 2 ); |
First, we have passed the $term parameter to our function. This variable will contain the database object for our term. The only information we need for our function is the term ID, so we put that into a variable to make things easy. We then use the get_option() function to retrieve the value of out term meta. Note, all term meta is stored in an array in the option named “taxonomy_{$term_id}”. So to get the value of our specific meta field, we’d use $term_meta[‘custom_term_meta’];
The results of this function will look like this:
Next is our save function. This will take the value entered in the field and store it in the taxonomy option.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Save extra taxonomy fields callback function. function save_taxonomy_custom_meta( $term_id ) { if ( isset( $_POST['term_meta'] ) ) { $t_id = $term_id; $term_meta = get_option( "taxonomy_$t_id" ); $cat_keys = array_keys( $_POST['term_meta'] ); foreach ( $cat_keys as $key ) { if ( isset ( $_POST['term_meta'][$key] ) ) { $term_meta[$key] = $_POST['term_meta'][$key]; } } // Save the option array. update_option( "taxonomy_$t_id", $term_meta ); } } add_action( 'edited_category', 'save_taxonomy_custom_meta', 10, 2 ); add_action( 'create_category', 'save_taxonomy_custom_meta', 10, 2 ); |
The function takes the ID of our term as a parameter. A quick check if performed to make sure that data is being sent from our custom field, and if it is, the current value of the field is retrieved from the database. Next, each of our custom fields (remember, we can setup more than one in a single array) is looped through. In the loop, each of the field values is inserted into the $term_meta array. Once the loop is complete, the taxonomy option is updated, storing our field values in the database.
Just like with the first two functions, the save function is tied to our particular taxonomy with an add_action() hook, and, again with the genres example, if you attached your fields to a taxonomy called “genres”, then you would use these hooks:
add_action( 'edited_genres', 'save_taxonomy_custom_meta', 10, 2 ); add_action( 'create_genres', 'save_taxonomy_custom_meta', 10, 2 ); |
That’s it! The process is really pretty simple.
If you’d like to see a real world example of what you can do with these kind of meta fields (I already mentioned a plugin at the top), check out the Fotos theme by my buddy AJ Clarke. He has password protected photo galleries. The password is set via a taxonomy custom field for the gallery categories. I had the pleasure of building the system for him, so I can tell you first hand how well it works. I’d highly encourage you check it out.
Just wanted to say thanks, this did the trick for me!
Anyone have any idea how to add an image uploader/media library handler using this? Would love to let users select/upload an image to a taxonomy…
Thanks!
The easiest way is to use the plugin by Michael Fields: http://wordpress.org/extend/plugins/taxonomy-images/
I’ve been parsing through the comments above, trying to figure out how to pull a term’s ID. I noticed this block of code, which seems entirely correct to me, yet I cannot get it working about of the box:
$term = get_term_by( ‘slug’, get_query_var( ‘term’ ), get_query_var( ‘taxonomy’ ) );
$t_ID = $term->term_id;
$term_meta = get_option(“taxonomy_$t_ID”);
if (isset($term_meta[‘date’])){
echo $term_meta[‘date’];
}
—where ‘date’ is my custom term name. Am I missing something?
Your code looks right. Does it output anything at all?
The error is “Notice: Trying to get property of non-object in /Applications/MAMP/htdocs/wordpress/wp-content/themes/twentyeleven/jcooknv.php on line 287”.
If I manually add the ID, it works and continues to give me the notice.
Sorry, to answer your question, no it does not output anything. Also, I realize that’s a notice, not an error 😛
That notice means it is unable to determine the ID of the current term. Are you trying to do this on a term archive?
I’m working on a -single.php template for a custom post type. Haven’t tried it on an -archive.php template, but that’d be my next step.
Your code will not work on a single page, only on the archive. When working on single.php (or similar), you need to get the current object from the post itself, as it will not be set as a query var.
Yes! Figured that out and noticed your message almost simultaneously. Thanks again!
Any chance you could post a code snippet on how to use this on a non-archive page?
So how do I output the data in me template?
Thank you Pippin! very helpful. When people share knowledge like this restores my faith in mankind.
i want to use it in index.php
i used it and it didn’t work
can u write to me the right code plz ?
You should put the code into functions.php (inside your current theme) or inside of a custom plugin.
Did you did an error?
amazing – what can I say – I think that’s the second chunk of goodness you’ve helped me out with today!
This is great and has worked for me fine. I have used it to add a URL meta field to a custom post type taxonomy.
My only question is how do I then work with the information? I would like to display the taxonomy name in my template, with the meta data URL as the link, so how do I retrieve the meta data from a specific taxonomy for use in the template?
®
You can retrieve the info with the get_option() function. In the function that saves / updates the custom field, you have an option ID like this:
You simply pass the same option ID to get_option() to retrieve it. Make sense?
Fantastic, thanks so much for this. I had to alter the above code you posted in your comment in order to get the value in my template as :echo get_option(‘taxonomy_’ . $term_id . ‘[“option_key_here”]’);
didn’t output anything.
My code for getting value:
$array=get_option(‘taxonomy_’ . $term->term_id);
$customField=$array[‘custom_term_meta’];
Parabéns pelo artigo :). Thanks You!
Hello Pippin,
Thanx for the great tutorial. Can you please tell me how can I disable the escape of the html characters in my new fields cause I have to place some shortcodes there and I am having a hard time to do that.
Thank you,
Nikc
The easiest way is with the esc_html() function.
Thank you for your answer pippin. I thought I should add the function you told me at this line:
update_option( "taxonomy_$t_id", $term_meta );
and make it look like thatupdate_option( "taxonomy_$t_id", esc_html($term_meta) );
However when I do that I get nothing in return. Not even the text. What I waned is to be able to add shortcodes in these new fields.
Thank you again,
Nick
You should only ever use esc_html() when outputting the data, not when saving it.
I see what you mean, but right now it shows the following because it strips the quotes for security reasons I am guessing.
The returned result when I added the esc_html is
Related stories: [featured_stories ids=\'196\']
Related tags: Google
Sorry for asking so many times but I have no idea how to approach in order to fix this issue.
Thank you for your patience and kind help,
Nick
It seems that this comment area encodes the link and it actually appears correctly.
This is the actual result I am receiving: http://tinypic.com/view.php?pic=33clx80&s=6.
Thanks again,
Nick
Sorry for the delay. Can you show me the exact code you’re using to output that?
Hello Pippin,
First of all, I would like to thank you for trying to help.
This is the way I output the values:
$term = $wp_query->get_queried_object();
$term_id = $term->term_id;
$term_meta = get_option('taxonomy_' . $term_id);
and this is the way I store the values:
function save_taxonomy_custom_meta( $term_id ) {
if ( isset( $_POST['term_meta'] ) ) {
$t_id = $term_id;
$term_meta = get_option( "taxonomy_$t_id" );
$cat_keys = array_keys( $_POST['term_meta'] );
foreach ( $cat_keys as $key ) {
if ( isset ( $_POST['term_meta'][$key] ) ) {
$term_meta[$key] = $_POST['term_meta'][$key];
}
}
// Save the option array.
update_option( "taxonomy_$t_id", $term_meta );
}
}
add_action( 'edited_vm_sector', 'save_taxonomy_custom_meta', 10, 2 );
add_action( 'create_vm_sector', 'save_taxonomy_custom_meta', 10, 2 );
Thank you for trying to help.
Regards,
Nick
Hmm, that’s weird. There definitely isn’t anything in your code that would cause that.
Do you have any plugins or other code snippets that might be interfering?
hi Pippin
nice script.
I have one doubt..I need to show my custom taxonomy terms order by “this custom filed”.
in this case what will be my “key” for order option?
That isn’t possible like that, except by doing a lot more custom development. I’d suggest you take a look at the Category and Terms Order plugin by NSP-Code.
Thanks!
This works like a charm and is incredibly useful for the project I am working on!
Hey Pippin, great code!
I’m looking for a way to display only tags associeated with a certain meta value wp-admin/edit-tags.php
Can you give any help?
Thanks in advance!
So only get tags that have a particular meta value stored?
yes! I’m trying to bind tags and users, I’ve already learned on your blog, so I’m able to create meta for users and a specific tag on user creatin, just can’t find a filter or a hack, or a parse to show only tags with a certain meta on wp-admin…
I don’t know of a way to do that, sorry.
Hello every one.
i use your code and every thing is well. but problem is i do not know how can i show result inside custom post type loop. ???
$query = array(
'post_type' => 'projects',
'posts_per_page' => 1000,
);
query_posts($query);
while(have_posts()) {
the_post();
$parentscategory ="";
foreach((get_the_category()) as $category) {
if ($category->category_parent == 0) {
$parentscategory .= $category->cat_ID;
}
}
echo get_option('projects_category_' . $parentscategory . '["custom_term_meta"]');
}
Move your echo get_option() up into the foreach() loop.
I’ve spent a few hours trying to figure this out, but am stumped and am hoping you can help point me in the right direction. I know it’s possible to display the meta field for a taxonomy term in a post using Nicola’s code above:
$array=get_option(‘taxonomy_’ . $term->term_id);
$customField=$array['custom_term_meta'];
echo $customField;
Where I’m having trouble is displaying two or more terms using custom fields in the same post.
I’m creating a site about books. Books are added as posts. I’ve got a taxonomy “writers” with the term “Stephen King” and use ‘custom_term_meta” to display his website address at the bottom of the post, as well as on his single taxonomy page. With a single author, this works great.
If I add a book that has two authors, echoing $customField will obviously only display one author URL and ignore the other. Is there an easy way to display both? I tried using an array, but my knowledge of php is lacking and my many attempts didn’t have a positive result. Any suggestions would be greatly appreciated! Cheers!
Hey Eric, what you need to do is the get_the_terms() function to retrieve all of the authors connected to the current item. Once you have the authors, you will use a foreach() loop to loop through each author, retrieving the get_option() for each one of them.
Does that make sense?
Took your advice and was able to get it working, after a bit of trial and error. Thanks!
Is it possible to add more than one field?
Yes, you can add as many as you want.
what parameters do i have to change to do this
You need to change the name attribute of each input field. This will cause the value of that field to get mapped to a separate element in the array of values that is stored in the option’s table.
Make sense?
Perfect! Thanks a lot.
🙂
Thank for wonderful code..
Only one suggestion for those who are not getting output
$array=get_option('taxonomy_' . $term->term_id);
$customField=$array['custom_term_meta'];
echo $customField;
above code works fine for out put if you are just copy pasting code please check quotes for ‘taxonomy_’
I’ve been beating my head against a wall for days, and I can’t figure this out. I can’t get the meta data to to output in my theme. I’m using this code:
$array=get_option(‘taxonomy_’ . $term->term_id);
$customField=$array[‘custom_term_meta’];
echo $customField;
And nothing is being displayed. It seems $term is outputting the slug of the entry. When I look in my database, this is stored as “taxonomy_13”, and it I manually put “taxonomy_13” in the script rather than letting it generate, it works. I can’t figure out what I’m doing wrong?
How are you retrieving `$term`?
The only way I can get any kind of output at all is if I hard-code a taxonomy in as below. All else is copy and pasted via your instructions into functions.php
Any help at all would be greatly appreciated! Thanks
$array=get_option('taxonomy_' . '14');
$customField=$array['custom_term_meta'];
echo $customField;?>
The only part you should replace is the ’14’. Replace it with the ID of the term you are retrieving an option from.
To be honest I’m not changing your code at all, I’m using taxonomy_$t_id and that doesn’t work either.
I’ve followed your tutorials to the letter and it’s not working. I’m pulling my hair out trying to get it working! here is my funcion.php code
// Add term page
function pippin_taxonomy_add_new_meta_field() {
// this will add the custom meta field to the add new term page
?>
term_id;
// retrieve the existing value(s) for this meta field. This returns an array
$term_meta = get_option( "taxonomy_$t_id" ); ?>
<input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="">
<?php
}
add_action( 'product_brand_edit_form_fields', 'pippin_taxonomy_edit_meta_field', 10, 2 );
// Save extra taxonomy fields callback function.
function save_taxonomy_custom_meta( $term_id ) {
if ( isset( $_POST['term_meta'] ) ) {
$t_id = $term_id;
$term_meta = get_option( "taxonomy_$t_id" );
$cat_keys = array_keys( $_POST['term_meta'] );
foreach ( $cat_keys as $key ) {
if ( isset ( $_POST['term_meta'][$key] ) ) {
$term_meta[$key] = $_POST['term_meta'][$key];
}
}
// Save the option array.
update_option( "taxonomy_$t_id", $term_meta );
}
}
add_action( 'edited_product_brand', 'save_taxonomy_custom_meta', 10, 2 );
add_action( 'create_product_brand', 'save_taxonomy_custom_meta', 10, 2 );
And I’m calling it with this:
$array=get_option('taxonomy_' . '$t_id');
$customField=$array['custom_term_meta'];
echo $customField;
This returns a “$” which is obviously no use to me. If i replace ‘$t_id’ with ’14’ then i get a result. otherwise nadda.
Thanks for this, worked a treat on one of our projects!
How would you use this for a boolean value? I want to use a checkbox rather than a text field.
Store the option value as 1, that way you can do a simple boolean check on it.
Hello! Your post was really helpful. Many thanks!
I have a question. How do I output more than one custom field into a loop?
I’m using this code:
term_id;
$term_meta = get_option(“album_$t_ID”);
if (isset($term_meta[‘capa’])){?>
<img src="” height=”300″ />
Everything is running well. But it only output one custom field, and not each custom field for each custom taxonomy.
Something like this, for example:
<img src="” height=”300″ />
Is there a way to do that? Thanks in advance!
You can use something like this:
Thank you 🙂
It’s always wonderful tutorial by pippin. I’m sorry to bother you, why you not give an example code how to display the output of custom meta fields on this tutorial? Thanks for your hard work.
Hey man, this rocks. I am encountering a problem when trying to implement on multiple taxonomies. I have tried renaming things but can’t seem to get it to not break. Any advice? Thanks for this tutorial and thanks for any help-
Disregard my last comment, I am a dummy and was calling the function multiple times in different taxonomies. WOOPS
Okay!
Hello there,
I’ve used your code to add another field called ‘pctracker_sortorder’. For sorting the taxonomy on output. But how do I call that value and sort it?
Thanks.
Jason
It’s explained in the tutorial. Did you follow my example?