Skip to content
wp-skills
Register
tools/wordpress-taxonomy-generator

WordPress Taxonomy Generator

Build a register_taxonomy() call: hierarchical or flat, the post types it attaches to, permalinks, REST, a default term and its own capabilities — with the label set WordPress actually uses for the hierarchy you picked.

Up to 32 characters of lowercase letters, numbers, dashes and underscores. register_taxonomy() rejects anything longer.

Attach to

Comma separated, for post types that are not in the list above.

Off behaves like tags: a flat list with a comma-separated input. WordPress fills in a different set of labels for each.

Properties

The default is a checkbox list for a hierarchical taxonomy and a tag input for a flat one. 'No meta box' is for terms assigned in code.

Blank uses the taxonomy key. This is not the same as disabling it.

Default term

Assigned to posts with no term of this taxonomy, the way Uncategorized works. Created when the taxonomy registers. Leave blank for none.

Derived from the name when left blank.

Names manage_/edit_/delete_/assign_ capabilities after the taxonomy key instead of reusing the category ones. No role holds them until you grant them — including administrator.

Blank uses the taxonomy key.

snippet.php
// Register custom taxonomy
// Taxonomy: Genre
function create_genre_taxonomy() {
	$labels = array(
		'name'                       => _x( 'Genres', 'Taxonomy General Name', 'text-domain' ),
		'singular_name'              => _x( 'Genre', 'Taxonomy Singular Name', 'text-domain' ),
		'menu_name'                  => __( 'Genres', 'text-domain' ),
		'all_items'                  => __( 'All Genres', 'text-domain' ),
		'search_items'               => __( 'Search Genres', 'text-domain' ),
		'edit_item'                  => __( 'Edit Genre', 'text-domain' ),
		'view_item'                  => __( 'View Genre', 'text-domain' ),
		'update_item'                => __( 'Update Genre', 'text-domain' ),
		'add_new_item'               => __( 'Add New Genre', 'text-domain' ),
		'new_item_name'              => __( 'New Genre Name', 'text-domain' ),
		'not_found'                  => __( 'No Genres found', 'text-domain' ),
		'no_terms'                   => __( 'No Genres', 'text-domain' ),
		'most_used'                  => __( 'Most Used', 'text-domain' ),
		'items_list'                 => __( 'Genres list', 'text-domain' ),
		'items_list_navigation'      => __( 'Genres list navigation', 'text-domain' ),
		'back_to_items'              => __( '← Go to Genres', 'text-domain' ),
		'item_link'                  => _x( 'Genre Link', 'navigation link block title', 'text-domain' ),
		'item_link_description'      => _x( 'A link to a Genre.', 'navigation link block description', 'text-domain' ),
		'parent_item'                => __( 'Parent Genre', 'text-domain' ),
		'parent_item_colon'          => __( 'Parent Genre:', 'text-domain' ),
		'filter_by_item'             => __( 'Filter by Genre', 'text-domain' ),
		'parent_field_description'   => __( 'Assign a parent term to build a hierarchy of Genres.', 'text-domain' ),
	);

	$args = array(
		'labels'             => $labels,
		'description'        => __( 'Lorem ipsum dolor sit amet.', 'text-domain' ),
		'hierarchical'       => true,
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'show_in_nav_menus'  => true,
		'show_tagcloud'      => true,
		'show_in_quick_edit' => true,
		'show_admin_column'  => true,
		'sort'               => false,
		'show_in_rest'       => true,
		'rewrite'            => true,
		'query_var'          => true,
	);

	register_taxonomy( 'genre', array( 'post' ), $args );
}
add_action( 'init', 'create_genre_taxonomy', 0 );

// Permalinks for a new taxonomy only work once the rewrite rules are rebuilt.
// Visiting Settings > Permalinks is enough; flush_rewrite_rules() on every load
// is not, and is expensive.