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.

  1. Scott

    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!

  2. jcnv

    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?

    • Pippin

      Your code looks right. Does it output anything at all?

  3. jcnv

    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.

    • jcnv

      Sorry, to answer your question, no it does not output anything. Also, I realize that’s a notice, not an error 😛

    • Pippin

      That notice means it is unable to determine the ID of the current term. Are you trying to do this on a term archive?

    • jcnv

      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.

    • Pippin

      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.

    • jcnv

      Yes! Figured that out and noticed your message almost simultaneously. Thanks again!

    • Mike Jackson

      Any chance you could post a code snippet on how to use this on a non-archive page?

  4. terry

    So how do I output the data in me template?

    • Pippin
      echo get_option('taxonomy_' . $term_id . '["option_key_here"]');
  5. Miguel

    Thank you Pippin! very helpful. When people share knowledge like this restores my faith in mankind.

  6. Mohamed

    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 ?

    • Pippin

      You should put the code into functions.php (inside your current theme) or inside of a custom plugin.

      Did you did an error?

  7. QLStudio

    amazing – what can I say – I think that’s the second chunk of goodness you’ve helped me out with today!

  8. Richard

    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?

    ®

    • Pippin

      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:

      taxonomy_option_$term_id

      You simply pass the same option ID to get_option() to retrieve it. Make sense?

  9. Nicola Elvin

    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’];

  10. Guilherme

    Parabéns pelo artigo :). Thanks You!

  11. nickast

    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

    • Pippin

      The easiest way is with the esc_html() function.

    • nickast

      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 that
      update_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

    • Pippin

      You should only ever use esc_html() when outputting the data, not when saving it.

  12. nickast

    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

  13. nickast

    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

    • Pippin

      Sorry for the delay. Can you show me the exact code you’re using to output that?

    • nickast

      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

    • Pippin

      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?

  14. praful

    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?

    • Pippin

      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.

  15. Root

    Thanks!

    This works like a charm and is incredibly useful for the project I am working on!

  16. Alvaro

    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!

    • Pippin

      So only get tags that have a particular meta value stored?

    • Alvaro

      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…

    • Pippin

      I don’t know of a way to do that, sorry.

  17. Kashif Munir

    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"]');
    }

    • Pippin

      Move your echo get_option() up into the foreach() loop.

  18. Eric

    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!

    • Pippin

      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?

    • Eric

      Took your advice and was able to get it working, after a bit of trial and error. Thanks!

  19. Andreas Edler

    Is it possible to add more than one field?

    • Pippin

      Yes, you can add as many as you want.

    • Andreas Edler

      what parameters do i have to change to do this

    • Pippin

      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?

  20. WpTide.com

    Perfect! Thanks a lot.

    🙂

  21. Nauman

    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_’

    • Darrell

      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?

    • Pippin

      How are you retrieving `$term`?

    • Mike Jackson

      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;?>

    • Pippin

      The only part you should replace is the ’14’. Replace it with the ID of the term you are retrieving an option from.

    • Mike Jackson

      To be honest I’m not changing your code at all, I’m using taxonomy_$t_id and that doesn’t work either.

    • Mike Jackson

      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.

  22. David

    Thanks for this, worked a treat on one of our projects!

  23. How would you use this for a boolean value? I want to use a checkbox rather than a text field.

    • Pippin

      Store the option value as 1, that way you can do a simple boolean check on it.

  24. Bruno Monteiro

    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!

    • Pippin

      You can use something like this:

      1
      2
      3
      4
      
      $term_meta = get_option("album_$t_ID");
      foreach( $term_meta as $field ) {
      	echo $field;
      }
  25. Darto KLoning

    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.

  26. Austin

    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-

  27. Austin

    Disregard my last comment, I am a dummy and was calling the function multiple times in different taxonomies. WOOPS

    • Pippin

      Okay!

  28. Jason

    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

    • Pippin

      It’s explained in the tutorial. Did you follow my example?

Comments are closed.