// FREE TOOL · PRODUCT SCHEMA GENERATOR
Product schema generator
Describe one product; get Product plus Offer JSON-LD with the merchant listing rules checked while you type — price above zero, currency present, a price date that has not expired — and the product block that carries the same values on the page.
Required. Google suggests several ratios of the same shot: 1x1, 4x3, 16x9.
At most one brand name.
Digits only — 8, 12, 13 or 14 of them. The URL form is not supported.
Digits and a dot. No currency symbol, no thousands separator — that is a schema.org rule, not a preference.
A date already in the past can stop the listing from showing at all.
The URL of the policy you marked up under Organization. Google prefers that to a copy inside every Offer.
Only for ratings your own site collected from buyers. Never copy them in from another site.
Leave empty and Google assumes a 5-point scale.
Everything runs in this page. No product name, price or image URL leaves your browser.
How to generate product schema
Three required properties, two required Offer properties, and a handful of rules that decide whether the listing shows at all. The generator checks each one as you type and writes the visible block from the same values.
- Name the product and add images. name and image are required for a merchant listing. Several ratios of the same photograph beat one, and every URL has to be crawlable and indexable.
- Fill in the offer. A price greater than zero and a three-letter currency code. Those two are what turns a Product into something Google can list as being for sale.
- Set availability and the price date. Availability and itemCondition are emitted as short names, which Google supports. Leave priceValidUntil empty rather than letting yesterday sit in it.
- Point at your policies instead of copying them. Mark up shipping and returns once under Organization, then reference those nodes by @id here. Google recommends the global policy over one repeated in every offer.
- Paste both outputs. The JSON-LD goes in the product page. The visible block carries exactly the price, availability and codes the markup declares — which is the rule the markup has to satisfy anyway.
Three properties on the product, two on the offer
A product schema generator turns product details into Product and Offer JSON-LD — the structured data Google reads for price, availability and product identifiers. The required set is short and worth memorising, because most of what generators demand is not in it.
| Level | Required | What happens without it |
|---|---|---|
| Product | name, image, offers | No merchant listing. offers has to be an Offer — an AggregateOffer is accepted for product snippets only, because a merchant listing needs you to be the seller. |
| Offer | price (or priceSpecification.price), priceCurrency | Nothing to list. priceCurrency is required whenever price is given, and merchant listings additionally require the price to be greater than zero. |
Everything else — brand, sku, gtin, description, availability, itemCondition, priceValidUntil, aggregateRating — is recommended. Recommended is not decorative: an identifier is how anything matches your page to the same product on another site. But a generator that will not emit until you fill fourteen boxes is enforcing its own form, not Google's rules.
The price rules that quietly kill a listing
A price is where product markup goes wrong silently — the JSON-LD validates, the listing just never appears.
- Write the number, not the presentation. schema.org's usage guidelines say to use a dot for the decimal point, to avoid using a comma as a readability separator, and to put the currency in
priceCurrencyrather than an ambiguous symbol in the value.1,299.00and€24are both broken;1299.00withEURis not. - Zero is not a price. Unlike product snippets, merchant listing experiences require a price greater than zero. A free plan or a "call for quote" placeholder of 0 disqualifies the offer.
- A stale date is worse than no date. Google's wording is blunt: your listing may not display if
priceValidUntilindicates a past date. This is the single most common decayed-markup bug on shops that set the field once in 2023 and never touched it. The generator compares it against today and flags it as an error, not a nicety. - One value per enumeration.
availabilityanditemConditioneach take exactly one value. Google supports the short names without the URL prefix —InStock,NewCondition— which is what this tool emits, so the visible text and the markup can be the same characters.
On a sale price, do not overwrite the old one: keep the active price in price and add the original as a UnitPriceSpecification marked priceType: StrikethroughPrice. Marking the active price with a priceType is what makes Google ignore the whole specification.
Shipping and returns are not required — and Google would rather you moved them
Two properties get quoted as mandatory all over the advice on this topic: shippingDetails and hasMerchantReturnPolicy. We checked the source before building the form. Both are listed under recommended properties of Offer, not required — and Google's own note goes further than that:
We recommend you provide a global shipping policy for your business under Organization markup instead […] Only if some of your products have specific shipping policies for which you need to override your global policy, or if you don't provide a standard shipping policy for your business, use this property under Offer.
The same paragraph appears for returns. So the correct shape for most shops is: mark the policy up once, on the Organization, and reference it from each offer by identifier — shippingDetails.hasShippingService with only an @id, and hasMerchantReturnPolicy with only an @id. That is what the two fields in this form produce. Copying a full policy object into ten thousand product pages is the thing to avoid, not the thing to do.
If you genuinely have per-product shipping, the offer-level properties are there — with a smaller set of supported sub-properties than the organization-level ones.
Stars: whose ratings you may use
aggregateRating on a product you sell is allowed — a shop showing ratings its own buyers left is normal, and the self-serving restriction Google documents applies to LocalBusiness and Organization pages, not to a product. What is not allowed is anything else:
- Don't aggregate reviews or ratings from other websites. Pulling an average off a marketplace and marking it up on your own page is against the review snippet guidelines.
- Don't include fake or undisclosed incentivized reviews — reviews not based on a genuine experience, or written in exchange for money, discounts or free products without a clear disclosure.
- At least one of
ratingCountorreviewCountis required once you have an aggregate rating. A bare average is not a rating. - The scale is 5 unless you say otherwise. If
bestRatingis omitted, 5 is assumed and 1 is the floor; a 9.2 out of 10 marked up withoutbestRatingis a nine-point-two-star product.
The full set of review rules — including the one that makes a business's own reviews of itself ineligible — lives on the review schema generator. If your product page also carries a shop address or opening hours, that is a separate node: see the local business schema generator.
// FAQ
What is a product schema generator?
A product schema generator turns product details into Product and Offer JSON-LD — the structured data Google reads for price, availability and product identifiers. This one checks the merchant listing rules as you type and writes a matching visible product block from the same values.
What is required in Product structured data?
On the product: name, image and offers. On the offer: a price and a priceCurrency, and for merchant listing experiences the price has to be greater than zero. The offers value must be an Offer rather than an AggregateOffer, because a merchant listing assumes you are the seller.
Are shippingDetails and hasMerchantReturnPolicy required?
No. Both are recommended properties of Offer, and Google recommends putting a global shipping and return policy under Organization markup instead, then referencing those nodes from each offer by @id. Use the offer-level properties only to override the global policy for specific products.
Why is my product rich result not showing even though the markup validates?
The most common cause is a priceValidUntil date in the past — Google states the listing may not display when that date has passed. A price of zero, a missing priceCurrency, or an image URL blocked from crawling will do the same while leaving the JSON-LD technically valid.
How should the price be written?
As a plain number with a dot for the decimal point: 1299.00, not 1,299.00 and not €1299. The currency belongs in priceCurrency as a three-letter ISO 4217 code. Those are schema.org usage guidelines, and Google links to them from the product documentation.
Can I mark up ratings on my own products?
Yes, when they come from your own buyers. You may not aggregate ratings from other websites, and you may not mark up fake or undisclosed incentivized reviews. The self-serving-review restriction that blocks star ratings applies to LocalBusiness and Organization pages, not to a product you sell.
How do I mark up a sale price?
Keep the current, active price in the price property, then add the original as a UnitPriceSpecification with priceType set to StrikethroughPrice. Do not put a priceType on the active price — a price specification carrying both is ignored.
Ten thousand product pages. Which ones does Google actually have?
Checking your own domain is free: every page with its live HTTP status and whether Google has it indexed, impressions and positions against the previous window, and traffic by source with AI engines counted separately. One command, from inside your agent.
$ npm i -g @clize/clize && clize install $ clize seo check --domain yourshop.com[ Agent SEO by Clize → ]