Create Custom Taxonomies in WordPress: A Comprehensive Guide

WordPress is renowned for its flexibility, allowing users to organize and display content in nearly endless ways. At the heart of this organization lies taxonomies—a system for grouping posts (or custom post types) based on shared characteristics. While WordPress comes with two default taxonomies—Categories (hierarchical) and Tags (non-hierarchical)—they often fall short for specialized content types. For example, an e-commerce site might need to group products by "Brand" or "Product Type," a recipe blog by "Cuisine" or "Diet," or a portfolio by "Client" or "Project Type."

This is where custom taxonomies shine. By creating custom taxonomies, you can tailor WordPress’s content organization to your specific needs, improving user experience, SEO, and content discoverability. In this guide, we’ll dive deep into what custom taxonomies are, why you need them, and how to create, display, and manage them—whether you’re a developer comfortable with code or a user preferring plugins.

Table of Contents#

  1. Understanding WordPress Taxonomies: The Basics

    • 1.1 What Are Taxonomies?
    • 1.2 Default Taxonomies: Categories vs. Tags
    • 1.3 Custom Taxonomies: Definition and Use Cases
  2. Why Create Custom Taxonomies?

    • 2.1 Improved Content Organization
    • 2.2 Enhanced User Experience
    • 2.3 SEO Benefits
    • 2.4 Scalability for Complex Sites
  3. Creating Custom Taxonomies: Two Methods

    • 3.1 Method 1: Using Code (register_taxonomy())
      • 3.1.1 Prerequisites: Child Themes or Custom Plugins
      • 3.1.2 The register_taxonomy() Function: Parameters Explained
      • 3.1.3 Step-by-Step Example: Hierarchical Taxonomy
      • 3.1.4 Step-by-Step Example: Non-Hierarchical Taxonomy
    • 3.2 Method 2: Using Plugins (No Code Required)
      • 3.2.1 Custom Post Type UI (CPT UI)
      • 3.2.2 Advanced Custom Fields (ACF)
  4. Managing Custom Taxonomies in the WordPress Admin

    • 4.1 Adding and Editing Terms
    • 4.2 Bulk Actions and Term Hierarchies
    • 4.3 Taxonomy Settings: Slugs, Labels, and Permalinks
  5. Displaying Custom Taxonomies on the Front End

    • 5.1 Basic Display with Template Tags
    • 5.2 Advanced Display: Custom Queries and Templates
    • 5.3 Displaying Taxonomy Archives
  6. Advanced Custom Taxonomy Techniques

    • 6.1 Adding Custom Meta Fields to Taxonomy Terms
    • 6.2 Custom Rewrite Rules and Permalinks
    • 6.3 Integrating with Gutenberg and Block Themes
    • 6.4 Querying Posts by Custom Taxonomy Terms
  7. Troubleshooting Common Custom Taxonomy Issues

    • 7.1 Taxonomy Not Showing in Admin
    • 7.2 Permalinks Not Working (404 Errors)
    • 7.3 Terms Not Appearing on the Front End
    • 7.4 Conflicts with Plugins or Themes
  8. Best Practices for Custom Taxonomies

    • 8.1 Use Child Themes or Custom Plugins (Avoid Core Edits)
    • 8.2 Choose Descriptive Slugs and Labels
    • 8.3 Limit Taxonomies to What You Need
    • 8.4 Document Your Taxonomy Structure
  9. Conclusion

  10. References

1. Understanding WordPress Taxonomies: The Basics#

1.1 What Are Taxonomies?#

In WordPress, a taxonomy is a way to group and classify content. Think of it as a filing system for your posts, pages, or custom post types (CPTs). The word "taxonomy" derives from the Greek taxis (arrangement) and nomos (law), meaning "the law of arrangement."

At its core, a taxonomy consists of:

  • Terms: The individual categories or tags within the taxonomy (e.g., "Fiction" or "Non-Fiction" in a "Genre" taxonomy).
  • Relationships: How terms relate to each other (e.g., parent-child relationships in hierarchical taxonomies).

Taxonomies help both users and search engines understand your content structure, making it easier to find relevant posts.

1.2 Default Taxonomies: Categories vs. Tags#

WordPress ships with two built-in taxonomies:

FeatureCategories (Hierarchical)Tags (Non-Hierarchical)
StructureTree-like (parent/child relationships)Flat (no hierarchy)
Use CaseBroad grouping (e.g., "News," "Reviews")Specific details (e.g., "sustainability," "AI")
Required?Optional (but posts can have one)Optional (can have multiple)
Default Slug/category/[term]/tag/[term]

While useful for basic blogs, these default taxonomies are limited. For example, a food blog might need to group recipes by "Cuisine" (Italian, Thai), "Diet" (Vegan, Gluten-Free), and "Cooking Method" (Baked, Grilled)—none of which fit neatly into Categories or Tags.

1.3 Custom Taxonomies: Definition and Use Cases#

A custom taxonomy is a user-defined classification system tailored to specific content types. Unlike default taxonomies, custom taxonomies can be:

  • Hierarchical: Like Categories (e.g., "Product Type" with child terms "Laptops" → "Gaming Laptops").
  • Non-Hierarchical: Like Tags (e.g., "Skills" with terms "JavaScript," "Python," "Design").

Common Use Cases:

  • E-Commerce: "Brand" (Nike, Adidas), "Product Category" (Shoes, Apparel), "Color" (Red, Blue).
  • Events: "Venue" (Convention Center, Park), "Organizer" (Tech Corp, Community Group).
  • Education: "Course Level" (Beginner, Advanced), "Subject" (Math, Science).
  • Real Estate: "Property Type" (Apartment, House), "Amenity" (Pool, Garage).

2. Why Create Custom Taxonomies?#

Custom taxonomies are more than just organizational tools—they transform how users interact with your site and how search engines index it. Here’s why they matter:

2.1 Improved Content Organization#

Default taxonomies force a one-size-fits-all approach. Custom taxonomies let you segment content by multiple criteria. For example, a travel blog could use:

  • Hierarchical: "Destination" (Europe → France → Paris).
  • Non-Hierarchical: "Activity" (Hiking, Food Tour), "Season" (Summer, Winter).

This granularity makes content easier to manage for admins and discoverable for users.

2.2 Enhanced User Experience#

Visitors can filter content by specific attributes. A user interested in "Vegan Thai Recipes" can click the "Vegan" and "Thai" terms to see only relevant posts, reducing friction and keeping them on your site longer.

2.3 SEO Benefits#

Search engines prioritize sites with clear, logical structures. Custom taxonomies create keyword-rich URLs (e.g., /cuisine/thai/vegan/) and help search engines understand content relationships, potentially boosting rankings for long-tail keywords.

2.4 Scalability for Complex Sites#

As your site grows, default taxonomies become unwieldy. Custom taxonomies scale with your content, ensuring organization remains manageable even with thousands of posts.

3. Creating Custom Taxonomies: Two Methods#

You can create custom taxonomies in WordPress using code (for developers) or plugins (for non-developers). We’ll cover both.

3.1 Method 1: Using Code (register_taxonomy())#

The most flexible way to create custom taxonomies is by using WordPress’s built-in register_taxonomy() function. This method requires basic PHP knowledge but offers full control over labels, behavior, and integration.

3.1.1 Prerequisites: Child Themes or Custom Plugins#

Never modify WordPress core files (e.g., wp-includes/ or wp-content/themes/twenty twenty-three/). Instead:

  • Child Theme: If you’re using a custom theme, add code to your child theme’s functions.php.
  • Custom Plugin: For better portability (e.g., if you switch themes), create a simple plugin. To do this:
    1. Create a folder in wp-content/plugins/ (e.g., my-custom-taxonomies).
    2. Add a file my-custom-taxonomies.php with a plugin header:
      <?php  
      /*  
      Plugin Name: My Custom Taxonomies  
      Description: Adds custom taxonomies for my site.  
      Version: 1.0  
      Author: Your Name  
      */  

3.1.2 The register_taxonomy() Function: Parameters Explained#

The register_taxonomy() function registers a new taxonomy. Its syntax is:

register_taxonomy( $taxonomy, $object_type, $args );  

Let’s break down the key parameters:

ParameterDescription
$taxonomyUnique slug for the taxonomy (e.g., genre). Use lowercase, no spaces.
$object_typePost type(s) to attach the taxonomy to (e.g., post, book, array('post', 'page')).
$argsArray of settings (labels, hierarchy, visibility, etc.).

The $args array is critical. Here are the most important settings:

  • labels: An array of text labels for the taxonomy (singular, plural, menu name, etc.). Required for clarity.
  • hierarchical: true (like Categories) or false (like Tags).
  • public: true to make the taxonomy visible to users and search engines.
  • show_ui: true to display the taxonomy in the WordPress admin.
  • rewrite: Controls URL structure (e.g., array('slug' => 'genre') for /genre/fiction/).
  • show_in_rest: true to enable Gutenberg/REST API support (required for block editors).

3.1.3 Step-by-Step Example: Hierarchical Taxonomy#

Let’s create a hierarchical "Genre" taxonomy for a "Book" custom post type (CPT). First, assume you have a "Book" CPT (if not, register one first).

Code Snippet:

// Register "Genre" taxonomy for "Book" CPT  
function create_book_genre_taxonomy() {  
    $labels = array(  
        'name'              => _x( 'Genres', 'taxonomy general name', 'textdomain' ),  
        'singular_name'     => _x( 'Genre', 'taxonomy singular name', 'textdomain' ),  
        'search_items'      => __( 'Search Genres', 'textdomain' ),  
        'all_items'         => __( 'All Genres', 'textdomain' ),  
        'parent_item'       => __( 'Parent Genre', 'textdomain' ),  
        'parent_item_colon' => __( 'Parent Genre:', 'textdomain' ),  
        'edit_item'         => __( 'Edit Genre', 'textdomain' ),  
        'update_item'       => __( 'Update Genre', 'textdomain' ),  
        'add_new_item'      => __( 'Add New Genre', 'textdomain' ),  
        'new_item_name'     => __( 'New Genre Name', 'textdomain' ),  
        'menu_name'         => __( 'Genre', 'textdomain' ),  
    );  
 
    $args = array(  
        'hierarchical'      => true, // Like Categories  
        'labels'            => $labels,  
        'show_ui'           => true,  
        'show_admin_column' => true, // Show column in Books list table  
        'query_var'         => true, // Allow querying by genre (e.g., ?genre=fiction)  
        'rewrite'           => array( 'slug' => 'genre' ), // URL slug: /genre/fiction/  
        'show_in_rest'      => true, // Enable Gutenberg support  
    );  
 
    register_taxonomy( 'genre', array( 'book' ), $args ); // Attach to "book" CPT  
}  
add_action( 'init', 'create_book_genre_taxonomy', 0 );  

Explanation:

  • labels: Customizes text throughout the admin (e.g., "Add New Genre" instead of the default "Add New Term").
  • hierarchical => true: Allows parent/child terms (e.g., "Fiction" → "Science Fiction").
  • show_admin_column: Adds a "Genre" column to the Books list in the admin, making it easy to see assigned terms.
  • rewrite: Sets the URL slug to /genre/[term]/ (e.g., /genre/fiction/).

3.1.4 Step-by-Step Example: Non-Hierarchical Taxonomy#

Now, let’s create a non-hierarchical "Tag"-like taxonomy: "Author Skill" for a "Writer" CPT.

Code Snippet:

function create_author_skill_taxonomy() {  
    $labels = array(  
        'name'                       => _x( 'Author Skills', 'taxonomy general name', 'textdomain' ),  
        'singular_name'              => _x( 'Author Skill', 'taxonomy singular name', 'textdomain' ),  
        'search_items'               => __( 'Search Author Skills', 'textdomain' ),  
        'popular_items'              => __( 'Popular Author Skills', 'textdomain' ), // Shows in tag cloud  
        'separate_items_with_commas' => __( 'Separate skills with commas', 'textdomain' ),  
        'add_or_remove_items'        => __( 'Add or remove skills', 'textdomain' ),  
        'choose_from_most_used'      => __( 'Choose from most used skills', 'textdomain' ),  
        'not_found'                  => __( 'No author skills found.', 'textdomain' ),  
        'menu_name'                  => __( 'Skills', 'textdomain' ),  
    );  
 
    $args = array(  
        'hierarchical'          => false, // Like Tags  
        'labels'                => $labels,  
        'public'                => true,  
        'show_ui'               => true,  
        'show_in_rest'          => true,  
        'rewrite'               => array( 'slug' => 'author-skill' ),  
        'update_count_callback' => '_update_post_term_count', // Required for non-hierarchical counts  
    );  
 
    register_taxonomy( 'author-skill', 'writer', $args ); // Attach to "writer" CPT  
}  
add_action( 'init', 'create_author_skill_taxonomy', 0 );  

Key Differences from Hierarchical:

  • hierarchical => false: Disables parent/child terms.
  • popular_items and separate_items_with_commas: Labels specific to tag-like taxonomies.
  • update_count_callback: Ensures post counts update correctly (use _update_post_term_count for non-hierarchical).

3.2 Method 2: Using Plugins (No Code Required)#

If you’re not comfortable with PHP, plugins like Custom Post Type UI (CPT UI) or Advanced Custom Fields (ACF) simplify taxonomy creation.

3.2.1 Custom Post Type UI (CPT UI)#

CPT UI is the most popular plugin for managing custom post types and taxonomies. Here’s how to use it:

  1. Install and Activate: Go to Plugins → Add New, search for "Custom Post Type UI," install, and activate.
  2. Create Taxonomy: Navigate to CPT UI → Add/Edit Taxonomies.
  3. Configure Settings:
    • Taxonomy Slug: Enter a unique slug (e.g., genre).
    • Plural Label: "Genres" (name shown in the admin menu).
    • Singular Label: "Genre" (used for singular terms).
    • Attach to Post Types: Select the post type(s) (e.g., "book").
    • Hierarchical: Check "Yes" for Category-like, "No" for Tag-like.
  4. Advanced Options (optional):
    • Rewrite Slug: Customize the URL (e.g., book-genre instead of genre).
    • Show Admin Column: Check to display the taxonomy in the post list.
  5. Save Taxonomy: Click "Add Taxonomy" to finish.

CPT UI automatically handles the register_taxonomy() code in the background.

3.2.2 Advanced Custom Fields (ACF)#

While ACF is primarily for custom fields, its "Taxonomy" field type lets you attach existing taxonomies to post types. For creating taxonomies, use it with CPT UI, or use the premium "ACF Taxonomy" add-on for advanced features like term meta fields.

4. Managing Custom Taxonomies in the WordPress Admin#

Once created, custom taxonomies appear in the WordPress admin, just like Categories and Tags.

4.1 Adding and Editing Terms#

  • Add Terms: Navigate to the taxonomy menu (e.g., Books → Genres). Click "Add New Genre," enter a name, slug (auto-generated if left blank), and description.
  • Edit Terms: Hover over a term and click "Edit" to modify its name, slug, parent (for hierarchical), or description.

4.2 Bulk Actions and Term Hierarchies#

  • Bulk Actions: Select multiple terms and use "Delete" or "Edit" to modify them in bulk.
  • Hierarchies: For hierarchical taxonomies, drag-and-drop terms to reorder or set parents (e.g., drag "Science Fiction" under "Fiction").

To adjust settings later:

  • Code Method: Edit your register_taxonomy() args and re-save.
  • Plugin Method (CPT UI): Go to CPT UI → Manage Taxonomies, click "Edit" next to your taxonomy, and update settings.

Critical: After changing rewrite slugs, flush permalinks: Go to Settings → Permalinks and click "Save Changes" (no need to edit anything). This updates WordPress’s URL rewrite rules.

5. Displaying Custom Taxonomies on the Front End#

Creating taxonomies is useless if users can’t see them. Here’s how to display terms and taxonomy archives.

5.1 Basic Display with Template Tags#

WordPress provides template tags to output taxonomy terms. Add these to your theme files (e.g., single-book.php, content-book.php).

Example 1: Display Terms for a Post#

To show "Genre" terms for a book post:

<?php  
// Get terms for the current post in the "genre" taxonomy  
$genres = get_the_terms( get_the_ID(), 'genre' );  
 
if ( $genres && ! is_wp_error( $genres ) ) : ?>  
    <div class="book-genres">  
        <h4>Genres:</h4>  
        <ul>  
            <?php foreach ( $genres as $genre ) : ?>  
                <li>  
                    <a href="<?php echo esc_url( get_term_link( $genre->slug, 'genre' ) ); ?>">  
                        <?php echo esc_html( $genre->name ); ?>  
                    </a>  
                </li>  
            <?php endforeach; ?>  
        </ul>  
    </div>  
<?php endif; ?>  

Explanation:

  • get_the_terms( $post_id, $taxonomy ): Retrieves terms attached to the post.
  • get_term_link( $term, $taxonomy ): Generates a link to the term’s archive page.
  • esc_url() and esc_html(): Sanitize output to prevent XSS attacks (always use these!).

Example 2: Display Term Descriptions#

To show a term’s description (e.g., on the archive page):

<?php  
// On taxonomy-genre.php (archive template)  
$term = get_queried_object(); // Get current term  
 
if ( $term->description ) : ?>  
    <div class="term-description">  
        <?php echo wpautop( esc_html( $term->description ) ); ?>  
    </div>  
<?php endif; ?>  

5.2 Advanced Display: Custom Queries and Templates#

Use WP_Query to fetch posts by taxonomy terms. For example, display all "Science Fiction" books:

$args = array(  
    'post_type' => 'book',  
    'tax_query' => array(  
        array(  
            'taxonomy' => 'genre',  
            'field'    => 'slug',  
            'terms'    => 'science-fiction',  
        ),  
    ),  
);  
 
$query = new WP_Query( $args );  
 
if ( $query->have_posts() ) :  
    while ( $query->have_posts() ) : $query->the_post();  
        // Display post title, excerpt, etc.  
        the_title( '<h2>', '</h2>' );  
    endwhile;  
    wp_reset_postdata(); // Reset post data  
endif;  

5.3 Displaying Taxonomy Archives#

WordPress automatically generates archive pages for taxonomies (e.g., /genre/fiction/). To customize these:

  1. Create a Taxonomy Template: Copy your theme’s archive.php and rename it taxonomy-{taxonomy}.php (e.g., taxonomy-genre.php).
  2. Customize the Template: Add term descriptions, filters, or unique styling.

For example, add a heading with the term name:

<h1 class="archive-title">  
    <?php single_term_title( 'Genre: ' ); ?>  
</h1>  

6. Advanced Custom Taxonomy Techniques#

Take your taxonomies to the next level with these pro tips.

6.1 Adding Custom Meta Fields to Taxonomy Terms#

Add extra data to terms (e.g., a "Genre Image" for book genres). Use add_term_meta() and get_term_meta():

Step 1: Add Meta Field to Term Edit Screen

// Add meta field to "genre" taxonomy edit page  
function add_genre_image_meta_field() {  
    ?>  
    <div class="form-field">  
        <label for="genre_image"><?php _e( 'Genre Image', 'textdomain' ); ?></label>  
        <input type="text" name="genre_image" id="genre_image" value="<?php echo esc_attr( get_term_meta( get_queried_object_id(), 'genre_image', true ) ); ?>">  
        <p><?php _e( 'Enter the URL of the image for this genre.', 'textdomain' ); ?></p>  
    </div>  
    <?php  
}  
add_action( 'genre_add_form_fields', 'add_genre_image_meta_field', 10, 2 );  
add_action( 'genre_edit_form_fields', 'add_genre_image_meta_field', 10, 2 );  
 
// Save meta field  
function save_genre_image_meta_field( $term_id ) {  
    if ( isset( $_POST['genre_image'] ) ) {  
        update_term_meta(  
            $term_id,  
            'genre_image',  
            sanitize_text_field( $_POST['genre_image'] )  
        );  
    }  
}  
add_action( 'created_genre', 'save_genre_image_meta_field' );  
add_action( 'edited_genre', 'save_genre_image_meta_field' );  

Step 2: Display the Meta Field

// In taxonomy-genre.php  
$genre_image = get_term_meta( get_queried_object_id(), 'genre_image', true );  
if ( $genre_image ) : ?>  
    <img src="<?php echo esc_url( $genre_image ); ?>" alt="<?php single_term_title(); ?>">  
<?php endif; ?>  

For a user-friendly interface, use plugins like Advanced Custom Fields or Term Meta Manager.

Customize URLs further with rewrite rules. For example, change /genre/fiction/ to /books/genre/fiction/:

// In register_taxonomy() args  
'rewrite' => array(  
    'slug' => 'books/genre',  
    'with_front' => false, // Disable prefixing with blog URL  
),  

Flush permalinks after making changes (Settings → Permalinks → Save).

6.3 Integrating with Gutenberg and Block Themes#

To make taxonomies editable in the Gutenberg editor:

  • Ensure show_in_rest => true in your register_taxonomy() args (required for REST API access).
  • Use the "Taxonomy" block or third-party blocks like "Custom Taxonomy Display" to show terms in posts.

6.4 Querying Posts by Custom Taxonomy Terms#

Use tax_query in WP_Query to filter posts by multiple terms or taxonomies:

// Get posts in "genre" = "fiction" AND "author-skill" = "science"  
$args = array(  
    'post_type' => 'book',  
    'tax_query' => array(  
        'relation' => 'AND',  
        array(  
            'taxonomy' => 'genre',  
            'field'    => 'slug',  
            'terms'    => 'fiction',  
        ),  
        array(  
            'taxonomy' => 'author-skill',  
            'field'    => 'slug',  
            'terms'    => 'science',  
        ),  
    ),  
);  
$query = new WP_Query( $args );  

7. Troubleshooting Common Custom Taxonomy Issues#

Even with careful setup, issues can arise. Here’s how to fix them:

7.1 Taxonomy Not Showing in Admin#

  • Check public and show_ui: Ensure public => true and show_ui => true in $args.
  • Post Type Attachment: Verify the taxonomy is attached to an existing post type (e.g., register_taxonomy( 'genre', 'book', ... )—does "book" CPT exist?).
  • Plugin/Theme Conflict: Deactivate other plugins or switch to a default theme (e.g., Twenty Twenty-Three) to rule out conflicts.
  • Flush Permalinks: Go to Settings → Permalinks and save changes.
  • Rewrite Slug Conflicts: Ensure the taxonomy slug doesn’t clash with post types, pages, or other taxonomies (e.g., don’t use category as a slug).

7.3 Terms Not Appearing on the Front End#

  • Check get_the_terms(): Ensure you’re using the correct taxonomy slug (e.g., get_the_terms( $post_id, 'genre' )—not genres).
  • Post Type Context: If using a custom template (e.g., single-book.php), ensure it’s assigned to the correct post type.

7.4 Conflicts with Plugins or Themes#

Some plugins (e.g., SEO, security) may restrict taxonomy visibility. Temporarily deactivate plugins and test, or check their settings for taxonomy restrictions.

8. Best Practices for Custom Taxonomies#

Follow these guidelines to keep your taxonomies maintainable and effective:

8.1 Use Child Themes or Custom Plugins (Avoid Core Edits)#

Never modify core WordPress files. Use child themes for theme-specific taxonomies or custom plugins for site-wide taxonomies (plugins survive theme switches).

8.2 Choose Descriptive Slugs and Labels#

  • Slugs: Use lowercase, hyphens, and keywords (e.g., author-skill instead of as).
  • Labels: Be specific (e.g., "Product Category" instead of "Type").

8.3 Limit Taxonomies to What You Need#

Too many taxonomies confuse users and admins. Only create what’s necessary for your content.

8.4 Document Your Taxonomy Structure#

Keep a record of:

  • Taxonomy slugs and post type attachments.
  • Term hierarchies (parent/child relationships).
  • Custom meta fields and their purposes.

9. Conclusion#

Custom taxonomies are a powerful tool for transforming WordPress from a simple blog platform into a robust content management system. By organizing content around specific attributes, you improve user experience, boost SEO, and scale your site with ease.

Whether you’re a developer coding with register_taxonomy() or a beginner using plugins like CPT UI, the key is to align taxonomies with your content’s unique needs. Start small—create one taxonomy, test it, and expand as needed. Your future self (and your users) will thank you.

10. References#