**TL;DR.** Product review structured data drives star ratings in Google SERPs and AI search citations. Emit `aggregateRating` for products with 3+ reviews and individual `review[]` for the top 3–10. Collect reviews through a verified channel — fake or self-serving reviews get penalized.

## Why review schema matters

Star ratings in SERP listings increase CTR by 10–30% in competitive niches. AI engines (Perplexity, ChatGPT) also surface aggregate ratings when answering "what's the best..." queries.

Real-world impact:

- A 4.7-star product with 200 reviews outclicks a starless product even at a lower position.
- Google AI Overviews surfaces "X has a 4.7 average rating across 200 reviews" when reviews are structured.
- Conversion lifts: 5–15% from star display alone.

## aggregateRating

The core structured data:

```json
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Brown Leather Messenger Bag",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.7",
    "reviewCount": 218,
    "bestRating": "5",
    "worstRating": "1"
  }
}
```

Fields:

- `ratingValue`: the average rating, typically with one decimal.
- `reviewCount`: total number of reviews aggregated.
- `bestRating`: usually 5. Default if omitted.
- `worstRating`: usually 1. Default if omitted.
- `ratingCount`: alternative to `reviewCount` for ratings without written content.

## Individual review[]

To strengthen citability — both for Google's Rich Results and AI engines — emit the top 3–10 individual reviews:

```json
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Brown Leather Messenger Bag",
  "aggregateRating": { ... },
  "review": [
    {
      "@type": "Review",
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "5",
        "bestRating": "5"
      },
      "author": {
        "@type": "Person",
        "name": "M.J."
      },
      "datePublished": "2026-04-12",
      "reviewBody": "Beautifully crafted bag. Leather is full-grain and stitching is clean. Hardware feels solid. Carrying it daily for 3 months and it's aging perfectly."
    },
    {
      "@type": "Review",
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "4",
        "bestRating": "5"
      },
      "author": {
        "@type": "Person",
        "name": "K.L."
      },
      "datePublished": "2026-03-28",
      "reviewBody": "Beautiful bag. Slightly larger than I expected — be sure to check dimensions. Quality is excellent."
    }
  ]
}
```

Required per `Review`:

- `reviewRating.ratingValue`
- `author.name` (Person or Organization)
- `datePublished`
- `reviewBody` (the actual text)

Optional but helpful:

- `name` (review title)
- `reviewAspect` (specific aspect rated)

## Verified reviews only

Google's [review snippet guidelines](https://developers.google.com/search/docs/appearance/structured-data/review-snippet) require reviews to be:

- From real customers (not fake or self-written).
- About a specific product (not the store overall, unless on the store's page).
- Original (not duplicates of reviews on other sites).

How to collect verified reviews:

1. **Post-purchase email**: ask customers 5–14 days after delivery to leave a review. Include a verification token in the link.
2. **Third-party platforms**: Trustpilot, Yotpo, Reviews.io, Google Customer Reviews. These platforms verify customer identity (typically via order match) and provide structured data.
3. **Native integration**: collect reviews directly in your storefront with order-history verification.

Avoid:

- Anonymous reviews from unverified visitors.
- AI-generated review content.
- "Friends and family" reviews not flagged as such.
- Buying reviews from third parties.

Penalty for self-serving / manipulative reviews: SERP demotion, sometimes site-wide.

## The self-serving review penalty

In 2019 Google introduced the "self-serving review" rule. The rule: **don't emit review schema for the entity that owns the page.**

| Schema location               | Allowed?                          |
| ----------------------------- | --------------------------------- |
| Product schema on a PDP        | Yes (about the product)            |
| Organization schema on home    | **No** (about the brand itself)    |
| LocalBusiness schema on About  | **No**                             |
| Service schema on a service page | **No**                          |
| Recipe / Book / Movie reviews   | Yes if from real consumers          |

Result: star ratings on Product schema show in SERPs. Self-serving Organization reviews are silently stripped.

## Combine with 2026 Product schema

A complete 2026 Product JSON-LD:

```json
{
  "@context": "https://schema.org",
  "@type": "Product",
  "@id": "https://example.com/products/leather-bag#product",
  "name": "Brown Leather Messenger Bag",
  "description": "Handcrafted full-grain leather messenger bag with brass hardware.",
  "image": ["https://example.com/.../leather-bag.avif"],
  "brand": { "@type": "Brand", "name": "Acme" },
  "sku": "ACM-MSGR-001",
  "gtin": "1234567890123",
  "material": "leather",
  "color": "brown",
  "offers": {
    "@type": "Offer",
    "price": "149.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock",
    "url": "https://example.com/products/leather-bag",
    "hasMerchantReturnPolicy": { "@id": "https://example.com/#return-policy" },
    "shippingDetails": { "@id": "https://example.com/#shipping-us" }
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.7",
    "reviewCount": 218,
    "bestRating": "5",
    "worstRating": "1"
  },
  "review": [ /* top 3–10 reviews */ ]
}
```

## Validating

1. [Google Rich Results Test](https://search.google.com/test/rich-results) — confirms eligibility and previews the star display.
2. [Schema Markup Validator](https://validator.schema.org) — syntax-only validation.
3. Google Search Console → Enhancements → Review snippets — production coverage.

## Cache invalidation

When a new review arrives, update aggregateRating and re-render the PDP. In Next.js with cache tags:

```ts
async function submitReview(productId: string, review: ReviewInput) {
  await db.reviews.insert({ productId, ...review });
  await recomputeProductRating(productId);
  revalidateTag(`product-rating-${productId}`);
  revalidateTag(`product-${productId}`);
}
```

The `product-rating-{id}` tag refreshes JSON-LD aggregateRating; the `product-{id}` tag refreshes the full PDP.

## How Ordiko emits review schema

- `aggregateRating` from `products.reviewSummary` materialized view.
- Top 5 `review[]` from `reviews` table (sorted by helpfulness or recency).
- Cache tag `seoTags.productRating` invalidated on every review write.
- Built-in verified-customer flag — only verified reviews count toward aggregate.
- Locale-aware: review schema served in the locale of the page.

## FAQ

**How many reviews do I need before adding aggregateRating?**
Schema.org doesn't specify a minimum, but Google recommends at least 3 to avoid sparse-data warnings. Below 3, omit aggregateRating — emitting a 5-star rating from one review can look manipulative.

**Can I emit reviews collected outside my site (e.g., Trustpilot)?**
Yes if the review is genuinely about the product (not the store) and you have rights to display it. Cross-domain reviews are valid schema. Many merchants use Trustpilot, Yotpo, or Google Customer Reviews and re-emit the review schema on the product page.

**Why did Google stop showing stars for some product pages?**
In 2019 Google restricted review snippets — they no longer show for 'self-serving reviews' (reviews of your own business on your own site). They still show for product reviews collected from real customers. If you lost stars, check whether your reviews are actually customer-driven.

**How does Ordiko emit review schema?**
Ordiko's storefront PDP emits aggregateRating from the products.reviewSummary view and the top 5 review[] entries from the reviews table. The cache tag seoTags.productRating invalidates on every new review, keeping the schema fresh.
