WordPress Taxonomy Generator

Generate register_taxonomy() code with full labels, hierarchical or tag-style terms, REST support, rewrite rules and a default term.

Runs in your browser

Taxonomy

Lowercase, max 32 characters, singular — e.g. genre, event_type.

Output
Attach to post types

Comma-separated post type keys.

Behaviour
Type

Needed for the block editor and /wp-json/wp/v2/ endpoints.

URLs & queries

Term archive: /genre/parent/child/

query_var
Default term

Like “Uncategorized” — used when no term is chosen (WordPress 5.5+).

functions.php snippet

// Register Custom Taxonomy: Genres.
// After adding this code, visit Settings → Permalinks and click Save to flush rewrite rules.
if ( ! function_exists( 'myplugin_register_genre_taxonomy' ) ) {
	/**
	 * Registers the "genre" taxonomy.
	 */
	function myplugin_register_genre_taxonomy() {
		$labels = array(
			'name'                       => _x( 'Genres', 'taxonomy general name', 'my-plugin' ),
			'singular_name'              => _x( 'Genre', 'taxonomy singular name', 'my-plugin' ),
			'menu_name'                  => __( 'Genres', 'my-plugin' ),
			'search_items'               => __( 'Search Genres', 'my-plugin' ),
			'popular_items'              => __( 'Popular Genres', 'my-plugin' ),
			'all_items'                  => __( 'All Genres', 'my-plugin' ),
			'parent_item'                => __( 'Parent Genre', 'my-plugin' ),
			'parent_item_colon'          => __( 'Parent Genre:', 'my-plugin' ),
			'name_field_description'     => __( 'The name is how it appears on your site.', 'my-plugin' ),
			'slug_field_description'     => __( 'The “slug” is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'my-plugin' ),
			'parent_field_description'   => __( 'Assign a parent genre to create a hierarchy.', 'my-plugin' ),
			'desc_field_description'     => __( 'The description is not prominent by default; however, some themes may show it.', 'my-plugin' ),
			'edit_item'                  => __( 'Edit Genre', 'my-plugin' ),
			'view_item'                  => __( 'View Genre', 'my-plugin' ),
			'update_item'                => __( 'Update Genre', 'my-plugin' ),
			'add_new_item'               => __( 'Add New Genre', 'my-plugin' ),
			'new_item_name'              => __( 'New Genre Name', 'my-plugin' ),
			'separate_items_with_commas' => __( 'Separate genres with commas', 'my-plugin' ),
			'add_or_remove_items'        => __( 'Add or remove genres', 'my-plugin' ),
			'choose_from_most_used'      => __( 'Choose from the most used genres', 'my-plugin' ),
			'not_found'                  => __( 'No genres found.', 'my-plugin' ),
			'no_terms'                   => __( 'No genres', 'my-plugin' ),
			'filter_by_item'             => __( 'Filter by genre', 'my-plugin' ),
			'items_list_navigation'      => __( 'Genres list navigation', 'my-plugin' ),
			'items_list'                 => __( 'Genres list', 'my-plugin' ),
			'most_used'                  => _x( 'Most Used', 'taxonomy', 'my-plugin' ),
			'back_to_items'              => __( '← Go to Genres', 'my-plugin' ),
			'item_link'                  => _x( 'Genre Link', 'navigation link block title', 'my-plugin' ),
			'item_link_description'      => _x( 'A link to a genre.', 'navigation link block description', 'my-plugin' ),
		);

		$args = array(
			'labels'             => $labels,
			'hierarchical'       => true,
			'public'             => true,
			'publicly_queryable' => true,
			'show_ui'            => true,
			'show_in_menu'       => true,
			'show_in_nav_menus'  => true,
			'show_admin_column'  => true,
			'show_in_rest'       => true,
			'show_tagcloud'      => false,
			'show_in_quick_edit' => true,
			'query_var'          => true,
			'rewrite'            => array(
				'slug'         => 'genre',
				'with_front'   => false,
				'hierarchical' => true,
			),
		);

		register_taxonomy( 'genre', array( 'post' ), $args );
	}
}
add_action( 'init', 'myplugin_register_genre_taxonomy', 0 );
Flush permalinks
Term archive URLs work only after rewrite rules are regenerated: save Settings → Permalinks once.

What is a custom taxonomy in WordPress?

A taxonomy is a way to group content. WordPress ships with two: categories, which are hierarchical and can have parents and children, and tags, which are flat keywords. A custom taxonomy adds your own grouping — genres for books, locations for events, brands for products, skills for team members — complete with its own admin screen, editor panel, archive URLs and REST endpoint.

Taxonomies are registered with register_taxonomy( $key, $object_types, $args ) on init. The $object_types decide which post types the terms attach to, and hierarchical decides whether editors get a category-style checkbox tree or a tag-style input. The labels array controls every string in the UI, from “Add New Genre” to “Separate genres with commas”.

This generator produces translation-ready code with the full set of labels, validates the key against WordPress’s reserved query terms (using a key like name, type or year silently breaks front-end queries) and outputs either a snippet or a standalone plugin that flushes rewrite rules on activation.

How to use the WordPress Taxonomy Generator

  1. Enter a singular taxonomy key (max 32 characters). Names are suggested — adjust irregular plurals.
  2. Tick the post types to attach it to, and add custom post type keys such as book if needed.
  3. Choose hierarchical (category-style) or flat (tag-style), and keep show_admin_column on to see terms in the post list.
  4. Set the rewrite slug and, optionally, a default term that is assigned when none is chosen.
  5. Copy or download the code and save Settings → Permalinks once so term archives resolve.

Example

A hierarchical “Genre” taxonomy attached to a book post type (labels shortened):

register_taxonomy(
	'genre',
	array( 'book' ),
	array(
		'labels'            => $labels,
		'hierarchical'      => true,
		'show_admin_column' => true,
		'show_in_rest'      => true,
		'rewrite'           => array( 'slug' => 'genre', 'hierarchical' => true ),
	)
);

Hierarchical or flat?

  • Hierarchical taxonomies suit a controlled vocabulary editors pick from: departments, product categories, regions. With hierarchical rewrites URLs read like /genre/fiction/thriller/.
  • Flat taxonomies suit free-form keywords editors type as they go: ingredients, skills, topics. The block editor shows a token field with “most used” suggestions.
  • You can change hierarchical later without losing terms, but existing parent/child relationships are ignored when it is off.

Working with custom post types and fields

Taxonomies usually pair with a custom post type from the CPT Generator. The generated code hooks init at priority 0 so the taxonomy exists before post types registered at the default priority reference it. To store extra data on terms — a colour or an icon per genre — use the ACF Field Generator with a “Taxonomy” location rule, and query terms in a shortcode.

Frequently Asked Questions

Why can’t I use “type” or “name” as a taxonomy key?

Taxonomy keys become public query variables. WordPress already uses dozens of names such as name, type, year, author and order in WP_Query, so a taxonomy with one of those keys hijacks unrelated requests and causes 404s. The generator blocks the full reserved list.

Why doesn’t my taxonomy appear in the block editor?

The block editor loads taxonomies through the REST API, so show_in_rest must be true. Also confirm the post type itself has show_in_rest enabled.

What does show_admin_column do?

It adds a column with each post’s terms to the posts list table, and every term links to a filtered list of posts. It is one of the most useful flags for editors.

How do I query posts by a custom taxonomy?

Use a tax_query in WP_Query, for example array( array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => 'fiction' ) ). Template files named taxonomy-genre.php control the term archive layout.

What happens to terms if I remove the code?

The terms and their relationships stay in the database (wp_terms, wp_term_taxonomy, wp_term_relationships). They reappear as soon as the taxonomy is registered again with the same key.