Home › Guides

Product schema for AI shopping, with copy-paste JSON-LD

Updated 2026-10-16 · 12 min read · By the ProductSeen team

Structured data is a small block of code that labels the facts on your product page: this is the name, this is the price, this is in stock, this is the barcode. Search engines have used it for years. AI shopping assistants use the same labels to read your products quickly and accurately.

What "Product schema" means

schema.org/Product is a shared vocabulary for describing products. You add it to a page as JSON-LD, a <script type="application/ld+json"> block that visitors don't see. A crawler that reads the page gets clean facts instead of guessing from your layout.

The fields that matter, in priority order

FieldWhy AI shopping tools care
name, description, imageThe basics of what the product is and how it looks.
offers.price + priceCurrencyNeeded to answer "under $100" questions and compare prices.
offers.availabilityAssistants avoid recommending items they can't confirm are in stock.
brandLets the AI answer brand questions and trust the listing.
gtin (or gtin12/gtin13), mpn, skuUnique identifiers that match your item to the same product across the web. See our GTIN guide.
aggregateRating, review"Best rated" is a common way to shop.
shippingDetails, hasMerchantReturnPolicyAnswers "free shipping?" and "easy returns?" questions.
color, size, material, categoryHelps match specific requests like "black, size 10, leather".

Copy-paste JSON-LD (plain HTML)

Replace the values with your own. Every value must match what's visible on the page.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Men's Merino Wool Crew Sock, Cushioned",
  "description": "Midweight merino wool sock with a cushioned sole. Machine washable. Fits US men's sizes 8-12.",
  "image": [
    "https://yourstore.com/images/sock-front.jpg",
    "https://yourstore.com/images/sock-side.jpg"
  ],
  "sku": "MW-CREW-GRY-L",
  "gtin13": "0123456789012",
  "brand": { "@type": "Brand", "name": "Your Brand" },
  "color": "Gray",
  "material": "Merino wool",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.7",
    "reviewCount": "128"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://yourstore.com/products/merino-crew-sock",
    "price": "24.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "shippingDetails": {
      "@type": "OfferShippingDetails",
      "shippingRate": { "@type": "MonetaryAmount", "value": "0", "currency": "USD" },
      "shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
      "deliveryTime": {
        "@type": "ShippingDeliveryTime",
        "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
        "transitTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
      }
    },
    "hasMerchantReturnPolicy": {
      "@type": "MerchantReturnPolicy",
      "applicableCountry": "US",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": 30,
      "returnMethod": "https://schema.org/ReturnByMail",
      "returnFees": "https://schema.org/FreeReturn"
    }
  }
}
</script>

Only include aggregateRating if you display genuine customer reviews on the page.

Copy-paste JSON-LD for Shopify (Liquid)

First, check whether your theme already outputs Product schema (search your theme code for application/ld+json or structured_data). Many themes use Shopify's built-in {{ product | structured_data }} filter. If yours has nothing, or you want more fields, add a snippet like this to your product section or main-product template. Back up your theme first.

{%- assign v = product.selected_or_first_available_variant -%}
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": {{ product.title | json }},
  "description": {{ product.description | strip_html | strip_newlines | truncate: 5000 | json }},
  "url": {{ request.origin | append: product.url | json }},
  "image": [{% for img in product.images limit: 5 %}{{ img | image_url: width: 1200 | prepend: "https:" | json }}{% unless forloop.last %},{% endunless %}{% endfor %}],
  "brand": { "@type": "Brand", "name": {{ product.vendor | json }} },
  {%- if v.sku != blank %}"sku": {{ v.sku | json }},{% endif %}
  {%- if v.barcode != blank %}"gtin": {{ v.barcode | json }},{% endif %}
  "offers": [
    {%- for variant in product.variants -%}
    {
      "@type": "Offer",
      "name": {{ variant.title | json }},
      {%- if variant.sku != blank %}"sku": {{ variant.sku | json }},{% endif %}
      {%- if variant.barcode != blank %}"gtin": {{ variant.barcode | json }},{% endif %}
      "price": {{ variant.price | divided_by: 100.0 | json }},
      "priceCurrency": {{ cart.currency.iso_code | json }},
      "availability": "https://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}",
      "url": {{ request.origin | append: variant.url | json }}
    }{% unless forloop.last %},{% endunless %}
    {%- endfor -%}
  ]
}
</script>

Notes on this snippet:

Organization schema for your homepage

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Your Brand",
  "url": "https://yourstore.com",
  "logo": "https://yourstore.com/logo.png",
  "sameAs": [
    "https://www.instagram.com/yourbrand",
    "https://www.tiktok.com/@yourbrand"
  ],
  "contactPoint": { "@type": "ContactPoint", "contactType": "customer service", "email": "help@yourstore.com" }
}
</script>

How to test

  1. Run a product URL through Google's Rich Results Test or the Schema Markup Validator to catch syntax errors.
  2. Run a ProductSeen scan to see what share of your sampled products have price, availability, brand, GTIN and reviews.
  3. View the page source (not the browser inspector) to confirm the block is in the raw HTML. Crawlers that don't run JavaScript won't see schema that's injected later.

Mistakes to avoid

Next: give AI assistants a plain-text overview of your store with llms.txt.

See what AI can read about your products

Free scan: AI crawler access, Product schema, GTINs, reviews, sitemap and llms.txt. Results in under a minute, with the top fixes in plain English.

Scan my store free

Frequently asked questions

Does my Shopify theme already include Product schema?

Most current Shopify themes output Product JSON-LD, but many leave out brand, barcodes, reviews, shipping or return details. Older, custom and headless storefronts often have none. Test a product URL to know for sure.

Should I use JSON-LD or microdata?

Both are valid schema.org formats, but JSON-LD is easier to maintain because it sits in one script block instead of being woven through your HTML. Google recommends JSON-LD.

Can I add review markup for reviews I wrote myself?

No. Only mark up genuine reviews from customers that are visible on the page. Fake or self-written review markup violates Google's guidelines and can mislead shoppers.

Will having two Product schema blocks cause problems?

Duplicate or conflicting blocks can confuse parsers. If an app adds its own Product schema, remove or merge the theme's version so there's one complete, consistent block.

More guides