Rocky_Mountain_Vending/components/review-schema.tsx

87 lines
2.2 KiB
TypeScript

import { businessConfig } from "@/lib/seo-config"
interface Review {
author?: string
rating?: number
reviewBody?: string
datePublished?: string
}
interface ReviewSchemaProps {
aggregateRating?: {
ratingValue: number
reviewCount: number
bestRating?: number
worstRating?: number
}
reviews?: Review[]
}
/**
* Review Schema Component
* Implements AggregateRating and Review schema markup for SEO
* Based on review data from reputation hub and Google reviews
*/
export function ReviewSchema({ aggregateRating, reviews }: ReviewSchemaProps) {
if (!aggregateRating && (!reviews || reviews.length === 0)) {
return null
}
const structuredData: any = {
"@context": "https://schema.org",
"@type": "AggregateRating",
}
if (aggregateRating) {
structuredData.ratingValue = aggregateRating.ratingValue
structuredData.reviewCount = aggregateRating.reviewCount
structuredData.bestRating = aggregateRating.bestRating || 5
structuredData.worstRating = aggregateRating.worstRating || 1
}
// If we have individual reviews, create a full Review schema
if (reviews && reviews.length > 0) {
const reviewItems = reviews.map((review) => ({
"@type": "Review",
author: {
"@type": "Person",
name: review.author || "Customer",
},
reviewRating: review.rating
? {
"@type": "Rating",
ratingValue: review.rating,
bestRating: 5,
worstRating: 1,
}
: undefined,
reviewBody: review.reviewBody,
datePublished: review.datePublished,
}))
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "LocalBusiness",
name: businessConfig.name,
aggregateRating: structuredData,
review: reviewItems,
}),
}}
/>
</>
)
}
// Just aggregate rating
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
/>
)
}