Someone just asked ChatGPT for the best pour-over dripper under $50. Your product fits perfectly. It didn't come up.
That's the problem this guide solves. You're going to write product schema AI assistants can actually read: Product and Offer markup carrying your price, your stock, your reviews, and your identifiers, so the assistant cites your page instead of guessing at it. This is for ecommerce and product-led teams who own their product pages, whether that's Shopify, WooCommerce, or a headless build. By the end you'll have a working template, a validation loop, and a way to tell whether it's landing.
Here's the good news: product schema for recommendations is a data problem, not a content problem. Data problems have fixed answers, and you can finish this one.
Why AI assistants skip your products
AI shopping surfaces build answers from three inputs: the structured data on your page, your merchant feeds, and partner feed programs. When your product structured data is missing or wrong, the assistant doesn't give up. It falls back on whatever text it can scrape off the page, which is usually incomplete and out of sync with your live offer.
Put another way, AI shopping schema isn't a ranking trick. It's the difference between an assistant reading your offer and an assistant paraphrasing your marketing copy.
That's how you end up recommended at last month's price. Or listed as out of stock when you're not. Or summarized so generically that the shopper never gets a link back to you.
The shift is real and it's already priced in. Surveys of shoppers heading into 2026 show most of them plan to use AI assistants somewhere in their buying process, and analysts tracking large retailers have watched AI assistant referrals climb into meaningful share of total traffic. Early conversion data on that traffic looks healthy too: shoppers arriving from an LLM tend to convert at a better rate than non-branded organic search, likely because the assistant already did the filtering.
So the question isn't whether to bother. It's which fields to fill in first.
Step 1: Audit which product URLs already emit schema
Start with what you have. You probably have more than you think.
Pull your full list of product URLs from your sitemap. For a sample of them (twenty is plenty to start), fetch the page and look for a <script type="application/ld+json"> block containing "@type": "Product". Do this on the raw HTML response, not in your browser's inspector. This distinction matters more than anything else in this step, and I'll explain why in a moment.
Log four things per URL: does a Product block exist, does it have an identifier, does it have a nested Offer with price and availability, and does the page return a clean 200. That's your product structured data baseline, and it's the only number you need before you start fixing anything.
You'll know this step is done when you can say what percentage of your catalog emits valid Product markup, and you've spotted the pattern behind the gaps. The gaps are almost never random. They cluster by template: your main PDP template is fine, your bundles are empty, your clearance pages never got the update.
Where people go wrong: checking in the browser inspector. Your inspector shows the DOM after JavaScript has run. Most crawlers and nearly all AI assistants don't execute client-side JavaScript, so a JSON-LD block injected after hydration is invisible to them and perfectly visible to you. Check the server response. If you're on a JavaScript-heavy stack, this one check explains most missing citations.
Step 2: Write the product schema AI assistants can parse
This is the core of the work, and it's smaller than it looks. Everything downstream is a variation on this block.
Google requires four things on Product for rich-result eligibility: name, image, description, and at least one identifier from sku, gtin, or mpn. The nested Offer requires price, priceCurrency, and availability. That's it for the baseline. Everything else earns you a richer treatment.
Here's a complete single-SKU block with the policy fields already layered in:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Artisan Pour-Over Coffee Dripper",
"image": [
"https://example.com/dripper-front-1200x1200.jpg",
"https://example.com/dripper-side-1200x1200.jpg"
],
"description": "Single-cup pour-over coffee dripper with a stainless-steel filter, designed for even extraction over a 3-minute brew.",
"sku": "DPR-001",
"gtin13": "0860001530017",
"mpn": "DPR-001-MP",
"brand": {
"@type": "Brand",
"name": "Acme Brew Co."
},
"offers": {
"@type": "Offer",
"url": "https://example.com/p/artisan-pour-over-dripper",
"priceCurrency": "USD",
"price": "48.00",
"priceValidUntil": "2026-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": "Acme Brew Co.",
"url": "https://example.com"
},
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn"
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "241",
"bestRating": "5",
"worstRating": "1"
}
}
A few details that trip people up:
price is a numeric string. No currency symbol, no thousands separators. The currency lives in priceCurrency as an ISO 4217 code.
availability takes the full schema.org enum URL, not a word. https://schema.org/InStock, not InStock. The other values you'll actually use are OutOfStock, PreOrder, BackOrder, and Discontinued.
offers.url should be your canonical PDP. This is the link an assistant cites. Leave it out and a recommendation engine can still describe your product but has nowhere to send the shopper.
image needs to be crawlable, HTTPS, and at least 100x100. Bigger is better for shopping cards. If your CDN variant is hotlink-protected or returns a 403 to a bot, the listing can get dropped over an image you thought was fine.
You'll know this step is done when one product page carries a block like this in the server HTML and the values match what a shopper sees on screen.
Step 3: Populate your identifier stack
Identifiers are how an assistant knows your dripper and a marketplace's listing of your dripper are the same object. Get these right and you get consolidated, accurate recommendations. Get them wrong and you're a stranger in your own category.
Work the stack in order:
sku: your internal stock code. Always populate this. It's the backstop.gtin(or the specificgtin8,gtin12,gtin13,gtin14): only when you have a real manufacturer barcode.mpn: the manufacturer-assigned part number, when one exists.
Populate every identifier you legitimately have. Multiple identifiers on one Product is normal and helpful.
Selling private-label or unbranded goods? No GTIN exists for your products, and that's completely fine. It isn't a penalty. Use mpn plus a stable internal sku and move on.
Where people go wrong: inventing identifiers to fill the field. A fabricated GTIN doesn't resolve to anything, and mismatched identifiers are a trust problem, not a blank one. An empty field is better than a wrong one.
Step 4: Layer on the fields Google needs for merchant listings
Google splits product markup into two experiences, and the difference decides how much surface you get.
Product snippets work on any product page. Lighter requirements. They power review stars, price, and availability badges in regular results.
Merchant listings apply to pages where the shopper can buy directly from you. They need more: your Offer has to carry shippingDetails and hasMerchantReturnPolicy, and the markup has to line up with your Merchant Center feed.
If you sell direct, you want merchant listings. Add shippingDetails as an OfferShippingDetails object with shippingDestination, deliveryTime (handling time plus transit time), and shippingRate. Add hasMerchantReturnPolicy as a MerchantReturnPolicy with your return window, method, and fees.
While you're in the feed, Google has called out eight Merchant Center attributes that feed AI Overview product panels specifically: product highlights, product details, variant options, shipping, returns, merchant return policy, energy attributes where your category requires them, and loyalty program attributes. If you've been treating your feed as a Shopping-tab chore, this is the moment to treat it as ecommerce schema for AI surfaces instead.
You'll know this step is done when Rich Results Test reports your page eligible for merchant listings, not just snippets.
Step 5: Handle variants without duplicating your catalog
Sizes and colors are where clean implementations turn into noise.
Every variant is genuinely a different product. Different identifier, different price, sometimes different image, its own Offer. The right shape is a ProductGroup parent that links to child Product items through hasVariant, with variesBy naming the axis (size, color) and each child carrying its own sku and Offer.
This is where product schema for recommendations differs from schema written purely for search results. An assistant asked for a medium in black needs to resolve to one buyable variant with one price, not to a parent product with a range attached.
What you're avoiding: a separate full Product block for every single variant on the same page. Shopify does this by default. WooCommerce does it for variable products. It's the single most common structural mistake in ecommerce implementations, and it makes your one product look like fourteen near-identical products.
The same rule catches category pages. A collection page that emits a Product block for every SKU it lists reads as spammy structured data. Use ItemList for collection pages, and Product markup only on the canonical PDP.
Step 6: Ship it on your actual platform
The template is universal. Getting it into your stack is not. Find yourself below.
Shopify
Your default theme already emits a baseline Product block on every PDP: name, image, description, sku, brand when the metafield is populated, and an Offer with price, currency, availability, and url. That's a real head start.
What's missing by default:
gtin13,gtin12,mpn: add through product metafields.aggregateRatingandreview: add through your reviews app, and make sure it ships the markup in the page HTML rather than fetching it client-side.shippingDetailsandhasMerchantReturnPolicy: theme customization or a schema app.priceValidUntil: bind it to your sale end date, or use a rolling window.
Then consolidate those per-variant blocks under a ProductGroup.
WooCommerce
WooCommerce emits no product schema by default, so you're picking a plugin. Yoast WooCommerce SEO outputs Product, Offer, AggregateRating, and Review. Rank Math does Product and Offer on the free tier. Schema Pro handles Product, Offer, return policy, and shipping with minimal configuration.
Watch two things: variable products emitting one block per variation, and price formatting picking up locale separators. Your price needs to stay a clean numeric string.
BigCommerce
Cornerstone emits base Product JSON-LD on PDPs. Other Stencil themes vary, and custom themes usually drop it entirely. Validate before you assume.
Headless and custom builds
You have the most control here, so build the discipline in.
Render the JSON-LD server-side. Use one shared serializer that builds the Product block from the same canonical product object your UI renders, so page and markup cannot disagree by construction. For variants, generate the ProductGroup summary plus per-variant entries with isVariantOf pointing home. Revalidate your JSON-LD cache on the same cadence as your PDP cache.
Step 7: Submit your feeds to each engine
On-page markup makes you readable. Feeds make you fresh. Most surfaces want both, and the two must agree.
Google Merchant Center. Your feed drives the Shopping tab, free listings, and the AI Overview product panels. Price, availability, currency, and GTIN must match your JSON-LD exactly.
ChatGPT Shopping. Product discovery runs on a feed you upload through OpenAI's merchant onboarding portal. Required fields include item_id, title, description, url, image_url, price with currency, availability, and two opt-in flags: is_eligible_search and is_eligible_checkout. Both flags need to be true for a SKU to surface. Availability uses a short enum here (in_stock, out_of_stock, pre_order, backorder, unknown), not schema.org URLs. Feeds go up as JSONL or CSV, refreshed daily at minimum. Onboarding is gated behind an application review, so start it before you need it.
Perplexity Shopping. Perplexity pulls from its Merchant Program feed first, then editorial selection, then web crawl. The program is free to join and doesn't require ad spend, and priority goes to feeds that are accurate and fresh. Their feed uses Google Merchant Center format, so you're mostly reusing work.
Bing. Bing reads schema.org Product and Offer directly and takes a standard Merchant Center feed, no separate program required.
Claude. No dedicated shopping surface today. When Claude browses, it reads your public page, structured data included. Clean markup is the whole strategy.
Common mistake: treating the feed as the source of truth and letting the page drift, or the reverse. Price and availability that disagree across page, JSON-LD, and feed is the number one reason product rich results get suppressed. It's not a penalty so much as a trust decision. If two of your own sources contradict each other, an engine has no reason to believe either one.
Step 8: Validate in three layers, then ship
Don't guess. There are three free checks and they take about ten minutes together.
- Syntax. The Schema Markup Validator confirms your JSON-LD parses and matches the schema.org type graph. It catches malformed Offer nesting, a missing
@context, and invalid enum values. - Eligibility. Google's Rich Results Test shows what Google actually detected and whether you qualify for product snippets, merchant listings, or both. This is where missing required fields surface.
- Indexing. Search Console under Enhancements then Products gives you the site-level view: parse counts, warnings, and any manual actions across your catalog.
Run all three after every template change. Templates are where breakage scales.
Where people go wrong: validating one product and calling the catalog done. Validate one URL per template, not one URL per site.
Keep the results somewhere your team can see. An AI shopping schema rollout dies quietly when nobody notices a theme update stripped the identifiers back out three weeks later.
Step 9: Watch what AI assistants actually say about your products
Markup makes you eligible. It doesn't make you recommended. Relevance, merchandising, and content quality still decide who gets named, so the last step is closing the loop.
Write down the ten prompts a real buyer would type. "Best pour-over dripper under $50." "Pour-over vs French press for one person." Then run them across the assistants your shoppers use and record what comes back: are you mentioned, are you cited with a link, and whose pages are winning the ones you lose?
Do it manually first. It's tedious and it's honest, and one afternoon of it will teach you more than any dashboard.
When the manual version stops scaling, that tracking is what DeepSmith automates: it checks your prompts on a schedule across ChatGPT, Perplexity, Gemini, Claude, and Google AI Mode depending on your plan, reports mention rate, citation rate, and share of voice over time, shows which of your pages earn citations, and shows which competitor pages take the ones you don't. The schema work makes you citable. This tells you whether it worked, and where the next gap is.
What to do next
Pick one product template. Not the catalog, one template.
Add the block from Step 2, layer on shipping and returns, run the three validators, and push it. Then repeat on the next template. Momentum matters more than a perfect rollout, and templates mean the work compounds fast. Ten templates done properly is a full catalog of ecommerce schema for AI assistants to read, and most stores have fewer than ten.
If you want the tracking loop running while you do the schema work, start a free DeepSmith trial and set up your buyer prompts. You'll have a baseline to compare against once the markup lands.
You've got this. It's a checklist, and you've already read it.



