Product structured data for AI shopping agents: the complete JSON-LD guide
Valid JSON-LD for Product, Offer, AggregateRating, MerchantReturnPolicy, OfferShippingDetails and ProductGroup, and how AI shopping agents use it.
By the ConversionVector teamUpdated 16 min read
Contents
Direct answer: AI shopping agents compare offers on facts: price, currency, availability, identifiers, delivery cost and time, returns terms, variants and ratings. Product structured data in JSON-LD is the most reliable way to give them those facts in the HTML your server sends, without the agent having to guess from your layout. Most retailers mark up the basics and stop. In our Agent Commerce Index (Q4 2026), 92% of the 225 scored retailers failed our check for shipping cost in structured data and 84% failed the one for returns terms. The examples below close those gaps and follow schema.org and Google's merchant listing documentation.
This guide is for developers and SEO leads. It covers what to mark up, four copy-ready examples (a UK product page, a US product page, a variant group and store-wide policies), the rules that matter more than the markup, and how to test what an agent actually receives.
Last verified: 25 October 2026 against schema.org, Google Search Central, OpenAI's help pages and Shopify's and WooCommerce's own documentation and code. Google updates these pages often, so every fact below names its source.
How agents actually use product data
The vendors do not publish exactly how their assistants parse a page, so the honest position is this:
- Google documents it. Product and Offer markup, including shipping and returns, can make a page eligible for Google's merchant listing experiences, alongside Merchant Center feeds. For Google AI Mode and Gemini, Shopify's Help Center says "Product discovery for Google AI Mode and Gemini is powered by Google Merchant Center" (Shopify Help Center), so keep your markup and your Merchant Center data in step.
- OpenAI describes the inputs. OpenAI's help page says ChatGPT considers "structured metadata from first-party and third-party providers (e.g., price, product description)" when choosing products, and ranks merchants "based on factors like availability, price, quality, and whether they are the maker or primary seller of that item" (OpenAI Help Center). On its merchants page, OpenAI answers "Do I need a product feed if ChatGPT already crawls my site?" with "No, but feeds give you greater control". So for a crawled site, what is on your pages is one of the inputs.
- Page-fetching agents read raw HTML. An agent that fetches your page without running JavaScript sees only what your server sends. JSON-LD in that HTML is unambiguous. A price assembled by a script after load may never reach it. Our spec checks this directly (LEG-08: product name and price are in the HTML an agent receives).
- Agents compare, so gaps cost you. When an assistant chooses between two shops selling the same item, the one that states free delivery in two days and a 30-day free returns window gives it something to say. A shop whose terms sit only in prose on a policy page makes the agent work harder to find them.
Structured data does not guarantee a recommendation. It removes some of the most common reasons an agent cannot make one.
What to mark up, and how the Index scores it
Our open Agent Conversion Score specification (v0.6, CC BY 4.0) checks these properties. The right-hand column shows the share of the 225 scored Index retailers failing that check, where it was among the ten most common failures in the published Index data file. The Index was scored on spec v0.5; these checks are unchanged in v0.6.
| What | schema.org property | Spec check | Index retailers failing |
|---|---|---|---|
| Product markup present | Product | LEG-01 | |
| Numeric price | Offer.price | LEG-02 (failing caps the score at 50) | |
| Currency | Offer.priceCurrency | LEG-03 | |
| Availability | Offer.availability | LEG-04 | |
| Identifiers | gtin, gtin13, mpn, sku | LEG-05 | 47% |
| Brand | brand | LEG-06 | |
| Name and price in the server-rendered HTML | (page HTML) | LEG-08 | |
| Structured price matches the page | Offer.price vs visible price | OFF-01 | |
| Promotions expressed structurally | priceSpecification, validThrough | OFF-03 | 44% |
| Shipping cost | OfferShippingDetails.shippingRate | OFF-04 | 92% |
| Returns terms | MerchantReturnPolicy | OFF-06 | 84% |
| Variants | ProductGroup, hasVariant | TRX-09 | |
| Payment methods declared | acceptedPaymentMethod or a UCP profile | TRX-08 | 46% |
| Ratings with a count | AggregateRating.reviewCount | TRU-01 | 64% |
| Business identity | Organization with sameAs, contact details | LEG-07, TRU-04, TRU-05 |
Example 1: a complete product page (UK store)
A single-variant product with price, identifiers, brand, rating, free UK delivery in one to four days, and a 30-day free returns window. The seller points to the Organization block in Example 4 by @id.
{
"@context": "https://schema.org",
"@type": "Product",
"@id": "https://www.example.co.uk/products/trail-jacket#product",
"name": "Ridgeline Waterproof Trail Jacket",
"description": "Three-layer waterproof jacket, 20,000 mm hydrostatic head, 380 g, recycled nylon shell.",
"url": "https://www.example.co.uk/products/trail-jacket",
"image": [
"https://www.example.co.uk/images/trail-jacket-1x1.jpg",
"https://www.example.co.uk/images/trail-jacket-4x3.jpg"
],
"sku": "RTJ-200-NVY-M",
"gtin13": "5012345678900",
"mpn": "RTJ200",
"brand": { "@type": "Brand", "name": "Ridgeline" },
"material": "Recycled nylon",
"color": "Navy",
"size": "M",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": 4.6,
"reviewCount": 212,
"bestRating": 5
},
"offers": {
"@type": "Offer",
"url": "https://www.example.co.uk/products/trail-jacket",
"price": 149.00,
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": { "@id": "https://www.example.co.uk/#organization" },
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "GBP" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "GB" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" }
}
},
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn"
}
}
}
Why each part is there:
gtin13,mpnandsku. Identifiers let an agent match your listing to the same product elsewhere and compare like with like. Google recommends using "the most specific GTIN that applies to your product" in numerical form. Use real GTINs from your supplier or your GS1 allocation. The ones in these examples are placeholders with valid check digits.priceas a number,priceCurrencyas an ISO 4217 code. Write149.00, not"£149". Google's merchant listings require a price greater than zero. A missing numeric price fails LEG-02, which caps our score at 50.availabilityas a schema.org URL. Usehttps://schema.org/InStock,OutOfStock,PreOrder,BackOrderor another value Google lists. Google says not to specify more than one value, and keep it current.shippingDetailswithdeliveryTime. Google's format splits delivery intohandlingTime(days before dispatch) andtransitTime(days in transit), each aQuantitativeValuewith whole-numberminValueandmaxValueandunitCodeDAY. Google allows oneshippingRateperOfferShippingDetails, in the same currency as the offer.hasMerchantReturnPolicy. A finite window withmerchantReturnDays(counted from delivery), the return method and the fee model. Use the window you actually offer. In the UK and EU, consumers buying goods at a distance generally have a 14-day cancellation period from delivery (Consumer Contracts Regulations 2013, reg. 30; Directive 2011/83/EU, Article 9), with exceptions, so a 30-day window is a commercial choice on top of it. This is not legal advice.aggregateRatingwithreviewCount. Google's review snippet guidelines say that if you use AggregateRating, "users should be able to see that aggregate rating on the page", and rule out fake or undisclosed incentivised reviews and ratings aggregated from other websites.
Google recommends putting a standard return and shipping policy under Organization (Example 4) and using Offer-level markup only to override it. We still show the terms on the Offer here for two reasons. First, an agent that reads a single product page sees only that page. Second, our score's OFF-04 and OFF-06 checks look for a shipping rate and a return policy on the product page's Offer. If your terms are store-wide, you can do both: keep the full policy on Organization and repeat the short Offer-level version, generated from the same source so they never disagree.
Example 2: the same product for a US store
US prices are normally shown before sales tax, so the structured price is pre-tax too. This example adds a second shipping destination (Canada) with a paid rate, and a return policy that charges a return shipping fee.
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Ridgeline Waterproof Trail Jacket",
"sku": "RTJ-200-NVY-M",
"gtin12": "012345678905",
"brand": { "@type": "Brand", "name": "Ridgeline" },
"image": "https://www.example.com/images/trail-jacket.jpg",
"offers": {
"@type": "Offer",
"url": "https://www.example.com/products/trail-jacket",
"price": 179.00,
"priceCurrency": "USD",
"priceValidUntil": "2026-11-30",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"shippingDetails": [
{
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "USD" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 3, "maxValue": 5, "unitCode": "DAY" }
}
},
{
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 14.95, "currency": "USD" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "CA" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 5, "maxValue": 8, "unitCode": "DAY" }
}
}
],
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "US",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 60,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/ReturnShippingFees",
"returnShippingFeesAmount": { "@type": "MonetaryAmount", "value": 6.95, "currency": "USD" }
}
}
}
Points that differ by market:
- Tax display. Mark up the price the shopper sees. In the UK, EU and Australia that is normally tax-inclusive. In the US and Canada it is normally before sales tax, with tax added at checkout.
- One
OfferShippingDetailsper destination or rate. Google allows oneshippingRateperOfferShippingDetailsand says to "specify multiple OfferShippingDetail properties" to indicate multiple rates. Agents comparing "delivered by Friday" need the destination to match the shopper. - One currency per URL. If you sell in several currencies, Google asks for "a distinct URL per currency". A currency switcher that rewrites the visible price on one URL, while the markup stays in one currency, is a common cause of price mismatches.
priceValidUntil. Useful when a price is time-limited. Google warns that "your listing may not display if thepriceValidUntilproperty indicates a past date", so keep it in the future or remove it.- Return fees.
ReturnShippingFeeswithreturnShippingFeesAmountstates what a return costs, which agents can compare directly. Google says to leave out the amount when you useFreeReturnorReturnFeesCustomerResponsibility.
Example 3: variants with ProductGroup
For a product sold in sizes and colours, Google documents ProductGroup with productGroupID, variesBy and hasVariant, and recommends nesting the variants under the group as "the most compact and natural representation". Shared properties such as brand sit on the group. Each variant is a Product with its own SKU or GTIN, URL, price and availability. This example also shows a sale price with a strikethrough.
{
"@context": "https://schema.org",
"@type": "ProductGroup",
"name": "Ridgeline Waterproof Trail Jacket",
"description": "Three-layer waterproof jacket in three colours and five sizes.",
"url": "https://www.example.co.uk/products/trail-jacket",
"brand": { "@type": "Brand", "name": "Ridgeline" },
"productGroupID": "RTJ200",
"variesBy": ["https://schema.org/size", "https://schema.org/color"],
"hasVariant": [
{
"@type": "Product",
"sku": "RTJ-200-NVY-M",
"gtin13": "5012345678900",
"name": "Ridgeline Waterproof Trail Jacket, Navy, M",
"image": "https://www.example.co.uk/images/trail-jacket-navy.jpg",
"color": "Navy",
"size": "M",
"offers": {
"@type": "Offer",
"url": "https://www.example.co.uk/products/trail-jacket?colour=navy&size=m",
"price": 149.00,
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
},
{
"@type": "Product",
"sku": "RTJ-200-NVY-L",
"gtin13": "5012345678917",
"name": "Ridgeline Waterproof Trail Jacket, Navy, L",
"image": "https://www.example.co.uk/images/trail-jacket-navy.jpg",
"color": "Navy",
"size": "L",
"offers": {
"@type": "Offer",
"url": "https://www.example.co.uk/products/trail-jacket?colour=navy&size=l",
"price": 149.00,
"priceCurrency": "GBP",
"availability": "https://schema.org/OutOfStock",
"itemCondition": "https://schema.org/NewCondition"
}
},
{
"@type": "Product",
"sku": "RTJ-200-OLV-M",
"gtin13": "5012345678924",
"name": "Ridgeline Waterproof Trail Jacket, Olive, M",
"image": "https://www.example.co.uk/images/trail-jacket-olive.jpg",
"color": "Olive",
"size": "M",
"offers": {
"@type": "Offer",
"url": "https://www.example.co.uk/products/trail-jacket?colour=olive&size=m",
"price": 119.00,
"priceCurrency": "GBP",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"priceType": "https://schema.org/StrikethroughPrice",
"price": 149.00,
"priceCurrency": "GBP"
},
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
]
}
How this helps an agent:
- It can pick the right variant. A shopper asking for "navy, size L" gets a correct answer: that variant is out of stock, while navy M is available.
- Each variant has its own URL. Google's guidelines require that the site can "preselect each variant directly with a distinct URL", showing the right image, price and availability. An agent can then link or navigate straight to the chosen size and colour. Our spec checks that variants are expressed structurally (TRX-09).
- Promotions are explicit. Google's merchant listing docs say a strikethrough price sets "the
priceTypeproperty toStrikethroughPrice" inside a price specification, and that you should not mark the active price withpriceType. The active price stays on the Offer. This is the kind of structured promotion OFF-03 looks for, a check 44% of Index retailers failed. If the sale has an end date, addvalidFromandvalidThrough(orpriceValidUntilon the Offer).
If your variant picker is built in JavaScript and the page HTML carries only one variant, the agent sees one size and one price. Generate the full group on the server.
Example 4: Organization identity and store-wide policies
Put this on your homepage or your policy page, or in a site-wide template. It establishes who the seller is (spec checks LEG-07, TRU-04, TRU-05) and carries a store-wide return policy and shipping service, so the standard terms live in one place.
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://www.example.co.uk/#organization",
"name": "Ridgeline Outdoor",
"url": "https://www.example.co.uk/",
"logo": "https://www.example.co.uk/logo.png",
"email": "help@example.co.uk",
"telephone": "+44-20-7946-0000",
"address": {
"@type": "PostalAddress",
"streetAddress": "1 Example Street",
"addressLocality": "Leeds",
"postalCode": "LS1 1AA",
"addressCountry": "GB"
},
"sameAs": [
"https://www.instagram.com/example",
"https://www.linkedin.com/company/example"
],
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": ["GB", "IE"],
"returnPolicyCountry": "GB",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn",
"refundType": "https://schema.org/FullRefund",
"merchantReturnLink": "https://www.example.co.uk/returns"
},
"hasShippingService": {
"@type": "ShippingService",
"name": "Standard UK delivery",
"shippingConditions": {
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "GB" },
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "GBP" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 3, "unitCode": "DAY" }
}
}
}
}
OnlineStore is a subtype of Organization, and it is the type Google uses in its own return policy example. Google's return policy documentation says a standard policy "can be specified using the MerchantReturnPolicy structured data type nested under the Organization structured data type using the hasMerchantReturnPolicy property", with product-level policies under Offer as overrides. Store-wide shipping works the same way through hasShippingService, which Google documents in its shipping policy guide, including order-value thresholds, cut-off times and destinations you do not ship to.
For Google specifically, policies set in several places follow an order of precedence. The merchant listing documentation lists it from strongest to weakest: product-level feeds submitted in Merchant Center, settings in the Content API for Shopping, settings in Merchant Center or Search Console, product-level markup, then Organization-level markup. If you set returns in Merchant Center, Google uses those. Other agents only see what is on your page, so keep the markup in step with Merchant Center.
Rules that matter more than the markup
Match the page exactly
The structured price must equal the price an agent finds in the HTML it receives (spec check OFF-01). Common causes of a mismatch:
- JSON-LD cached at build time while the price changed.
- A currency switcher that changes the visible price but not the markup.
- Promotions applied by a script after load.
- A VAT-exclusive figure in the markup on a VAT-inclusive UK or EU page.
A mismatch can be worse than no markup, because the agent may quote the wrong figure with confidence. In the UK, misleading price information can also be a consumer-law issue: section 226 of the Digital Markets, Competition and Consumers Act 2024 covers "the provision of false or misleading information relating to a product". This is not legal advice.
Serve it in the HTML
Render JSON-LD on the server, inside the initial HTML. Google itself recommends "putting Product structured data in the initial HTML for best results", and warns that JavaScript-generated markup "can make Shopping crawls less frequent and less reliable", which matters for fast-changing price and availability (merchant listing guidelines). Agents that fetch pages without a browser may not see script-injected markup at all. Tag-manager JSON-LD is the riskiest form.
Fetching and browsing agents can experience the same store very differently. In our Index, of the 116 stores where we could run the basket test, 8 let a page-fetching agent reach checkout while 96 let in an agent that browses like a person. That test measures checkout access rather than markup, but it shows why you should check what a non-browser fetch receives.
One product, one set of facts
Do not publish conflicting Product blocks from your theme, a reviews app and an SEO plugin on the same page. Choose one source and remove the others. Then check that the name, brand and price agree with your feed and with Merchant Center.
Keep it honest
Mark up only what is on the page and true. Google's general structured data guidelines say "Don't mark up content that is not visible to readers of the page". That means no ratings from reviews you do not display, no InStock on items you cannot ship, and no free-delivery claims that exclude the shopper's region.
Testing your markup
- Validate the syntax with the Schema Markup Validator, schema.org's general validator.
- Check Google eligibility with the Rich Results Test. Its supported types include merchant listings, product snippets, return policy and shipping policies. Google's merchant listing guide tells you to validate with it, then deploy a few pages and check them with the URL Inspection tool.
- Check what a fetching agent receives. Fetch the page without a browser and confirm that the JSON-LD and the visible price are in the raw HTML:
curl -s -A "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot" \
https://www.example.co.uk/products/trail-jacket \
| grep -o '<script type="application/ld+json">[^<]*' | head -c 2000
If this returns nothing while your browser shows the markup, it is being injected by script. If it returns a 403 or a challenge page, the problem is access, not markup: see are you blocking AI shopping agents? or try the AI access checker.
- Run the free score. The Agent Conversion Score fetches your homepage and up to five product pages as a real browser and as GPTBot, ChatGPT-User, PerplexityBot and ClaudeBot, and runs the 49 checks in the spec. You get a score out of 100 and a grade on screen; with your email you also get your blocker and your highest-value fixes.
Platform notes
- Shopify: Shopify's
structured_dataLiquid filter outputs a schema.orgProductfor products without variants and aProductGroupfor products with variants. The output example in Shopify's documentation carries price, currency and availability but no shipping or returns properties, so check what your theme emits before adding an app, to avoid duplicate blocks. - WooCommerce: the core
WC_Structured_Dataclass outputs Product markup with an Offer (anAggregateOfferprice range for variable products whose variations differ in price) and passes each offer through thewoocommerce_structured_data_product_offerfilter. In the current code it does not addshippingDetailsor an Offer-level return policy; it emits a link-onlyMerchantReturnPolicyunderOnlineStoreon the refund and returns page. Shipping, Offer-level returns and a full variant group need a template change, that filter, or a plugin. - Adobe Commerce, BigCommerce and Salesforce Commerce Cloud: output varies by theme and version. Check the server-rendered HTML rather than the admin settings.
- Any platform: if your platform cannot generate this markup from your catalogue, our Hosted Agent Layer (currently a waitlist product, piloting on WooCommerce and BigCommerce) is designed to generate Product, Offer, Organization and AggregateRating JSON-LD from its offer graph and serve it by tag or at the edge.
Common mistakes
- Price as a string with a symbol (
"£149") instead of a number pluspriceCurrency. - Availability left at InStock for out-of-stock variants.
- Shipping and returns only on a policy page. This is the most common product-data gap in the Index (92% and 84% failing).
- One Product block for a product with twenty variants.
- Markup injected by a tag manager that page-fetching agents never see.
- Duplicate, conflicting Product blocks from several plugins.
- Ratings with no
reviewCount, or ratings from reviews not shown on the page. - An expired
priceValidUntilleft on a live price. - Copying a US example onto a UK page (pre-tax price, USD, US shipping destination), or the reverse.
For the wider picture of what is live in agentic commerce and where structured data fits among the fixes, see agentic commerce for retailers. To see how the 225 Index retailers were measured, read the Agent Commerce Index explained.
Sources
- schema.org, Product, ProductGroup, MerchantReturnPolicy and hasShippingService, read 25 October 2026
- Google Search Central, Merchant listing (Product, Offer) structured data, last updated 8 September 2026, read 25 October 2026
- Google Search Central, Product variant structured data, Merchant return policy, Merchant shipping policy, Review snippet and General structured data guidelines, read 25 October 2026
- Google Search Console Help, Rich Results Test, read 25 October 2026
- OpenAI Help Center, Shopping with ChatGPT Search, and OpenAI, ChatGPT merchants, read 25 October 2026
- Shopify Help Center, Google AI Mode and Gemini (agentic storefronts), and Shopify.dev, structured_data filter, read 25 October 2026
- WooCommerce, class-wc-structured-data.php on GitHub (trunk), read 25 October 2026
- Consumer Contracts (Information, Cancellation and Additional Charges) Regulations 2013, regulation 30 and Digital Markets, Competition and Consumers Act 2024, section 226 (legislation.gov.uk); Directive 2011/83/EU, Article 9
- ConversionVector, Agent Commerce Index Q4 2026 and its data file (CC BY 4.0, scored on spec v0.5), and Agent Conversion Score specification v0.6
Examples are valid JSON and follow schema.org and Google's merchant listing, variant, return policy and shipping policy documentation as of 25 October 2026. Brand names, identifiers and addresses in the examples are placeholders.
Questions
- Do AI assistants like ChatGPT read JSON-LD?
- The assistants do not publish exactly how they parse pages. What is documented is that Google uses Product and Offer structured data for merchant listings, and that OpenAI says ChatGPT selects products using structured metadata such as price and ranks merchants on factors like availability and price. JSON-LD in the HTML your server sends is the most reliable way to give any agent those facts without it having to guess from your layout.
- What is the minimum product structured data a store needs?
- A Product with name, image, brand and an identifier (GTIN, MPN or SKU), and an Offer with a numeric price, priceCurrency and availability. Google's merchant listings require name, image and an Offer with a price above zero and a currency. In our scoring spec, a missing numeric Offer price (LEG-02) caps the whole score at 50.
- Should I put returns and shipping in structured data if they are already on a policy page?
- Yes. In the Agent Commerce Index Q4 2026, 92% of the 225 scored retailers failed the check for shipping cost in structured data and 84% failed the one for returns terms. Google recommends a store-wide policy under Organization, with Offer-level markup only to override it. Agents that read one product page only see what is on that page, so state the terms on the Offer as well.
- How should I mark up size and colour variants?
- Use a ProductGroup with productGroupID, variesBy and hasVariant, with one Product and Offer per variant carrying its own SKU or GTIN, price and availability. Google also requires that each variant can be preselected with its own URL. That lets an agent pick the right size and see what is in stock.
- Should the price include VAT or sales tax?
- Use the price the shopper sees on the page. In the UK and EU that is normally VAT-inclusive; in the US and Canada it is normally before sales tax. The structured price must match the visible price, or agents may quote the wrong figure.
Published . Last updated . More in Structured data and product feeds and the guide library.
Related guides
- Agent readiness
Are you blocking AI shopping agents? A complete guide to robots.txt, CDN and WAF
Which AI crawlers and shopping agents to allow, the exact user agents, Cloudflare, Akamai, Fastly and AWS WAF settings, and how to test your store.
Updated · 15 min read
- Agentic commerce
Agentic commerce for retailers: what's live, what's hype and what to fix first
What AI shopping agents can do for retailers in the US, UK, EU, Canada and Australia as of October 2026, and the fixes to make first.
Updated · 14 min read
- Agent readiness
The Agent Commerce Index explained: how 225 UK and US retailers score for AI agents
How the Agent Commerce Index Q4 2026 scored 225 retailers for AI agents, what it found by sector, the most common failures and how to compare your store.
Updated · 11 min read