Skip to content
Published

Canonical & Duplicate

The /products/ + /collections/products/ Duplicate, Decoded

Every Shopify product is reachable at two URLs by design: /products/handle and /collections/foo/products/handle. The platform auto-emits a canonical tag pointing the collection-prefixed URL back to the canonical /products/handle1. The default robots.txt also blocks /collections/*+* filter combinations and /search to suppress the other thin-duplicate URL patterns2. This cluster covers what to do when the auto-canonical fails.

The four leaves: auto-canonical behaviour, collection-prefixed URL suppression, the filtered /collections/*+* pattern, and the internal /search noindex.

The Shopify-specific duplicate pattern

Shopify routes every product at /products/handle and also at /collections/foo/products/handle whenever the product belongs to a collection. The platform auto-canonicals the collection-prefixed URL back to the canonical /products/handle, which means Google treats them as one resource — but only when the canonical tag is correctly emitted by the theme. Custom-coded theme templates, third-party page-builder apps, and stores using the within: collection Liquid filter without a canonical override are the cases where the auto-canonical fails.

html The two URLs every Shopify product has, and the canonical that resolves them
 <!-- URL 1: the canonical product URL --> https://yourstore.com/products/linen-roman-shade <!-- URL 2: the collection-prefixed URL (when the product is in a collection) --> https://yourstore.com/collections/window-treatments/products/linen-roman-shade <!-- Themes auto-emit on URL 2: --> <link rel="canonical" href="https://yourstore.com/products/linen-roman-shade" /> 

What Shopify's auto-canonical actually does

Shopify's SEO overview states the platform auto-generates canonical tags 'to prevent duplicate content from appearing in search results.' The auto-canonical fires on products, collections, pages, and blog posts. It is self-referencing on the canonical URL (the page's canonical points to itself) and signal-bearing on duplicate URLs (the collection-prefixed product URL's canonical points to the /products/handle canonical URL). Per Google's canonicalization doc, this is the correct rel='canonical' pattern — Google reads it as a strong signal but reserves the right to choose a different canonical if other signals contradict.

The leaf at /shopify-seo/canonical-tags/ covers the auto-canonical behaviour, the GSC Pages report that surfaces "User-declared vs Google-selected canonical" mismatches4, and the rare cases where the auto-canonical fires incorrectly (custom themes that broke the canonical_url Liquid object, third-party page builders that re-render the head, or per-template overrides that conflict with the global canonical).

Filtered collection URLs and the /collections/*+* pattern

Shopify collections support faceted filtering — colour, size, price, vendor, tag. Each filter combination produces a URL like /collections/dresses/red+xl. The combination pattern is open-ended: every filter combo creates a unique URL with thin, near-duplicate content. Shopify's default robots.txt blocks /collections/*+* (the wildcard pattern matches any filter URL with two or more values) to suppress this duplicate URL surface from Google's crawl. Unblocking this is almost never the right move.

The leaf at /shopify-seo/filtered-collections/ covers the pattern, the few legitimate cases for unblocking specific filter URLs (typically when a filter combination represents a genuinely distinct product offering with hand-curated content above the grid), and the alternative architecture: surface high-value filter combinations as dedicated collections with their own descriptions and canonical URLs, not as filter URLs.

Shopify's default robots.txt blocks /search (the internal search results URL). Internal search results pages are inherently thin-content — they render a query string ('blue dress') against a product list with no editorial content, no unique meta, and no canonical product. Google has long downgraded sites that allow internal search pages to compete with editorial pages. Leaving /search blocked is the correct default.

When the auto-canonical fails

Three failure modes account for most Shopify canonical issues: (1) custom-coded theme templates that lost the canonical_url Liquid object during a redesign; (2) third-party page-builder apps (PageFly, Shogun, GemPages) that re-render the page head and skip the auto-canonical; (3) stores using the within: collection Liquid filter to render collection-aware product templates without a canonical override. Each failure mode produces a different GSC signature.

The collection-canonical leaf at /shopify-seo/collections-products-canonical/ covers the within: collection case in detail — it is the most common Shopify-specific canonical failure on stores with custom theme work. The pattern is to add an explicit {% if template == 'product' %}<link rel="canonical" href="{{ canonical_url }}" />{% endif %} in theme.liquid when the global canonical is rendered conditionally.

The GSC Pages report under "Duplicate, Google chose different canonical than user" is the diagnostic surface. If that report shows a Shopify store's collection-prefixed product URLs with the wrong selected canonical, the theme has broken the auto-canonical — not a content issue, a code issue.