# Product schema for AI shopping agents

> Product/catalog schema: Product data is the most valuable and the least machine-readable. The fix: add product schema. Standard: schema.org/Product.

- Source: /checks/product-schema
- Site: AgenticWebScore
- Language: English

---
Product data is the most valuable and the least machine-readable: price, availability and returns are usually rendered for a person to read and never declared for a machine to parse.

| Property | Value |
| --- | --- |
| Check id | `product-schema` |
| Dimension | Commerce Protocols (15%) |
| Tier | Essential — pool 80 pts |
| Weight inside tier | 3 |
| Impact | Critical |
| Maturity | Adopted — A ratified standard with real deployment. |
| Conditional | Yes — scored only on commercial sites |
| Publishing skill | `product-schema` |
| Standards | schema.org/Product |

## What is measured

Conditional: reported n/a and excluded from the score unless the scanner has already seen a commercial signal on the site (Product/Offer/AggregateOffer JSON-LD, an add-to-cart or buy-now action, or a cart/checkout link); this check itself never creates the signal. It then flattens the JSON-LD it holds for the homepage and, when reachable, the /products, /shop and /store paths, and passes on any "@type": "Product", "Offer" or "AggregateOffer" — a partial (0.7) when that markup exists only on a product or collection page, and a fail when no such type is found anywhere.

## Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

```bash
DOMAIN=shop.example.com
for p in / /products /shop; do printf '%s: ' "$p"; curl -sL "https://$DOMAIN$p" | grep -Eo '"@type"[[:space:]]*:[[:space:]]*"(Product|Offer|AggregateOffer)"' | sort -u | tr '\n' ' '; echo; done
```

## The fix

This is the artifact to ship. It is the complete change, not a description of one.

```html
<!-- /products/aurora-desk-lamp : the product itself -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Aurora Desk Lamp",
  "sku": "ADL-100-BLK",
  "description": "Dimmable LED desk lamp, 2700-5000K, USB-C.",
  "brand": { "@type": "Brand", "name": "Aurora" },
  "offers": {
    "@type": "Offer",
    "url": "https://shop.example.com/products/aurora-desk-lamp",
    "price": "1299.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}
</script>
<!-- Homepage / : the same Offer inside an ItemList, so the catalogue is readable from the root -->
<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "ItemList", "itemListElement": [
  { "@type": "Offer", "url": "https://shop.example.com/products/aurora-desk-lamp", "price": "1299.00", "priceCurrency": "USD", "availability": "https://schema.org/InStock" }
] }
</script>
```

> A Product that carries no Offer still fails the homepage test, so keep at least one Offer on / — an ItemList whose itemListElement entries are Offers is enough.

## Standards referenced

- `schema.org/Product`

## Related checks

| Check | Tier | Impact | Same skill |
| --- | --- | --- | --- |
| `payment-protocols` — Agent payment standard support (AP2/ACP/x402/UCP) | Recommended | High | — |
| `agent-purchase` — Agent purchase policy | Recommended | High | — |
| `ucp-manifest` — UCP manifest (/.well-known/ucp) | Emerging | Medium | — |
| `returns` — Return and shipping terms machine-readable | Recommended | Medium | — |
| `agent-analytics` — Agent traffic measurement | Emerging | Low | — |
| `inventory-freshness` — Inventory and price freshness | Recommended | High | — |
| `seller-identity` — Seller identity declared | Recommended | Medium | — |
| `shipping-costs` — Shipping cost and delivery declared | Recommended | High | — |
