I am creating a WordPress site with a Products page, and I'm using a Custom Post Type to create the products to display under this page.

Here is a sample of the product structure I have created:

Products (top-level page)

  • Tools (as a parent products post type)
    • Bars
    • Cleaners
    • Connectors
    • Joints
    • Punches
    • Valves
  • Structures
    • Tents
    • Fences
  • Materials
  • Accessories

Some of these products will need to be available on a taxonomy archive page using multiple categories. For example, the 'Bars' product will have 'Milling', 'Production' and 'Retrieval' as categories. The 'Cleaners' product will have 'Retrieval' as a category. Punches will have 'Milling' as a category.

I have set up a Custom Taxonomy for my Products post type with the following structure (using taxonomy-product_categories.php for the archive page):

  • Tools (as a parent product_categories taxonomy)
    • Milling
    • Production
    • Retrieval

I would like the URLs to look like this:

example.com/products/tools          (for 'tools' product post type)
example.com/products/tools/bars     (for 'bars' product post type)
example.com/products/milling        (for 'milling' product_categories taxonomy)

Here is the setup for my custom post type and taxonomy:

function create_posttype() {

    // register products post type
    $product_labels = array(
        'name'               => __( 'Products', '__x__' ),
        'singular_name'      => __( 'Product', '__x__' ),
    $product_args = array(
        'labels' => $product_labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'rewrite' => array( 'hierarchical' => true, 'with_front' => false ),
        'capability_type' => 'page',
        'has_archive' => false,
        'hierarchical' => true,
        'supports' => array('title', 'editor', 'revisions', 'thumbnail', 'page-attributes', 'excerpt'), 
    register_post_type( 'products', $product_args );

    // register product taxonomy
    $taxonomy_product_category_args = array(
        'labels'            => array(
            'name'                       => __( 'Product Categories', '__x__' ),
            'singular_name'              => __( 'Product Category', '__x__' ),
        'public'            => true,
        'show_in_menu'      => true, 
        'show_in_nav_menus' => true,
        'show_ui'           => true,
        'show_admin_column' => false,
        'hierarchical'      => true,
        'rewrite'           => array( 'hierarchical' => true, 'with_front' => false ),

    register_taxonomy( 'product_categories', 'products', $taxonomy_product_category_args );

add_action( 'init', 'create_posttype' );

This results in URLs that look like this:

example.com/products/tools                      (for 'tools' product post type)
example.com/products/tools/bars                 (for 'bars' product post type)
example.com/product_categories/tools/milling    (for 'milling' product_categories taxonomy)

I have tried using 'slug' => 'products' as a rewrite argument for the taxonomy, which returns a 404 error when trying to access the taxonomy archive page (I have been religious about flushing rewrite rules by saving the Permalinks Settings page).

I have read at least 20 to 30 posts here on this site, the WordPress Codex, and various blogs. I have tried various combinations of add_rewrite_rule and add_filter (term_link/generate_rewrite_rules/rewrite_rules_array). The closest I came was using this code (which does rewrite the 'product_categories' slug to 'products', but again generates a 404 error, even after flushing rewrite rules on the Permalinks Settings page):

add_filter( 'term_link', 'change_product_categories', 10, 2 );
function change_product_categories( $permalink, $term ) {
    if ($term->taxonomy == 'product_categories') $permalink = str_replace('product_categories', 'products', $permalink);
    return $permalink;

How can I get the 'product_categories' slug to appear as the 'products' slug without throwing a 404 error?

Apologies for the long question, I just wanted to provide as much relevant detail as I could. Many thanks in advance!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.