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. Tanner

    Great tutorial, thanks for putting this together, Pippin!

  2. Sam

    How to get the field value in template ?

    • Pippin

      Which template?

  3. giligan

    Hi Pippin

    Thanks for the tutorial.
    I had one problem – when trying my own custom taxonomy, it actually didn’t work giving an error on this line:

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

    saying it doesn’t exists. Did I misunderstand and I can’t use it like this?

    The taxonomy does registers, appears and works

    Thanks

    • Pippin

      Did you replace “mycustomtax” with the actual name of your taxonomy?

  4. oxcar

    Hi there, great tutorial!

    I was wondering if there is a way I can retrieve the custom field and print it out on the “category.php” template.

    For the title, for example, you do this:

    What would be the right way for doing this with the custom field?

    Thanks!

    • Pippin

      Definitely. You will retrieve it in exactly the same way that we retrieved it in the admin, using get_option()

  5. Anvar

    Great tutorial! Many thanks

  6. Matt Cromwell

    Thanks for this great tool, Pippin. The field was added really easily into the Category edit page without trouble. My only trouble is in spitting the data onto the archive.php page. You mentioned in a comment above that I just need to use get_option() but that doesn’t seem to be working for me. Here’s what I added to my archive.php page:

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

    It returns this error:
    Notice: Undefined variable: t_id in …\wp-content\themes\cys\archive.php on line 32
    Notice: Array to string conversion in …wp-content\themes\cys\archive.php on line 34
    Array

    Any advice?

  7. Matt Cromwell

    OK, I think I got it working. I had to reference the category id. This is the simplest way I could see to spit out the values onto the archive.php page:

    $category = get_category($cat);
    $term_meta = get_option( “taxonomy_{$cat}” );
    echo $term_meta[‘custom_term_meta’];

    Hope that helps someone. Thanks!

  8. John Plastow II

    Once you have meta fields attached to your taxonomy’s terms, is there a way to change the order in which your terms are displayed with get_terms() using those meta fields? For example, by a date in yyyymmdd format?

    • Pippin

      No, get_terms() doesn’t offer an option for that.

  9. Betadev

    Hi, freinds !
    It is possible to add a classname to form tag of taxonomy backend insert form ?

    • Pippin

      Which form, could you be a little more specific?

    • betadev

      Yes, i want to add a class name as i sayed to the form of inserting taxonomies in backend.
      Example of page : …./wp-admin/edit-tags.php?taxonomy=category

  10. Kerry

    Thank you – this helped me so much!!!

  11. khawir

    It seems to be working when you update the custom fields but not when a new category is created…
    I wonder if it has to do with the priority in the add action hook

  12. Hicham

    Hi Pippin,

    Thanks for this post. Do you have any idea about sorting the fields? like moving the custom field above the “Description” field. I looked over the available hooks but couldn’t find anything to do that.

    Meanwhile, i use jQuery to move the custom field but it’ll be better if there’s a solution to do it the WordPress way 🙂

    Here’s the jQuery code:

    $(“div.mycustomfield”).insertBefore($(“textarea[name=description]”).parent());

    * mycustomfield is a class i’ve added to the div form-field to identify the custom field

    Best,

  13. phuongdp

    It’s very helpful for me.
    Thank so much.

  14. pranav

    This blog is really helpful
    Thanx a lot… 🙂

  15. Matt

    Good stuff, helped a ton.

    Does anyone knows if wp_list_categories can sort on these custom taxonomy terms? That would be fantastic, but I don’t think it can. Custom query time.

    • Pippin

      No it cannot, sorry.

    • Nikola Nikolov

      If you’d want to sort by the custom fields for terms, you’d have to create your own terms_meta table(since right now you’re storing the meta as a serialized array and I believe sorting that would be impossible – I have however successfully queried based on values of a serialized array using LIKE, but that was pretty hack-ish 🙂 ).

      Generally the method in this article is easier and quicker(than adding a custom table) and will work for everyone that wants to just be able to add a photo, or some extra info about terms, but will not work for anyone that needs to do more complicated things(like using meta queries, etc. – since you’d have to customize those functions as well).

  16. geomagas

    Another great article with really valuable info.
    Thanks again, Pippin!

  17. prasun

    very good tutorial Thanks a lot

  18. Pranav

    How to add checkbox as metafield?

  19. nay

    Hi Pippen,

    Do you know how to add a Checkbox? I am able to save the serialized data using your method, but it always stays checked and won’t uncheck when I re-save.

    Thanks

    (code) input type=”checkbox” name=”my_meta[friend]” value=”1″ (code)

    • Pippin

      Could you show me your complete code? Paste it to pastebin.com and then share the link.

  20. Matt

    I am trying to add a field to input the url of the custom archive page for the category. It looks like the form part works, but when I save a url into the form field, it is not there when I edit it again. HELP!

    Awesome tutorial, by the way.

    http://pastebin.com/vhqM3dPB

  21. nay

    I posted the PasteBin above. Can anyone help me get checkboxes to work successfully? Here it is again:

    http://pastebin.com/976LaLtR

    Thanks

    • Nikola Nikolov

      Hi nay,

      Try the modified version at http://pastebin.com/MzDpi9GE . I only added a couple of new lines before

      $cat_keys = array_keys( $_POST[‘term_meta’] );

      This line checks to see if “former_employee” field is not set ( the ! isset(... part ) and set it’s value to an empty string(you can set it to false as well) if that’s the case.
      When you uncheck a checkbox, the browser doesn’t actually send this checkbox to the server, since – well, it’s not checked. One simple way to work around this issue is to change the checkboxes with selects, that have “Yes” and “No” options(you can set the value of “No” to “”).

      I haven’t tested the code, but it should work.

    • nay

      Thanks Nikola! I will test it and report back. Appreciate your help 🙂

    • nay

      It works Nikola! Thank you sir 😀

  22. fazzy A

    I ve a very basic question.
    where to put those three functions mentioned by pippin.
    I mean in which php file.
    should i include it in my themes function.php

  23. Yugandhar

    Hi Pippin.

    This tutorial was helpful. I have a doubt.

    I added this code in functions.php and created 5 new custom meta fields. Now, when I click on existing categories in the taxnomies, these custom meta elements are not coming in edit page. Even for new taxanomy categories also it is not coming.

    Can u help me, how can I add/edit this custom meta this in Edit Taxanomy category mode also.

  24. gusswib

    Hi, this is great tutorial.

    How about if i want to add checkbox ? and also for taxonomy custom post

    Thank you

  25. Kyaviger

    Thanks it works great. But after making new term fields won’t clean up and list of term is not updated.

  26. Chris

    Thanks for the tutorial, it’s helped me out a lot. Would there be a case for verifying a nonce before saving the data, or is that covered in hooking into the ‘edited_category’ and ‘create_category’ actions?

    • Pippin

      There should probably be a nonce added there.

    • Ulrich

      The data also needs to be sanitized.

    • Ulrich

      I don’t think a nonce is needed as WordPress already adds one to the form.

  27. Ulrich

    Why did you save the options in the options table instead of `wp_term_taxonomy` where the description and parent info is kept?

    • Pippin

      You can certainly do that, but you would have to create some new custom columns in the table.

      This method is really “hackish” but it one of the better options available until WordPress implements a taxonomy metadata API.

    • Chris

      I think there’s a lot to be said for simple solutions, but looking at the Metadata API I think the technically correct solution would be to create a new database table (something along the lines of wp_termmeta) and save the data in there using update_metadata().
      As it happens I found this article in the first place for some work I’m doing with WooCommerce and I was interested to see they seem to be doing something along these line. The tables they add include wp_woocommerce_termmeta (I assume the _woocommerce is to avoid future naming conflicts).

    • Pippin

      There are plans to do that in WordPress core.

  28. Peter K

    Big thanks, Pippin! Very simple and direct.

  29. Caroline

    Hey Pippin, great tutorial as always!

    Here’s a snippet I pulled together to “output” new custom meta data. It works perfectly on my end – for use on taxonomy.php page (to show new meta data alongside default taxonomy data – like description and title). I’m thinking about storing the array data into a transient for caching purposes (as this information will rarely change), what do you think?

    http://pastebin.com/LBvK6MtW

Comments are closed.