How to Create a Nested Taxonomy Inside a Custom Post Type

Summary

In this article, I explain how to create a nested taxonomy within a WordPress custom post type. I start by discussing that taxonomies typically operate independently and do not support nested structures by default. I then walk through the process of registering a taxonomy and post type for the nested structure.

If you register a post type and taxonomy with slugs faqs and sections respectively:

  • Register the taxonomy first.
  • Set the taxonomy’s rewrite param to /faqs/section
  • Set the post type’s rewrite param to faqs/topic

Introduction

Post Type and Taxonomy Map of How the Sections Should Be Nested Under the Frequently Asked Questions Post Type
Post Type and Taxonomy Map of How the Sections Should Be Nested Under the Frequently Asked Questions Post Type

Taxonomies, by their nature, have their own base and don’t have a nested structure inside post types. For example, if I registered a taxonomy with a REST base of sections, the URLs would be for each term:

  • domain.com/sections/term-1/
  • domain.com/sections/term-2/

If I were to register a post type named FAQs, with base faqs, the structure would be:

  • domain.com/faqs/my-question-answer-1/
  • domain.com/faqs/my-question-answer-2/

What if the two could be married and could share a single base? In this quick tutorial, I’ll show you how.

Registering the FAQs taxonomy to enable nesting

The key is to register your taxonomy first, so when the post type is registered, it correctly recognizes the nested base.

We’ll be using the WordPress function register_taxonomy.

add_action( 'init', 'dlx_add_faqs_post_type_taxonomy', 11 );
function dlx_add_faqs_post_type_taxonomy() {
	register_taxonomy(
		'section',
		'faqs',
		array(
			'labels'            => array(
				'name'          => 'Sections',
				'singular_name' => 'Section',
			),
			'hierarchical'      => true,
			'show_in_rest'      => true,
			'show_admin_column' => true,
			'rewrite'           => array(
				'slug' => '/faqs/section',
			),
			'public'            => true,
			'show_ui'           => true,
		)
	);
}Code language: PHP (php)

I’m creating a taxonomy named section, for an object type (yet to be registered) named faqs.

Note the rewrite section. I’m using slug: /faqs/section

This rewrite tells WordPress to rewrite any taxonomy term to : /faqs/section/term-1/

Registering the Post Type

Next, register the custom post type using the WordPress function register_post_type.


add_action( 'init', 'dlx_add_faqs_post_type', 12 );
function dlx_add_faqs_post_type() {
	register_post_type(
		'faqs',
		array(
			'labels'       => array(
				'name'          => 'FAQs',
				'singular_name' => 'FAQ',
			),
			'menu_icon'    => 'dashicons-media-document',
			'rewrite'      => array(
				'slug' => 'faqs/topic',
			),
			'public'       => true,
			'show_in_rest' => true,
			'has_archive'  => true,
			'with_front'   => false,
			'taxonomies'   => array( 'section' ),
			'supports'     => array( 'title', 'editor', 'thumbnail' ),
		),
	);
}Code language: PHP (php)

This will be loaded at priority 12 to load after the taxonomy has been registered. This is important for rewrites.

This time in the rewrite argument, I’ve set the slug to: faqs/topic

This will allow a URL like:

  • domain.com/faqs/topic/my-question-answered/
  • domain.com/faqs/topic/my-other-question-answered/

Note, I could have left rewrite as the default for the post type if I wanted a structure like: domain.com/faqs/my-question-answered/. The danger here is collisions if a topic and section are named with the same slug.

Conclusion

Post Type Nested Admin View
Post Type Nested Admin View

In this quick tutorial, I demonstrated how to create a nested taxonomy within a post type. The downsides of this approach include the potential for naming collisions; however, the structure is highly flexible from an SEO perspective.

If you have any questions, please leave a comment.

Like the tutorial you just read? There's more like it.

There's more where that came from. Enter your email and I'll send you more like it.

This field is for validation purposes and should be left unchanged.

Ask a Question or Leave Feedback

Your email address will not be published. Required fields are marked *