How to set product category base the same as shop base in WooCommerce

I’ve been searching in the Internet for guide how to fix the 404 error when I set product category base the same as shop base in WooCommerce and unfortunately there’s no ultimate solution that works for me. So I decided to work on that myself and here is my solution:

A quick brief of the problem: in Settings \ Permalinks, if I set:

  • Shop base: shop
  • Product category base: shop (same as shop base)
  • Product permalink base: Shop base with category, e.g. shop/%product_cat%

then when visit each of the following pages, I get the following result:

  • Shop: works
  • Product category base: 404 error
  • Product permalink base: works

To fix that 404 error, I use the snippet below (you can insert into functions.php file or better – in a plugin):

add_filter( 'rewrite_rules_array', function( $rules )
    $new_rules = array(
        'shop/([^/]*?)/page/([0-9]{1,})/?$' => 'index.php?product_cat=$matches[1]&paged=$matches[2]',
        'shop/([^/]*?)/?$' => 'index.php?product_cat=$matches[1]',
    return $new_rules + $rules;
} );

This simply adds a new rewrite rules for product category. This rewrite rule sits on top of all WordPress rewrite rules, so it takes priority to be performed first.

Hope the small snippet can help you fix the unexpected 404 error, which took me 2 hours looking for solution!


  1. Thanks for this. We’re doing something similar only instead of ‘shop’ we have a different base (like ‘items’). However, what we see is that for ‘2nd’ order categories (e.g. /items/parent-cat/child-cat ) we get a 404. Thoughts?

  2. Hey!

    Thank you so much for this snippet! Exactly what I needed. Your research into this saved me a lot of time. Thanks again!


  3. I have the same problem.. the child categories still give 404 even after the fix

  4. Hi,

    after adding you code in function.php file i get this error :

    Parse error: syntax error, unexpected ‘$new_ruless’ (T_VARIABLE) in /home2/ajlopez/public_html/SITE-URL/dev/wp-content/themes/deharo-child/functions.php on line 49

    Please help me.


  5. Am I understanding that this will remove the word “category” or “tag” or whatever is defined in product category urls?

    Has any progress been made on nested categories?

  6. Awesome! I’ve probably spent 20 hours testing a great number of suggested solutions and plugins. The Woocommerce SEO plugin only erases the slug, but doesn’t inject the shop base before – worthless.

    I use it in conjunction with Breadcrumb NavXT. Recommend it, works flawlessley … so far.

    Here Mark Ward also explains a way of updating hard coded links throughout the database, if need be:

    Have you found any problems with this related to redirects? Or any other problems whatsoever?

  7. Problems … it doesn’t seem to work for certain categories, perhaps when i create new sub-categories.

    I also get strange redirects from these sub-categories on the left, to these products on the right:

    /produkter/kontaktdon/cirkulara/ ==> /produkter/bakkapor/cirkulara-2/
    /produkter/kontaktdon/rektangulara/ ==> /produkter/bakkapor/rektangulara-2/

    I guess this is what people warns about when trying to accomplish this.

    In other words, I can’t list the products of the sub-categories /cirkulara/ and /rektangulara/.


  8. I am having zero luck with this. I get the same 404 issue as before. I have added this code the the bottom of my themes functions.php file and changed the ‘shop’ to ‘products’. I have also changed the shop page title and slug to “products”. I then went to my permalinks settings and changed the ‘product-category’ permalink to ‘products’ as well. I then update the permalinks to Custom Base “/products/%product_cat%” and save it.

    After taking these steps I still get a 404.

    What am I missing?

  9. Huge thanks for that! Had been looking for a while and almost ready to give up when I found your solution.

    At first it did not seem to work, but then I tried inactivating the Yoast SEO pluin on my test site, and then it worked!

    So I went to my production site where I use the SEO Ultimate plugin and added your fix there. The exact same thing happened. It did not work until I deactivated the SEO plugin. But there I tried activating it again, and voalá – it worked!

    Surprised, I went back to the test site and reactivated Yoast SEO, and it worked there too!

    So my advice to you that did not get it working. Try deactivate and reactivate your SEO plugin. I don’t know why, but it worked for me.

    1. Yes. I added the following Rule to the suggested script:
      ‘shop/([^/]*?)/([^/]*?)/?$’ => ‘index.php?product_cat=$matches[2]’

      In the End you have:
      add_filter( ‘rewrite_rules_array’, function( $rules ) {
      $new_rules = array(
      ‘shop/([^/]*?)/page/([0-9]{1,})/?$’ => ‘index.php?product_cat=$matches[1]&paged=$matches[2]’,
      ‘shop/([^/]*?)/?$’ => ‘index.php?product_cat=$matches[1]’,
      ‘shop/([^/]*?)/([^/]*?)/?$’ => ‘index.php?product_cat=$matches[2]’
      return $new_rules + $rules;

      This supports nested categories!

  10. Thanks for this. It set me on the right track. A few things that I discovered that may be helpful for others:
    1. It initially didn’t work for me, and on further digging I discovered that the Yoast Woocommerce SEO plugin was stepping on my rewrite rules. The article states that the example rewrite rule “sits on top of all WordPress rewrite rules” and therefore takes higher priority, however `add_filter` actually needs to be called with an extra parameter indicating its priority. In this case, we should give our rule a number greater than 10 (the default) so that it gets executed after all other rewrite rules. See gist below.
    2. Some people noted that this only worked after they stopped/started their seo plugin or did some other magical sequence of things. This is because the wordpress rewrite rules need to be flushed, which is something your seo plugin probably does on activation/deactivation. The other way to achieve this is to just go to permalink settings and hit the save button. Ideally though, we should put our rewrite rules in a plugin and call `flush_rewrite_rules` on activation/deactivation. See gist below.
    3. Regarding nested categories, it isn’t possible to support an arbitrary number of nested categories because wordpress can’t tell the difference between a link to a product and a link to a category if the url base is the same. I ended up writing my rewrite rules to accommodate subcategories with a specific naming convention so that the regex in the rewrite rules can differentiate between products and categories. See the gist for more detail.
    Good luck 🙂

    1. Hello Ryan

      i have used your plugin but unable to activate it

      my problem is i have set Product category base = shop and Shop base with category = /shop/%product_cat%/

      but when i visit to my product or category it show me 404 error

      please can you help me to solve this problem

  11. Here is a solution:
    Go to Woocommerce – Products tab
    Set the following like this:
    Shop page -> Shop
    Shop Page Display -> Show products
    Default Category Display -> Show products
    Save changes

    Go to Settings – Permalinks

    [Common Settings section]
    Set the following like this:
    Post name

    [Optional section]
    Category base – leave empty
    Tag base – leave empty
    Product category base -> shop
    Product tag base – leave empty
    Product attribute base – leave empty

    [Product Permalinks section]
    Custom base -> /%product_cat%

    1. While this will work fine for WooCommerce, normal WordPress posts and pages will result in a 404 error.

      Do you have a workaround for this?

  12. Sadly, I used WP All Import to import products and categories and re-did that once again only to find out it was permalinks / rewrites. Sigh.

    Thank you for this!!!

  13. Hi, thats cool, but how to do that with a child of child category? (shop/cat/subcat1/subcat2/product_name)


  14. Awesome!! Just lost half a day trying to figure out how to solve this problem.. you’ve saved my mental health and my coronary!
    Thaaaaaaaaaaaank youuuuuuuuuuuuu!!!!!

Comments are closed.