The SEO Bug Hiding in Plain Sight: Duplicate Product Schema on Shopify

A few weeks into a structured data cleanup on this store, I added a custom Product schema block to the theme, covering brand, offers, and pricing for every product page. It validated fine. It looked complete. And it sat there quietly breaking something I did not find out about until Search Console sent a very specific email: New Merchant listings structured data issues detected. Critical issue: Duplicate field 'brand'.

DigiStoreSG

The part that made this hard to catch

The instinct when you hear "duplicate field" is to go looking for a copy-paste mistake, two schema blocks stacked in the same file, a leftover snippet from an earlier edit. I checked the theme's Liquid source top to bottom. One Product schema block. No duplication anywhere in the code I could see.

The actual duplicate was not in the file at all. Modern Shopify themes, Dawn and its successors including Horizon, already inject a baseline Product schema automatically, at the platform level, through a mechanism called content_for_header. This is not something that shows up when you search theme source files, because it is not in any theme file. Shopify renders it directly into the page's final HTML at request time, invisible to anyone auditing the Liquid templates the normal way.

So the actual state of the page was two separate, independent Product schema blocks: Shopify's own, and mine, both declaring a brand field for the same product, on every single product page on the store. Google's structured data parser does not merge conflicting declarations gracefully, it flags them as exactly what they are, a duplicate.

Why an audit of the source code did not catch it

An earlier SEO audit on this same store had concluded the theme had zero Product schema, based on a genuinely careful review of every Liquid file in the theme. That conclusion was correct, for the files. It was wrong for the actual rendered output, because the files are not the whole story. Anything injected through content_for_header, or by an installed app, or by Shopify's own platform code, will never show up in a source audit, only in the final HTML a browser or a crawler actually receives.

The lesson generalises past this one bug: an SEO audit that only reads theme source code is auditing half the page. The other half is Shopify's own runtime output, and the only way to see it is to fetch a live rendered page and read what actually comes back.

The fix, and why it was not what I expected

The fix was smaller than the investigation. Remove the custom Product schema block entirely, and let Shopify's native version stand alone as the only source. No content was lost, since the native schema already covers the standard fields, brand, offers, price, availability, that most stores need. The custom addition had been solving a problem that did not exist.

Two other custom schema types stayed untouched: Article schema for blog posts, and BreadcrumbList and CollectionPage schema for collection pages. Shopify does not natively inject either of these, so there was no duplication risk there, confirmed by the fact that adding them earlier had produced clean validation with no Merchant Center complaints.

How to actually check for this on your own store

  • Do not trust a theme source code review alone to tell you what structured data exists on a live page. Fetch the actual rendered HTML of a real product page and search it directly for application/ld+json blocks.
  • If you find more than one Product type schema block on the same page, that is very likely this exact issue, one from your theme's custom code, one from Shopify's platform-level injection.
  • Before adding any custom Product schema to a Shopify theme, check first whether your theme is one of the modern generation, Dawn, Horizon, and their derivatives, that already handles this natively. If it does, the safer default is to leave Product schema alone entirely and only add what is not already covered.
  • Google Search Console's Merchant listings report will eventually surface this as a critical issue, but only after it has been live long enough to get crawled and flagged, which can be weeks. Checking proactively is faster than waiting for the email.

The broader point

This was not a mistake made from carelessness, it came from doing the audit thoroughly and trusting the result. The gap was not in the effort, it was in the method, checking source files instead of checking what actually gets served. Any Shopify merchant adding custom structured data is worth asking the same question before they start: is the platform already doing part of this for me, invisibly, and would I even be able to tell if it was?

More from this series

This is part of an ongoing look at running this store with AI assistance, see also managing a Shopify store with Claude and AI answer engines and llms.txt.

Frequently asked questions

Does my Shopify theme already have Product schema built in?
If it is Dawn, Horizon, or one of the other modern reference themes, very likely yes, injected at the platform level rather than in the theme's editable files. Older or heavily customised themes may not, so it is worth checking the live rendered HTML rather than assuming either way.

How do I check if my page has duplicate Product schema?
Fetch the actual rendered HTML of a live product page, not the theme source files, and search for application/ld+json script blocks with type Product. More than one is the signal.

Will duplicate schema actually hurt my SEO?
Google Search Console treats it as a critical issue specifically because, per Google's own description, critical issues can prevent a page or feature from appearing in Search results at all, not just a minor validation warning.

How long does it take for Search Console to flag this kind of issue?
It depends on Google's crawl schedule for the affected pages, which can take days to weeks. Proactively checking rendered HTML is faster than waiting for a Merchant Center notification.

Should I remove all custom structured data from my theme?
No, only the parts that duplicate what Shopify already injects natively, mainly baseline Product schema on modern themes. Schema types Shopify does not provide, like Article schema for blog content, remain safe and useful to add.