Skip to content

Duplicate Content · The product-URL pattern

Stopping Collection-Prefixed URLs from Competing

Every Shopify product is reachable at two URLs by default: the bare /products/handle and the collection-prefixed /collections/foo/products/handle. The first is the canonical primary URL. The second is the navigation-context URL Shopify renders when a customer reaches the product from a collection. The auto-canonical handles this correctly out of the box1. The one trap: the within: collection Liquid filter can break the auto-canonical if used carelessly.

Published Verified 2026-05-22

The pattern: every Shopify product lives at two URLs

Shopify's URL routing makes every product reachable at two paths: the bare /products/handle (the primary URL) and the collection-prefixed /collections/COLLECTION-HANDLE/products/handle (the contextual URL). The same template renders at both paths — the same title, the same description, the same images, the same Add to Cart. To a search engine without canonical guidance, these are two URLs serving identical content. That's the duplicate-content surface Shopify's auto-canonical was designed for.

The pattern emerges naturally from Shopify's navigation. When a customer clicks a product card on a collection page, the link defaults to /collections/{collection-handle}/products/{product-handle} — preserving the collection context for the customer (so the "back to collection" arrow knows where to go) and for theme features like "next product in collection." The same product clicked from a search result or a direct link uses the bare /products/{product-handle}.

The duplicate-content concern: without a canonical pointing the variant URL to the primary, Google could index both, split ranking signals across them, and treat one as a thinner duplicate. Shopify's URL structure is described in the Optimize-site doc2 as "a simple, readable structure" — the canonical is what makes that structure work for SEO.

Why Shopify keeps the collection-prefix URL

Shopify could route every product link through /products/handle and avoid the duplicate entirely. They don't because the collection-prefix URL serves three real purposes. (1) Theme features like 'previous / next product' know which collection to traverse based on the URL prefix. (2) Faceted filtering preserves filter state across product clicks (the customer who filtered to 'red dresses' stays inside 'red dresses' after clicking a product). (3) Analytics attribution can map a product click back to its source collection. Removing the collection prefix would break all three. The auto-canonical is the duplicate-content tradeoff Shopify accepts for the navigation UX.

This is a deliberate platform design tradeoff. The auto-canonical means SEO consolidates correctly while the customer-facing navigation works the way it should. Most merchants never see the collection-prefix URLs because they don't appear in the sitemap and don't appear in copy-link contexts; they only surface when a customer copies the URL from the browser bar mid-navigation.

The default canonical fix

Shopify's themes ship with a canonical tag in theme.liquid's head that resolves to canonical_url — the Liquid object that always returns the bare /products/handle for a product, regardless of how the page was reached. When Google crawls /collections/foo/products/bar, it finds a canonical pointing to /products/bar, consolidates signals to the canonical, and treats the collection-prefixed URL as a duplicate. Per Google's canonical guidance, ranking signals (links, engagement, freshness) flow to the canonical.

Verify the canonical with a single curl on a collection-prefixed URL:

bash Verify the auto-canonical on the collection-prefixed URL
 # Expected: canonical points to the bare /products/handle curl -sL https://yourstore.com/collections/all/products/linen-shirt \  | grep -i 'canonical' # Expected output (verbatim shape): # <link rel="canonical" href="https://yourstore.com/products/linen-shirt"> 

If the output points to anything other than the bare /products/handle URL, the auto-canonical is broken. Shopify's SEO FAQ3 names the debug path: inspect theme.liquid, main-product.liquid, and any page-builder app templates active on the affected route. Google's canonical doc4 confirms the ranking consolidation behavior.

The within: collection Liquid trap

The Liquid filter within: collection generates collection-prefixed product URLs in custom theme code. Developers use it for product loops that should preserve the collection context (e.g. a custom 'related products' block that pulls from the parent collection). The trap: every link emitted with within: collection is a /collections/foo/products/bar URL. The auto-canonical still works on the destination page, but the link itself is the variant URL, and many such links across the site create more crawlable variant URLs than necessary. The fix is to use within: collection only where the collection context is genuinely needed, and to add an explicit canonical override on any custom template that emits these links heavily.

The pattern in theme code looks like a product link generated with {{ product.url | within: collection }}. The output is a collection-prefixed URL even when the surrounding template would otherwise emit a bare product URL. The fix: use {{ product.url }} (no within: filter) for any product link that doesn't need the collection context preserved — sitewide product recommendations, search results, related-product widgets that don't depend on collection context.

Three-step remediation if your store is affected

If a Shopify store is generating crawlable /collections/foo/products/bar URLs that Google is indexing alongside the bare /products/bar, three remediation steps fix it. (1) Confirm the auto-canonical is intact — curl a collection-prefixed URL and verify the canonical tag points to the bare /products/handle. (2) Audit theme code for unnecessary within: collection filters on product links and remove them where collection context isn't required. (3) In Google Search Console, monitor the 'Duplicate, Google chose different canonical' report; affected URLs should shift to 'Duplicate, submitted URL not selected as canonical' over 4-6 weeks as Google re-crawls and re-consolidates.

The two-step diagnostic is fast and conclusive: curl | grep canonical on five representative URLs (homepage, product via bare URL, product via collection-prefixed URL, collection, blog article) confirms the auto-canonical is doing its job. If the canonical tags are intact, the platform is handling the duplicate correctly even if both URLs appear in raw crawl data — Google's index will consolidate.

For the broader cluster context, see the duplicate-content hub and the sister article on Shopify auto-canonicals. For the filter URL pattern (/collections/*+*) handled by robots.txt rather than canonical, see filtered collections.