Shopify duplicate product URLs: why they happen and how to fix them

Shopify serves every product at /products/handle and again at /collections/collection-handle/products/handle. Shopify points the canonical tag at the /products/ URL, but most themes still link to the collection version, so Google crawls thousands of duplicates. Fix the product-card links in your theme, control filter and tag URLs, and keep one URL per product in your sitemap and internal links.
- Shopify makes every product reachable under several URLs: collection paths, /collections/all, variants and more.
- Shopify’s canonical tag points to /products/, but your theme’s internal links usually don’t.
- The fix is a small theme edit: remove
within: collectionfrom product links. - Check the result in Search Console’s Page indexing report over the following weeks.
Why does Shopify create two URLs for every product?
Shopify lets a product appear in a collection’s context. When a shopper clicks a product from a collection page, many themes send them to /collections/hats/products/blue-cap instead of /products/blue-cap. Both addresses load the same page.
Multiply that by every collection a product sits in, then add filter parameters, tag pages and pagination, and a 500-product store can expose tens of thousands of URLs to Google, most of them duplicates.
Where else do duplicate URLs come from on Shopify?
Collection paths are the biggest source, but not the only one:
| Source | Example | What to do |
|---|---|---|
| Collection-aware product links | /collections/hats/products/blue-cap | Link to /products/ in the theme |
| The “all” collection | /collections/all/products/blue-cap | Same fix; avoid linking to /collections/all in navigation |
| Variant parameters | /products/blue-cap?variant=4021 | Leave the canonical in place; link to the base URL |
| Tag filters | /collections/hats/blue | Keep out of the index unless it targets a real search |
| Sort and filter parameters | ?sort_by=price-ascending | Rely on robots.txt.liquid and noindex rules |
| Pagination | /collections/hats?page=2 | Fine to crawl; make sure page 1 is the one that ranks |
How big does the problem get on a real catalogue?
Bigger than most store owners expect. Take an example store with 500 products, where each product sits in three collections on average. That’s 1,500 collection-path URLs, another 500 under /collections/all, plus the 500 real /products/ URLs: around 2,500 addresses for 500 products, before filters, tags or variants are counted.
Add a few tag filters per collection and the count multiplies again. Google doesn’t crawl unlimited URLs per visit, so every duplicate it fetches is a real product or collection page it didn’t.
Doesn’t Shopify’s canonical tag already fix this?
Partly. Shopify adds a canonical tag on collection-aware product URLs pointing to the /products/ version, which tells Google which one you prefer. But a canonical is a hint, not a command. When every internal link on your site points to the collection version, you’re sending Google mixed signals: the tag says one URL, the links say another.
The result is wasted crawl budget, slower discovery of new products, and ranking signals split across URLs that should be one. On larger catalogues it’s often why new products take weeks to get indexed.
How do you check if your store has the problem?
Four checks, ten minutes, no apps needed:
- Click a product from a collection page and look at the address bar. If it contains /collections/…/products/, your theme links to collection-aware URLs.
- Open Search Console → Pages. Look for “Duplicate, Google chose different canonical than user” and “Alternate page with proper canonical tag”. Large numbers point to this problem.
- Search Google for
site:yourstore.com inurl:/collections/ inurl:/products/to see how many collection-path product URLs are indexed. - Crawl the store with a tool like Screaming Frog and count internal links pointing to /collections/*/products/ URLs.
How do you fix duplicate product URLs on Shopify?
Fix the cause, not just the symptom. These are the steps we take in the theme, in this order:
- Fix product-card links. In your theme’s product card snippet, remove the
within: collectionfilter so product links point straight to /products/handle. - Check every other template. Search the theme code for the same filter in featured-product, recommendation and search-result sections.
- Control filter URLs. Decide which filtered collection pages deserve to rank, and keep the rest out of the index through robots.txt.liquid and noindex rules.
- Tidy tag pages. Tag-filtered collection URLs rarely deserve to rank on their own; keep them out of the index unless they target a real search.
- Keep one URL everywhere. Make sure your sitemap, internal links, structured data and ads all use the /products/ URL.
- Check it worked. Watch the “Duplicate, Google chose different canonical” report in Search Console fall over the following weeks.
What mistakes should you avoid when fixing it?
Most failed fixes come from one of these:
- Editing the live theme. Always duplicate it, make the change on the copy, preview, then publish.
- Fixing one template only. Product cards often live in several snippets; miss one and duplicates keep appearing.
- Blocking collection-path URLs in robots.txt. Google then can’t see the canonical tag on them. Fix the links instead.
- Removing collection context shoppers rely on. Breadcrumbs can still show the collection without changing the product URL.
- Not re-checking after theme updates. A theme update can bring the old snippet back.
What changes after the fix?
Expect quiet, compounding gains rather than an overnight jump. Google crawls fewer duplicates, finds new products faster, and consolidates links and signals on one URL per product. That makes every other improvement, from collection architecture to content, count for more.
It’s one of the first things we fix on every Shopify store, because the rest of the work builds on it. A few results from full Shopify engagements, where technical clean-up was one part of the plan:
