Shopify's architecture creates duplicate-content problems through collection filters, pagination, and product variants. This tutorial walks Canadian merchants through identifying and resolving these issues using Shopify's native settings, liquid template edits, and strategic canonicalization—no app bloat required.
Shopify's URL structure prioritizes customer experience over SEO hygiene. Every product can appear at multiple paths: the canonical /products/product-handle, collection-scoped URLs like /collections/winter-jackets/products/product-handle, and URLs appended with sorting or filter parameters. Shopify indexes all of these by default unless you intervene. Collections with pagination create /collections/collection-name?page=2 URLs, and variant selectors sometimes append query strings. The platform also serves both www and non-www versions until you lock down a primary domain in settings. For Canadian stores running bilingual setups—especially Quebec-focused shops—duplicate English and French product pages without proper hreflang signals compound the problem. Google interprets these as competing pages rather than language variants, splitting link equity and muddying topical authority.
Before fixing anything, confirm what Google has actually indexed. In Google Search Console, navigate to Coverage and filter by Indexed status. Export the list and scan for patterns: multiple URLs per product, ?page= parameters, ?sort_by= strings, or collection-path duplicates. Use the URL Inspection tool on a sample product to see which URL Google considers canonical—if it differs from your intended version, your signals are being ignored. Run a site:yourdomain.myshopify.com search in Google and compare results to a site:yourcustomdomain.ca search; if the myshopify.com URLs appear, your primary domain isn't properly configured. Also check for http versus https indexing. This audit reveals whether you're dealing with a few dozen duplicates or thousands, which dictates whether you can fix this yourself in a few hours or need a developer to script bulk canonical updates across liquid templates.
Shopify's default product.liquid and collection.liquid templates often lack explicit canonical tags, relying on Shopify's server-level hints—which don't always override collection-path variants. Open your theme editor and locate the product.liquid file. In the <head> section, add:
- <link rel="canonical" href="{{ shop.url }}{{ product.url }}" />
This forces all product variants and collection-scoped URLs to point back to /products/product-handle. For collections, edit collection.liquid to include:
- <link rel="canonical" href="{{ shop.url }}{{ collection.url }}" />
and strip pagination parameters so ?page=2 canonicalizes to the base collection URL. If your theme uses Liquid sections rather than monolithic templates, you may need to add these snippets to a reusable header include. Save and deploy. Test by viewing page source on a product accessed via /collections/some-category/products/product-handle—the canonical tag should point to /products/product-handle.
Collection sorting (?sort_by=price-ascending) and filter facets (?filter.p.tag=Red) generate useful browsing paths but rarely deserve independent indexing. In your collection.liquid template, add conditional meta robots tags. Use Liquid to detect query parameters: {% if collection.sort_by or collection.filters %}<meta name="robots" content="noindex,follow" />{% endif %}. This tells crawlers to follow links but not index the filtered view. If your store uses Shopify's native filter system introduced in Online Store 2.0 themes, check that the theme's collection-template snippet already handles this—many modern themes do. For older themes or custom builds, you'll need to insert this logic manually. Verify by appending a sort parameter to a collection URL and inspecting the rendered HTML. The noindex tag should appear only on parameterized URLs, not the base collection. This step alone can remove hundreds of low-value indexed pages without sacrificing crawl budget on useful category pages.
Navigate to Settings > Domains in your Shopify admin. If you see both www.yourdomain.ca and yourdomain.ca listed, or both http and https versions, Shopify isn't enforcing a single canonical domain. Click the domain you want as primary and select "Make primary." Shopify will 301-redirect all variants to that choice. Ensure your SSL certificate is active—Shopify provides free SSL, but if you transferred an existing domain recently, the cert may still be provisioning. Also confirm that your custom domain is the primary, not the myshopify.com subdomain. If customers or old links still resolve to yourstore.myshopify.com, those URLs can get indexed. Canadian stores using .ca domains should verify the domain is set to the .ca version, not a .com fallback. After making changes, allow 24-48 hours for DNS propagation, then recheck Search Console's Coverage report. Previously indexed duplicates may take weeks to drop as Google recrawls and respects the 301s.
Shopify's multi-currency and Shopify Markets features can create additional URL variants: /en-ca/products/item versus /fr-ca/products/item, or currency-appended parameters. If you serve both English and French audiences—common for Ottawa, Montreal, or nationally-focused Canadian merchants—implement hreflang tags in your theme.liquid <head>. Use Liquid to output alternate language versions: <link rel="alternate" hreflang="en-CA" href="{{ shop.url }}/en-ca{{ product.url }}" /> and <link rel="alternate" hreflang="fr-CA" href="{{ shop.url }}/fr-ca{{ product.url }}" />. Canonicalize each language version to itself, not to a single English URL, so Google indexes both but understands they're translations. For currency switchers that append ?currency=CAD, ensure these parameters don't create separate indexed pages—canonicalize parameterized URLs back to the base product URL. Test by accessing your store via a VPN set to Quebec and confirming the French URLs render proper hreflang and canonical tags.
After deploying canonical and noindex changes, return to Search Console weekly. The Coverage report's Excluded tab should show an increase in "Duplicate, submitted URL not chosen as canonical" or "Alternate page with proper canonical tag" entries—both are positive signals that Google respects your directives. Use URL Inspection on previously problematic collection-path product URLs; Google should report "User-declared canonical" pointing to /products/product-handle. If Google still selects a different URL as canonical, check for conflicting signals: redirect chains, inconsistent internal links, or missing canonical tags in AMP or mobile templates. Organic traffic to product pages should stabilize or improve as link equity consolidates on single URLs. Expect full reindexing to take 30-60 days depending on crawl frequency. If you have a large catalog—thousands of SKUs—submit an updated sitemap filtered to canonical product and collection URLs only, omitting parameterized variants. This accelerates Google's understanding of your preferred structure.
Most duplicate-content problems are solvable with theme template edits and Shopify's native settings. Apps that promise one-click fixes often just add the same canonical and noindex tags you can insert manually in liquid files. Save the monthly subscription fee unless you have a heavily customized headless setup or lack access to theme code. For standard Shopify themes, direct edits are faster and give you full control.
Plan on four to eight hours total: one to two hours auditing indexed URLs in Search Console, two to four hours editing theme templates to add canonical tags and noindex directives, and one to two hours testing and validating changes. Larger catalogs with custom filter logic or bilingual Markets configurations may require a developer's help, adding cost but not drastically extending timelines. Full reindexing by Google typically completes within 30 to 60 days after deployment.
Properly implemented canonicals and noindex tags consolidate ranking signals onto your preferred URLs, which usually stabilizes or improves rankings over time. Short-term fluctuations can occur as Google recrawls and reassigns authority, but you're correcting an underlying weakness. If you see sudden drops, verify that you didn't accidentally noindex important pages or canonicalize products to the wrong URL. The risk of inaction—diluted link equity and confused crawlers—outweighs the minimal risk of a correctly executed fix.
Canonical tags are sufficient and preferred for Shopify product duplicates. Redirecting every /collections/category/products/item path to /products/item would require thousands of individual redirects and break user experience for customers navigating via collections. Canonicals tell search engines which URL to index while preserving internal navigation. Reserve 301 redirects for retired products, merged collections, or domain migrations—not for routine collection-path variants.
Add a conditional noindex meta tag in your collection.liquid template that triggers when Shopify's paginate object is on a page beyond one. Use Liquid syntax to check the current page variable and output <meta name="robots" content="noindex,follow" /> when appropriate. Alternatively, canonicalize all paginated pages back to the base collection URL. Either approach prevents Google from treating page two onward as unique content. Most modern Shopify themes handle this natively, but older or custom themes may require manual insertion.
Yes. If you serve English and French product pages—common for Ottawa, Montreal, or national Canadian retailers—you must implement hreflang tags so Google understands the pages are translations, not duplicates. Each language version should canonicalize to itself, not to a single master URL. Without hreflang, Google may suppress one language's pages or split ranking signals between them. Also ensure that URL structures clearly differentiate languages, such as /en-ca/ and /fr-ca/ prefixes, and that internal links respect language context.