Skip to main content
SEO

Shopify Duplicate Content: How to Fix /collections/ Product URLs and Canonicals

Why a Shopify product can have more than one URL, what canonical tags fix and don't, and how to remove collection-aware links in Liquid without breaking things.

October 30, 2026 16 min read Talha Butt.
Share

Shopify Duplicate Content: How to Fix /collections/ Product URLs and Canonicals

Quick answer: Shopify’s within Liquid filter builds a product URL inside a collection, such as /collections/bedding/products/linen-duvet-cover, and Shopify’s documentation tells developers to consider the SEO implications. Many themes use it, so one product can be linked at two addresses. Shopify sets a canonical URL on each page, and Google treats a canonical tag as a strong signal, not a command. The fix is to make internal links point at the plain /products/ URL, check what your store does with the collection version, and keep breadcrumbs working without within. Duplicate your theme, test, and have a developer review before you publish.

Some guides say Shopify “handles duplicate content automatically”. Others call it a disaster. The truth sits in between, and it has moved recently.

Shopify does set canonical URLs, and they do much of the work. But your own theme may still link to the collection version of every product from every collection page. On a larger catalogue, those extra URLs can add up, and your internal links give Google two answers to “which URL is the real one?”

This guide covers where the duplicates come from, what the canonical tag does and does not do, how to check your own store, how to fix collection-aware product links in Liquid, and what you give up when you do. For the robots.txt side, see our guide to Shopify robots.txt. For page-level work, see our guides to collection page SEO and the product page SEO checklist.

Where Shopify’s duplicate URLs come from

Every Shopify product has a main address:

/products/linen-duvet-cover

A theme can also link to the same product inside a collection it belongs to. The handles below are illustrative:

/collections/bedding/products/linen-duvet-cover
/collections/new-arrivals/products/linen-duvet-cover
/collections/sale/products/linen-duvet-cover

Shopify’s documentation for the within filter describes it as generating a product URL “within the context of the provided collection”, and tells you to consider the SEO implications of using it. So whether collection-path URLs exist on your store in practice depends on your theme (does it link to them?) and on how Shopify answers a request for one (see the next section).

Other near-duplicate URLs:

SourceExampleWhat to check
Variant parameters/products/x?variant=123Canonical should point to the plain product URL
Tag-filtered collections/collections/bedding/linenThin, near-duplicate pages; decide index or noindex
Filter and sort parameters?filter.v.availability=1, ?sort_by=price-ascendingCanonical and robots.txt behaviour
Paginated collections/collections/bedding?page=2Self-referencing canonical
Vendor and type listings/collections/vendors?q=BrandExist only if your theme links to them

What Shopify’s canonical tag does (and doesn’t do)

Most themes output the canonical tag in the <head> of layout/theme.liquid. Shopify’s Dawn theme does it with one line:

<link rel="canonical" href="{{ canonical_url }}">

Shopify’s documentation describes the canonical_url object only as “the canonical URL for the current page” and refers you to Google’s canonical documentation. It does not list what it returns for each URL type. That is behaviour you can observe, and it can change, so here is what was observed on Shopify’s own Dawn demo store (os2-demo.myshopify.com) on 30 October 2026:

  • A variant URL (?variant=...) had a canonical pointing to the plain /products/ URL.
  • Sorted and filtered collection URLs had a canonical pointing to the plain collection URL.
  • A paginated URL (?page=2) had a canonical pointing to itself, which is what Google recommends.
  • A tag-filtered collection URL returned a normal page with a canonical pointing to itself, and no robots meta tag. A canonical tag was not folding those pages into the main collection.
  • A request for a collection-path product URL (/collections/all/products/some-product) did not load a duplicate page. It returned a 301 redirect to /products/some-product.

That last result matters. Shopify’s documentation does not describe it, older merchant reports said these URLs returned a normal page (status 200) with a canonical tag, and it may not apply to every store. Test yours using the checks below.

Google’s documentation on consolidating duplicate URLs lists redirects and rel="canonical" as strong signals and sitemap inclusion as a weaker one. It also says to link to the canonical URL rather than the duplicates, and not to use robots.txt for canonicalisation. Google still picks the canonical itself, using several signals, which is why a canonical tag is not a command.

The rule: your internal links, canonical tags and sitemap should all name the same URL. When they agree, Google gets one clear signal.

How to check whether your store has the problem

Right-click a product on a collection page and copy the link address. If it looks like /collections/[name]/products/[handle], your theme uses collection-aware links.

Method 2: See what Shopify does with the collection version

Type yourstore.com/collections/[collection]/products/[product] into your browser, using a product and a collection it belongs to.

  • If the address bar changes to /products/[product], your store redirects the collection version. Your links still send shoppers and Googlebot through a redirect on the way.
  • If the address stays the same, view the page source and search for rel="canonical". The canonical should be the plain /products/ URL.

Method 3: Search Console

In Google Search Console > Indexing > Pages, look at these statuses. The definitions below follow Google’s page indexing report help:

  • “Alternate page with proper canonical tag”: the page points to a canonical page that is indexed. Google says there is nothing you need to do. A very large count of collection-path URLs here shows Google is finding many duplicates.
  • “Duplicate, Google chose different canonical than user”: you marked this page as canonical, but Google thinks another URL is a better canonical. Use URL Inspection to compare the two.
  • “Duplicate without user-selected canonical”: the page is a duplicate of another and does not declare a preferred canonical. Google describes this as working as intended, but if it picked the wrong URL you can mark the canonical yourself.

Method 4: Crawl the store

Crawl your store with a tool such as Screaming Frog SEO Spider. Filter the internal links (inlinks) for URLs that contain both /collections/ and /products/. The count shows how many internal links point at collection-path product URLs.

Before you start: duplicate your live theme (Online Store > Themes, then the … menu > Duplicate), make every change on the copy, preview it, and test it. Have a developer review the changes before you publish. Variable names and file layouts differ between themes, and a small mistake in a theme file can break a store page.

Step 1: Find the within filter

On the theme copy, open Edit code and search the whole theme for:

within: collection

and also for:

| within:

Files where it commonly appears (names vary by theme):

  • snippets/card-product.liquid, product-card.liquid or product-grid-item.liquid
  • sections/main-collection-product-grid.liquid or sections/collection-template.liquid
  • sections/featured-collection.liquid
  • snippets/related-products.liquid
  • Search result and predictive search templates

Dawn’s current product card snippet, as published on Shopify’s GitHub repository on 30 October 2026, links to {{ card_product.url }} with no within filter. Older themes, many premium themes and heavily customised copies of Dawn may differ, so search your own theme rather than assuming.

This is a fragment: change only the matching line inside the file you found in Step 1. Do not replace the whole file.

{%- comment -%} Before: links to /collections/[name]/products/[handle] {%- endcomment -%}
<a href="{{ product.url | within: collection }}">{{ product.title }}</a>

{%- comment -%} After: links to /products/[handle] {%- endcomment -%}
<a href="{{ product.url }}">{{ product.title }}</a>

The variable name may differ in your theme, for example card_product.url or item.url. Keep the variable and remove only the | within: collection part.

Some apps (filters, quick view, upsells, wishlist) output their own product links. Check a collection page again after the change. If an app still outputs collection-path URLs, check its settings or ask its developer.

Step 4: Preview, test and publish

Preview the theme copy and click through several collection pages. Confirm product links go to /products/..., and that breadcrumbs, “back to collection” links and analytics still behave as you expect (see below). Publish only after a developer has reviewed the change.

What you lose when you remove within: collection

Shopify’s documentation says the within filter lets you reach the associated collection object from the product template. Themes use that context for:

  • Breadcrumbs: “Home > Bedding > Linen Duvet Cover”
  • “Back to collection” links and next or previous product navigation
  • Analytics and app context. The Google Analytics 4 ecommerce events view_item_list, select_item, view_item and add_to_cart can carry an item_list_id and item_list_name, which record the list (for example a collection) a product came from. How your theme or apps fill those fields varies. Some may read the collection from the page, so removing within can change what they report.

If your store already redirects collection-path URLs (Method 2 above), the shopper lands on the plain /products/ URL either way, so that URL-based context is already gone. Check what your breadcrumbs and reports show today before you assume the change is what breaks them.

Your options:

  1. Use a primary collection for breadcrumbs. Store each product’s main collection in a collection-reference metafield (for example custom.primary_collection) and read it in the breadcrumb. Each product then has one consistent breadcrumb path whichever page the shopper came from.
  2. Keep list context for analytics another way. If attribution by collection matters to you, ask a developer to record the list name when the shopper clicks (for example in a data attribute on the link, passed to your analytics on click) instead of in the URL. Do not add the collection to the URL as a query parameter: that creates new addresses for the same product.
  3. Leave within in place if analytics or an app depends on it and nobody can replicate it safely. In that case, rely on the canonical tag and clean sitemap, and monitor Search Console. This is a reasonable trade-off, not a failure.
  4. Replace next and previous navigation with a related products section, if shoppers barely use it.

Do not use product.collections.first as a fallback. Shopify’s documentation describes product.collections only as the collections the product belongs to, with no ordering, so the first can be a broad collection such as “Home page”, “All” or “Sale”. If no primary collection is set, show no collection step.

This is a full snippet file. Create a new file called snippets/breadcrumb-primary-collection.liquid in your theme copy and paste in the following:

{%- assign crumb_collection = product.metafields.custom.primary_collection.value -%}
<nav aria-label="Breadcrumb">
  <a href="{{ routes.root_url }}">Home</a>
  {%- if crumb_collection != blank -%}
    / <a href="{{ crumb_collection.url }}">{{ crumb_collection.title }}</a>
  {%- endif -%}
  / <span aria-current="page">{{ product.title }}</span>
</nav>

Then add this fragment in your product template or product section, where the breadcrumb should appear. Replace any breadcrumb your theme already outputs rather than adding a second one, and check any breadcrumb markup (BreadcrumbList) still matches what shoppers see:

{% render 'breadcrumb-primary-collection', product: product %}

To set it up, create the metafield definition first (Settings > Custom data > Products, type: collection reference), then set it on each product. The custom namespace is what the admin usually suggests; if yours differs, change product.metafields.custom.primary_collection to match. Shopify documents that a collection-reference metafield’s value returns a collection object. Test on your theme copy.

Other duplicate pages to deal with

Tag-filtered collection pages

Shopify’s tag filtering adds the tag handle to the collection URL, such as /collections/bedding/linen, and combines tags with +. Shopify says a tag that applies to no products is redirected to the collection URL with the tag removed. These pages are usually thin versions of the main collection. You have two options:

  • If the tag has real search demand (for example “linen bedding”), turn it into a real collection with its own title and copy. See our collection page SEO guide.
  • If it does not, noindex it. This is a fragment to add inside the <head> of layout/theme.liquid:
{%- if template.name == 'collection' and current_tags.size > 0 -%}
  <meta name="robots" content="noindex">
{%- endif -%}

Shopify documents template.name as returning collection on collection pages, and current_tags as available in collection (and blog) templates. After adding it, view the source of a plain collection URL (it should not contain the robots tag) and of a tag URL (it should). If a plain collection page shows the tag, remove the snippet straight away. If your theme or an SEO app already outputs a robots meta tag, do not add a second one. Use noindex on its own: follow is not a value Google documents, and it is the default anyway.

Do not combine noindex with a robots.txt block. Google’s robots meta tag documentation says that if a page is disallowed in robots.txt, the noindex rule is never seen.

Vendor and product-type listings

Shopify’s link_to_vendor filter creates links like /collections/vendors?q=Brand. These pages exist when your theme links to them, and not every store serves them (the Dawn demo store returned a 404). If yours do, and they are thin, you can noindex them. This is a fragment for the same <head> of layout/theme.liquid:

{%- if request.path contains '/collections/vendors' or request.path contains '/collections/types' -%}
  <meta name="robots" content="noindex">
{%- endif -%}

If you also added the tag-page snippet, combine both conditions in one if so the tag is output once. Test it as above.

Filter and sort parameters

Shopify’s Help Center says its default robots.txt keeps sorted collection pages (/collections/*sort_by*) and filtered collection pages (/collections/*+*) from being crawled. The robots.txt served by the Dawn demo store on 30 October 2026 also contained a rule for URLs with two filter parameters. A single filter parameter is not covered by those patterns, so check yours. For how to edit robots.txt, see our Shopify robots.txt guide. Do not block anything until you have checked it does not carry valuable traffic.

/collections/all

If /collections/all is linked as “Shop all”, it can stay. Give it a generic title such as “Shop all products” so it does not compete with your real category pages.

Paginated collection pages

/collections/bedding?page=2 should keep a self-referencing canonical (page 2 canonicalises to page 2). Google’s pagination guidance says not to use the first page of a sequence as the canonical for the others, and to give each page its own canonical URL. Check that your theme or an app has not changed this.

Duplicate content that isn’t about URLs

URL duplicates are only part of the picture. These content duplicates are worth checking too:

  1. Supplier product descriptions. The same text appears on every retailer stocking the product. Rewrite your top sellers first (see the product page SEO checklist).
  2. Near-identical products. Separate products for each colour with the same description compete with each other. Combine them as variants, or make each one genuinely different.
  3. Overlapping collections. “Linen sheets” and “linen sheet sets” chasing the same search. Merge them or give each a distinct keyword target.
  4. Boilerplate blocks. The same long shipping or brand paragraph on every page. Keep it short.

What not to do

  • Don’t block /collections/*/products/* in robots.txt. Google says not to use robots.txt for canonicalisation, and a blocked URL cannot show its canonical tag. Fix the links instead.
  • Don’t noindex product pages to “fix” duplicates. Google does not recommend noindex for choosing a canonical within a site, because it blocks the page from Search entirely. You would remove the version you want to rank.
  • Don’t canonicalise paginated pages to page 1.
  • Don’t run several SEO apps that each edit canonicals or robots tags. View the source of a product page and a collection page and confirm there is one canonical tag and no more than one robots tag.
  • Don’t expect the admin’s URL Redirects tool to fix this. Shopify’s URL redirect help says you can redirect only from URLs that no longer load, so it will not redirect a collection-path URL that still returns a page.
  • Don’t change handles to fix duplicates without a redirect. Shopify’s collection settings help describes an option to create a redirect from the old handle when you edit a collection’s URL. For products, check what your admin offers when you edit the handle.

How to check the fix worked

  1. Re-crawl the store and confirm internal links to /collections/*/products/* have dropped to near zero.
  2. Check what the collection version does (Method 2 above) on a few products.
  3. Inspect a product URL in Search Console’s URL Inspection tool. Compare the User-declared canonical with the Google-selected canonical; they should match.
  4. Watch the Pages report as Google recrawls. There is no fixed timeline. The count of “Alternate page with proper canonical tag” URLs should fall, and “Google chose different canonical” entries should shrink if your links were the cause.
  5. Check Crawl stats (Settings > Crawl stats in Search Console, root-level properties only) for the mix of URLs Google requests.
  6. Check your analytics. If you use list or collection reporting, confirm it still records what you expect.

Key takeaways

  • The within filter creates collection-path product URLs, and Shopify’s documentation tells you to consider the SEO implications.
  • Shopify sets canonicals, but a canonical is a strong signal, not a command. Internal links, canonicals and sitemaps should name the same URL.
  • Test what your store does with a collection-path URL. It redirected on Shopify’s demo store on 30 October 2026, but this is undocumented.
  • The main fix is in your theme: remove | within: collection from product links, on a duplicate theme, after testing and developer review.
  • Keep breadcrumbs with a primary-collection metafield, not product.collections.first, and keep analytics context another way or leave within in place.
  • Make thin tag-filtered pages real collections or noindex them.
  • Never block product URLs in robots.txt or noindex product pages to fix duplicates.

FAQs

Does Shopify automatically handle duplicate content?

Partly. Shopify outputs a canonical URL on each page. On Shopify’s Dawn demo store on 30 October 2026, variant, sorted and filtered URLs pointed at the main version and the collection-path product URL redirected. But it did not fold tag-filtered pages into the main collection, and your theme and apps can still link to duplicates or change the tags. Check your own store.

What does within: collection do in Shopify?

It is a Liquid filter that generates a product URL within a collection’s context, such as /collections/bedding/products/linen-duvet-cover, and gives the product template access to the collection object. Shopify’s documentation tells you to consider the SEO implications, because the product is then linked at a second URL.

Is /collections/x/products/y bad for SEO?

The URL itself is not harmful. What matters is how your store answers a request for it (a redirect, or a page with a canonical tag) and whether your own links point at it. Linking straight to /products/y keeps your signals consistent.

Should I block /collections/*/products/* in robots.txt?

No. Google says not to use robots.txt for canonicalisation, and a URL it cannot crawl cannot show its canonical tag. Fix your theme’s internal links instead.

What does “Duplicate, Google chose different canonical than user” mean?

You marked the page as canonical, but Google thinks another URL is a better one and indexed that instead. Use URL Inspection to compare the two, and check that your internal links, canonical tags and sitemap name the same URL.

Should paginated collection pages have a canonical to page 1?

No. Google recommends giving each page in a sequence its own canonical URL, so page 2 points to page 2.

Will fixing duplicate URLs improve my rankings?

It removes mixed signals, but nothing is guaranteed. Whether rankings move depends on what else is holding the store back, such as thin collection pages, weak product content or limited authority.

Want this checked properly?

Duplicate URLs are worth checking early in any Shopify SEO audit, along with crawl waste, schema conflicts and thin collection pages. The fixes are often small. Finding them, and changing a live theme safely, is where the care goes. Prism3’s Shopify SEO service covers technical fixes such as duplicate URLs and canonical tags, done in order of revenue impact, inside your theme’s Liquid code where needed. We do not change anything on your store without your approval. Or book a free 30-minute diagnostic and we will go through your store’s links on a screen-share. For the wider picture, see our Shopify SEO guide.

About the author

Talha Butt is the founder of Prism3, a founder-led Shopify SEO, GEO and CRO agency for DTC brands in Australia and the US. Talha has four years of growth marketing experience across different industries and now focuses on DTC brands.

Free 30-min diagnostic

Seen enough?
Book a free diagnostic.

We'll look at your store's search pages, find what is costing you traffic and tell you what to fix first. No pitch. No email gate. 30 minutes.

More from Prism3