WordPress Custom Post and Custom Taxonomy Permalinks

I have the following setup:
– A custom post type called Products.
– A custom taxonomy called Product Categories.
– A page called Products with a custom page template assigned to it. This page template allows me to query my custom posts and display them in a layout of my choosing. Slug is set to /products.

I wanted my urls for my products to display in the following way:

Or to be more specific:
– View my “Products” page set with the custom template at the url /products
– View each “Product Category” on a url of /products/product-category
– View my custom post type “Products” on a url of /products/product-category/product-name

But nothings ever easy. The trouble I was having was that both my product page and product post type wanted to use the same slug (/products) and therefore conflicted causing 404’s. Not only that but custom taxonomies by default do not show the category in the url, and finally although in my head it made sense as a user to see the url /products/product-category/product-name they were not in any kind of heirarchical structure within wordpress to order them in a url this way.

So after a lot of googling and after finding this really helpful article I finally managed to put together some code that fixed the problem.

add_action( 'init', 'register_custom_post_types' );
//Set up Product Post Type
function register_custom_post_types() {
	register_post_type('products', array(
		'label' => __('Products'),
		'singular_label' => __('Product'),
		'public' => true,
		'show_ui' => true,
		'capability_type' => 'post',
		'hierarchical' => true,
		'rewrite' => array( 'slug' => 'products/%productcats%' ),
		'publicly_queryable' => true,
		'query_var' => true,
		'has_archive' => true,
		'supports' => array('title','editor','thumbnail','excerpt'),
        //Set up Product Categories
	register_taxonomy('productcats', 'products', array(
		'hierarchical' => true,
		'label' => 'Categories',
		'singular_label' => 'Category',
		'rewrite' => array( 'slug' => 'products' ),
//Fix Permalinks
add_filter('post_link', 'product_permalink', 10, 3);
add_filter('post_type_link', 'product_permalink', 10, 3);
function product_permalink($permalink, $post_id, $leavename) {
	if (strpos($permalink, '%productcats%') === FALSE) return $permalink;
		// Posts
		$post = get_post($post_id);
		if (!$post) return $permalink;
		// Custom Taxonomy
		$terms = wp_get_object_terms($post->ID, 'productcats');
		if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
		else $taxonomy_slug = 'uncategorized';
	return str_replace('%productcats%', $taxonomy_slug, $permalink);
//Flush permalinks
flush_rewrite_rules( false );

For a step by step explanation of the permalink function please refer to the original article I found on google. You may find you need to go to settings/permalinks in your admin and save again for the changes to take effect. You will already need to have the custom permalink structure set to /%postname%. More information on setting up custom page templates, custom post types and custom taxonomies can be found on the wordpress codex.


  1. I looked across the vastness of Google, to find a solution on this blog after hours and hours. Thanks, this helped me a lot.

    Mateus Neves - 09 Jun 2011
  2. Hi, I have come across your article after many hours of searching, testing various things and ‘flushing permalinks’.

    What you describe is the EXACT scenario I am trying to achieve. Please could you share with me what your template file structure is? (Or even better a working example would be amazing!)

    You mention you have a custom template for the main products index. Could this not be achieved using ‘archive-products.php’ or ‘page-products.php’ negating the need to set a custom template?

    Are you modifying the loop on this template?

    Also what are you using to display the category pages e.g. ‘/products/product-category’. According to the wordpress docs ‘taxonomy-productcats.php’ should work but it I get a 404 even after flushing permalinks.

    Hope you can help 🙂

    Matt Agland - 29 Jan 2014
  3. Hi

    I wrote this article back in 2011 and quite a bit has changed with wordpress since. You are right in saying that I could now use archive-products or page-products but these templates didnt exist at the time of writing. I think there are probably far easier/better ways of implementing this now but unfortunately I dont have any recent examples to share. If your not using http://www.advancedcustomfields.com/ to create your custom fields do have a look it makes things far easier and this article looks like its more up to date than mine on changing url structures: http://wsipowerontheweb.com/change-url-structure-of-custom-post-type-and-custom-taxonomy-in-wordpress/

    Hope that helps!

    Hannah - 30 Jan 2014

Leave a Reply

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