Search “Shopify variant duplicate content” and most of what comes back says the same thing: don’t worry about it, Shopify adds canonical tags automatically, problem solved. That advice isn’t wrong, exactly. It’s just incomplete, and it’s the reason stores keep finding variant URLs sitting in Google’s index months or years after someone told them this was already handled.
Shopify’s default canonical tag behaviour genuinely does most of the heavy lifting here. But “most” isn’t “all,” and the gap between the two is where a meaningful chunk of ecommerce SEO teams lose time chasing symptoms, thin content warnings, cannibalisation between near-identical URLs, inconsistent structured data, without tracing them back to the actual cause.
This post goes past the basic canonical-tag explanation into what’s actually happening with variant URLs, where the default behaviour breaks down in practice, what Shopify’s Search & Discovery app does and doesn’t control here, and the specific technical checks worth running on a store that’s dealing with this at scale.
How Shopify Generates Variant URLs
Every Shopify product lives at one canonical path: /products/product-handle. When a product has variants, size, colour, material, whatever the store has set up as options, Shopify doesn’t create separate URLs for each variant by default. Instead, selecting a variant on the storefront appends a query parameter to the existing product URL: /products/product-handle?variant=41234567890123.
That number is the variant ID, a unique identifier Shopify assigns to each variant combination. Functionally, this lets the store link directly to a pre-selected variant, useful for linking straight to “Blue, Large” from an email, an ad, or a collection page that pre-selects a specific option. Technically, it means the underlying page, same template, same Liquid, same core content, is now reachable at dozens or even hundreds of distinct URLs for a product with many variant combinations.
This is the root of the duplicate content risk: one real page, many valid URLs pointing at effectively the same content, differing only in which variant is pre-selected (which usually changes the displayed price, image, and availability, but not the underlying page copy, headings, or structure).
Shopify’s Default Canonical Tag Behaviour
Out of the box, Shopify’s theme architecture handles this reasonably well. The <head> section of the product template outputs a canonical tag using the canonical_url object, which resolves to the base product URL, /products/product-handle, without the variant query string, regardless of which variant URL was actually requested.
In plain terms: if someone lands on /products/mens-tee?variant=41234567890123, the page still declares /products/mens-tee as its canonical version in the page’s <head>. That’s the correct, intended signal, it tells Google “this is a variant of that page, index the base version, not this one.” This is genuinely well-built into Shopify’s default themes and has been standard behaviour for a long time. If your theme hasn’t been heavily customised around the product template, this part is very likely already working correctly.
Where This Still Goes Wrong in Practice
The canonical tag is a signal, not an instruction. Google treats it as a strong hint, not a guaranteed directive, and there are several specific, common ways the theory breaks down on real stores.
Variant-specific landing pages from ads and email. Marketing teams routinely link straight to a specific variant, “shop the red one” in a Meta ad, “your size is back in stock” in a Klaviyo flow, using the ?variant= URL because it pre-selects the right option for the shopper. That’s good UX. But if that URL then earns backlinks, gets shared, or picks up enough direct traffic and external signals, Google can and sometimes does choose to index the variant URL anyway, canonical tag notwithstanding. Google has been explicit for years that rel=canonical is a hint it can override when other signals (like a large volume of external links pointing at the “non-canonical” URL) point the other way.
Custom theme code that breaks canonical output. Any theme customisation that touches the product template’s <head>, a developer adding custom meta tags, a page builder app injecting its own head content, or a poorly implemented internationalisation setup, can silently override or duplicate the canonical tag. This is worth physically checking, not assuming: view source on a handful of variant URLs and confirm the canonical tag is present, correct, and there’s only one of it.
Legacy indexed URLs from before a fix. If a store previously had a theme or app that didn’t handle this correctly, older custom themes in particular sometimes lacked proper canonical output, Google may still have those variant URLs indexed from years ago, even after the underlying issue was fixed. Canonical tags help Google consolidate going forward; they don’t automatically deindex URLs that were already crawled and indexed under different conditions.
Sitemap inclusion via apps. Shopify’s native sitemap.xml does not include variant URLs, it lists each product once, at its base URL. That’s correct behaviour. But some third-party apps, custom sitemap generators, or feed apps for other purposes (Google Shopping feeds, affiliate feeds) generate their own supplementary sitemaps or product feeds, and it’s not unusual for these to include full variant URLs where a plain product feed would do. If Google discovers variant URLs via a sitemap, that’s a stronger indexing signal than discovering them incidentally via a link.
What the Search & Discovery App Does (and Doesn’t) Control
Shopify’s Search & Discovery app, found under Sales channels > Search & Discovery in the admin, manages on-site search relevance, filtering, and product recommendations. It’s worth being precise about its actual scope here, because it’s easy to assume it governs variant URL canonicalisation. It doesn’t, directly.
What it does affect, and where it connects to the same underlying duplicate content problem, is collection filtering. When Search & Discovery’s filter feature is enabled, applying filters on a collection page (size, colour, price range, availability) generates URL parameters, ?filter.v.option.size=Large, for example, that create their own set of near-duplicate collection page variations, for exactly the same underlying reason as product variants: same core content, different URL, driven by a selected option.
Practical settings and checks worth running in Search & Discovery and the surrounding theme setup:
- Confirm which filters are enabled per collection, the more filter combinations available, the more URL variations get generated, and not every filter combination needs to be independently crawlable
- Check whether filtered collection URLs carry a canonical tag back to the unfiltered collection URL (theme-dependent; not all themes handle this by default the way product pages do)
- Where a theme doesn’t canonicalise filtered URLs cleanly, consider a
noindex, followdirective on filtered result pages via theme customisation, so Google can still crawl through to individual products without indexing every filter permutation as a separate page - Avoid linking internally to filtered URLs from navigation or footer menus where a clean, unfiltered collection URL would do the same job
This is a related but distinct problem from product variant URLs, same mechanism (parameters generating URL variations of the same content), different part of the store, and it compounds the total duplicate content surface area if left unmanaged alongside variant URLs.
Left unmanaged together, product variant URLs and filtered collection URLs are one of the more common reasons a mid-sized or larger catalogue on Shopify develops a technical SEO issue that’s genuinely worth a proper Shopify technical SEO review, the fix isn’t one setting, it’s checking canonical behaviour, filter configuration, sitemap contents, and indexed-URL data together to see where signals are actually breaking down versus where they’re already working as intended.
Structured Data Considerations
Shopify’s default themes output Product structured data (JSON-LD) with an offers array reflecting variant-level pricing and availability. This is generally fine and is what powers price and availability information in rich results. The risk shows up when variant URLs get indexed separately: Google may then have two or more indexed URLs, the base product and one or more variant URLs, each carrying their own instance of the same structured data, with only price or availability differing.
This doesn’t usually cause a manual penalty or anything dramatic, but it can produce inconsistent or conflicting information in rich results (the wrong variant’s price showing for a general product search, for example) and adds noise Google has to reconcile. Running affected product pages through Google’s Rich Results Test, and checking the Merchant Center or Search Console for price/availability mismatches, is a reasonable diagnostic step if you’re seeing inconsistent rich result data on a product with many variants.
A Practical Fix Checklist
For a store that wants to actually verify this rather than assume it’s handled, here’s a working sequence:
- View source on several variant URLs (
?variant=appended) across different product types and confirm exactly one correct canonical tag is present in the<head>, pointing to the base product URL. - Search Console: check the Page Indexing report for URLs containing
variant=under “Indexed, though blocked” or, more importantly, “Indexed”, any variant URL appearing as independently indexed is worth investigating. - Audit outbound links to variant URLs from ad campaigns, email flows, and any internal linking, not to eliminate them (linking to a pre-selected variant is often good UX), but to know the scale of external signals pointing at them.
- Check for third-party sitemaps or feeds that might include variant URLs, separate from Shopify’s native sitemap.xml.
- Review Search & Discovery filter settings per collection and confirm filtered URLs either canonicalise back to the base collection or carry appropriate indexing directives.
- Spot-check structured data on a handful of high-variant products for consistency between what’s indexed and what’s actually being shown in search results.
- Decide deliberately, product by product, where separate pages genuinely make sense (see below) rather than leaving it as an accident of how variants happened to be set up.
When to Use Separate Product Pages Instead of Variants
Sometimes the right fix isn’t tighter canonicalisation, it’s recognising that a “variant” shouldn’t be a variant at all. If different colourways, materials, or configurations of a product have genuinely different search demand, different imagery worth its own page, and different buyer intent (a customer searching “leather laptop bag” versus “canvas laptop bag” is asking a different question, not just picking an option), separate product pages with their own unique content and their own targeted keyword can outperform folding everything into one product with a colour selector.
This is a deliberate content and information architecture decision, not a default. Most product options, size, in particular, rarely justify separate pages, since size doesn’t usually reflect distinct search intent. Colour and material sometimes do, especially where search volume data supports it. This is worth deciding case by case rather than applying a blanket rule across a whole catalogue.
FAQ
Does Shopify automatically fix variant URL duplicate content?
Mostly, yes, Shopify’s default theme architecture outputs a canonical tag pointing variant URLs back to the base product URL, which is the correct signal. But canonical tags are a strong hint, not a guarantee, and factors like heavy external linking to variant URLs, legacy indexed pages, or theme customisations can still result in variant URLs getting indexed despite the canonical tag being technically correct.
Can I stop Shopify from creating ?variant= URLs at all?
Not through standard settings, and it’s generally not something you’d want to disable, the ability to link to a pre-selected variant is useful for marketing and for shoppers navigating directly to the right option. The fix is managing indexation and canonicalisation properly, not preventing the URLs from existing.
Should every product variant have its own SEO-optimised page?
No, and defaulting to that approach usually creates more duplicate content risk, not less. Separate pages make sense when a variant reflects genuinely distinct search intent and demand, different colours or materials people search for by name, for example, not for every size or minor option.
How do I find out if Google has indexed my variant URLs?
Check the Page Indexing report in Google Search Console and look for URLs containing variant= under the indexed status. You can also run a site search like site:yourdomain.com.au inurl:variant directly in Google, though Search Console data is more reliable and complete.
Does the Search & Discovery app control canonical tags for variant URLs?
No, canonical tag output for product variant URLs comes from the theme’s product template, not the Search & Discovery app. Search & Discovery controls on-site search and collection filtering, which creates a related but separate duplicate content risk through filtered URL parameters on collection pages.
Next Step
If you suspect variant URLs or filtered collection pages are creating duplicate content issues on your store, a Shopify SEO audit will check actual indexation data against your theme’s canonical behaviour rather than assuming the default settings are working as intended. Prefer to talk it through first? You can book a call with our team.