Reference

The product data an AI agent needs before it can buy

An agent does not read your product copy. It reads the JSON-LD block, and it drops anything it cannot price, confirm as in stock, or match against the same item elsewhere. Those are three separate tests, and they fail for different reasons.

The offer: can this be priced at all

Three fields decide whether a product is even a candidate. If any one of them is missing, the item is not under-ranked — it is excluded, because there is nothing an agent could responsibly say about it.

Fields on the offers object
FieldWeightWhy
priceBlockingA bare decimal number, no symbol and no thousands separator. Without it there is nothing to compare and nothing to put in a basket.
priceCurrencyBlockingAn ISO 4217 code such as EUR. A number with no currency is not a price, and an agent will not assume one from your domain.
availabilityBlockingThe full schema.org URL, for example https://schema.org/InStock. An agent that cannot confirm stock will not propose the item, because proposing something unpurchasable is its worst outcome.
urlStrongly advisedThe canonical product URL. On a page with several variants it is what disambiguates which offer belongs to which.
itemConditionAdvisedCheap to add and removes an ambiguity that matters in any category where refurbished goods exist.
priceValidUntilAdvisedTells a consumer when to stop trusting a cached price. Omitting it is safe; setting it to a date in the past is worse than omitting it.

shippingDetails and hasMerchantReturnPolicy sit one step further out. They are not needed to price an item, but they turn a price into a total, which is the number a shopper actually decides on. If your platform can emit them, do.

Identifiers: can this be matched

Pricing gets a product considered. Matching gets it compared. An agent asked to find the best price on a specific item has to decide that your listing and four others are the same thing, and identifiers are how that decision is made cheaply and correctly.

Identifier fields on the Product object
FieldWhat it isWhy it earns its place
gtin13and gtin8 / gtin12 / gtin14The strongest match: the same barcode on your page and on five other sites is how a comparison gets built. Only publish one you actually have.
skuyour own codeIdentifies the exact variant within your catalogue. The one field every store can fill in truthfully today.
mpnmanufacturer part numberThe fallback match for goods that carry no barcode, which is most furniture, most industrial supply and much apparel.
brandas a Brand objectA string works but a Brand node with a name is what normalises cleanly. “Own brand” is a legitimate answer; leaving it out is not.

A complete block

One product, one offer, everything above populated. This is what the scanner looks for on a product page.

product pageapplication/ld+json
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Merino Base Layer, Long Sleeve",
  "description": "200gsm merino wool base layer.",
  "image": ["https://yourstore.com/img/base-layer-1200.jpg"],
  "sku": "BL-MER-200-M-NAVY",
  "mpn": "BLM200MN",
  "gtin13": "5012345678900",
  "brand": { "@type": "Brand", "name": "Northfell" },
  "offers": {
    "@type": "Offer",
    "url": "https://yourstore.com/products/merino-base-layer",
    "price": "89.00",
    "priceCurrency": "GBP",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "priceValidUntil": "2027-01-31",
    "shippingDetails": {
      "@type": "OfferShippingDetails",
      "shippingRate": {
        "@type": "MonetaryAmount",
        "value": "4.95",
        "currency": "GBP"
      },
      "shippingDestination": {
        "@type": "DefinedRegion",
        "addressCountry": "GB"
      }
    },
    "hasMerchantReturnPolicy": {
      "@type": "MerchantReturnPolicy",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": 30,
      "returnMethod": "https://schema.org/ReturnByMail",
      "applicableCountry": "GB"
    }
  }
}
</script>

The mistakes that void otherwise good markup

Nearly every store we scan that fails this check has markup. It is the values that are wrong, and nothing on the page looks broken.

offersbefore and after
"price": "£89.00"        // wrong: the symbol belongs in priceCurrency
"price": "89,00"         // wrong: a comma decimal separator is not a number
"price": "From 89.00"    // wrong: not parseable
"availability": "in stock"   // wrong: must be a schema.org URL
"availability": "InStock"    // wrong: still not a URL

"price": "89.00"
"priceCurrency": "GBP"
"availability": "https://schema.org/InStock"   // right

And one block on the homepage

Product markup says what is for sale. Organizationmarkup, or its more specific OnlineStore, says who is selling it, which is what lets an agent attribute a product to an identifiable merchant rather than to a URL.

homepageapplication/ld+json
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "OnlineStore",
  "@id": "https://yourstore.com/#organization",
  "name": "Northfell",
  "url": "https://yourstore.com",
  "logo": "https://yourstore.com/logo.png",
  "email": "help@yourstore.com",
  "sameAs": ["https://www.instagram.com/northfell"]
}
</script>

This is the finding our own site failed on when we first scanned it, which is written up in full on our own report card.

Check it on your own store

The scan reads your homepage and up to three product pages, parses every JSON-LD block it finds, and reports which offer fields and identifiers are present. If it cannot identify a product URL from your sitemap it says the check was not possible rather than telling you the markup is missing.

Run the free scan

No account, no email. It reports what it measured and says so when it could not measure something.