Product JSON-LD for AI shopping agents
Product JSON-LD is a schema.org Product block with an Offer (price, currency, availability) in a script tag of the product page's server HTML. AI shopping agents and Google Shopping read it as the machine-readable version of the page; it must include Google's required merchant-listing fields and match the price shoppers see.
Updated · By the Medusa team
- Category
- Product data (25% of score)
- Impact
- High
- Scanner check
- Product structured data meets Google merchant listing requirements
Why AI agents need Product JSON-LD
Visible HTML tells an agent roughly what a page is about. JSON-LD tells it exactly: this is a Product, this is its GTIN, the price is 89.00, the currency is USD, it is in stock. There is no guessing which number on the page is the sale price and which is the “compare at” price.
The evidence that it’s used:
- OpenAI says shopping in ChatGPT search uses “structured metadata from first-party and third-party providers”.
- Google Merchant Center can auto-update product data from on-page structured data, and Google’s merchant listing guide warns that JavaScript-generated markup makes Shopping crawls less frequent and less reliable.
- Agents that don’t run JavaScript (see server-rendered product facts) can only read JSON-LD that’s in the initial HTML.
Google also notes structured data isn’t strictly required for its AI features (AI optimization guide), but for commerce it’s the cleanest way to hand an agent an unambiguous price and stock status.
What the scanner checks
The scanner parses every <script type="application/ld+json"> block (including @graph arrays) on up to three sampled product pages. It uses a ProductGroup if present, otherwise the first named Product, and reads Offer or AggregateOffer nodes.
| Field | Level | Accepted as |
|---|---|---|
| Product JSON-LD | Required | Product or ProductGroup node |
name, image |
Required | Non-empty |
offers |
Required | At least one Offer / AggregateOffer |
offers.price |
Required | price, lowPrice or priceSpecification.price, greater than 0 |
offers.priceCurrency |
Required | On the offer or its priceSpecification |
offers.availability |
Recommended | Any value |
| Identifier | Recommended | gtin, gtin8, gtin12, gtin13, gtin14, mpn or sku on the product or offer |
brand, description |
Recommended | Non-empty |
It also runs a price match: when a page has a single offer, the JSON-LD price must appear in the visible text (formats like 1,299.50, 1.299,50 and 1299.50 are accepted).
| Result | Condition |
|---|---|
| Pass | Every sampled page has all required and recommended fields and no price mismatch. |
| Partial | Some fields are missing or a minority of pages have a mismatch. |
| Fail | No sampled page has Product JSON-LD, or more than half have a price mismatch. |
| Inconclusive | No product page could be fetched. |
How to add complete Product JSON-LD
Render this in the server HTML of every product page, generated from the same data that renders the visible price:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Merino Crew Sweater",
"description": "Midweight merino wool crew neck sweater.",
"image": ["https://your-store.com/images/merino-crew.jpg"],
"sku": "MCS-NAVY-M",
"gtin13": "0123456789012",
"brand": { "@type": "Brand", "name": "Your Brand" },
"offers": {
"@type": "Offer",
"url": "https://your-store.com/products/merino-crew",
"price": "89.00",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
</script>
Rules that matter:
- Price uses a dot decimal and no currency symbol (
"89.00"), andpriceCurrencyis an ISO 4217 code. - Availability uses the schema.org enum (
https://schema.org/InStock,OutOfStock,PreOrder,BackOrder). - Never hardcode or cache the price separately from the visible price. A mismatched price is worse than no markup.
- Products with options should use
ProductGroupwith oneProductper variant; see product variants. - Add return and shipping policy to complete the picture; see return and shipping data.
Verify with Google’s Rich Results Test. A product URL should show a valid merchant listing with no errors.
How to fix it on Medusa
- Not shipped by default. Medusa is headless, so Product JSON-LD is the storefront’s job, and the DTC starter storefront doesn’t output it.
- Where to add it: the product page server component at
apps/storefront/src/app/[countryCode]/(main)/products/[handle]/page.tsx. It already fetches the product with calculated variant prices, so buildoffers.priceandpriceCurrencyfromvariant.calculated_priceand render a<script type="application/ld+json">tag as the Next.js JSON-LD guide recommends. - Code example: Is Medusa agent-ready? has a full snippet, including availability from inventory fields.
Common mistakes
- Injecting JSON-LD with a tag manager or client-side script, so it’s absent from the server HTML.
"price": "$89.00"or"price": "89,00"instead of"89.00".- Marking up the “compare at” price instead of the selling price.
- A price of
0on products that are “price on request”.
Sources
Frequently asked questions
- Do AI agents use structured data?
- OpenAI says ChatGPT shopping results use structured metadata from first- and third-party sources, and Google Merchant Center can update products from on-page structured data. Agents that read raw HTML can only use JSON-LD that is in the server response.
- Which Product JSON-LD fields are required?
- For Google merchant listings, name, image and offers with a price above zero and a priceCurrency are required. Availability, a GTIN/MPN/SKU, brand and description are recommended, and this check expects them too.
- Is microdata enough instead of JSON-LD?
- Google accepts microdata and RDFa, but this scanner reads only JSON-LD, which is the format Google recommends. Add a JSON-LD block to pass.
- What happens if the JSON-LD price doesn't match the page?
- Google requires markup to match visible content, and an agent quoting a stale price is worse than none. The scanner flags pages where a single-offer JSON-LD price isn't shown in the page text.
Run your store on a platform built for agentic commerce
Medusa is open-source, headless commerce with a full Store API agents can call and storefronts you control end to end.
Deploy on Medusa Cloud
Open-source commerce with a full Store API, hosted and scaled for you. Your storefront, your data model.
Storefront skills for coding agents
Teach Claude Code, Cursor or Codex to build storefronts with the patterns these checks look for.
npx skills add medusajs/medusa-agent-skills