DEV Community

Max
Max

Posted on Originally published at storecanary.io

Shopify structured data warnings your clients can't ignore

TL;DR

  • Shopify's structured_data Liquid filter emits a fixed set of properties (@context, @id, @type, brand, category, description, image, name, offers, url). Anything outside that list shows as "missing" in Search Console forever, no matter what you change in the theme.
  • The same "Missing field" message can mean two different things. Google's Product Snippets result type barely requires anything (name plus one of review/aggregateRating/offers), while Merchant Listings requires name, image, and an Offer with price and priceCurrency above zero. A missing image is cosmetic for one result type and invalidating for the other.
  • If a property the filter does emit (name, image, offers, price, priceCurrency, description) shows up as missing on a live product, something on the store is overriding the theme's output: an empty admin field, a hand-rolled JSON-LD snippet, or a second block injected by an app.

The bug report you'll get from a client

A client forwards a Search Console screenshot: dozens of "Missing field" warnings under structured data, sitting there for months. Search any Shopify forum or theme vendor help center for this and the advice is always the same: these are warnings, not errors, ignore them.

That advice is half right, and the half that's wrong is the expensive half. Some of these warnings are the deterministic output of Shopify's own theme code and will never resolve no matter what you touch. Others mean a product is currently invalid for Google Shopping, and nobody noticed because nothing in the Shopify admin surfaces it.

This is a reference for telling the two cases apart before you spend an afternoon fixing the wrong one.

What does "invalid" actually mean in this report?

Google's rich result report docs don't grade messages by a severity label. They sort by consequence: non-critical issues sit under "Improve item appearance," critical ones under "Why items are invalid." A valid item has no critical issues; an invalid one has at least one, and it won't render as a rich result at all.

The question to answer for a client isn't "warning or error." It's whether the report marks the item invalid, which Search Console prints right next to the message.

Why does the same "missing image" warning have two different severities?

Google evaluates a product page against more than one result type, and the requirements aren't the same:

  • Product snippets require name, plus one of review, aggregateRating, or offers. image isn't in the required or recommended tables at all.
  • Merchant listings require name, image, and a nested Offer with price and priceCurrency. Google states it directly: "Unlike product snippets, merchant listing experiences require a price greater than zero."

So Missing field "image" isn't a fixed-severity message; its severity depends on which report you're reading. A merchant posted the exact failure to the Shopify community: Merchant Listing report, "1 invalid item detected," missing image, on nearly every product. The thread ends unanswered.

If you don't already know which report a given warning came from, check the merchant listings vs. product snippets split before doing anything else.

What does a stock Shopify theme actually emit?

Everything below hinges on one fact worth verifying yourself. Shopify's structured_data Liquid filter, the line most Dawn-derived themes use to generate product markup, emits a fixed key set:

@context, @id, @type, brand, category, description,
image, name, offers, url

offers: @id, @type, availability, price, priceCurrency, url
Enter fullscreen mode Exit fullscreen mode

The same reference documents that a product without variants outputs as Product, and with one or more variants as ProductGroup.

That list is the whole diagnostic. A property outside it was never going to appear, so its absence tells you nothing. A property inside it that Google reports missing means the live markup diverges from what the filter would have produced. That's a real bug.

Which warnings are safe to close as won't-fix?

These name properties the filter never emits. Expect them on a healthy store, indefinitely:

Message What it means Where to actually fix it
Missing field "priceValidUntil" No price expiry declared; Google decides on its own. Theme markup, or leave it.
Missing field "shippingDetails" / "hasMerchantReturnPolicy" Shipping/return terms aren't in page markup. Usually Merchant Center or Search Console settings, not the theme (Google reads settings before markup).
Missing field "aggregateRating" / "review" No review data on the page. A review app, not the theme.
No global identifier provided (e.g., gtin, mpn, isbn) No product identifier declared. Recommended, not required. The product record; also affects Merchant Center distribution separately.

Two of these deserve a second look before you close the ticket. Shipping and returns is the case where editing the theme changes nothing at all: Google documents an order of precedence that puts Merchant Center and Search Console settings above page markup. Identifiers are only "recommended" for rich results while still gating Merchant Center distribution, a separate system reading the same absent value on its own terms.

Which warnings mean you actually have a bug to fix?

These name properties the filter does emit. If Google reports one missing, the live page diverges from stock theme output. On merchant listings, name, image, offers, price, and priceCurrency are required, so the item is invalid:

  • Missing field "image": required for merchant listings. Either no image is assigned in the admin, or the block Google parsed isn't the theme's.
  • Missing field "name": required for both result types. The filter always emits it, so its absence means Google parsed a different block than the one the filter produced.
  • Missing field "offers" / "price" / "priceCurrency": required for merchant listings. Check variants first: the filter outputs ProductGroup when a product has variants, and the offer's position differs from the single-product shape most guides assume.
  • Missing field "description": emitted by the filter, so its absence points at an empty description field on that specific product. Recommended rather than required, so this costs appearance rather than eligibility.

The product looks completely normal in the admin: active, priced, photographed, published. The page it actually serves is missing something Google requires.

What do "invalid value" warnings mean, as opposed to "missing"?

A third family doesn't say a property is absent. It says the value present can't be used: Invalid ISO 4217 currency code, Value in field "property name" must be positive, Duplicate field "property name", Invalid enum value in property "property name", Invalid URL in field "property name".

These name a value the filter wouldn't produce on its own, since it builds every value from the product record. A malformed value points at a second source on the same page: an app block, a hand-rolled snippet left in the theme, or an old block a migration forgot to remove. Duplicate field in particular is the tell that two JSON-LD blocks are competing on one page, and Google is reading the wrong one (or both).

How do you actually check a client's store?

  1. Note which report the warning is in. Merchant Listings or Product Snippets, and whether the item is marked invalid or only flagged for appearance. Everything else follows from these two facts.
  2. Read the markup Google actually receives, not your theme source. Run the URL through the Rich Results Test and count the <script type="application/ld+json"> blocks on the page. More than one product block is a common reason the parsed markup differs from what the theme alone would output.
  3. Compare the reported property against the filter's key list above. Outside the list, it's structural and won't change. Inside it, something on the store removed it.
  4. Fix structural ones at their real source, not in the theme: shipping/returns through Merchant Center or Search Console settings, identifiers on the product record, reviews through the review app.
  5. Treat a missing required property as a broken page, not a warning. Find the block that dropped name, image, offers, price, or priceCurrency, and fix that block instead of layering a second one on top.

One caveat: if you check by viewing page source instead of the Rich Results Test, remember JS-injected markup can be present in Google's rendered view and absent from raw source (or the reverse). Raw source isn't proof either way, the same trap behind phantom noindex tags that only appear in the rendered DOM.

Why does the same warning keep reappearing after you fix it?

The won't-fix group is stable. Once you know which properties the theme never emits, those warnings stop being informative.

The actual-bug group isn't stable, which is the argument for monitoring instead of a one-time audit. A review app adds a block. A theme update replaces the file holding a hand-rolled snippet. A merchandiser removes a product's last variant, changing whether the page declares Product or ProductGroup. Someone deletes a photo during routine catalog cleanup, and merchant listings just lost a required property. None of this looks like a risky change to whoever made it; it's routine store operation, and each change can silently alter what the page declares to Google.

Nothing announces it when this happens. Search Console reports on its own crawl schedule, so today's report describes pages Google fetched some time ago. The Shopify admin has no screen at all for the shape of a page's structured data. The product looks fine everywhere you'd think to check, which is why a client can be told "warnings are optional" in one audit and be sitting on invalid merchant listings by the next.

If you build or maintain Shopify stores for clients, how do you currently catch this? Manual Rich Results Test spot-checks, a recurring Search Console export, something custom? Curious what's actually working for other agencies.

The full version of this article, with screenshots and ongoing updates, lives on the StoreCanary blog.

Top comments (0)