How to Add Categories/Taxonomies to Custom Post URLs?

The lack of advanced permalink customization tools in the WordPress core is one of its biggest shortcomings. One limitation is the inability to include category slugs in custom post type permalinks.

Although you may easily add a category to the permalinks of built-in posts, custom taxonomies and post types do not allow it by default.

Adding a custom taxonomy slug to a custom post type's URL is not that straightforward. If you know how to code, you may do this by adding more rewrite rules with PHP code snippets. However, implementing this may not be the easiest option for typical WordPress user.

Instead of writing code yourself, a ready-made plugin like Permalink Manager can provide an out-of-the-box solution. This would make adding taxonomies to custom post type URLs much easier.

Add category to custom permalinks

How to Add Custom Taxonomy in Custom Post Type Permalink?

Before we continue, have a look at the following sample to see how the plugin might help you in rearranging your permalinks. The below example has been simplified on purpose to clearly demonstrate how it works.

Original WordPress permalinks (custom post type items)

New permalinks item customized with Permalink Manager (custom post type items with tax slugs included)

The procedure is straightforward, and you should have no difficulty completing it. If you want to include custom taxonomy slugs in your WordPress permalinks, you'll need to go to the Permalink Manager section ("Tools -> Permalink Manager -> Permastructures").

Permastructures section where you can add category to custom post type permalinks
The initial permastructure settings.

Now, scroll down until you find the custom post type that you want to adjust. In this simple example, we are adding two taxonomies to the permalinks for the "Cars" post type ("Manufacturer" and "Fuel").

How to edit Cars permalinks?
You may change the settings for each post type independently.
The custom field permastructure tags should be structured as follows: %custom_taxonomy_name%.

After that, you should insert the tags into the permastructure. The names of custom taxonomies are also the permastructure tags. If necessary, you may locate all of the possible permastructure tags in the "Permastructure tags" section.

New permastructure settings for custom post type
For the sake of this example, we shall use the %manufacturer% and %fuel%. The tags will vary depending on your specific case.
New permalink formats and existing permalinks

The taxonomy slugs will be automatically incorporated in all new post URLs. If you want to use the new formats on existing URLs, you will need to regenerate them.

A sample post permalink with category slug included
Both Manufacturer & Fuel terms' slugs are now present in single Car permalink.

How to Remove Parent Category Slugs From Post Permalinks?

Each taxonomy registered with WordPress can be either hierarchical or nonhierarchical. The first one allows you have parent and child terms, same as with inbuilt categories. For example, you may have a custom taxonomy named "countries" and add parent term named "Europe" with child terms such as "Germany", "France", and "Italy". The second type (nonhierarchical) will function identically to post tags.

With Permalink Manager, you have the ability to include both hierarchical and flat taxonomies in your post permalinks. Furthermore, the plugin can be customized to automatically remove parent category slugs.

With SEO in mind, there are several cases when it may be preferable to keep the URLs of custom post type items as short as possible. The instructions below may be helpful if you want to add a single term slug to post permalinks but not the whole trail including their parent terms.

Depending on your requirements, you may either add a single slug of the highest-level parent or the lowest-level child.

  • To use just the top parent slug, append the suffix "_top" to the end of the taxonomy permastructure tag.
    For example, replace %product_cat% with %product_cat_top%.
  • In the latter case, the suffix added to the end of the tag should be "_flat" to use the slug of the lowest-level term.
    For example, replace %product_cat% with %product_cat_flat%.

Initial permalink format

New permalink format with top-parent term slug only

New permalink format with lowest-child term slug only

Remove parent slug from Product permalinks.
New product permalinks will include only one (lowest-level) product category slug.

Primary Category Support

Permalink Manager is compatible with the "primary category" functionality of Yoast SEO, The SEO Framework, RankMath, and SEOPress. In summary, by default, the plugin replaces the "%taxonomy%" (e.g., %department%) tag in post permalinks with the slugs of actual categories' that are selected as the primary category.

Let us break it down using the most straightforwards examples possible. As you can see in the example below, the top-level category ("Sales") was chosen as the "primary category", and as a result, only its slug will be used in the URL for the post.

Top category selected
In this case, the top-category was chosen as the "primary category".

To make the difference clear, let us look at what happens when the lowest-level term is chosen. When the child category is selected, the slugs of all of its parent categories are included in the post URL, as shown in the screenshot below.

Lowest level term selected
If "Switzerland" is selected, Permalink Manager will follow the category hierarchy and append the slugs of parent categories ("sales/europe/switzerland") to the post permalink.

You may deactivate Permalink Manager's support for "primary category" in the plugin options. After you disable it, the default post permalink will use the lowest available category (including its parents, if available).

You can disable "Primary category" support in Permalink Manager settings.

How to Modify Term Slug in Post Permalinks Programmatically?

If you know how to code, you can modify the category slug that is used when the post's default URL is generated. In particular, you may create a custom function that will replace the %taxonomy% tag (eg. %category%), which is dynamically populated with the slug of the category chosen for the post.

permalink_manager_filter_term_slug($slug, $selected_term, $post, $all_terms, $taxonomy)
Variable Description
$slug The slug or slugs trail used to replace %taxonomy% tag (eg. %category%) in default post permalinks (string)
Example input: europe/central-europe/slovakia
$selected_term Term object chosen to be used in the default permalink of a post (WP_Term)
$post The post object for which the default permalink is generated (WP_Post)
$all_terms Array of all terms that are linked to the post that the default URL is generated for (WP_Term[])
$taxonomy The name of the taxonomy (string)
Example input: category

How to Add Multiple Top-Parent Categories’ Slugs to Single Post Permalink?

Below is a simple example code snippet that demonstrates how you can use it to have Permalink Manager add the slugs of two top-parent categories to a single post permalink using the function. It may also be used for other post types and taxonomies if you modify it to your needs.

* The snippet changes the category slug used when default custom permalink is generated for a post
function pm_multiple_top_categories_in_uri($slug, $selected_term, $post, $all_terms, $taxonomy) {
	// Use the snippet only for ‘category’ slug in ‘post’ custom permalinks
	if(empty($post->post_type) || $post->post_type !== 'post' || $taxonomy !== 'category') {
		return $slug;
	if(!empty($all_terms) && count($all_terms) > 1) {
		// Get only top-level categories
		$top_parent_terms = wp_filter_object_list($all_terms, array('parent' => 0));
		if(!empty($top_parent_terms) && count($top_parent_terms) > 1) {
			// Reset array keys
			$top_parent_terms = array_values($top_parent_terms);
			// We need two slugs, therefore the loop will repeat until $slugs_counter is “2”
			$top_parent_terms = array_slice($top_parent_terms, 0, 2);
			foreach($top_parent_terms as $top_parent_term) {
				if(empty($top_parent_term->slug)) { continue; }
				$new_category_slug = (empty($new_category_slug)) ? $top_parent_term->slug : "{$new_category_slug}/{$top_parent_term->slug}";
	return (!empty($new_category_slug)) ? $new_category_slug : $slug;
add_filter('permalink_manager_filter_term_slug', 'pm_multiple_top_categories_in_uri', 10, 5);
Go up