(taxonomy)_edit_form_fieldsaction-hookWP 3.0.0

Allows adding extra fields (custom fields or metadata fields) to the taxonomy item (term) editing page.

Use (taxonomy)_add_form_fields when fields need to be added to the term creation page.

Usage

add_action( '(taxonomy)_edit_form_fields', 'wp_kama_taxonomy_edit_form_fields_action', 10, 2 );

/**
 * Function for `(taxonomy)_edit_form_fields` action-hook.
 * 
 * @param WP_Term $tag      Current taxonomy term object.
 * @param string  $taxonomy Current taxonomy slug.
 *
 * @return void
 */
function wp_kama_taxonomy_edit_form_fields_action( $tag, $taxonomy ){

	// action...
}
$tag(WP_Term)
The current term object.
$taxonomy(string)
Taxonomy name.

Examples

#1 Add metadata fields when creating and editing a taxonomy item

This example adds three fields—Title, Description, and Keywords—to the standard category taxonomy, that is, WordPress categories.

<?php
$taxname = 'category';

// Fields displayed when adding a taxonomy item
add_action("{$taxname}_add_form_fields", 'add_new_custom_fields');
// Fields displayed when editing a taxonomy item
add_action("{$taxname}_edit_form_fields", 'edit_new_custom_fields');

// Save when adding a taxonomy item
add_action("create_{$taxname}", 'save_custom_taxonomy_meta');
// Save when editing a taxonomy item
add_action("edited_{$taxname}", 'save_custom_taxonomy_meta');

function edit_new_custom_fields( $term ) {
	?>
		<tr class="form-field">
			<th scope="row" valign="top"><label>Title</label></th>
			<td>
				<input type="text" name="extra[title]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'title', 1 ) ) ?>"><br />
				<span class="description">SEO title</span>
			</td>
		</tr>
		<tr class="form-field">
			<th scope="row" valign="top"><label>Description</label></th>
			<td>
				<input type="text" name="extra[meta_description]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'meta_description', 1 ) ) ?>"><br />
				<span class="description">SEO description</span>
			</td>
		</tr>
		<tr class="form-field">
			<th scope="row" valign="top"><label>Keywords</label></th>
			<td>
				<input type="text" name="extra[keywords]" value="<?php echo esc_attr( get_term_meta( $term->term_id, 'keywords', 1 ) ) ?>"><br />
				<span class="keywords">SEO keywords</span>
			</td>
		</tr>
	<?php
}

function add_new_custom_fields( $taxonomy_slug ){
	?>
	<div class="form-field">
		<label for="tag-title">Title</label>
		<input name="extra[title]" id="tag-title" type="text" value="" />
		<p>SEO title</p>
	</div>
	<div class="form-field">
		<label for="tag-description">Description</label>
		<input name="extra[meta_description]" id="tag-description" type="text" value="" />
		<p>SEO description</p>
	</div>
	<div class="form-field">
		<label for="tag-keywords">Keywords</label>
		<input name="extra[keywords]" id="tag-keywords" type="text" value="" />
		<p>SEO keywords</p>
	</div>
	<?php
}

function save_custom_taxonomy_meta( $term_id ) {
	if ( ! isset($_POST['extra']) ) return;
	if ( ! current_user_can('edit_term', $term_id) ) return;
	if (
		! wp_verify_nonce( $_POST['_wpnonce'], "update-tag_$term_id" ) && // wp_nonce_field( 'update-tag_' . $tag_ID );
		! wp_verify_nonce( $_POST['_wpnonce_add-tag'], "add-tag" ) // wp_nonce_field('add-tag', '_wpnonce_add-tag');
	) return;

	// Everything is OK. Save or delete the data
	$extra = wp_unslash($_POST['extra']);

	foreach( $extra as $key => $val ){
		// Validate the key
		$_key = sanitize_key( $key );
		if( $_key !== $key ) wp_die( 'bad key'. esc_html($key) );

		// Sanitize the value
		if( $_key === 'tag_posts_shortcode_links' )
			$val = sanitize_textarea_field( strip_tags($val) );
		else
			$val = sanitize_text_field( $val );

		// Save the value
		if( ! $val )
			delete_term_meta( $term_id, $_key );
		else
			update_term_meta( $term_id, $_key, $val );
	}

	return $term_id;
}

The metadata fields can then be retrieved in a template or elsewhere using get_term_meta(). For term ID 10, for example:

$title = get_term_meta( 10, 'title', 1 );
$meta_description = get_term_meta( 10, 'meta_description', 1 );

#2 SEO metadata fields for a term

This class adds custom metadata fields to WordPress taxonomy terms such as categories and tags. The fields are used for SEO, particularly to specify title and keywords metadata for each taxonomy term.

The class defines two static arrays: $metabox and $fields. The $metabox array contains one entry for the metabox heading, while $fields contains the field data for each custom field.

The class provides several methods:

  • init() initializes the class and connects it to WordPress to add custom taxonomy fields.
  • init_hooks() attaches the hooks that add custom taxonomy fields.
  • add_new_custom_fields() displays the custom fields on the taxonomy term creation page.
  • edit_new_custom_fields() displays the custom fields on the taxonomy term editing page.
  • save_term_meta() saves custom field values when a taxonomy term is created or edited.

The class checks whether the current user has permission to edit the taxonomy term and verifies the nonce to prevent unauthorized access to the custom fields.

Overall, it provides a convenient and configurable way to add SEO metadata fields to WordPress taxonomy terms.

final class Term_Seo_Meta_Fields {

	private static array $metabox = [
		'title' => 'SEO headings',
	];

	private static array $fields = [
		'title' => [
			'title' => 'SEO Title <title>',
			'desc' => '',
			'show_on_add' => true,
		],
		'keywords' => [
			'title' => 'SEO keywords <keywords>',
			'desc' => '',
			'show_on_add' => false,
		]
	];

	public static function init(): void {

		// Init later to have all taxonomies registered
		add_action( 'init', [ __CLASS__, 'init_hooks' ], 20 );
	}

	public static function init_hooks(): void {

		$taxes = get_taxonomies( [
			'public' => true,
			'publicly_queryable' => true,
		] );

		foreach( $taxes as $taxname ){

			// Fields when adding a taxonomy element
			add_action( "{$taxname}_add_form_fields", [ __CLASS__, 'add_new_custom_fields' ] );
			// Fields when editing a taxonomy element
			add_action( "{$taxname}_edit_form_fields", [ __CLASS__, 'edit_new_custom_fields' ] );

			// Saving when adding a taxonomy element
			add_action( "create_{$taxname}", [ __CLASS__, 'save_term_meta' ] );
			// Saving when editing a taxonomy element
			add_action( "edited_{$taxname}", [ __CLASS__, 'save_term_meta' ] );
		}
	}

	public static function add_new_custom_fields( $taxonomy ): void {

		$fields = array_filter( self::$fields, static fn( $fdata ) => ! empty( $fdata['show_on_add'] ) );

		if( ! $fields ){
			return;
		}

		?>
		<div class="form-field">
			<h4><?= self::$metabox['title'] ?></h4>
			<p><?= hl_placeholders()->names_html( 'global' ) ?></p>
		</div>
		<?php

		foreach( $fields as $name => $fdata ){
			?>
			<div class="form-field">
				<label for="tag-title"><?= $fdata['title'] ?></label>
				<input name="seotermmeta[<?= $name ?>]" id="tag-title" type="text" value=""/>
				<?php if( ! empty( $fdata['desc'] ) ){ ?>
					<p><?= $fdata['desc'] ?></p>
				<?php } ?>
			</div>
			<?php
		}

	}

	public static function edit_new_custom_fields( $term ): void {

		?>
		<tr class="form-field">
			<th colspan="2" style="padding: 0; font-weight: normal;">
				<h3><?= self::$metabox['title'] ?></h3>
				<p class="description">
					Placeholders: <?= hl_placeholders()->names_html( 'global' ) ?>
					<br><br>
					<code>description</code> is entered in the Description field (placeholders also work there).
				</p>
			</th>
		</tr>
		<?php

		foreach( self::$fields as $name => $fdata ){
			?>
			<tr class="form-field">
				<th scope="row"><label><?= $fdata['title'] ?></label></th>
				<td>
					<input type="text" name="seotermmeta[<?= $name ?>]"
						   value="<?= esc_attr( get_term_meta( $term->term_id, $name, true ) ) ?>"
					>
					<?php if( ! empty( $fdata['desc'] ) ){ ?>
						<p class="description"><?= $fdata['desc'] ?></p>
					<?php } ?>
				</td>
			</tr>
			<?php
		}
	}

	public static function save_term_meta( $term_id ): void {

		if(
			empty( $_POST['seotermmeta'] ) ||
			! current_user_can( 'edit_term', $term_id ) ||
			(
				! wp_verify_nonce( $_POST['_wpnonce'], "update-tag_$term_id" )
				&&
				! wp_verify_nonce( $_POST['_wpnonce_add-tag'], "add-tag" )
			)
		){
			return;
		}

		$seometa = wp_unslash( $_POST['seotermmeta'] );

		foreach( $seometa as $meta_key => $val ){

			if( ! isset( self::$fields[ $meta_key ] ) ){
				/** @noinspection ForgottenDebugOutputInspection */
				wp_die( 'bad key' . esc_html( $meta_key ) );
			}

			$val = sanitize_text_field( $val );
			if( $val ){
				update_term_meta( $term_id, $meta_key, $val );
			}
			else{
				delete_term_meta( $term_id, $meta_key );
			}
		}
	}

}

Changelog

Since 3.0.0 Introduced.

Where the hook is called

In file: /wp-admin/edit-tag-form.php
(taxonomy)_edit_form_fields
wp-admin/edit-tag-form.php 259
do_action( "{$taxonomy}_edit_form_fields", $tag, $taxonomy );

Where the hook is used in WordPress

Usage not found.