Guide
Composables
useReviews() and useReviewSchema() — reactive, type-safe review data and Schema.org JSON-LD.
useReviews()
The useReviews() composable is auto-imported and provides reactive access to your review data.
Basic Usage
<script setup lang="ts">
const { reviews, aggregate, pending } = useReviews()
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else>
<p>Average: {{ aggregate?.average }} ({{ aggregate?.total }} reviews)</p>
<div v-for="review in reviews" :key="review.id">
<strong>{{ review.author.name }}</strong> — {{ review.rating }}/5
<p>{{ review.text }}</p>
</div>
</div>
</template>
Options
const { reviews, aggregate, sources, nextPageToken, totalAvailable, pending, error, refresh } = useReviews({
provider: 'google', // 'google' | 'trustpilot' | 'serpapi' | 'outscraper' | 'bookingcom' | 'mock' | 'all'
limit: 20,
language: 'en',
sort: 'newest',
minRating: 3,
pageToken: undefined, // pagination token from a previous response
immediate: true // fetch on mount (default: true)
})
Return Values
| Property | Type | Description |
|---|---|---|
reviews | ComputedRef<NormalizedReview[]> | Array of normalized reviews |
aggregate | ComputedRef<AggregateRating | null> | Average, total, and star distribution |
sources | ComputedRef<{ provider, count, average }[]> | Per-provider breakdown |
nextPageToken | ComputedRef<string | undefined> | Token for fetching next page (single-provider only) |
totalAvailable | ComputedRef<number | undefined> | Total reviews on the platform (single-provider only) |
pending | Ref<boolean> | Loading state |
error | Ref<Error | null> | Error state |
refresh | () => Promise<void> | Manually re-fetch reviews |
Provider-Specific Fetch
const { reviews: googleReviews } = useReviews({ provider: 'google' })
const { reviews: tpReviews } = useReviews({ provider: 'trustpilot' })
const { reviews: mockReviews } = useReviews({ provider: 'mock' })
// All configured providers (aggregated)
const { reviews: allReviews } = useReviews({ provider: 'all' })
Pagination
nextPageToken and totalAvailable are available in single-provider mode. Pass the token back as pageToken to fetch the next page:
const page1 = useReviews({ provider: 'serpapi', limit: 10 })
// When ready to load next page:
const page2 = useReviews({
provider: 'serpapi',
limit: 10,
pageToken: page1.nextPageToken.value
})
nextPageToken is undefined in aggregated mode (provider: 'all').Lazy Load
const { reviews, refresh: loadReviews } = useReviews({
provider: 'all',
immediate: false // don't fetch on mount
})
// Trigger manually — e.g. on button click or intersection observer
await loadReviews()
useReviewSchema()
useReviewSchema() auto-injects a <script type="application/ld+json"> block into your page <head> with Schema.org structured data. This enables Google rich snippets — star ratings appearing in search results.
Basic Usage
<script setup lang="ts">
const { reviews, aggregate } = useReviews()
useReviewSchema(reviews, aggregate, {
name: 'Grand Hotel Istanbul',
})
</script>
Options
useReviewSchema(reviews, aggregate, {
name: 'Grand Hotel Istanbul', // required
description: 'Luxury hotel in Istanbul',
url: 'https://example.com',
image: 'https://example.com/hotel.jpg',
type: 'Hotel', // Schema.org @type, default: 'LocalBusiness'
})
| Option | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Business/entity name |
description | string | No | Short description |
url | string | No | Canonical page URL |
image | string | No | Business image URL |
type | string | No | Schema.org @type (default: 'LocalBusiness') |
Common type values: Hotel, Restaurant, TouristAttraction, LocalBusiness.
Generated Output
The composable generates an AggregateRating entry plus up to 20 individual Review entries — Google's minimum for rich snippet eligibility:
{
"@context": "https://schema.org",
"@type": "Hotel",
"name": "Grand Hotel Istanbul",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": 120,
"bestRating": 5,
"worstRating": 1
},
"review": [
{
"@type": "Review",
"author": { "@type": "Person", "name": "Ahmet Y." },
"datePublished": "2025-03-20",
"reviewBody": "Harika bir otel deneyimi...",
"reviewRating": { "@type": "Rating", "ratingValue": 5, "bestRating": 5, "worstRating": 1 }
}
]
}
Returns
const { schema } = useReviewSchema(reviews, aggregate, { name: 'My Business' })
// schema is a ComputedRef<Record<string, unknown> | null>
Server API Routes
The module automatically registers these Nitro server routes:
| Route | Description |
|---|---|
GET /api/_reviews | Fetch from all configured providers (aggregated) |
GET /api/_reviews/:provider | Fetch from a specific provider |
Query Parameters
| Param | Type | Description |
|---|---|---|
limit | number | Max reviews to return |
language | string | Language filter (e.g. tr, en) |
sort | string | Sort order (provider-specific) |
minRating | number | Minimum rating filter (1-5) |
pageToken | string | Pagination token (single-provider only) |