# Individual Review schema is present for displayed reviews

- **Pattern:** `ab-001217` (`ecommerce-reviews.schema-seo.review-schema`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001217
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001217)

## Why it matters

Individual `Review` schema.org blocks make each shopper review eligible for its own rich result — author name, star rating, and date displayed inline in SERPs alongside the product. Without them, your reviews exist only in HTML that search crawlers cannot interpret as structured endorsements. The schema.org `Review.reviewRating` mapping requires `ratingValue` as a number and `author` as a `Person` object with a `name` field — omitting either means Google's parser rejects the block silently. Stores with per-review schema see measurably higher long-tail SERP presence because individual reviews can surface as standalone snippets for "[product] review" queries.

## Severity rationale

High because absent per-review schema.org markup forfeits rich-result eligibility for every individual review, reducing organic SERP visibility across all long-tail review queries.

## Remediation

Add a `Review` JSON-LD block to `components/ReviewItem.tsx` populated from the review database record.

```tsx
// components/ReviewItem.tsx
export function ReviewItem({ review }: { review: Review }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'Review',
    author: { '@type': 'Person', name: review.author_name ?? 'Anonymous' },
    reviewRating: {
      '@type': 'Rating',
      ratingValue: review.rating, // number, not string
      bestRating: 5,
      worstRating: 1
    },
    reviewBody: review.text,
    datePublished: review.created_at.toISOString()
  }

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
      />
      <article className="review">
        <strong>{review.author_name ?? 'Anonymous'}</strong>
        <StarDisplay rating={review.rating} />
        <time dateTime={review.created_at.toISOString()}>{formatDate(review.created_at)}</time>
        <p>{review.text}</p>
      </article>
    </>
  )
}
```

Validate the output with Google's Rich Results Test after deploying — the `ratingValue` type mismatch (string vs number) is the most common silent failure.

## Detection

- **ID:** `review-schema`
- **Severity:** `high`
- **What to look for:** Count the number of individual Review schema.org blocks generated per product page. For each Review block, count the required fields: (1) `@type: "Review"`, (2) `author` with name, (3) `reviewRating` with `ratingValue`, (4) `reviewBody`, (5) `datePublished`. Report: X of 5 fields present per review schema.
- **Pass criteria:** At least 3 displayed reviews per product page include JSON-LD schema markup with at least 4 of 5 required fields: `@type: "Review"`, `author` with name, `reviewRating` with `ratingValue`, `reviewBody`, and `datePublished`. The schema data must be populated from the review database record.
- **Fail criteria:** No individual Review schema found on any product page, or fewer than 3 reviews have schema markup, or Review blocks have fewer than 4 of 5 required fields.
- **Skip (N/A) when:** The project has no displayed reviews or no review display component exists.
- **Detail on fail:** `"0 individual Review schema blocks found on product pages. Reviews are rendered in HTML but invisible to structured data parsers."`
- **Remediation:** Add Review schema to the review display component in `components/ReviewItem.tsx`:

  ```tsx
  // components/ReviewItem.tsx
  export function ReviewItem({ review }) {
    const schema = {
      '@context': 'https://schema.org',
      '@type': 'Review',
      author: { '@type': 'Person', name: review.author_name },
      reviewRating: { '@type': 'Rating', ratingValue: review.rating },
      reviewBody: review.text,
      datePublished: review.created_at.toISOString()
    }

    return (
      <>
        <script type="application/ld+json">
          {JSON.stringify(schema)}
        </script>
        <article>
          {/* review display */}
        </article>
      </>
    )
  }
  ```

## External references

- schema-org Review
- schema-org Review.reviewRating

Taxons: findability

HTML version: https://auditbuffet.com/patterns/ab-001217
