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. Kim B

    This is a great tutorial and something I’ve been searching for. I am very new to wordpress and so am not familiar with the worpress framework. My question is where should I add these functions?

    • Muhammad Shoaib Murtaza

      Kim B, you should add this code in your theme’s functions.php file

    • mobby

      wordpress is not a framework but a foundation. Zend, Code Igniter , YII are frameworks like .NET is in Microsoft.

  2. Edward

    Anyone having problems retrieving the values on a custom taxonomy archive page may find the following useful:


    $t_id = get_queried_object()->term_id;
    $term_meta = get_option( "taxonomy_$t_id" );
    echo $term_meta['custom_term_meta'];

    Thanks, Pippin.

    • Rock

      Thanks, I really need this code.

    • Jhuonas

      Thanks so much man, you just save my day!

  3. Joydeep

    Can I add single or multiple image field(s) using this function?

    • Pippin

      Yes, definitely, you will just need to tweak the HTML and the save routine accordingly.

  4. Rebecca Giddings

    Thanks for the great post!

    I understand how to pull the meta data using the get_option function, as you described:

    $t_id = 3; // You will want to retrieve this somehow
    echo get_option( “taxonomy_$t_id” );

    Is there any way to do the reverse? If I know what the meta data value is for a given category, is there a way to get the associated category ID? Thanks!

    • Pippin

      You could get that by doing a custom select query using the wpdb class. Are you familiar with that?

    • Rebecca Giddings

      Not 100%. After doing some reading online, I get the basic idea. But when I do something like:

      `$category = $wpdb->get_row(“SELECT * FROM $wpdb->term_taxonomy WHERE TAXONOMY = ‘category'”);

      print_r($category);`

      I don’t see the custom meta as one of the options. Could you point me in the direction of a good tutorial that might help me pull the information I’m looking for from the database?

      Thanks again!

  5. Joe

    I saw that Edward posted something about actually retrieving the value on a custom taxonomy archive page, but does anyone know how to retrieve it on a single.php page?

    • Ulrich

      You could add something like this within the loop or use what Edward posted.
      “`
      $terms = get_the_terms( $post->ID, ‘category’ );
      $term_meta = get_option( “taxonomy_$terms->term_id” );
      echo $term_meta[‘custom_term_meta’];
      “`

  6. Joe

    Thanks Ulrich, it doesn’t seem to be working. Below is what i’m doing:

    ‘name’,
    ‘order’ => ‘ASC’,
    ‘taxonomy’ => ‘locations’,
    );
    $terms = get_the_terms( $post->ID, ‘category’ );
    $term_meta = get_option( “taxonomy_$terms->term_id” );
    $categories = get_categories($args);
    foreach($categories as $category) {
    echo ‘‘ . $category->name . ‘ ‘;
    echo ” . $category->description . ”;
    echo ” . echo $term_meta[‘custom_term_meta’] . ”;
    }
    ?>

    I can’t seem to get it to work. Any help would be great!

    Thanks again!

    • Ulrich

      @Joe this should work
      ‘name’,
      ‘order’ => ‘ASC’,
      ‘taxonomy’ => ‘locations’,
      );
      $categories = get_categories($args);
      foreach($categories as $category) {
      $term_meta = get_option( “taxonomy_$category->term_id” );
      echo ‘‘ . $category->name . ‘ ‘;
      echo ” . $category->description . ”;
      echo ” . echo $term_meta[‘custom_term_meta’] . ”;
      }
      ?>

  7. gordon

    Hi!

    Great tutorial Pippin!

    Unfortunatelly I can’t make the results will be visible on the single.php page.
    I tried Edward and Ulrich solutions and they don’t seem to work in my case.
    The below code shows only name and description of my custom taxonomy but no custom_term_meta…

    $terms = get_the_terms( $post->ID , ‘author’ );
    if($terms) {
    foreach( $terms as $term ) {
    echo $term->description.”;
    echo $term->name.”;
    $term_meta = get_option( “taxonomy_$terms->term_id” );
    echo $term_meta[‘custom_term_meta’];
    }
    }

    Any help?

    • Pippin

      Try replacing $post->ID with get_the_ID()

  8. Ponyx

    Hi,
    Thank you very for your code, it’s really great and simple.
    Like I’m not a good developer at all, could you give some clue to add a single image using your function ?

    Thks !

  9. Jerome

    Hi pippin,

    Thank you very much for this tutorial mate. This helped me a lot in a project for one of my customers.

    Managed to get to create an image uploader for any taxonomy and display it in the front and backend of the plugin.

    Cheers !

    Jerome.

    • Leo

      Hi Jerome,

      Would you please share your snippet to add an image uploader for taxonomies? I am looking to find this solution for one of my projects. Thanks.

      Leo

  10. Nonbrake

    Hi,
    how can I change/add priority in admin?
    How can I add the wp-editor to custom field (textarea) based on this example?

    Thanks

    • Pippin

      I’m not sure what you mean, could you elaborate?

    • nonbrake

      Hello,
      I create custom field for taxonomy product_cat (product category for Woocommerce).
      1) How can I change/add priority of this custom field in administration – I mean position of custom field in administration category between other fields (under/above the term-description). For meta fields you can use the priority = normal/high/ … and here?

      2) How can I add the wp-editor to this custom filed? I tried add editor (tinymce) using wp-editor ( http://codex.wordpress.org/Function_Reference/wp_editor ) or jQuery but without success.

      Thanks

  11. Beatrice

    I am slightly confused. Will users will be able to pass a hidden custom value directly to the “category” posts section. This is what I’m trying to accomplish: A user fills out a gravity form. I don’t want them to have to choose the category. I want to choose it for them without going into wordpress and choosing it for them. I want that form to pass it on to the category “specified” section. Can I accomplish this with this function?

    • Pippin

      Not without further custom development, sorry.

  12. George

    Hey Pippin,

    great code! Helped me a lot setting up additional fields for taxonomy terms in the backend.
    Returning the additional field for the current term in taxonomy.php works as well.

    But I also have a tree-like navigation on single-taxonomy_name.php, archive-taxonomy_name.php and taxonomy.php that displays a hierarchical list of all terms. I also want to show additional fields content here, but can’ t wrap my head around how to do that. Simply returning $term_meta[‘custom_term_meta’] doesn’t seem to do the trick.

    Here’s a basic version of my walker. Any ideas?

    Thanks very much!

    function return_terms() {
    $taxonomies = array( ‘taxonomy_name’ );
    $args = array(
    ‘orderby’ => ‘name’,
    ‘order’ => ‘ASC’,
    ‘hide_empty’ => false,
    ‘fields’ => ‘all’,
    ‘parent’ => 0,
    ‘hierarchical’ => true,
    ‘child_of’ => 0,
    ‘pad_counts’ => false,
    ‘cache_domain’ => ‘core’
    );
    $terms = get_terms($taxonomies, $args);
    $term_meta = get_option( “taxonomy_$terms->term_id” );

    $return .= ”;
    foreach ( $terms as $term ) {
    $return .= sprintf(
    ‘%2$s ‘ . $term_meta[‘custom_term_meta’] . ‘%3$s’,
    $term->term_id,
    $term->name,
    $term->description
    );
    $return .= ”;
    }
    $return .= ”;

  13. Jeff B.

    Since this is being actively used, people should know that this method will potentially break with the eventual shared term splitting currently scheduled for WordPress 4.2. Terms in multiple taxonomies sharing the same slug/name will be issued new IDs and the associated meta won’t be retrieved correctly.

    Some of the discussion can be found here, for those who are interested:
    https://core.trac.wordpress.org/ticket/30335

  14. Jonathan M.

    There’s a small issue with the code that displays the custom fields on the Edit page:

    <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="”>

    I think you meant for the esc_attr method that is used in the ternary check to be a call to isset() instead.

  15. Gianluca

    Hey Pippin,

    thank for the great piece of code.
    One question, I need to use this with a multiple-select field, as right now, this code will save only the last option selected.
    Is there a way to easily accomplish this? Could you point me in the right direction?

    Thanks again for the code

    Have a nice sunday

  16. Tekeste G/anenia

    Can you please show us to do the same thing for custom taxonomies?

    • Tekeste G/anenia

      ohhh my bad… I just saw it.

    • Pippin

      It works exactly the same way.

  17. Thomas

    Hi Pippin

    Can you show the code for how to do this for checkbox where we have to save multiple values.

  18. Sehrish Malik

    Hi , its not saving value on update. how to save value on updating the taxonomy? i am working on custom taxonomy.

    • Pippin

      Could you show me the exact code you’re using?

  19. Chakladar

    Hi, very nice tutorial. I have saved my meta text for custom taxonomy. How can I show this meta of that custom taxonomy in a custom post ?

    • Pippin

      You can do that by using the get_option() function with the same key as you used in update_option().

  20. Jacob Wolf

    How would I print the input for this field as a HTML line somewhere?

    • Pippin

      Could you be a bit more specific about what you’re trying to do?

  21. Gianluca

    Hey Pippin,

    I’y for question it againt.
    I need to use this with a multiple-select field, as right now, this code will save only the last option selected.
    Is there a way to easily accomplish this? Could you point me in the right direction?

    Thanks again for the code

    Have a nice weekend

    • Pippin

      For a multi-select, add [] to the name attribute.

  22. Lucas

    Thanks

  23. syihab

    thank’s a lot…is simple custom taxonomies… 😀

  24. Ranish Malhan

    How to add upload image field?

  25. Aaron

    I would love to know how to include checkboxes using the above method. I cannot figure out how to save them. Thanks

  26. Konstantin

    Hi i really really need your help with this.

    I am trying to implement the same thing but for tags, i noticed that anytime it gets to this line

    $term_meta = get_option( “taxonomy_$t_id” );

    it will fail and return NULL. So When i go into editing the tag… the custom field value is not showing. i figured for tags implementation it might be a different name with taxonomy_$t_id…but i have searched and searched, nothing… Would really appreciate an answer asap as i have a deadline. Thank you

    • Pippin

      If you can show me the complete code you’re using, I can try and identify why it’s failing.

    • Konstantin

      Posted the code, hope you saw it.

    • Konstantin

      The only difference is changing the hooks which are different from categories

      This:
      add_action( ‘category_add_form_fields’, ‘pippin_taxonomy_add_new_meta_field’, 10, 2 );

      add_action( ‘category_edit_form_fields’, ‘pippin_taxonomy_edit_meta_field’, 10, 2 );

      To:
      add_action( ‘add_tag_form_fields’, ‘pippin_taxonomy_add_new_meta_field’, 10, 2 );
      add_action( ‘edit_tag_form_fields’, ‘pippin_taxonomy_edit_meta_field’, 10, 2 );

      Can i also assume. the Save function will work out of the box? or would i need tweeks there too?

    • Konstantin

      Hello and hope all is well. Were you able to see the code i provided? Please let me know. Thank you!

  27. Konstantin

    THANK YOU FOR TRYING TO HELP. I JUST FIGURED IT OUT.

    • Pippin

      Glad to hear it!

    • Chuck

      OK so i’m good with these changes:

      add_action( ‘add_tag_form_fields’, ‘pippin_taxonomy_add_new_meta_field’, 10, 2 );
      add_action( ‘edit_tag_form_fields’, ‘pippin_taxonomy_edit_meta_field’, 10, 2 );

      In fact I’d already figured those out based on something I already read someplace else. The issue(s) I have are related to the saving of data. What changes are needed to actually get the data to save?

    • Pippin

      That’s shown above in the tutorial.

      add_action( 'edited_genres', 'save_taxonomy_custom_meta', 10, 2 );
      add_action( 'create_genres', 'save_taxonomy_custom_meta', 10, 2 );

      Replace “genres” with “post_tag”

  28. menem

    how to create boxpost in custom taxonomy

  29. Pippin

    Everyone, I have disabled further comments on this post as the methods described here are largely out of date.

    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/

  30. Marianne McDougall

    Really interesting article and I see a couple of folks are having some problems. If you put the code into functions.php inside of a custom plugin – that should work for you.

Comments are closed.