How to Add Taxonomies to Custom Post Type Permalinks?

One of the most frustrating limitations of the built-in permalink system is how it handles custom post types. You can easily add categories' slug in post URLs, but when it comes to custom post types and their taxonomies, WordPress simply does not support that structure by default.

While this can be done with PHP and custom rewrite rules, it often turns into a complicated process and for most WordPress users, this can be overwhelming.

You can still get this done even if you do not know how to code. Permalink Manager offers a simple and quickest way to add taxonomies to your custom post type URLs without using any extra code snippets.

Add category to custom permalinks

How to Add Custom Taxonomy in Custom Post Type Permalink?

Adding taxonomies to permalinks is one of the common ways people use Permalink Manager. The example shown here is just one way to use it, but the plugin allows for a lot more customization.

In this example, we are adding two taxonomies, "Manufacturer" and "Fuel" to the single permalinks of the "Cars" post type:

http://example.com/%fuel%/%manufacturer%/%car%
http://example.com/diesel/ford/ford-fiesta/

It is quite simple to set this up. First, navigate to the "Tools -> Permalink Manager -> Permastructures" section and scroll down until you find the custom post type that you want to adjust.

Adding category to custom post type permalinks

Now, you need to insert the taxonomy tag into the permastructure input field. The tag is the name of your custom taxonomy, wrapped in percent signs (e.g. %fuel% and %manufacturer%).

Repeat the same process for your post type and taxonomy, adjusting the tag as needed.

You should format the taxonomy tag like this: %custom_taxonomy_name%.

New permastructure settings for custom post type

If necessary, you may find all of the possible permastructure tags, by clicking the "Available tags" button.

After the changes, the taxonomy slugs will automatically be included in the custom permalinks, after you create and publish a new post.

To prevent broken links and 404 errors that could affect UX and SEO, the permalinks for existing posts are not updated automatically. If you would like to update existing URLs to match the new format, you will need to regenerate them.

To prevent this, you can use the plugin to save the old URLs as fallback redirects.

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

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.

Extra Customization Options

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
http://example.com/%product_cat%/%product%

http://example.com/clothing/t-shirts/cotton/happy-ninja
http://example.com/clothing/jackets/leather/biker-black

New permalink format with top-parent term slug only
http://example.com/%product_cat_top%/%product%

http://example.com/clothing/happy-ninja
http://example.com/clothing/biker-black

New permalink format with lowest-child term slug only
http://example.com/%product_cat_flat%/%product%

http://example.com/cotton/happy-ninja
http://example.com/leather/biker-black

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

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);

Troubleshooting

Category Not Appearing in Post Permalink

If your post URL is missing the category, and you're using a third-party plugin to import or sync content, the plugin is likely inserting posts before assigning categories. This is common with tools for job boards, directories, product syncing, or bulk content imports.

These plugins usually change how WordPress normally saves and publishes a post. Instead of doing everything in one call, they split it into two steps.

  1. Firstly, they create the empty post using wp_insert_post() function, usually with only the title and content.
  2. Then, after the post is saved and the custom permalink is generated, they assign taxonomies (like categories) and metadata.

The categories in step two are not processed by Permalink Manager because they have not been assigned at that stage, which causes incomplete URLs.

The same issue can occur if you add the posts manually from the admin dashboard and publish them before assigning categories.

Recommended fix: Many plugins provide their own action hooks that are called after posts are created.

Here is how you might use this with Permalink Manager and Dokan. To make sure the custom permalink is generated correctly after a product is added, you can generate the custom permalink once again after the dokan_new_product_added hook is called by Dokan.

/**
* Regenerates the custom permalink for a newly added product in Dokan.
*
* This function is hooked into Dokan's 'dokan_new_product_added' action, which fires
* when a vendor creates a new product.
*
* @param int $product_id The ID of the newly created product.
*/
function pm_dokan_generate_product_permalink( $product_id ) {
	if ( class_exists( 'Permalink_Manager_URI_Functions_Post' ) ) {
		$new_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $product_id );
		Permalink_Manager_URI_Functions::save_single_uri( $product_id, $new_uri, false, true );
	}
}
add_action( 'dokan_new_product_added', 'pm_dokan_generate_product_permalink', 100 );

If no dedicated action hooks are available, you can also force Permalink Manager to regenerate the custom permalink after a category or taxonomy has been set using built-in set_object_terms hook.

The example below applies to WooCommerce products (with product categories), but you can modify the $taxonomy variable to apply it to other post types and taxonomies.

/**
* Regenerates the custom permalink for a post when its taxonomy terms are updated.
*
* This hook can be useful when third-party plugins assign categories
* or taxonomies *after* the post is created (e.g., during import or sync).
* It ensures the custom permalink is updated to reflect the assigned terms.
*
* @param int $post_id The ID of the post being updated.
* @param array $terms An array of term IDs.
* @param array $tt_ids Term taxonomy IDs.
* @param string $taxonomy Taxonomy slug (e.g., 'product_cat', 'category', etc.).
* @param bool $append Whether to append the new terms to the existing terms.
* @param array $old_tt_ids An array of old term taxonomy IDs.
*/
function pm_regenerate_product_permalink( $post_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
	if ( $taxonomy === 'product_cat' && class_exists( 'Permalink_Manager_URI_Functions_Post' ) ) {
		$default_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $post_id );
		Permalink_Manager_URI_Functions::save_single_uri( $post_id, $default_uri, false, true );
	}
}
add_action( 'set_object_terms', 'pm_regenerate_product_permalink', 9, 6 );

Last updated by Maciej Bis on: May 2, 2025.


Maciej BisFounder of Permalink Manager & WordPress Developer

The developer behind Permalink Manager, a plugin for managing permalinks, has been working with WordPress, creating custom plugins and themes, for more than a decade.

Go up