Add Custom Fields to a Taxonomy

In this tutorial I will show you step by step how to add a custom field to a custom taxonomy in WordPress. Of course, this method is going to work great for default taxonomies as well.

First of all I will show you how to do it without any plugins and then we will do the same with the help of my Simple Fields plugin, so you can see the difference.

Well, let’s take a look what we are going to create here.

WordPress custom fields in taxonomy
Here I decided to add multiple fields – a simple text field and an image field.

And this is how it looks when you go edit a specific taxonomy term:

add custom fields on edit term pages

Please also keep in mind, that if you find tutorials where it is recommended to manually create a database table for term metadata, those tutorials are completely outdated. WordPress already has wp_termmeta table since version 4.4.

Add Fields to the Add New Term Screen

To add the fields on the “Add new” screen we are going to use an action hook {TAXONOMY}_add_form_fields and all we have to do is to echo the fields. You have to replace {TAXONOMY} with the actual taxonomy name, for example it could be post_tag for Tags or category for Categories.

I decided that we will add fields to WordPress Tags taxonomy, so the filter hook is going to look like post_tag_add_form_fields.

<?php
add_action( 'post_tag_add_form_fields', 'rudr_add_term_fields' );

function rudr_add_term_fields( $taxonomy ) {
	?>
		<div class="form-field">
			<label for="rudr_text">Text Field</label>
			<input type="text" name="rudr_text" id="rudr_text" />
			<p>Field description may go here.</p>
		</div>
		<div class="form-field">
			<label>Image Field</label>
			<a href="#" class="button rudr-upload">Upload image</a>
			<a href="#" class="rudr-remove" style="display:none">Remove image</a>
			<input type="hidden" name="rudr_img" value="">
		</div>
	<?php
}

We also have $taxonomy parameter available here, it is just a taxonomy name. It is quite helpful if you are going to add multiple fields to multiple taxonomies at the same time and then for example to add one more field to one specific taxonomy.

Result:

fields on add new tag page
We can add fields to the Add New tag page with post_tag_add_form_fields action hook.

Creating Image Uploader Field

I think everything is crystal clear with the simple text field. But what about the file uploader? When creating the field we just added a couple of buttons and a hidden field but there is more than that, at least we need some JavaScript code that allows us to open WordPress media uploader modal window. I recommend you to check my separate tutorial, you can find there everything you need.

Reset Fields on Add New Term

The thing is that when you add a new term it is going to be added via AJAX, so after performing the asynchronous call we have to empty our custom fields. Our default text field is going to be emptied automatically but what about the image field?

In order to explain exactly what I mean here is a screenshot:

empty custom fields after adding new terms in WordPress

Our goal right now is to add an additional JavaScript event (we can use jQuery in WordPress admin, it is ok).

jQuery( function( $ ){

	let numberOfTags = 0;
	let newNumberOfTags = 0;

	// when there are some terms are already created
	if( ! $( '#the-list' ).children( 'tr' ).first().hasClass( 'no-items' ) ) {
		numberOfTags = $( '#the-list' ).children( 'tr' ).length;
	}

	// after a term has been added via AJAX	
	$(document).ajaxComplete( function( event, xhr, settings ){

		newNumberOfTags = $( '#the-list' ).children('tr').length;
		if( parseInt( newNumberOfTags ) > parseInt( numberOfTags ) ) {
			// refresh the actual number of tags variable
			numberOfTags = newNumberOfTags;
	
			// empty custom fields right here
			$( '.rudr-remove' ).each( function(){
				// empty hidden field
				$(this).next().val('');
				// hide remove image button
				$(this).hide().prev().addClass( 'button' ).text( 'Upload image' );
			});
		}
	});
});

Add Fields to the Edit Term Screen

Very similar to the previous part of the tutorial, the main difference is that we have to populate the field in case the metadata is presented.

Let’s begin with an action hook {TAXONOMY}_edit_form_fields. For post_tag taxonomy it is going to be post_tag_edit_form_fields, for your custom taxonomy it could be your_custom_taxonomy_edit_form_fields.

<?php
add_action( 'post_tag_edit_form_fields', 'rudr_edit_term_fields', 10, 2 );
function rudr_edit_term_fields( $term, $taxonomy ) {

	// get meta data value
	$text_field = get_term_meta( $term->term_id, 'rudr_text', true );
	$image_id = get_term_meta( $term->term_id, 'rudr_img', true );

	?><tr class="form-field">
		<th><label for="rudr_text">Text Field</label></th>
		<td>
			<input name="rudr_text" id="rudr_text" type="text" value="<?php echo esc_attr( $text_field ) ?>" />
			<p class="description">Field description may go here.</p>
		</td>
	</tr>
	<tr class="form-field">
		<th>
			<label for="rudr_img">Image Field</label>
		</th>
		<td>
			<?php if( $image = wp_get_attachment_image_url( $image_id, 'medium' ) ) : ?>
				<a href="#" class="rudr-upload">
					<img src="<?php echo esc_url( $image ) ?>" />
				</a>
				<a href="#" class="rudr-remove">Remove image</a>
				<input type="hidden" name="rudr_img" value="<?php echo absint( $image_id ) ?>">
			<?php else : ?>
				<a href="#" class="button rudr-upload">Upload image</a>
				<a href="#" class="rudr-remove" style="display:none">Remove image</a>
				<input type="hidden" name="rudr_img" value="">
			<?php endif; ?>
		</td>
	</tr><?php
}

Some moments related to the code above:

  • Function has two parameters: $termWP_Term object of a currently edited term, $taxonomy – just taxonomy name.
  • We’re using get_term_meta() function here to get the term meta data.
  • Never forget to escape the data you get from the database. We are using esc_attr() and absint() for that purpose.
  • medium parameter value of wp_get_attachment_image_url() function is an image size name you’re going to use here. By default is is thumbnail.

And we have it:

add custom fields on edit term pages
Oh sorry, the image is not going to be displayed here unless you completed the next step of the tut.

Save Fields

The last step is to save our fields values into the database.

Guess what – we also have two action hooks for that – created_{TAXONOMY} and edited_{TAXONOMY}. Luckily we can connect the same callback function to both of them.

add_action( 'created_post_tag', 'rudr_save_term_fields' );
add_action( 'edited_post_tag', 'rudr_save_term_fields' );
function rudr_save_term_fields( $term_id ) {
	
	update_term_meta(
		$term_id,
		'rudr_text',
		sanitize_text_field( $_POST[ 'rudr_text' ] )
	);
	update_term_meta(
		$term_id,
		'rudr_img',
		absint( $_POST[ 'rudr_img' ] )
	);
	
}

The only thing to say is that I really really hope that you know the difference between esc_attr() and sanitize_text_field(). In case you don’t, please read this tutorial right now.

Not so difficult, but below I am going to show you even more simple way to create taxonomy custom fields!

Super-simple Example

Sometimes it takes too long to create fields from scratch. So I created Simple Fields plugin, it allows to simplify the process and to save tons of time.

For example all the work we were doing above can be replaced with this simple code snippet placed into your current theme functions.php file.

add_filter( 'simple_register_taxonomy_settings', 'rudr_taxonomy_fields' );
function rudr_taxonomy_fields( $fields ) {
	$fields[] = array(
 		'id'	=> 'mishatest',
 		'taxonomy' => array( 'post_tag' ),
 		'fields' => array(
			// text field
			array(
				'id' => 'rudr_text',
				'label' => 'Text Field',
				'type' => 'text',
			),
			// image field
			array(
				'id' => 'rudr_img',
				'label' => 'Image Field',
				'type' => 'image',
			),
 		)
 	);
	return $fields;
}

That’s really it.

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X