Use Categories in Product URLs for Magento SEO without Duplicate Content
Magento provides the option to use categories in your product URLs for the search engine optimization benefits it brings, but they’ve implemented it in a very unusual way. Basically, if you enable this option, you’ll end up with at least 4 URLs per product. Once people realize it, this often raises a number of concerns including possible duplicate content penalty from Google, fractured link juice for product pages, frustrated admins, etc.
With so many people also searching for a clever solution, I decided disabling the feature was an unacceptable solution, and took the challenge.
First you have to enable the “Use categories path for product URLs” feature under System > Configuration > Catalog > Search Engine Optimization.
Use categories path for product URLs – This determines how the URL Rewrites autogenerate. If you choose Yes, the URL rewrite for products will include the associated category, and a separate rewrite will generate for each associated category. If you choose No, the URL Rewrites will include only the product name, and there will be only one rewrite, regardless of how many categories the product is associated to.
Once this feature is enabled, you’ll be to use any of these URLs to visit the same product page:
-
/catalog/product/view/id/<product_id>
example: http://www.domain.tld/catalog/product/view/id/6
Internal to Magento; never actually exposed. -
/catalog/product/view/id/<product_id>/category/<category_id>
example: http://www.domain.tld/catalog/product/view/id/6/category/10
Internal to Magento; never actually exposed. -
/name-of-product
example: http://www.domain.tld/super-dee-duper-tent-1000-olive
Normally used on the front page, in content blocks, or anywhere other than a category page. This is because without being on a category page, Magento doesn’t know which category would be appropriate to display in the URL (since it provides the ability to have multiple categories per product). Therefore it opts to not display any category at all. A bad decision in my opinion. -
/category-1/sub-category-1/name-of-product
example: http://www.domain.tld/sporting-goods/camping-hiking/super-dee-duper-tent-1000-olive
Used from category pages. -
/category-2/name-of-product
example: http://www.domain.tld/affordable-housing/super-dee-duper-tent-1000-olive
Used from category pages. -
etc.
Depending on how many categories per product.
Personally, I don’t like my products having multiple URLs. Between the front page and the category pages, two separate URLs are introduced to GoogleBot as it crawls through the pages. Even though you may not be seriously penalized for duplicate content, which page do you want to appear in Google SERPs? Which one do you want your customers to link at? You’re splitting your link juice and causing confusion.
When I saw this feature for the first time, all I really expected was a single URL like:
http://www.domain.tld/sporting-goods/camping-hiking/super-dee-duper-tent-1000-olive
Well, it took about four hours to find, but I finally came up with a patch to Magento core that delivers this result. Check it out below in unified diff / patch file format:
Index: app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php
===================================================================
--- app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php (revision 2102)
+++ app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php (working copy)
@@ -553,7 +553,11 @@
->from($this->getTable('core/url_rewrite'), array('product_id', 'request_path'))
->where('store_id=?', Mage::app()->getStore()->getId())
->where('is_system=?', 1)
- ->where('category_id=? OR category_id is NULL', $this->_urlRewriteCategory)
+// excluding this clause to facilitate one URL per product, and one that includes the category
+// if a product has multiple categories, the first one (by category_id) will be used
+// in most cases you'll probably only have one category because you only want one page per product for SEO reasons
+// for maximum link juice, no possibility of duplicate content, and a less confusing store
+// ->where('category_id=? OR category_id is NULL', $this->_urlRewriteCategory)
->where('product_id IN(?)', $productIds)
->order('category_id DESC'); // more priority is data with category id
$urlRewrites = array();
In my setup, each product only has one category. Although this will also work if you specify multiple categories per product, you won’t have complete control over which category is used for the official link.

(4.81 out of 5)
about 11 months ago
Great post. I have been wondering about this lately. I have been watching sites with 1000 products have over 14,000 urls indexed in Google. That’s a lot of PageRank leakage. It’s one thing to have a big site, but another one altogether to create it from duplicate content. This post will help that a bit.
They need the ability to add nofollow to specific links in Magento, especially empty review pages and the layered attribute navigation. I will be experimenting with nofollowing some of these links in the future to see what’s happens.
about 11 months ago
Stephan – nofollow would only work for the bots and spiders. but if a user comes along and finds a product they like and links to it on their blog, and another user links the same product under a different category URL, then you’ve essentially 1/2′d the link-juice between those two links. So there needs to be a way to “physically” restrict product URLs to just one.
Thanks for sharing the diff, Mike. Gonna give it a shot and see how it works on our setup which we’re launching … tomorrow!
about 11 months ago
hm, this code fix isn’t doing it for me. I’ve got products in multiple categories, and if I arrive at each product through a different category, then the URL ends up being unique for that category assignment …
about 11 months ago
@matt: Yep, you’ve correctly identified it is because you’ve got products in multiple categories. My setup has only one category per product, so that’s as far as I wanted to develop the patch.
If you end up taking it further to where it can work with multiple categories, please feel free to post your link here and let me know.
about 10 months ago
Thanks for sharing this solution, Mike. It worked out pretty good for all the links on my shop – except for the products in the my block “new products”. The URL is untouched and this in the form root/product.html.
I check my template and it calls the product link via echo $_product->getProductUrl() and returns the “faulty” URL. Could you give me a hint how to change these as well into SEO friedly links without losing link juice?
about 10 months ago
We’ve developed a full guide to Magento SEO at Yoast.com, hope you like it!