The most well-known shortcoming of the WordPress content management system is probably the lack of flexibility in terms of editing permalinks. One example of this limitation is the inability to add category slugs to custom post type items' permalinks.
When it comes to native post URLs, adding a category should not be an issue. The simplest method to accomplish this is to simply use native permalink settings. However, adding a custom taxonomy slug to a custom post type's URL is not that straightforward. Regrettably, this is not achievable using the built-in settings.
There are a large number of discussions on StackOverflow where users are seeking for a solution to this particular issue. It is possible to further personalize them by adding more rewrite rules and complicated PHP code snippets, if you are familiar with the WordPress API. However, this will need more time and work. The majority of WordPress users, however, will find this to be an inconvenient solution to their problem.
Using Permalink Manager, you can get around this limitation. The plugin, allows you to quickly and easily add category to custom post type permalinks. The main advantage of using it is that no programming experience is required on your behalf.

How to add custom taxonomy in custom post type permalink?
The URL examples provided below have been purposefully simplified in order to give you a better understanding of how this feature works. Although the example below uses custom taxonomies and post types, the same approach may be used to add categories to post permalinks.
Original WordPress permalinks (custom post type items)
http://example.com/product/%product%
http://example.com/product/cotton-t-shirt/
http://example.com/car/ford-focus/
New permalinks item customized with Permalink Manager (custom post type items with tax slugs included)
http://example.com/%product_cat%/%product%
http://example.com/calvin-klein/tops/t-shirts/cotton-t-shirt/
http://example.com/diesel/ford/ford-focus/
There are many ways to enhance the structure of your WordPress permalinks. You have the option to keep the permalink basis ("product" and "vehicle" highlighted in red in the example below), delete it totally, or change the permalink structure to something completely different. You may also use the same permalink basis for multiple content types or add custom fields to them.
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").

Now, scroll down to the bottom of the page 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").

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.

The taxonomy slugs will be automatically incorporated in all new post URLs. Existing URLs will need to be regenerated if you want to use the new formats on them too. You will find step-by-by-step instructions on how to do this in this post.

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

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.

Now, to show the difference in a clear way, let us see what happens when lowest-level term is chosen. This instance will be similar to the previous example. If 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.

If you do not want Permalink Manager to support "primary category" you can disable it in the plugin settings. If you disable it, the default post permalink will take the lowest available category (with parents, if any).
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);