Product

Product markup is how you tell search engines about a physical or digital good for sale. It powers the Product snippet rich result (star rating, price, availability) and the Merchant listing rich result (the shopping card shown above regular results). For ecommerce sites this is the single highest-impact schema type.

The example is XooTee Classic, a fictional graphic t-shirt made by Xoo Code Inc. and sold at the Dunmore store. It follows the schema.org/Product vocabulary and it's the first XooCode example to demonstrate @id cross-references. The brand and manufacturer both resolve to the Organization example's Xoo Code Inc. The offers.seller resolves to the LocalBusiness example's Dunmore store. No entity is redefined inline. Once your Organization and LocalBusiness entities have stable @ids, every Product you mark up can reference them with three lines instead of thirty.

The entry also covers the two Google requirements authors miss most often: priceValidUntil (so Google doesn't suppress your offer after 90 days) and a populated aggregateRating with either reviewCount or ratingCount set (without one, the review snippet won't render).

Full example of schema.org/Product json-ld markup

The markup is verified as valid with Rich Results Test from Google.

Highlight legend:Required by GoogleRecommendedOptional
schema.org/Product
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@id": "https://xoocode.com/shop/xootee-classic#product",
  "@type": "Product",
  "name": "XooTee Classic",
  "description": "A premium cotton t-shirt printed with a stylized rendering of Jane Xoo's 1945 handwritten pediatric medical notes. Designed and produced by Xoo Code Inc., sold exclusively at the Xoo Code Shop Dunmore. Limited annual production run.",
  "image": [
    "https://xoocode.com/shop/xootee/xootee-classic-front.jpg",
    "https://xoocode.com/shop/xootee/xootee-classic-back.jpg",
    "https://xoocode.com/shop/xootee/xootee-classic-detail.jpg"
  ],
  "sku": "XOO-TEE-CL-001",
  "gtin13": "5710911234567",
  "mpn": "XOO-CLASSIC-1945",
  "productID": "xoo:XOO-TEE-CL-001",
  "url": "https://xoocode.com/shop/xootee-classic",
  "brand": {
    "@id": "https://xoocode.com#organization"
  },
  "manufacturer": {
    "@id": "https://xoocode.com#organization"
  },
  "category": "Apparel > T-Shirts > Graphic",
  "color": "Natural Bone",
  "material": "100% Organic Cotton",
  "weight": {
    "@type": "QuantitativeValue",
    "value": "220",
    "unitCode": "GRM"
  },
  "audience": {
    "@type": "PeopleAudience",
    "suggestedGender": "unisex",
    "suggestedMinAge": "16"
  },
  "award": "Scandinavian Design Finalist 2024",
  "offers": {
    "@type": "Offer",
    "@id": "https://xoocode.com/shop/xootee-classic#offer",
    "url": "https://xoocode.com/shop/xootee-classic",
    "price": "495.00",
    "priceCurrency": "DKK",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "priceValidUntil": "2026-12-31",
    "seller": {
      "@id": "https://xoocode.com/shop/dunmore-1290"
    },
    "hasMerchantReturnPolicy": {
      "@type": "MerchantReturnPolicy",
      "applicableCountry": "DK",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": "30",
      "returnMethod": "https://schema.org/ReturnByMail",
      "returnFees": "https://schema.org/FreeReturn"
    },
    "shippingDetails": {
      "@type": "OfferShippingDetails",
      "shippingRate": {
        "@type": "MonetaryAmount",
        "value": "49.00",
        "currency": "DKK"
      },
      "shippingDestination": {
        "@type": "DefinedRegion",
        "addressCountry": "DK"
      },
      "deliveryTime": {
        "@type": "ShippingDeliveryTime",
        "handlingTime": {
          "@type": "QuantitativeValue",
          "minValue": "0",
          "maxValue": "1",
          "unitCode": "DAY"
        },
        "transitTime": {
          "@type": "QuantitativeValue",
          "minValue": "1",
          "maxValue": "3",
          "unitCode": "DAY"
        }
      }
    }
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "@id": "https://xoocode.com/shop/xootee-classic#rating",
    "ratingValue": "4.5",
    "reviewCount": "2",
    "bestRating": "5",
    "worstRating": "1"
  },
  "review": [
    {
      "@type": "Review",
      "author": {
        "@type": "Person",
        "name": "Dana Crook"
      },
      "datePublished": "2024-11-03",
      "name": "Comfortable and conversation-starting",
      "reviewBody": "Picked this up at the Dunmore store after reviewing the shop itself last year. The print holds up after many washes and the cotton is genuinely soft. Love that the graphic tells a story.",
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "4",
        "bestRating": "5",
        "worstRating": "1"
      }
    },
    {
      "@type": "Review",
      "author": {
        "@type": "Person",
        "name": "Eva Lindgren"
      },
      "datePublished": "2024-12-18",
      "name": "A thoughtful gift",
      "reviewBody": "Bought one for my sister who is a nurse — she recognized the handwriting as medical notation immediately. Lovely concept, well executed.",
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "5",
        "bestRating": "5",
        "worstRating": "1"
      }
    }
  ],
  "isRelatedTo": {
    "@type": "Product",
    "name": "XooShoes Dunmore Edition",
    "url": "https://xoocode.com/shop/xooshoes-dunmore"
  },
  "isSimilarTo": {
    "@type": "Product",
    "name": "XooPremium Hooded Long Sleeve",
    "url": "https://xoocode.com/shop/xoopremium-hoodie"
  },
  "releaseDate": "2024-09-01"
}
</script>

Rich result preview

Approximate preview of what Google may render from this markup. Hover any element inside the card to see which JSON-LD path produced it. Google decides whether to show any rich result. Markup makes you eligible, not guaranteed.

google.com/search?q=buy%20xootee%20classic
(image)

XooTee Classic

A premium cotton t-shirt printed with a stylized rendering of Jane Xoo's 1945 handwritten pediatric medical notes. Designed and produced by

495.00 DKK4.5(2)In stock

Minimal valid version

The smallest markup that still produces a valid Product entity. Use it as the floor. Reach for the advanced example above when you want search engines and AI agents to understand more about your content.

schema.org/Product (minimal)
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "XooTee Classic",
  "image": "https://xoocode.com/shop/xootee/xootee-classic-front.jpg",
  "offers": {
    "@type": "Offer",
    "price": "495.00",
    "priceCurrency": "DKK",
    "availability": "https://schema.org/InStock"
  }
}
</script>

Google rich results this unlocks

Markup matching this example makes your page eligible for the following Google Search rich results. The primary target drives the required / recommended property classification in the advanced code block above.

Common Product mistakes

Mistakes that pass validation but silently fail to earn rich results or mislead consumers walking the graph. Avoid these and your markup will be ahead of most sites in the wild.

  1. 01

    Price with currency symbol in the string

    Wrong
    "price": "$19.99"
    Right
    "price": "19.99",
    "priceCurrency": "USD"

    Google silently rejects prices that contain currency symbols or commas. The price value must be numeric (as a string or number) and the currency must live in a separate priceCurrency field using the ISO 4217 three-letter code.

  2. 02

    Missing priceValidUntil

    Wrong
    Offer without priceValidUntil
    Right
    "priceValidUntil": "2026-12-31"

    Google treats offers without priceValidUntil as stale after roughly 90 days and may suppress the Product snippet. Set it to a realistic future date and keep it updated. A surprising number of ecommerce sites lose their rich results to this single missing field.

  3. 03

    aggregateRating without reviewCount or ratingCount

    Wrong
    "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": "4.5"
    }
    Right
    "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": "4.5",
      "reviewCount": "2"
    }

    schema.org doesn't strictly require reviewCount or ratingCount, so validators pass. But Google requires at least one of them for the Review snippet rich result. This is the classic 'valid schema, no rich result' trap.

Compare your markup against this exampleruns in your browser
Private. Runs entirely in your browser.

Comments

Loading comments...

Leave a comment