Short answer. Shopify serves every product at two URLs β /products/handle and /collections/name/products/handle β with the same content on both. When your theme links to the collection version everywhere but your canonical and sitemap point at the clean one, Google gets contradictory signals and may index the collection URL instead. Search Console reports that as "Duplicate, Google chose different canonical than user".
Nothing broke. The product is active, priced, in stock and crawlable. But in Search Console's Page indexing report a growing pile of your product URLs sits under a status you did not ask for, and the Google-selected canonical is not the URL you have been optimising, submitting and paying for clicks on.
What Search Console is actually telling you
Two statuses describe this, and they are not the same. Google's page indexing report documentation defines "Duplicate, Google chose different canonical than user" as a page that "is marked as canonical for a set of pages, but Google thinks another URL makes a better canonical" β and has indexed that other URL instead of yours. "Duplicate without user-selected canonical" is the version where your page declared nothing at all, so Google picked for you.
A third status, "Alternate page with proper canonical tag", is the healthy outcome: the collection-scoped copy defers to the clean product URL and Google agrees. If your collection URLs sit there, nothing here needs fixing.
How to confirm it on your own store in five minutes
- Open Search Console β Indexing β Pages and look for "Duplicate, Google chose different canonical than user". Open it and read the sample URLs: if they are
/products/β¦, your clean URLs are the ones losing. - Run one of those URLs through URL Inspection and compare User-declared canonical with Google-selected canonical. Google states plainly that it "might select the user-declared canonical, but sometimes Google might choose another URL that it considers a better canonical example", and that there is no guarantee it will choose yours.
- Search
site:yourstore.com inurl:/collections/ inurl:/products/in Google. Every result is a collection-scoped product URL that Google has kept in its index. - Open a collection page, click a product, and read the address bar. If it says
/collections/β¦/products/β¦, that is the URL your whole site is voting for. View source on it and read the<link rel="canonical">href: it should point at the clean/products/handleURL, and carry no query string.
Want this checked across your whole catalogue instead of five products? We read the canonical target of every product page in your public catalogue and flag the ones pointing somewhere they should not β read-only, no admin access, about 2 minutes. β free scan
Where the contradiction comes from
Your theme links to the collection version of every product. This is the usual root cause, and it is not a bug β it is a documented Liquid feature. Shopify's own reference for the within filter shows it turning /products/draught-of-immortality into /collections/sale-potions/products/draught-of-immortality, and warns on the same page that "a standard product page and a product page in the context of a collection have the same content on separate URLs". Most themes call it in the product card snippet, so every collection page and every "related products" block links away from the URL you declared.
And internal links are a signal Google weighs. Its canonicalization documentation calls rel="canonical" "a strong signal that the specified URL should become canonical", a sitemap entry only "a weak signal", and then tells you to "link to the canonical URL rather than a duplicate URL". A store that declares one URL and links to another from a thousand places has cast a thousand votes against its own declaration.
A canonical carrying a query parameter. If the tag on a product page resolves to something like /products/handle?variant=123, each variant is declaring itself the canonical version of the product, which is the opposite of consolidating them.
A canonical pointing somewhere it should not. Apps and theme edits that inject their own head markup can leave a product declaring a different product, or the .myshopify.com domain instead of your live one. Two canonical tags on one page is the worst case: contradictory declarations Google can discard entirely, leaving it to choose alone. Across the 822 Shopify stores we have scanned end to end, we read the canonical target of every product page, precisely because nothing in the admin displays it.
The fix
The goal is not to add a stronger tag. It is to stop the site contradicting itself, so all four things say the same URL:
- The internal links. In the theme's product card and related-product snippets, use
{{ product.url }}rather than{{ product.url | within: collection }}. This is the change that moves the needle, because it is the signal you were losing on volume. - The canonical tag. One tag per page, resolving to the clean
/products/handleURL, with no query string and no second tag added by an app. - The sitemap. Open
/sitemap_products_1.xmland confirm the form of the URL listed there matches what the canonical declares. - The feed. Google's specification for the
linkattribute requires your product's landing page on your verified domain. Submitting the collection-scoped URL while canonicalising to the clean one hands Google one more contradiction to resolve.
Then re-inspect one affected URL and request indexing. Canonical selection is recalculated on Google's own schedule, so expect the status to change over days, not minutes.
Why this one comes back
The edit is small. Keeping it is not. Product cards are theme code, so a theme update or a new theme can reintroduce within: collection without anyone deciding to; any app with theme access can add a second canonical tag to your head; and every new collection mints a fresh set of duplicate URLs for products that were previously fine. And because the choice rests on signals across your whole site rather than on the tag alone, a change you make somewhere else β a new navigation, a new app, a bulk import β can move it back without anyone touching the product.
It is the same shape as the phantom noindex and the product that quietly leaves the sitemap: the admin shows a healthy product while the disagreement lives between your theme, your feed and Google's index. Something has to read the live pages and compare.
Next in this cluster
Not sure which of your product URLs Google actually kept?
Scan my store for free