Duplicate content in ecommerce: variants, filters, canonicals
Why stores create duplicate URLs through variants, filters, sorting and pagination, and which fix fits which case. With a clear decision table.

Contents
An online store produces duplicate content almost by itself. Every variant, every filter, every sort order can end up as its own URL. This is rarely a penalty and usually a waste: Google crawls dozens of near-identical pages and splits signals like links, clicks and internal references across several URLs instead of concentrating them on one. This article covers where the duplicates come from, which fix belongs to which case, and how to verify the state of things in Search Console.
What duplicate content actually costs you
Google detects near-identical pages and picks one of them as the canonical URL. Your canonical declaration is a strong signal, not a command. When internal links, sitemap and canonical contradict each other, Google decides, and sometimes it decides in favour of the filter URL instead of your category page. Google says as much in its documentation on consolidating duplicate URLs: if you do not specify a preference, Google will identify the version it considers best.
The consequences are undramatic but they cost visibility:
- Crawling spreads sideways. The crawler collects tens of thousands of parameter URLs and reaches new products and updated category copy less often.
- Signals fragment. An external link to
?color=bluedoes not strengthen your main page when the relationship is unclear. - The wrong URL ends up in the index. Visitors land on a pre-filtered list instead of the category page you actually optimized.
- Your own pages compete. Two nearly identical categories for the same term do not double your chances, they produce two mediocre positions.
A manual action only becomes a risk when copied content is published at scale to manipulate search results. Variant and filter URLs are not that.
Where the duplicates come from
Variants
Colour, size, length, quantity. Many platforms append the selection as a parameter on the product URL. The text stays the same; sometimes the image and price change.
Filters and facets
?brand=, ?size=, ?price_max= and every combination of them. Five filters with five values each add up to thousands of URLs, almost all showing the same products in a different order.
Sorting and view options
?sort=price-asc, ?view=list, ?per_page=48. These parameters never change the content, only the presentation. This is the purest form of duplication.
Pagination
Pages 2, 3 and 4 of a category. Not a real duplicate, but frequently mishandled: pointing every subsequent page at page one with a canonical hides the products on the later pages.
Internal search results
/search?q=... generates unlimited pages that are empty or randomly filled depending on the input. They do not belong in the index.
Tracking parameters
?utm_source=newsletter, click IDs from ad platforms, affiliate parameters. Technically the same page, a new URL for the crawler.
One product in several categories
Some systems expose the same product under several paths. Shopify handles this internally with a canonical to the /products/ URL; in other systems you have to verify it.
Host and spelling variants
example.com and www.example.com, http and https, with and without a trailing slash, mixed case in the path, /index.php alongside /. Every variant that serves a page instead of redirecting is a separate URL.
Print, preview and staging views
Print versions, preview links, staging domains without protection. Classics, because nobody published them on purpose.
Textual duplicates
The same supplier text on hundreds of stores, identical descriptions across every variant, category copy where only the category word was swapped. Technically correct, editorially interchangeable. If you draft with generative tools, the rules that keep this from getting worse are in the article on AI product descriptions.
The tools and what they really do
| Tool | Effect | Not suitable for |
|---|---|---|
rel="canonical" | Signals which URL is the main version; consolidates signals | Pages with clearly different content; forcing a decision |
| Self-referencing canonical | Each page names itself as the main version; makes parameter variants unambiguous | Cases where a different URL should rank |
noindex (meta tag or HTTP header) | Page drops out of the index but stays crawlable and passes links on | URLs blocked in robots.txt, where Google never reads the tag |
robots.txt Disallow | Prevents crawling, saves crawl budget | Removing pages from the index; blocked URLs can still be listed |
| 301 redirect | Permanently merges host and spelling variants | Variants that must stay reachable as their own URL |
| Internal linking | The strongest signal for which URL you consider important | Replacing a canonical or a noindex |
nofollow on links | Does not reliably control crawling | Defusing a filter navigation |
Two pieces of advice that get passed around long after they expired. First: the URL Parameters tool in Search Console no longer exists. Google announced its deprecation in March 2022, because only a tiny fraction of the configurations stored in it were still useful for crawling and Google handles parameters automatically now. Today you steer parameters through canonicals, internal links and robots.txt. Second: rel="next" and rel="prev" are no longer used by Google. The documentation says plainly that Google no longer uses these tags, although the links may still be used by other search engines. The same page also tells you to give each paginated page its own canonical URL and not to use page one as the canonical for the whole sequence — see Google's guidance on pagination and incremental page loading.
And one rule worth writing on the wall: never combine noindex with a canonical pointing at a different page. Google's own wording is that it does not recommend using noindex to prevent selection of a canonical page within a single site, because it blocks the page from Search completely, and that rel="canonical" is the preferred solution. Pick one mechanism per URL.
Decision table: which case needs which fix
| Case | Fix | Why |
|---|---|---|
Sort and view parameters (sort, view, per_page) | Canonical to the clean category URL; no internal links to parameter URLs | Content is identical, order is not its own search intent |
Tracking parameters (utm, click IDs) | Canonical to the clean URL | Same page; campaign links should not enter the index |
| Variants without their own demand (sizes, quantities) | One product page with a selector, variant URLs canonical to it | Concentrates all signals on one page |
| Variants with real demand (colour in fashion, capacity in electronics) | Own indexable page with its own title, images and copy; self-referencing canonical | People search for “model in black”, so that needs a page |
| Filters with search demand (a brand inside a category) | Treat as a category: title, intro copy, an internal link from the navigation | It deserves a landing page of its own |
| Filters without demand, few combinations | noindex, keep crawlable | Out of the index, links still work |
| Filters without demand, very many combinations | Limit crawling (robots.txt on the parameter pattern), no internal links to them | Volume is the problem, not the individual page |
| Pagination (page 2 onwards) | Self-referencing canonical per page, plain links between pages, keep indexable | Only then does Google find the products on later pages |
| Internal search results | noindex, plus a robots.txt brake if they are crawled heavily | Unlimited pages with no standalone value |
| Cart, account, checkout | noindex | Nothing there for searchers |
www/non-www, http/https, trailing slash, index.php | 301 to one spelling, link consistently everywhere | One page, one URL |
| Print and preview views | Canonical to the normal view, or switch them off | Pure duplication |
| Staging or test environment | Protect with a password | Blocking alone is often not enough |
| The same products in two stores or language versions | Pick one main version; for languages add hreflang | Without a clear relationship, Google decides |
Rule of thumb: if a human being would search for the page in that exact state, it belongs in the index. If not, it does not, and the only remaining question is whether noindex or a crawl block is the right tool.
Step by step: clean up in seven steps
- Take stock. Open the page indexing report in Search Console and read the not-indexed statuses. Their exact labels in the English interface are "Duplicate without user-selected canonical", "Duplicate, Google chose different canonical than user" and "Alternate page with proper canonical tag". The first is a task, the third is the normal state. If you also see a large block of "Crawled - currently not indexed", work through that status in parallel, because the causes overlap.
- Collect the parameters. Write down every parameter your store generates: filters, sorting, variants, tracking, pagination. Your server logs or a crawler's URL list show what Google actually fetches.
- Classify each parameter. Does it change the content, only the presentation, or nothing at all? That determines which row of the table above applies.
- Check demand before you delete. For filters and variants, verify whether there are searches for them. In Search Console, the Queries view tells you what the page already earns impressions for today.
- Unify canonicals. Every indexable page names itself; every duplicate variant names the main page. Use absolute URLs and the same spelling as in the sitemap and internal links.
- Straighten internal links. Sitemap, navigation, breadcrumbs and product grids may only point at canonical URLs. When canonical and internal links contradict each other, the link often wins. The wider structure sits in the ecommerce SEO guide.
- Measure again. After two to four weeks, revisit the same reports: has the number of duplicate statuses dropped, are the right URLs indexed, do category pages rank instead of filter URLs? For individual URLs, URL Inspection shows the canonical Google selected.
Five mistakes that come up most often
- robots.txt block plus noindex. Google cannot read the noindex. Choose one.
- Every paginated page canonical to page one. You are declaring the products from page two onwards unimportant.
- Canonical to a redirected or unreachable URL. The signal gets ignored.
- Canonical to the homepage. This gets set on product pages more often than you would think, and the result is that no product page ranks at all.
- Redirect chains.
http://example.comtohttps://example.comtohttps://www.example.comto the target. Shorten every chain; one hop is enough.
What platforms already handle for you
Shopify sets canonicals for products reachable through collection paths and maintains its own robots.txt, editable through the robots.txt.liquid template. The specifics of variants, where Shopify's model differs from most systems, are covered in Shopify product variants and SEO, and the platform settings in the Shopify SEO guide. Lightspeed eCom also sets canonicals for products assigned to several categories, but the available settings differ by version, so check what your backend offers instead of following a generic click path.
In both cases the same caveat applies: automatic canonicals cover product URLs, not the filter and sort parameters your navigation or a filter app produces. That is where the volume comes from. So after every new app and every theme update, check whether new parameter URLs suddenly appear in the index.
If you want to keep an eye on this continuously, the SEO audit in ecomando lists which URLs carry a foreign canonical or stay unindexed. And when the variant pages you decided to keep are worth real visibility, give them proper product schema markup so the right URL is the one showing a price in the results.
Frequently asked questions
Does Google penalise duplicate content?
As a rule, no. When pages are near-identical, Google picks one canonical URL itself and shows only that one. A manual action is only a risk when content is copied at scale to manipulate search results.
Do colour and size variants need their own pages?
Only when people genuinely search for them, for example a model in a specific colour. Otherwise variants belong on one product page with a selector, and the variant URLs point to that page with a canonical.
Should I block filter URLs in robots.txt?
Only for real crawl-budget problems, and carefully. Google cannot read a URL blocked in robots.txt, so it will never see a canonical or a noindex on it. For individual pages, noindex is usually the better tool.
How do I find duplicate pages in my store?
In the page indexing report in Search Console, under the pages that are not indexed. Statuses like “Duplicate without user-selected canonical” and “Duplicate, Google chose different canonical than user” point at exactly these cases.
Is the same manufacturer text on many stores a problem?
It is not grounds for a penalty, but it gives Google no reason to prefer your page. Add your own sections: use cases, fit, comparison with alternatives, care, what is included.


