Product Schema for Small Online Shops: Merchant Listings, Shipping and Returns Markup
To be eligible for Google’s merchant listing experiences, a product page needs Product structured data with a name, an image and a nested Offer carrying a price above zero and a priceCurrency; availability, shipping and returns are recommended on top. Since June 2024 (returns) and November 2025 (shipping) Google also accepts one site-wide shipping and return policy in your Organization markup, so a small shop no longer has to repeat them on every product. This guide gives you working JSON-LD for each piece, explains how variants and reviews are handled, and shows where Merchant Center free listings and AI shopping features fit, using only what Google and OpenAI actually document.
Key facts
- name + image + offers — The required Product properties for merchant listings
- June 2024 — Google added organization-level return policy markup
- Nov 2025 — Google added organization-level shipping policy markup (ShippingService)
- 50 billion+ — Product listings in Google’s Shopping Graph, per Google in May 2025
What Google requires on a product page
Google’s merchant listing documentation requires three things on Product: a name, at least one image, and an offers property containing an Offer with a price and a three-letter ISO 4217 priceCurrency (Google: merchant listing structured data). Everything else is recommended, but the recommended properties are what make a listing useful to a shopper.
Google separates two product experiences:
- Merchant listings are for pages where a shopper can buy the product from you. They can show price, availability, shipping and returns. Unlike product snippets, they require a price greater than zero.
- Product snippets are for pages that discuss products without selling them, such as an editorial review with pros and cons.
The rules that trip small shops most often:
- One product per page. The page must focus on a single product, or variants of the same product. Category pages and search results are not eligible.
- One currency per URL. If you sell in several currencies, Google asks for a distinct URL per currency.
- Markup must match the page. Merchant Center’s structured data guidance says the values must match what the customer sees, and calls incorrect data a violation of its guidelines (Merchant Center Help).
- Put it in the initial HTML. Since October 2024 Google’s docs recommend including
Productmarkup in the server-rendered HTML rather than injecting it with JavaScript, because Google says dynamically generated markup “can make Shopping crawls less frequent and less reliable”, which matters for fast-changing price and availability.
Recommended Offer properties worth filling in on every page: availability (for example InStock, OutOfStock, BackOrder, PreOrder), itemCondition (NewCondition, RefurbishedCondition or UsedCondition) and url. On Product, add description, brand, sku (no whitespace allowed), and a gtin or mpn where the product has one.
A complete Product example for a small shop
This is the minimum markup worth shipping on a real product page: required properties, plus brand, identifiers, availability and condition. Shipping and returns are deliberately left out because they live in the store-wide markup in the next two sections.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Hand-thrown Stoneware Mug, 12 oz, Sea Glass",
"description": "Wheel-thrown stoneware mug glazed in sea glass green. Dishwasher and microwave safe.",
"image": [
"https://shop.example.com/img/mug-seaglass-1x1.jpg",
"https://shop.example.com/img/mug-seaglass-4x3.jpg",
"https://shop.example.com/img/mug-seaglass-16x9.jpg"
],
"sku": "MUG-12-SEA",
"mpn": "MUG-12-SEA",
"brand": { "@type": "Brand", "name": "Example Pottery" },
"offers": {
"@type": "Offer",
"url": "https://shop.example.com/mugs/stoneware-mug-sea-glass/",
"price": 32.00,
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
</script>Notes on the choices:
- Images: Google recommends several high-resolution images in 16x9, 4x3 and 1x1 ratios. Use the same photos the page shows.
priceis a number, with a dot as the decimal separator and no currency symbol.- Sales: to show a crossed-out original price, Google’s documented pattern keeps the sale price in
Offer.priceand adds apriceSpecificationof typeUnitPriceSpecificationwithpriceTypeset tohttps://schema.org/StrikethroughPriceholding the original price. In July 2026 it added a “sale duration” section coveringvalidFrom,validThroughandpriceValidUntil. Be careful withpriceValidUntil: Google warns that a listing may not display if that date is in the past. - Category: since July 2026 the docs say
Product.categorycan be plain text or aCategoryCodepointing at a Google product category, matching Merchant Center.
Generate this from the same database row that renders the visible price and stock status, so the two can never disagree. A hard-coded block that someone forgets to update when the price changes is the most common cause of merchant listing problems.
Shipping: one store-wide policy, with per-product overrides
Google now recommends describing your general shipping policy once, under Organization, using the hasShippingService property and a ShippingService object (Google: merchant shipping policy). Google announced this in November 2025, alongside more shipping and returns options in Search Console (Search Central blog).
The only required property is shippingConditions: one or more ShippingConditions objects, each describing a rate and transit time that applies under certain conditions (destination, order value, weight or number of items). Put it on a single page, usually your shipping policy page or home page; Google says it does not need to be on every page. Here is a store that charges $6.95 under $75 and ships free above it, combined with the return policy from the next section:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://shop.example.com/#store",
"name": "Example Pottery",
"url": "https://shop.example.com/",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "US",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn",
"refundType": "https://schema.org/FullRefund"
},
"hasShippingService": {
"@type": "ShippingService",
"name": "Standard US shipping",
"fulfillmentType": "FulfillmentTypeDelivery",
"handlingTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 2, "unitCode": "DAY" },
"businessDays": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
},
"shippingConditions": [
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"orderValue": { "@type": "MonetaryAmount", "minValue": 0, "maxValue": 74.99, "currency": "USD" },
"shippingRate": { "@type": "MonetaryAmount", "value": 6.95, "currency": "USD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
}
},
{
"@type": "ShippingConditions",
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"orderValue": { "@type": "MonetaryAmount", "minValue": 75, "currency": "USD" },
"shippingRate": { "@type": "MonetaryAmount", "value": 0, "currency": "USD" },
"transitTime": {
"@type": "ServicePeriod",
"duration": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
}
}
]
}
}
</script>If one product ships differently, for example a bulky item with a flat $24 freight charge, override it on that product’s Offer with shippingDetails and an OfferShippingDetails object:
"offers": {
"@type": "Offer",
"price": 189.00,
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": { "@type": "MonetaryAmount", "value": 24.00, "currency": "USD" },
"shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
"deliveryTime": {
"@type": "ShippingDeliveryTime",
"handlingTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 4, "unitCode": "DAY" },
"transitTime": { "@type": "QuantitativeValue", "minValue": 3, "maxValue": 7, "unitCode": "DAY" }
}
}
}Which source wins. Google documents a precedence order, strongest first: Content API for Shopping settings, then Merchant Center or Search Console settings, then product-level markup, then organization-level markup. If you have already set shipping in Merchant Center, that is what Google uses; the markup is still useful as a fallback and for other consumers of your pages.
Returns: MerchantReturnPolicy at the organization level
A return policy goes under Organization (or a subtype such as OnlineStore) in hasMerchantReturnPolicy, as in the example above. Google added organization-level return policies in June 2024 and moved the return policy documentation to its own page in June 2025 (Google: merchant return policy).
Google accepts either of two minimum forms:
applicableCountry(ISO 3166-1 alpha-2 codes) plusreturnPolicyCategory, ormerchantReturnLink, the URL of your returns page.
The first form is better because it states the facts. The values you will use:
returnPolicyCategory:MerchantReturnFiniteReturnWindow(thenmerchantReturnDaysis required),MerchantReturnUnlimitedWindoworMerchantReturnNotPermitted.returnMethod:ReturnByMail,ReturnInStoreorReturnAtKiosk.returnFees:FreeReturn,ReturnFeesCustomerResponsibility, orReturnShippingFees(then addreturnShippingFeesAmount).refundType:FullRefund,ExchangeRefundorStoreCreditRefund.
You can still put a MerchantReturnPolicy on an individual Offer for an exception, such as final-sale items. In July 2025 Google clarified that offer-level policies support only a subset of the organization-level properties, so keep the full policy on the organization and use the offer level only for the exceptions. Precedence works the same way as shipping: Merchant Center and Search Console settings beat markup, and product-level markup beats organization-level markup.
Whatever you mark up must match the returns page a customer can read. If the page says 14 days and the markup says 30, fix the page or the markup before anything else.
Variants: ProductGroup, variesBy and hasVariant
Products that come in several sizes, colours or materials should be marked up as a ProductGroup containing one Product per variant (Google: product variants). Google launched this documentation in February 2024.
productGroupIDis the parent SKU. Each variant is linked to it either by nesting it underhasVariantor, on separate pages, withisVariantOforinProductGroupWithID.variesBylists the attributes that differ. Google supportshttps://schema.org/color,size,suggestedAge,suggestedGender,materialandpattern.- The group’s
nameis general; each variant’s name should be more specific and include the distinguishing value.
{
"@context": "https://schema.org",
"@type": "ProductGroup",
"name": "Hand-thrown Stoneware Mug",
"productGroupID": "MUG-12",
"url": "https://shop.example.com/mugs/stoneware-mug/",
"brand": { "@type": "Brand", "name": "Example Pottery" },
"variesBy": ["https://schema.org/color"],
"hasVariant": [
{
"@type": "Product",
"name": "Hand-thrown Stoneware Mug, 12 oz, Sea Glass",
"sku": "MUG-12-SEA",
"color": "Sea Glass",
"image": "https://shop.example.com/img/mug-seaglass-1x1.jpg",
"offers": { "@type": "Offer", "url": "https://shop.example.com/mugs/stoneware-mug/?color=sea-glass",
"price": 32.00, "priceCurrency": "USD", "availability": "https://schema.org/InStock" }
},
{
"@type": "Product",
"name": "Hand-thrown Stoneware Mug, 12 oz, Charcoal",
"sku": "MUG-12-CHR",
"color": "Charcoal",
"image": "https://shop.example.com/img/mug-charcoal-1x1.jpg",
"offers": { "@type": "Offer", "url": "https://shop.example.com/mugs/stoneware-mug/?color=charcoal",
"price": 32.00, "priceCurrency": "USD", "availability": "https://schema.org/OutOfStock" }
}
]
}Two layouts are supported. On a single-page setup, where choosing a colour changes a query parameter, there must be one canonical URL for the whole group, and each variant’s offers.url can carry its parameter. On a multi-page setup, where each variant has its own URL, every page needs full, self-contained markup for what it shows. The canonical decision matters here; see canonical tags and duplicate content.
Reviews and ratings: what you may mark up
A shop may add review and aggregateRating to a Product for genuine customer reviews of that specific product, but not star ratings for the business itself on its own site.
Google’s review snippet guidelines (Google: review snippet) say:
- Reviews must be about a specific item, not a category or a list of items.
- If a business controls the reviews about itself, its pages using
LocalBusinessor otherOrganizationmarkup are ineligible for star review features. That is why the stars belong onProduct, not onOnlineStore. - Since July 2025 the guidelines explicitly exclude reviews not based on a genuine experience, and reviews written in exchange for money, discounts or free products that do not clearly disclose it.
- Since November 2025 Google asks you not to indicate the reviewed item in more than one way in the same markup.
The ratings in your markup must be the ratings shown on the page. Importing star averages from another platform that are not displayed, or marking up five hand-picked testimonials as an aggregate rating, is exactly what these rules exclude. If you have no reviews yet, leave the properties out; an empty or invented rating helps nobody.
Merchant Center free listings and AI shopping features
Structured data and a Merchant Center feed work best together: Google says providing both “maximizes your eligibility to experiences and helps Google correctly understand and verify your data” (Google: product structured data).
Free listings. Merchant Center’s free listings cost nothing. Google’s help page says that with a free listing, your products can appear on Google Search, Google Maps, Gemini, YouTube, the Shopping tab, Google Images and Google Lens, and that the feature is on by default in most accounts (Merchant Center Help: free listings). For a small shop with a few dozen products, a Merchant Center account plus correct page markup is the cheapest way into Google’s shopping surfaces.
Automatic item updates. Merchant Center can read the structured data on your product pages and use it to update price, sale price, availability and condition in your product data, and Google says this is normally switched on already (Merchant Center Help). This is the practical link between your JSON-LD and your feed: accurate markup reduces disapprovals caused by price or stock mismatches.
Google AI Mode. In May 2025 Google said AI Mode shopping combines Gemini with the Shopping Graph, which it described as having more than 50 billion product listings, with more than 2 billion refreshed every hour (Google blog). Google does not publish a separate markup format for AI Mode; the documented inputs are the same Merchant Center data and product pages.
ChatGPT shopping. OpenAI’s help article says product results are selected independently and are not ads, that product information comes from “structured metadata from first-party and third-party providers”, and that merchants can provide a direct product feed to OpenAI; Shopify merchants are already integrated through Shopify Catalog (OpenAI Help). OpenAI does not document whether ChatGPT reads Schema.org markup on your pages, so treat markup as helpful for clarity, not as a guaranteed input. Checkout inside assistants is a separate topic: see agentic commerce protocols.
Testing, common mistakes, and when not to bother
Test every template before launch with Google’s Rich Results Test, then watch the Merchant listings and Product snippets reports in Search Console after Google recrawls.
- Price mismatch. The markup, the visible price and the feed must agree, including tax treatment.
- Stale
priceValidUntil. A date in the past can stop the listing from displaying. Omit it unless the price really expires. - Availability not updated when stock runs out. Render it from inventory, not by hand.
- Markup on category pages. Only pages where a shopper can buy one product are eligible.
- Policy contradictions between the returns page, the markup and Merchant Center settings.
- Whitespace in
sku, which Google does not allow.
Limits. Correct markup makes a page eligible; it does not guarantee a rich result, a free listing or a mention in an AI answer. If you sell services rather than shippable products, merchant listing markup is the wrong tool; use LocalBusiness markup instead. And if your platform already outputs complete Product markup (most hosted shop systems do), check its output before adding your own, because two conflicting Product blocks on one page are worse than one. Broader context on which markup still earns results is in which schema markup still matters in 2026.
Product facts: AIWebBuilding shops and the AI Indexing Pack
Stated plainly, so it can be checked against the product page:
- Shops on AIWebBuilding: sites built on AIWebBuilding include a shop.
- What it is: the AI Indexing Pack is a set of files you upload to your own website. It is sold by Built2WinWeb as a one-time purchase, with no subscription.
- What it ships: (1) a working MCP server using the Streamable HTTP transport, with typed output schemas and tool annotations; (2) Markdown content negotiation, so agents can request a clean text version of each page; (3) llms.txt, agents.txt and agent cards; (4) the full
/.well-known/discovery tree; (5) OAuth protected-resource metadata; (6) bot access control that verifies crawler identity; (7) a README with a verification checklist. - Requirements: PHP 7.4 or newer, Apache or LiteSpeed with
.htaccesssupport, FTP access, and a domain you control. Installation takes about 30 minutes. - What it is not: it is not a WordPress plugin (that is the separate WordPress edition, which needs WordPress 6.0+ and PHP 8.0+), it does not write content for you, it does not guarantee rankings or citations, and it is not a managed service.
- Free routes in: sites built on AIWebBuilding get the core built in, and a 50-day streak on FreeAIBoost unlocks the pack for one domain. Current prices are on the product pages.
Related reading
Frequently asked questions
What structured data does Google require for a merchant listing?
A Product with name and image, and a nested Offer with price (greater than zero) and priceCurrency. Availability, itemCondition, shipping, returns, brand and identifiers such as GTIN or MPN are recommended.
Can I put my shipping and return policy in Organization markup instead of on every product?
Yes. Google supports a store-wide return policy under Organization via hasMerchantReturnPolicy (added June 2024) and a store-wide shipping policy via hasShippingService and ShippingService (added November 2025), placed on one page of your site.
If Merchant Center and my markup disagree, which does Google use?
Google’s documented order is Content API for Shopping first, then Merchant Center or Search Console settings, then product-level markup, then organization-level markup. Make all of them match to avoid disapprovals.
How do I mark up products that come in several colours or sizes?
Use a ProductGroup with a productGroupID, list the differing attributes in variesBy, and add each variant as a Product under hasVariant or link it with isVariantOf. Each variant gets its own name, SKU and Offer.
Does Product schema get my shop into ChatGPT or Google AI Mode?
Google says AI Mode shopping uses its Shopping Graph, which Merchant Center free listings feed, and OpenAI says ChatGPT uses structured metadata from first-party and third-party providers plus direct merchant feeds. Neither documents page markup alone as a guaranteed route in.
Want your shop marked up properly?
We build product pages whose markup, prices and policies come from one source, so Google, Merchant Center and AI assistants all see the same facts.
Get a free quote