This article covers how to add existing taxonomies to a custom post type, and how to make that custom post type show up in those taxonomies’ archive pages.
We’ll take an example from our own work. We recently debuted Courses, a new way for us to thoroughly teach topics in WordPress development. Courses are just regular old posts for now, but we’re transitioning them into being their own custom post type. This has a number of advantages, such as making it easier to have a “Courses-only” archive page.
However, even though they’ll be their own custom post type, we want Courses to make use of three of our existing WordPress taxonomies:
category
, WordPress’s default category taxonomy,post_tags
, WordPress’s default tags taxonomy, anddifficulty
, a custom difficulty taxonomy that we’ve registered ourselves.
Moreover, we want Courses to mix with our other post types in archive pages. If, for example, you click “Intermediate” to find all of our content that’s at Intermediate difficulty, we want our Intermediate Courses to show up right alongside our regular Intermediate articles.
This turns out to have several steps to it. So this week, we’re going to cover how to add existing taxonomies to a custom post type, and how to make that custom post type show up in that taxonomy’s archive pages.
One more thing before we get started. If you’re looking to learn WordPress development, we’ve written the best guide to it out there:
The Best Way to Learn WordPress Development
Get Up and Running Today!
Up and Running is our complete “learn WordPress development” course. Now in its updated and expanded Third Edition, it’s helped hundreds of happy buyers learn WordPress development the fast, smart, and thorough way.Here’s what they have to say:
“I think anyone interested in learning WordPress development NEEDS this course. Watching the videos was like a bunch of lights being turned on.” -Jason, WordPress developer
“Other courses I’ve tried nearly always lack clear explanations for why WordPress does things a certain way, or how things work together. Up and Running does all of this, and everything is explained clearly and in easy-to-understand language.” -Caroline, WordPress freelancer
Now, let’s dive into the code for adding an existing taxonomy to a WordPress custom post type.
The Code
Below is the complete code we’ll be looking at today. This would be best as the only file in a standalone plugin. For more on registering plugins see our article on the topic.
// 1. Register post type
add_action( 'init', 'wpshout_register_cpts' );
function wpshout_register_cpts() {
$args = array(
'public' => true,
'label' => 'Courses',
'has_archive' => true,
'rewrite' => array( 'slug' => 'courses' ),
'supports' => array(
'title',
'editor',
'author',
'thumbnail',
'excerpt',
'comments',
'revisions'
),
);
register_post_type( 'course', $args );
}
// 2. Add existing taxonomies to post type
add_action( 'init', 'wpshout_add_taxonomies_to_courses' );
function wpshout_add_taxonomies_to_courses() {
register_taxonomy_for_object_type( 'category', 'course' );
register_taxonomy_for_object_type( 'difficulty', 'course' );
register_taxonomy_for_object_type( 'post_tag', 'course' );
}
// 3. Make Courses posts show up in archive pages
add_filter( 'pre_get_posts', 'wpshout_add_custom_post_types_to_query' );
function wpshout_add_custom_post_types_to_query( $query ) {
if(
is_archive() &&
$query->is_main_query() &&
empty( $query->query_vars['suppress_filters'] )
) {
$query->set( 'post_type', array(
'post',
'course'
) );
}
}
The big takeaway is that adding taxonomies to custom post types requires three distinct steps.
The code above does three things, in order:
- Register the “Courses” custom post type with the necessary attributes.
- Add three existing taxonomies—
category
,post_tag
, and our custom taxonomydifficulty
—to the Courses post type. - Cause Courses to show up in archive pages, so that a search by category, difficulty, and so on will include Courses results.
None of these three pieces is exceptionally difficult—it’s knowing that you need to do all three of them that was the big takeaway for me, and hopefully for you. Let’s look at each piece in more detail.
1. Registering Courses with register_post_type()
This section uses WordPress’s init
hook to run a call to register_post_type()
with a number of arguments given by an $args
array. If you’ve never registered a custom post type before, check out the Codex’s description of register_post_type()
itself. The $args
-and-a-function-within-a-WordPress-hook setup is absolutely core to WordPress, and register_post_type()
isn’t too hard to understand if you’re familiar with that pattern.
The one thing I want to mention is that manually including a 'supports'
parameter within $args
was necessary for us. If you leave it out of $args
entirely, your custom post type has some properties by default, but doesn’t have some (like excerpts) that we wanted. And if you include just 'supports' => 'excerpts'
, then it’ll turn off everything else—like post titles, authors, or content. So we felt it necessary to list every standard feature we want our Courses to have:
'supports' => array(
'title',
'editor',
'author',
'thumbnail',
'excerpt',
'comments',
'revisions'
)
2. Adding Existing Taxonomies to the Courses Custom Post Type
This simple section uses three calls to register_taxonomy_for_object_type()
to register the category
, post_tag
, and difficulty
taxonomies for Courses. These three lowercase strings are the “slugs” for the Category, Tag, and Difficulty taxonomies. We had to look them up for Category and Tag (since those are WordPress default taxonomies), and we knew that we’d given Difficulty the difficulty
slug when we’d registered it.
The end result looks like this:
Credit to Pippin Williamson for this section’s basic code. As a note, Pippin recommends that you use the plugins_loaded
hook rather than the init
hook if you’re doing this in a plugin; however, we tried this, and only init
worked for us.
3. Using pre_get_posts()
to Add Courses to Archive Pages
This last piece is essential if you want users to be able to actually click, for example, “Intermediate” and see a list of all Intermediate posts and Courses. It uses a function that hooks into WordPress’s important pre_get_posts
hook (which we’ll be explaining in detail soon!) to modify the query on every archive page such that both posts
and courses
are included.
Here is the function’s code again, with logic written in more detail as comments:
function wpshout_add_custom_post_types_to_query( $query ) {
if(
// If we're trying to generate an archive page, and
is_archive() &&
// If the current query is the page's main query, and
$query->is_main_query() &&
// If the query hasn't already been modified to ignore
// filters like the one we're writing
empty( $query->query_vars['suppress_filters'] )
) {
// Then set the query to fetch posts of type
// both "post" and "course"
$query->set( 'post_type', array(
'post',
'course'
) );
}
}
The final result (on a staging site I keep locally) looks like:
(Credit for this basic code pattern to CSS-Tricks. Note that we changed their is_category() || is_tag()
check to just is_archive()
, which covers all types of archives pages, including, for example, author pages.)
Now You Know How to Add Taxonomies to Custom Post Types
Thanks for reading. Again, each step in this process is somewhat simple, but knowing you have to do all three was a bit of an “Aha” moment as I did this myself.
As always, we’d love to read questions or comments below!
Thanks for this very clear and easy article, I was just looking for such information because I wanna add Tags feature to my portfolio custom type post and then allowing those custom type posts to be visible in the query result inside an archive page.
Next day I will try hope to be successful.
Many thanks, your articles are always clear and easy to understand even for a newbie as me.
Riccardo
[…] WordPress has a prewritten function that does what you want, like register_post_type(). […]
[…] create custom taxonomies by hand, you use register_taxonomy(), which you hook into WordPress’s init action […]
[…] is the best way to modify a default query. Here’s an important example from last week’s article on custom post types, causing a newly registered custom post type, Courses, to show up on the site’s archive […]
Excellent article!! Thank you.
🙂