Justin Tadlock

A refresher on custom taxonomies

When I wrote about custom taxonomies just a year ago, not much was known or understood about them in the WordPress community. For most people, anything beyond “tags” and “categories” was unneeded anyway. And, only having only taxonomies for blog posts was essentially useless.

However, with WordPress 3.0 around the corner and the introduction of custom post types, the usefulness of custom taxonomies will increase greatly.

Post types are your forms of content. Taxonomies are the glue that holds that content together, linking it in all kinds of neat ways.

As I delve deeper into the subject of post types and taxonomies in this series of posts, I’ll give more examples of how these two things are related and how they can be used to create any type of site you want with WordPress.

First, we need a primer on taxonomies.

In WordPress 3.0, taxonomies will be super-charged. While I do encourage you to go back and read my original post on custom taxonomies and my followup on how I created a movie database to gain a better understanding of taxonomies, I’ll try to cover the important details in this post.

A refresher on what taxonomies are

Taxonomies are a method for grouping content. They’re a way of intelligently creating an organizational system for data. Some examples include:

  • Finding actors (taxonomy) that have played in specific movies (content).
  • Listing musicians (taxonomy) that have performed on various albums (content).
  • Locating restaurants (content) that serve specific types of food (taxonomy).
  • Getting recipes (content) that use certain ingredients (taxonomy).
  • Searching for jobs (content) in different fields (taxonomy).
  • Visiting a forum (taxonomy) that lists forum topics (content).
  • Scanning for books (content) written by your favorite author (taxonomy).

Grouping content in this way simply isn’t possible with standard tags and categories. To understand the benefits of taxonomies, you have to open your mind to possibilities beyond a standard blog.

What’s new with taxonomies in 3.0?

Some things have changed since the major overhaul in WordPress 2.8 of taxonomies. Don’t worry; your previously-created taxonomies will still work fine. But, now you have much more control.

The biggest changes are:

  • Ability to create taxonomies for any post type (not just posts).
  • Hierarchical taxonomies now get admin screens just like non-hierarchical ones.
  • Control over the capabilities for editing, creating, deleting, and assigning terms.
  • Control over admin text for making the UI not seem so weird.

The register_taxonomy function

To register a taxonomy, we must use the register_taxonomy() WordPress function. It takes in three parameters.

register_taxonomy( $taxonomy, $objects, $arguments )


The $taxonomy parameter should be a unique name for your taxonomy that’s not used by any other taxonomy.

register_taxonomy( 'division', $objects, $arguments )


The $objects parameter can be a string (single object type) or an array (multiple object types). This represents the post types that you want to register your taxonomy for.

register_taxonomy( $taxonomy, array( 'post', 'page' ), $arguments )


The $arguments parameter is an array of arguments that help define how your taxonomy should function. I’ll cover these in more depth later.

register_taxonomy( $taxonomy, $objects, array() )

Creating a custom taxonomy

We’re going to keep everything pretty basic for this tutorial. Let’s create a taxonomy called division for your blog posts. The easiest way to do this is to add this code to your theme’s functions.php file or a plugin file.

add_action( 'init', 'register_my_taxonomies', 0 );

function register_my_taxonomies() {

        array( 'post' ),
            'public' => true,
            'labels' => array(
                'name' => __( 'Divisions' ),
                'singular_name' => __( 'Division' )

This will create a new item called “Divisions” for you under your “Posts” menu item in the admin.

Taxonomy screen in WordPress

Controlling your taxonomy

The arguments array (third parameter) of register_taxonomy() is the parameter that gives you fine-grain control over how your taxonomy functions in WordPress. It allows for about 10 arguments, which I’ll cover in detail here. In each section, I’ll give a basic code example of how each is used.


The public argument is sort of a catchall argument that controls whether your taxonomy is publicly used on the site or if works behind the scenes. Depending on whether it’s set to true or false, it’ll automatically set other arguments if they aren’t defined.

  • show_ui: Whether the taxonomy should be shown in the administration interface.
  • show_tagcloud: Whether to allow the taxonomy to be chosen in the tag cloud widget.
  • show_in_nav_menus: Whether to allow terms from the taxonomy in navigation menus.
'public' => true,
'show_ui' => true,
'show_tagcloud' => true,
'show_in_nav_menus' => true,


The hierarchical argument decides if your taxonomy’s terms are in a non-hierarchical (flat) or hierarchical format. By default, this is set to false, so the taxonomy will behave like the post tag taxonomy. Hierarchical taxonomies will behave like the category taxonomy.

'hierarchical' => false,


New in WordPress 3.0 is the ability to change the capabilities for who can use the taxonomy in the admin. By default, users of roles with the manage_categories capability can manage, edit, and delete terms, and those of roles with the edit_posts capability can assign terms to a “post.”

  • manage_terms: Ability to view terms in the administration. I don’t see any other use for this.
  • edit_terms: Grants the ability to edit and create terms.
  • delete_terms: Gives permission to delete terms from the taxonomy.
  • assign_terms: Capability for assigning terms in the new/edit post screen.

If you’re using a role management plugin like Members, you can assign which users have control over your terms. If not, I suggest not changing these capabilities.

'capabilities' => array(
    'manage_terms' => 'manage_divisions',
    'edit_terms' => 'edit_divisions',
    'delete_terms' => 'delete_divisions',
    'assign_terms' => 'assign_divisions'


The labels array is a set of text strings that control how your taxonomy is viewed in the admin. If your taxonomy is non-hierarchical, this defaults to the post tag wording. If it is hierarchical, it defaults to the category terminology.

  • name: The plural name that represents your taxonomy.
  • singular_name: The singular name for your taxonomy.
  • search_items: Text for the search button when searching the taxonomy terms.
  • popular_items: Header for the popular cloud of terms (not used with hierarchical taxonomies).
  • all_items: Text to display all of the terms of the taxonomy.
  • parent_item: Text for displaying the parent term (not used with non-hierarchical taxonomies).
  • parent_item_colon: Text for displaying the parent term followed by a colon (not used with non-hierarchical taxonomies).
  • edit_item: Represents the text when editing a term.
  • update_item: Displayed when updating a term.
  • add_new_item: Text to display for adding a new term.
  • new_item_name: Text to display for adding a new term name.
'labels' => array(
    'name' => __( 'Divisions' ),
    'singular_name' => __( 'Division' ),
    'search_items' => __( 'Search Divisions' ),
    'popular_items' => __( 'Popular Divisions' ),
    'all_items' => __( 'All Divisions' ),
    'parent_item' => __( 'Parent Division' ),
    'parent_item_colon' => __( 'Parent Division:' ),
    'edit_item' => __( 'Edit Divison' ),
    'update_item' => __( 'Update Division' ),
    'add_new_item' => __( 'Add New Division' ),
    'new_item_name' => __( 'New Division Name' ),


The query_var argument allows you to get posts based on particular terms of the taxonomy through a query string in the browser URL bar or through a WordPress function like query_posts() or class like WP_Query. This will default to the name of your taxonomy, but you can also set it to false to prevent queries.

'query_var' => 'division',


The rewrite argument gives you control over the permalink structure of your taxonomy’s term archives. You may want a structure like yoursite.com/divisions/blue-group, and this argument will give you control over that. It can be set to true, false, or an array of values. The values of the array are:

  • slug: The slug you want to prefix your term archives with.
  • with_front: Whether your term archives should use the front base from your permalinks settings.
'rewrite' => array( 'slug' => 'divisions', 'with_front' => false ),


update_count_callback allows you to write a custom function that will be called when the term count is updated. Most users shouldn’t need this and shouldn’t bother setting this.

'update_count_callback' => 'my_custom_count_callback',

To answer the 18 billion questions from the last year

Since I first published an article on taxonomies last year, I’ve gotten numerous questions on using them. The two questions that crop up the most:

  • Can I create a hierarchical taxonomy like categories?
  • Can I use my taxonomy with pages (or other post types)?

It’s been a long time coming, but I can finally say, “Yes! And. Yes!”

I didn’t want to overwhelm everyone with too much information in this tutorial. I mostly wanted to give a refresher on taxonomies and cover some of the new features. I encourage you to read my previous posts on the subject for a deeper understanding of taxonomies.

The problem I see now is that there’s one more question that needs answering — how to merge taxonomies and post types. I’ve touched on this a bit in this post, but you can expect a real-world example from me in the near future.