How to Add Categories to a Custom Post Type in WordPress
Custom post types are one of the most powerful features of WordPress, but they only reach their full potential when combined with categories and other taxonomies. Whether you are building a blog, portfolio, listing site, or custom content platform, connecting your custom content with the built-in category system can dramatically improve organization, navigation, and SEO.
Table of contents
Understanding How Categories Work in WordPress
Before linking categories to a custom post type, it helps to understand how WordPress handles them under the hood.
What Categories Really Are
In WordPress, categories are not just labels; they are a built-in taxonomy named category. A taxonomy is simply a way to group posts. The default ones are:
- category – hierarchical (supports parent/child relationships)
- post_tag – non-hierarchical (flat list of tags)
By default, these are attached to the post post type only. That’s why you don’t see category meta boxes when creating other types of content such as pages or custom post types, unless you explicitly register the connection.
Categories and Custom Post Types
A custom post type is just a different kind of content object, like product, portfolio, event, or movie. When you register it, you decide which taxonomies it supports. If you associate the category taxonomy, your custom posts will:
- Show the familiar category meta box on the edit screen.
- Be included on category archive pages (e.g.
/category/news/). - Benefit from category-based navigation menus and widgets.
- Gain internal linking structures that help search engines understand content relationships.
Methods for Adding Categories to a Custom Post Type
There are two primary approaches you can use, depending on how comfortable you are with code and how much control you need.
- Code-based: using
register_post_type()andregister_taxonomy_for_object_type(). - Plugin-based: using an interface like CPT UI, Pods, or similar tools.
The code approach is more flexible and is usually preferred for performance, stability, and maintainability, especially in custom themes or client projects.
Adding Categories When Registering a Custom Post Type
If you are already registering your custom post type in a theme or plugin, the cleanest method is to declare the taxonomies directly in register_post_type().
Basic Example of a Custom Post Type with Categories
The following code example shows how to register a simple custom post type and attach both categories and tags to it.
// Register Custom Post Type "movie"
function myprefix_register_movie_cpt() {
$labels = array(
'name' => __( 'Movies', 'textdomain' ),
'singular_name' => __( 'Movie', 'textdomain' ),
'add_new' => __( 'Add New', 'textdomain' ),
'add_new_item' => __( 'Add New Movie', 'textdomain' ),
'edit_item' => __( 'Edit Movie', 'textdomain' ),
'new_item' => __( 'New Movie', 'textdomain' ),
'view_item' => __( 'View Movie', 'textdomain' ),
'search_items' => __( 'Search Movies', 'textdomain' ),
'not_found' => __( 'No movies found', 'textdomain' ),
'not_found_in_trash' => __( 'No movies found in Trash', 'textdomain' ),
'menu_name' => __( 'Movies', 'textdomain' ),
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'show_in_rest' => true, // Enable block editor support
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
'taxonomies' => array( 'category', 'post_tag' ), // <-- Attach categories & tags
'rewrite' => array( 'slug' => 'movies' ),
'menu_position' => 20,
'menu_icon' => 'dashicons-format-video',
);
register_post_type( 'movie', $args );
}
add_action( 'init', 'myprefix_register_movie_cpt' );
Key details to note:
- The
taxonomiesargument defines which taxonomies should be associated with the post type. - Adding
'category'here is what makes the Category meta box appear in the editor for your custom posts. - Adding
'post_tag'is optional but often useful to mirror the behavior of regular posts.
Add this snippet to a custom functionality plugin or your theme’s functions.php file (preferably a child theme to prevent losing changes on updates).
Ensuring Registrations Run in the Correct Order
The built-in category taxonomy is registered very early during WordPress initialization. When you register your custom post type on the init action, the association is usually straightforward. If you are manipulating taxonomies or post types across multiple files or plugins, make sure everything is attached to the init hook with appropriate priorities to avoid race conditions.
Adding Categories to an Existing Custom Post Type
If you already have a custom post type that was registered without categories (perhaps by a theme, another plugin, or an older version of your code), you can still associate the built-in category taxonomy afterwards without rewriting the original registration.
Using register_taxonomy_for_object_type()
The register_taxonomy_for_object_type() function allows you to attach a taxonomy to a post type programmatically, even if the original code did not include it.
function myprefix_add_categories_to_movie_cpt() {
register_taxonomy_for_object_type( 'category', 'movie' );
register_taxonomy_for_object_type( 'post_tag', 'movie' ); // optional
}
add_action( 'init', 'myprefix_add_categories_to_movie_cpt' );
This approach is very useful when:
- You cannot modify the original code that registered the custom post type (e.g. a third-party plugin).
- You want to keep your functionality isolated in a custom plugin.
- You are progressively enhancing an existing site and need to preserve backward compatibility.
Once this code is in place and executed, the category interface appears for that custom content in the WordPress admin, and the taxonomy relationships are fully functional.
Refreshing Permalinks
Whenever you modify post type or taxonomy relationships, it is a good practice to refresh your site’s permalinks:
- Go to Settings > Permalinks in the dashboard.
- Click Save Changes without editing anything.
This flushes WordPress’s rewrite rules and prevents common 404 issues on archive or single pages after structural changes.
Creating a Custom Taxonomy Instead of Using Built-in Categories
Sometimes, the default category taxonomy is not the best semantic fit for your content. You may want a domain-specific taxonomy like genre, location, or topic that behaves similarly to categories but is decoupled from standard posts.
Registering a Category-Like Custom Taxonomy
The following example creates a hierarchical taxonomy called genre and associates it with the movie custom post type:
// Register "Genre" taxonomy for "movie" post type
function myprefix_register_genre_taxonomy() {
$labels = array(
'name' => __( 'Genres', 'textdomain' ),
'singular_name' => __( 'Genre', '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' => __( 'Genres', 'textdomain' ),
);
$args = array(
'hierarchical' => true, // behave like categories
'labels' => $labels,
'show_ui' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'genre' ),
);
register_taxonomy( 'genre', array( 'movie' ), $args );
}
add_action( 'init', 'myprefix_register_genre_taxonomy' );
This creates a taxonomy that looks and behaves like categories but is specific to your custom post type. You can still use the built-in categories in parallel if needed, or dedicate them to blog posts while using the custom taxonomy for specialized content.
Displaying Categories on the Front-End
Associating categories in the back-end is only half the job. To take full advantage, you should also output them on single templates, archive templates, and navigation components.
Showing Categories on Single Custom Post Templates
If your theme uses a specific template for a custom post type (for example, single-movie.php), you can use the_category() or get_the_term_list() to display the assigned terms.
Basic example with default categories:
<?php
// Inside the WordPress Loop
if ( has_category() ) {
echo '<div class="entry-categories">';
the_category( ', ' );
echo '</div>';
}
?>
If you prefer full control, you can use get_the_terms():
<?php
$terms = get_the_terms( get_the_ID(), 'category' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
echo '<ul class="entry-categories">';
foreach ( $terms as $term ) {
echo '<li><a href="' . esc_url( get_term_link( $term ) ) . '">' .
esc_html( $term->name ) .
'</a></li>';
}
echo '</ul>';
}
?>
For a custom taxonomy such as genre, just replace 'category' with 'genre' in the function calls.
Including Custom Post Types in Category Archives
Once categories are attached to your custom post type, content assigned to a category will automatically show on that category’s archive page if your theme’s queries do not strictly limit results to the default post type.
If you find that only standard posts appear on category archives, your theme may be filtering the main query. You can override this by hooking into pre_get_posts:
function myprefix_include_cpt_in_category_archives( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_category() ) {
$post_types = $query->get( 'post_type' );
if ( empty( $post_types ) ) {
// By default WP uses 'post'. Add our custom type as well.
$query->set( 'post_type', array( 'post', 'movie' ) );
}
}
}
add_action( 'pre_get_posts', 'myprefix_include_cpt_in_category_archives' );
Adjust the array to include all custom types you want visible on category archives. This approach is especially useful for content-heavy sites where categories are used as primary navigation.
SEO Considerations When Using Categories with Custom Post Types
Attaching categories to custom post types has significant implications for search performance and content architecture. Done correctly, it can strengthen topical clusters and internal linking; done poorly, it can introduce duplicate content or thin archives.
Benefits for Search Visibility
- Stronger topical clusters: Grouping custom posts and regular posts under the same category helps search engines understand relationships between different types of content.
- Improved crawl paths: Category archives create natural hubs of related links, which can increase the crawl efficiency for large sites.
- Better long-tail coverage: Combining descriptive category slugs with custom post type slugs can produce meaningful, keyword-rich URL structures.
Potential Pitfalls to Avoid
- Duplicate archives: If your custom post type has its own archive and appears in category archives, ensure each serves a distinct purpose or consider controlling indexation via SEO plugins.
- Overlapping taxonomies: Do not create multiple taxonomies that represent the same concept; this dilutes signals and confuses editors and search engines.
- Bloated archives: Categories containing too many disparate content types can become less useful for users; curate category usage carefully.
Using a dedicated SEO plugin, you can fine-tune indexing rules for specific archives and taxonomies, ensuring you only expose valuable, unique pages to search engines.
Using Plugins to Add Categories to a Custom Post Type
If you prefer a graphical interface, several plugins make it possible to attach categories to a custom post type without writing code. While the exact steps differ between tools, the general workflow is similar:
- Install and activate a custom post type or taxonomy management plugin.
- Locate the settings for your existing custom post type.
- Enable support for categories (and tags, if needed) in the post type settings.
- Save your changes and refresh the editor screen.
These tools are convenient for rapid prototyping or non-technical site managers. However, for production sites, capturing the configuration in code is often preferable for version control, portability, and performance.
Best Practices for Structuring Content with Categories and Custom Post Types
Simply turning on categories is not enough; you need a content strategy that makes the structure logical for both users and search engines.
When to Share Categories Between Posts and Custom Post Types
Sharing the same categories across post types is helpful when:
- You publish editorial content and custom resources around the same themes.
- Users naturally expect to browse by topic rather than by content format.
- You want combined category archives that present a holistic view of a subject.
In contrast, use separate taxonomies when:
- The topics of your custom content are domain-specific and would clutter the main category list.
- You want a dedicated navigation structure for a particular custom post type.
- Editorial posts and specialized content serve very different user journeys.
Planning URL Structures
Consider how category and custom post type slugs interact:
- For blog content, WordPress often uses structures like
/category/topic/. - For custom post types with archives, you might have
/movies/action-movies/or/movies/as the main archive. - Be cautious about overly nested or duplicate patterns that could confuse users or search engines.
Align your permalink and taxonomy strategy with a clear content hierarchy. Make sure categories and slugs are descriptive, consistent, and aligned with the language your audience uses.
Conclusion
Connecting categories to a custom post type transforms your content model from a collection of isolated items into a coherent, navigable system. With a few lines of code, you can:
- Expose familiar category controls in the editor for your custom content.
- Display categorized custom posts alongside standard posts on archive pages.
- Improve UX and SEO through structured, topic-based navigation.
Whether you attach the built-in category taxonomy directly, create a custom taxonomy tailored to your domain, or use a plugin-driven interface, the key is to think strategically about