Shopify SEO: Fixing the Technical Issues the Platform Creates
Shopify generates duplicate product and collection URLs, forces a fixed canonical pattern, and limits robots.txt control. A technical guide to auditing and fixing them.
Shopify serves most products at two URLs at once: /products/handle and /collections/collection/products/handle. The platform resolves this with an automatic canonical that points every product to the /products/handle version, which is correct — but it also generates tag pages, sort and filter parameters, and paginated collections that Shopify does not clean up for you. Most Shopify SEO work is auditing what the platform emits by default and confirming the canonical it sets is the one you actually want indexed.
The duplicate product URL problem
By default a Shopify product is reachable at its bare path (/products/leather-boots) and under every collection it belongs to (/collections/winter/products/leather-boots, /collections/sale/products/leather-boots, and so on). That is genuine duplicate content across many URLs.
Shopify handles this by writing a canonical tag on all of them pointing at the bare /products/handle. When that tag is present and correct, Google consolidates the collection-scoped copies onto one URL. The failure modes to audit:
- A theme or app strips or overwrites the canonical. Custom themes and some apps rewrite
<head>; if the canonical goes missing, Google is left to pick a representative URL from weaker signals. Crawlinx flags the absence ascanonical.missing. - Internal links point at the collection-scoped copy. Shopify's own
product_urlandwithinfilters often link products through their collection, so your internal links name a URL that differs from the canonical. Google honors a canonical far more readily when internal links agree with it. Prefer linking to the bare/products/handle. - Identical content, different URL. Where the canonical is absent or ignored, the same product body appears at multiple addresses — Crawlinx reports
duplicate.contentandduplicate.title.
The forced /products/handle canonical is a fixed Shopify pattern, not a choice. Work with it: make it the target of your internal links and your sitemap, and confirm every product actually carries it.
Faceted collections, sort, and filter parameters
Collection pages generate query parameters Shopify appends automatically: ?sort_by=price-ascending, ?page=2, and — with filters enabled — ?filter.v.price.gte= and similar. Each combination is a distinct crawlable URL serving a reordered or subset view of the same products. This is faceted navigation, the single most reported source of crawl waste.
Google's guidance is to control facets at the crawl layer rather than rely on canonical or nofollow. On Shopify your levers are:
- Block sort and filter parameters in robots.txt. Patterns like
Disallow: /*?sort_by=andDisallow: /*?filter.stop Google spending crawl budget on reordered duplicates. Confirm the parameter names your theme actually emits before blocking. - Keep pagination crawlable but self-canonical.
rel="next"/"prev"is deprecated; Google no longer uses it. Page 2 of a collection should carry a self-referencing canonical to page 2, never to page 1 — the pages are not duplicates. Do not canonicalize the whole series to the first page. - Watch parameter sprawl. Tracking and app parameters piled onto product and collection URLs inflate the crawlable surface. Crawlinx flags heavily parameterized URLs as
url.many_params.
See our crawl budget guide for how facet sprawl interacts with how often Google recrawls your real pages.
Thin tag pages and empty collections
Shopify auto-creates a listing page for every product tag (/collections/all/tag). On a store with dozens of tags this produces many near-empty or one-product pages that add nothing over the collections themselves. These are thin, low-value pages competing for the same crawl attention as your real category pages.
Audit them and either consolidate tags, noindex the tag listings, or block the tag URL pattern. Crawlinx flags pages with too little unique body content as content.thin. The same applies to empty or seasonal collections left live with no products — return them to a real state or take them down rather than leaving indexable shells.
robots.txt limits on Shopify
Shopify ships a managed robots.txt and historically did not let you edit it. Since 2021 you can override it through robots.txt.liquid in your theme, but the control is coarse: you edit a template that regenerates the file, and you cannot move the file or serve it from a custom path. Remember the platform-independent rules — robots.txt manages crawling, not indexing. A URL blocked in robots.txt can still be indexed URL-only if something links to it, and Google can never read a noindex on a blocked page because it never crawls it. To deindex a Shopify page, keep it crawlable and serve noindex; do not block it.
Shopify blocks some internal paths (/cart, /checkout, /admin, /search) by default, which is correct. Your additions should target the parameter patterns above, not whole product or collection sections.
Theme JavaScript rendering
Shopify renders product and collection pages server-side through Liquid, so the core content and links usually exist in the raw HTML — the healthy default. The risk is theme and app JavaScript that injects primary content after load: reviews widgets, dynamically loaded "related products," infinite-scroll collection grids, or variant descriptions swapped in by JS. Google renders JavaScript on a delayed second pass, and content behind scroll or click events is not seen at all.
Confirm your key content is in the server HTML, not injected. Crawlinx fetches both the raw and rendered DOM and flags body text that only appears after JavaScript runs as render.content_js_only. Products reachable only through a JS-driven infinite-scroll grid, with no crawlable paginated <a href>, can end up orphaned — links.orphan. The full mechanics are in our JavaScript SEO guide.
Sitemap behavior
Shopify generates /sitemap.xml automatically as an index pointing to child sitemaps for products, collections, pages, and blogs, and updates it as your catalog changes. You cannot edit it directly. Two things to verify: that URLs listed in it are indexable (a listed URL carrying noindex or a non-200 status contradicts the sitemap), and that products you have hidden or unpublished have actually dropped out. Crawlinx flags non-indexable URLs present in a sitemap as sitemap.non_indexable.
Takeaway
Shopify's SEO problems are structural and predictable: dual product URLs resolved by a forced canonical, auto-generated tag pages, and sort or filter parameters that multiply crawlable duplicates. The platform sets a sensible default canonical — your job is to make internal links, sitemap, and crawl rules agree with it, block parameter sprawl in the theme robots.txt, prune thin tag pages, and confirm theme JavaScript is not hiding content from the crawler. Run the full technical SEO audit checklist against a live store to see which of these the platform left for you.
Audit your own site — free
77 checks, internal PageRank, render-diff. No signup, results in ~30s.