SchemaValid
ENDE
Structured Data

Product Schema Price: How to Add It Without Breaking Your Listings

Published: 6 min read
Contents

If you landed here searching "schema price," you're probably after one of two things: what the price property in schema.org markup actually does, or how much a schema tool costs. This is about the first one — specifically, how to put a price inside Product structured data so Google can use it, and where people get it wrong.

What price actually is in Product schema

In schema.org's vocabulary, price isn't a property of Product directly — it lives on Offer, the object that describes the terms under which something is being sold. A minimal structure looks like this:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Executive Anvil",
  "offers": {
    "@type": "Offer",
    "price": "119.99",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

price accepts a number or a plain text value, and there's also PriceSpecification, a more detailed structured type with fields like minPrice, maxPrice, and valueAddedTaxIncluded. Most sites never need it — a plain price and priceCurrency on the Offer covers a single fixed price. PriceSpecification earns its keep when you need to say more than "this costs X," which is where ranges and multi-seller listings come in later.

119.99priceUSDpriceCurrencyInStockavailability2026-09-30priceValidUntilPrice fields inside a Product Offer — price and priceCurrency are required, the rest recommended

Four fields do the actual work, and only two of them are strictly required. The table below spells out which is which, and what Google does with each one:

FieldRequired by Google?Notes
priceYesMust be the current, active price — and it has to be greater than zero for Merchant listings, a stricter rule than schema.org's own spec.
priceCurrencyYes, if price is setISO 4217 three-letter code (USD, EUR, GBP), never a currency symbol.
availabilityRecommendedInStock, OutOfStock, PreOrder, LimitedAvailability, BackOrder, Discontinued, InStoreOnly, OnlineOnly, PreSale, or SoldOut — see the full list on Google's product snippet reference.
priceValidUntilRecommendedISO 8601 date. A past date can keep the listing from showing.

Source: Google's Merchant listing structured data reference, page as of July 2026 — Google updates these requirements periodically, so check the live page before shipping anything that depends on an exact rule.

availability and priceValidUntil are listed as recommended, not required, which makes it tempting to skip them. In practice, that's a mistake with two different price fields. First, priceValidUntil — Google's own documentation is blunt about it: a listing may not display once that date is in the past. There's no published grace period, no "a few days won't hurt." If you set it and forget it, the listing degrades silently, the same way an expired robots.txt directive quietly stops working instead of throwing an error. A stale priceValidUntil is the structured-data equivalent of a "sale ends Sunday" banner nobody took down: technically still there, doing nothing, fooling no one but the shopper who trusted it.

Watch out

Google checks that price and availability in your structured data match what's actually on the page, and what's in your product feed if you use Merchant Center. A mismatch — say, the schema says "$49.99" but the visible page has updated to "$54.99" — gets flagged as an inaccurate price status, and it's your live page that decides which number is correct.

Second, Google's requirements aren't frozen. In February 2025, Google added a beta validForMemberTier property so merchants can markup a separate loyalty-member price alongside the regular one — a price specification can't carry both that and a priceType value at the same time, and if it does, Google ignores the combination. If you're running a membership or loyalty program, that's worth reading the current spec for rather than guessing, since a beta property like this one is exactly the kind of thing that changes again before you'd notice.

Common mistakes

The table below lists five ways price markup breaks in practice, and the fix for each — all mechanical once you know which field is the culprit:

MistakeWhat happensFix
priceCurrency missingGoogle can't interpret the number — no price shownAlways pair price with a three-letter ISO 4217 code
Currency symbol instead of code€49.99 or $49.99 fails validationUse EUR / USD as the currency, 49.99 as the price
Price is zero or blank as a placeholderMerchant listing is rejected outrightDon't ship a price field until you have a real number
priceValidUntil left in the pastListing may stop showing, with no warning in Search ConsoleSet it forward and keep it maintained, or drop it if you can't
Schema price doesn't match the visible pageFlagged as inaccurate price statusGenerate the markup from the same source of truth as the page copy

None of these throw a visible error on your page — JSON-LD fails silently. The Schema Validator will catch structural problems like a missing priceCurrency, but a stale priceValidUntil or a mismatch against your visible price is something only you can catch, because the JSON itself is perfectly valid.

Price ranges and multiple sellers

A single Offer with one price only covers a single fixed price from a single seller. Two other situations need different handling:

  • A price range for one product: a T-shirt in three sizes at the same price doesn't need a range, but a product genuinely sold "from $80 to $120" depending on configuration uses PriceSpecification with minPrice and maxPrice instead of a flat price.
  • The same product sold by multiple sellers at different prices: this is what AggregateOffer is for, with lowPrice, highPrice, offerCount, and priceCurrency describing the spread across sellers, not a single seller's own range.

An AggregateOffer for a product eight different retailers stock might look like this — note the type change from Offer to AggregateOffer, and that there's no single price field at all:

{
  "@type": "AggregateOffer",
  "lowPrice": "89.00",
  "highPrice": "129.99",
  "priceCurrency": "USD",
  "offerCount": "8"
}

Mixing these up is an easy trap: putting lowPrice/highPrice on a plain Offer instead of switching the type to AggregateOffer produces markup that validates as JSON but doesn't mean what you intended. If you're building the markup by hand, this is exactly the kind of type mismatch that's easy to miss and annoying to debug later — the same category of mistake as the address-as-plain-string error that breaks LocalBusiness markup: the JSON is well-formed, the meaning isn't what the schema expects.

Build it with the generator instead

Our free Product Schema Generator handles the price, currency, availability, and GTIN fields for you, and outputs ready-to-paste JSON-LD for a single-price Offer. It runs entirely in your browser — nothing you type is sent to a server or stored anywhere.

Product Schema GeneratorGenerate Product JSON-LD with price, GTIN and ratings for Google Shopping.Open the tool

For range and multi-seller AggregateOffer structures, you'll still want to write the JSON-LD by hand or extend the generator's output — that's a deliberate gap in a generic tool, not a bug, since ranges and per-seller data are specific to how your catalog is structured.

Frequently asked questions

Does price in Product schema affect my Google ranking?
Not directly. It's not a ranking factor. What it does is make you eligible for Merchant listing and product rich result features in Search — whether those actually appear depends on Google's own systems and other quality signals.
Can I use a currency symbol like $ instead of USD?
No. Google's structured data requirements call for an ISO 4217 three-letter currency code such as USD or EUR, not a currency symbol.
What happens if I don't set priceValidUntil at all?
It's listed as recommended, not required, so omitting it won't invalidate your markup. But Google's own documentation notes that once you do set it, a past date can keep the listing from displaying — so if you add it, you need to keep it current.
Is PriceSpecification required for a simple online shop?
No. A plain price and priceCurrency on the Offer covers a single fixed price. PriceSpecification and its subtypes matter once you need a price range, tax-inclusive pricing, or other detail a flat price can't express.