WordPress Custom Taxonomies

Categories and tags are the built in taxonomies. With register_taxonomy() you can create your own grouping, like Genre for books, Brand for products or Location for events. If it is hierarchical it works like categories, and if not it works like tags.

Register a taxonomy for a post type

<?php
/**
 * Plugin Name: Books
 */
add_action( 'init', function () {
	register_post_type( 'book', array(
		'labels'       => array( 'name' => 'Books', 'singular_name' => 'Book' ),
		'public'       => true,
		'has_archive'  => true,
		'show_in_rest' => true,
		'supports'     => array( 'title', 'editor' ),
	) );

	register_taxonomy( 'genre', array( 'book' ), array(
		'labels'            => array( 'name' => 'Genres', 'singular_name' => 'Genre' ),
		'hierarchical'      => true,
		'public'            => true,
		'show_admin_column' => true,
		'show_in_rest'      => true,
		'rewrite'           => array( 'slug' => 'genre' ),
	) );
} );

The first parameter is the taxonomy name (genre), the second is the list of post types that can use it, and the third holds the options.

Terminal output

$ wp plugin activate tc-books
Plugin 'tc-books' activated.
Success: Activated 1 of 1 plugins.
$ wp taxonomy list –object_type=book –fields=name,label,hierarchical
name label hierarchical
genre Genres 1
$ wp term create genre "Fiction" –slug=fiction –porcelain
2
$ wp term create genre "Fantasy" –slug=fantasy –parent=2 –porcelain
3
$ wp post create –post_type=book –post_title="The Alchemist" –post_status=publish –porcelain
5
$ wp post term add 5 genre fiction
Success: Added term.
$ wp term list genre –fields=term_id,name,slug,parent,count
term_id name slug parent count
3 Fantasy fantasy 2 0
2 Fiction fiction 0 1

Options of register_taxonomy()

OptionMeaning
hierarchicaltrue: like categories (with parents). false: like tags
publicVisible on the front end and in the dashboard
show_admin_columnShow the terms as a column in the posts list
show_in_restNeeded for the block editor and REST API
rewriteThe URL base of the term pages
labelsTexts in the dashboard

Archive page and queries

Terminal output

$ curl -s -o /dev/null -w "%{http_code}\n" http://example.com/genre/fiction/
404
$ wp rewrite flush
Success: Rewrite rules flushed.
$ curl -s -o /dev/null -w "%{http_code}\n" http://example.com/genre/fiction/
200

The first answer is 404. WordPress did not know the new URL rule yet. After wp rewrite flush (the same as saving Settings > Permalinks) the page works. In a real plugin, flush the rules once in the activation hook, like we did in the Custom Post Types chapter.

Use tax_query to get posts by a custom taxonomy:

$q = new WP_Query( array(
	'post_type' => 'book',
	'tax_query' => array(
		array( 'taxonomy' => 'genre', 'field' => 'slug', 'terms' => 'fiction' ),
	),
) );
foreach ( $q->posts as $p ) {
	echo $p->post_title . ' => ' . implode( ', ', wp_get_post_terms( $p->ID, 'genre', array( 'fields' => 'names' ) ) ) . "\n";
}
Output

The Alchemist => Fiction

Useful functions

  • get_the_terms( $post_id, 'genre' ): terms of a post.
  • get_terms( array( 'taxonomy' => 'genre' ) ): list all terms.
  • the_terms( $post_id, 'genre', 'Genre: ', ', ' ): print terms as links.
  • wp_set_object_terms( $post_id, 'fiction', 'genre' ): set terms from code.
Note: Like post types, taxonomies are best registered in a plugin. Flush the permalinks once after you add a new taxonomy. Next: Custom Fields.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.