Blog · Machine readability

Product schema for AI shopping answers

Published 25 May 2026 · Updated 12 October 2026 · 8 min read

Product schema for AI shopping answers
Photograph: D Pl / unsplash

The short answer: Product schema does not buy you a slot in an AI shopping card. It makes one purchasable item machine readable when an assistant reads your page instead of your feed, and it keeps the page and the feed telling the same story about price, availability and identity. That second job is the one that quietly decides whether an engine will name a price next to your brand or skip you for a competitor whose numbers agree with themselves.

That is a narrower claim than most advice on the subject, and it is worth saying why.

The feed specification does not mention schema at all

Read OpenAI's commerce feed specification end to end and you will not find schema.org, JSON-LD or microdata named anywhere. The fields it asks for are its own: item_id, title, description, url, brand, seller_name, image_url, availability and price, nine of them required on every row, submitted as JSONL, CSV or tab delimited text. Google is equally direct about its generative surfaces. Its guidance on AI features says there is no special schema.org structured data you need to add to appear in AI Overviews or AI Mode.

So the honest version is this. Markup is not an entry ticket. It is an interpretation layer that matters in the moments when the engine has nothing better to read, and those moments are far more common than a feed-first mental model suggests. Of the two retrieval paths OpenAI documents, feed and live crawl, the feed one is open only to merchants who have submitted a feed through its programme. We cannot see how many shops have done that, and no engine publishes the figure. What we can say is that a shop which has not submitted one is readable only on the crawl path, where the page is the whole of the evidence.

What the markup is genuinely load-bearing for

Three things. The order below is our judgement from audit work, not a measured frequency: we have not counted outcomes in a way that would support a ranking, and we are not going to present one as if we had.

A price that survives chunking. Retrieval systems of this kind work on passages rather than whole pages. None of the engines publish how they split a page, so we are describing the general shape of retrieval, not any one engine's implementation. Inside a passage, context is thin. Your price lives in a styled component next to a struck-through comparison price, a loyalty price, a finance instalment and a bundle offer. In a passage, those four numbers are indistinguishable. In an Offer node with price and priceCurrency, exactly one of them is the current, active offer price, which is the phrasing Google's merchant listing documentation uses. Ambiguity is the enemy, and markup removes it cheaply.

An identity that resolves to one item. gtin, mpn and sku tell an engine that the thing on your page is the same thing in a marketplace listing, a review article and a comparison table. Without them an engine is matching on title strings, and title strings drift. This is the product-level version of the entity problem that sameAs and the identity links engines check covers at the brand level.

Agreement between your page and your feed. If you send a feed, the feed and the page are two claims about the same object. When they disagree on price or stock, you have handed the engine a reason to prefer a source it trusts more. Google states the expectation plainly for its own surfaces: do not mark up content that is not visible to readers of the page. Treat the feed as a third copy that has to match as well. We are extending a Google rule to engines that have not published one, and saying so. Product feeds for AI shopping surfaces goes into what the feed path itself demands.

Five ways Product markup fails on a real product page

These are ordered by how often they turn up in our audits, which is an impression from doing the work rather than a tallied count. Treat the order as a reading sequence, not a statistic.

The schema is rendered in the browser. The page looks fine. A fetch with scripting off returns a document with no Product node in it at all. A retrieval path that does not execute JavaScript then has nothing to read, and from outside we cannot tell which paths execute it. Google is specific about its own: its product variant documentation recommends putting Product structured data in the initial HTML, and warns that dynamically generated markup can make Shopping crawls less frequent and less reliable.

priceCurrency is missing. This is a Google rule, not a universal one. Its merchant listing documentation states that priceCurrency is required if price is specified, so the page can still qualify for a product snippet while failing to qualify as a merchant listing. One missing three letter string, and Google's richest interpretation of your page is unavailable. What the other engines do with a currency-less price, we cannot see.

One Product node carries a range. A page with eight sizes emits a single node with the cheapest price, or a "from" price, or an average. An assistant quotes a number the shopper cannot buy at, the shopper lands, bounces, and the brand gets a reputation for bait pricing it did not intend.

A GTIN that is not a GTIN. Schema.org's own gtin definition is unambiguous about the shape: 8, 12, 13 or 14 digits, with a valid GS1 check digit. Padded internal SKUs fail the check digit silently. If you have no GTIN, leave the property out and carry brand and mpn instead, rather than putting a value in a field that has a defined validation rule.

Ratings without reviews. An aggregateRating node on a page with no visible review content breaks a documented rule. Google's structured data general guidelines say not to mark up content that is not visible to readers of the page, and name fake reviews as misleading markup, with spam action as the stated consequence. Whether other engines discount a source for this, and for how long, is not something we can observe.

Variants are where most catalogues break quietly

Apparel and anything with colours is where this goes wrong. Google's model wants a ProductGroup holding the shared facts, variesBy naming the dimensions that differ, and every purchasable variant tied back with productGroupID and inProductGroupWithID. The supported variesBy values are a short list: color, size, suggestedAge, suggestedGender, material and pattern, referenced by their full schema.org URLs rather than bare words.

The failure is almost always the same. One page, one node, one price, and the variant information living entirely in a dropdown that only exists after a script runs. Every variant then inherits whatever the default option happened to be. If your variants have their own URLs, each one needs its own complete node, its own image, its own price and its own availability. Our view is that partial variant markup is worse than none, because it makes a confident claim that is wrong for most of your SKUs. That is an argument from how parsers behave, not a measured result.

Four checks, no tooling

Run these against ten of your highest-margin pages before you buy anything.

  1. Fetch the page the way a crawler would, with scripting off, and search the response for
  2. "@type":"Product". If it is absent, nothing else on this list matters yet.

  3. In the same response, confirm priceCurrency sits beside price inside offers, and
  4. that the number matches what a logged-out shopper sees.

  5. Take the gtin value and count the digits. Eight, twelve, thirteen or fourteen, or a GS1
  6. Digital Link URL built on such a string, and the check digit has to validate. Anything else should not be there.

  7. Pick one variant URL and one feed row for the same item. Compare price, availability
  8. and identifier field by field. Any mismatch is a live defect, not a tidy-up task.

The self-check extends this to ten checks across the whole site. The broader question of which markup to write first, when you cannot do everything at once, is the subject of Structured data for AI search: what to mark up first. What an assistant does with all of it once a shopping intent is detected is covered in Shopping inside ChatGPT, and what it reads.

Honest limits

This post is built almost entirely on vendor documentation, and the parts that are not are flagged as judgement. Several rules here are Google's and are cited as Google's: no other engine publishes an equivalent spec, so we do not know whether ChatGPT, Perplexity, Copilot or Grok treat a missing priceCurrency, an invalid GTIN or an unsupported rating the same way. The ordering of the failures is an impression from audit work, not a counted frequency, and we have not published a sample that would support one. We cannot tell you how heavily any engine weights Product markup against a feed row, because none of them publish that and the behaviour shifts between model releases. And we have no clean way to attribute a corrected priceCurrency to revenue, because these surfaces mostly send no usable referrer.

FAQ

Does Product schema get my products into ChatGPT shopping results? Not by itself. OpenAI's published commerce feed specification does not reference schema.org, JSON-LD or microdata anywhere, so markup is not a documented input to that feed. It matters on the crawl path, where your page is the only thing being read.

If I already send a feed, can I skip the markup? No, because the feed does not cover every retrieval path, and the two sources have to agree. A page that contradicts your feed gives an engine a reason to trust neither.

Which properties should I fix first? offers.price and offers.priceCurrency, then availability, then a real gtin or mpn. Those four carry most of the interpretive weight on a product page.

Is more markup always better? No. Markup that does not correspond to something visible on the page, such as a rating with no reviews behind it, costs you credibility across the whole domain.

Sources

All seven opened and were checked against the sentences citing them on 12 October 2026.

Related reading