Tips・Adding post types and taxonomies in WordPress

How to create custom taxonomies (register_taxonomy)

How to add your own classifications like "Season" and "Brand." Includes copy-and-paste register_taxonomy code, the difference between category-style and tag-style, archive templates and how to fix 404s.

“Season,” “Brand,” “Service area”—custom taxonomies classify posts along axes of your own choosing. You get the same mechanism as categories and tags, under whatever name you like.

function my_register_taxonomies() {
  register_taxonomy('season', ['shohin'], [
    'label'             => 'Season',
    'public'            => true,
    'hierarchical'      => true,    // true = category-style / false = tag-style
    'show_admin_column' => true,    // add a column to the admin list
    'show_in_rest'      => true,    // use it in the block editor
  ]);
}
add_action('init', 'my_register_taxonomies');

The first argument is the taxonomy name; the second is the post types to attach it to (an array lets you name several). That alone adds a “Season” selector to the product editing screen.

TipsHow to create custom post types (register_post_type)Want to create the custom post type first?

Category-style and tag-style

One line—hierarchical—changes its character entirely.

hierarchical: true (category-style)hierarchical: false (tag-style)
Parent/childSupportedNot supported
Editing screenChosen with checkboxesAdded by free text entry
What it suitsFixed classifications (season, area, industry)Keywords that keep growing (material, features)

“I want people to pick from a predetermined set” means category-style; “I want writers to add freely” means tag-style. Choose based on how the people running the site will work.

Argument cheat sheet

ArgumentMeaningCommon values
label / labelsThe name shown in the admin screen'Season'
publicWhether it appears on the sitetrue
hierarchicalWhether it can have parents and childrentrue / false
show_admin_columnWhether to add a column to the post listtrue
show_in_restBlock editor supporttrue
rewriteThe URL shape['slug' => 'season', 'with_front' => false]
show_in_nav_menusWhether it can be added to menustrue
meta_box_cbChange the input UIfalse hides the panel
query_varWhether it can filter via URL parametertrue

Archive pages and templates

Registering a taxonomy automatically creates an archive page per term.

/season/winter/     ← a list of posts belonging to "Winter"

The template responsible for that page is looked for in this order.

  1. taxonomy-season-winter.php (that specific term only)
  2. taxonomy-season.php (the whole taxonomy)
  3. taxonomy.php
  4. archive.php
  5. index.php

archive.php stands in even without a dedicated file, so confirm it works first and add files as you need them.

You can output the term’s name and description in the template like this.

<h1><?php single_term_title(); ?></h1>
<?php if ($desc = term_description()) : ?>
  <div class="term-desc"><?php echo wp_kses_post($desc); ?></div>
<?php endif; ?>
TipsTemplate hierarchy cheat sheet (which file gets used?)The big picture of the template hierarchy, in this cheat sheet

Showing a post’s terms

Output the terms attached to a post with get_the_terms() (or the_terms() if you want the HTML too).

<?php the_terms(get_the_ID(), 'season', 'Season: ', ', '); ?>

To build a list of the classification itself (a filter menu), use get_terms().

TipsListing categories and terms with get_termsHow to output term lists and build their links

Fetching only that term’s posts

When you’re building a list yourself, filter with tax_query.

$query = new WP_Query([
  'post_type' => 'shohin',
  'tax_query' => [
    ['taxonomy' => 'season', 'field' => 'slug', 'terms' => 'winter'],
  ],
]);
TipsFiltering by category and taxonomy with tax_queryHow to write tax_query conditions (AND/OR, multiple taxonomies)

Choosing between taxonomies and custom fields

Both are “extra information,” but their roles differ.

  • Taxonomyan axis for filtering lists. You get a dedicated archive page and URL, and filtering is fast
  • Custom fielda value displayed within the article. Price, size, date and so on

The rule of thumb is “do I want to browse a list by this data?” “I want to see only winter products” means a taxonomy; “I just want to display a price” means a custom field. It also makes a speed difference as content grows.

TipsFiltering and sorting by custom field with meta_queryHow to filter by custom field, and a note on speed

Naming rules and cautions

  • Lowercase alphanumerics and underscores, up to 32 characters
  • Avoid names WordPress uses—category, post_tag, type, author, name, date, terms and others
  • Don’t use the same name as a post type (the URLs collide)

Attaching it to a post type later

To use an existing taxonomy on another post type as well, one line does it.

add_action('init', function () {
  register_taxonomy_for_object_type('season', 'post');   // use "Season" on posts too
});

Conversely, to use the standard categories and tags on a custom post type, 'taxonomies' => ['category', 'post_tag'] in register_post_type() is the easy route.

Summary

  1. Just run register_taxonomy('name', ['post type'], [...]) on the init hook
  2. hierarchical decides category-style (pick from a set) or tag-style (add freely)
  3. taxonomy-<name>.php handles the archive. Without it, archive.php stands in
  4. Axes you want to filter by are taxonomies; values you only display are custom fields

Once you can design classifications, the same article data can be presented in many different ways.

FAQ

When should I use a custom taxonomy versus a custom field?
Use a taxonomy when it's an axis for filtering lists (you get a dedicated archive page and URL, and filtering is fast), and a custom field for information you only display within the article. "I want to filter by season" is a taxonomy; "I want to show a price" is a custom field.
What's the difference between category-style and tag-style?
If register_taxonomy's 'hierarchical' is true you get category-style (parents and children, chosen with checkboxes); false gives tag-style (no hierarchy, added by free text entry).
My taxonomy archive page 404s.
Open "Settings" → "Permalinks" and press "Save Changes" to regenerate the URL rules. Also confirm 'public' => true is set.
I want a taxonomy column in the admin post list.
Specify 'show_admin_column' => true and a column for that classification is added to the admin post list. It makes day-to-day work much easier, so turning it on by default is a good habit.