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.
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.
Add a Review JSON-LD block to components/ReviewItem.tsx populated from the review database record.
// 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.
ID: ecommerce-reviews.schema-seo.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:
// 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>
</>
)
}