Google Reviews
Google Business reviews integration via the Places API
Google Reviews Integration
The platform displays Google Business reviews on the storefront by fetching them from the legacy Google Places API (Place Details). Reviews are loaded server-side and cached via ISR to avoid client-side API calls.
Architecture
Reviews come from one server component fetcher, lib/server/google-data.ts, which calls the legacy Places API (Place Details) with ISR caching (2-hour revalidation). There is no client-accessible reviews endpoint; the former /api/reviews/google route was removed because it called the billable Places API (New) with no callers.
Environment Variables
| Variable | Description | Required |
|---|---|---|
GOOGLE_PLACES_API_KEY | Server-side Places API key | Recommended |
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY | Fallback if server key not set | Alternative |
GOOGLE_PLACE_ID | Google Place ID for the business | Recommended |
NEXT_PUBLIC_GOOGLE_PLACE_ID | Fallback public place ID | Alternative |
If no Place ID is configured, the fetcher returns empty reviews; set GOOGLE_PLACE_ID.
Setup
Find your Google Place ID
Search for your business on Google Maps and extract the Place ID from the URL, or use the Place ID Finder.
Enable the Places API
In Google Cloud Console, enable the Places API (New) for your project.
Configure environment variables
GOOGLE_PLACES_API_KEY=AIza...
GOOGLE_PLACE_ID=ChIJ...API Call
The Places API v1 is called with specific field masks:
GET https://places.googleapis.com/v1/places/{placeId}
Headers:
X-Goog-Api-Key: {apiKey}
X-Goog-FieldMask: reviews,rating,userRatingCountData Types
type Review = {
authorName: string
rating: number
text: string
relativePublishTime: string | null
}
type ReviewsData = {
reviews: Review[]
totalRating: number
totalReviews: number
}authorNamecomes fromreview.authorAttribution.displayNamerelativePublishTimeis formatted as a readable date string (e.g., "March 15, 2026")totalRatingis the aggregate business ratingtotalReviewsis the total review count fromuserRatingCount
Caching
Server Component Fetcher
Uses Next.js ISR with next: { revalidate: 7200 } (2 hours):
const response = await fetch(url, {
next: { revalidate: 7200 },
})API Route
Uses Next.js route segment config:
export const revalidate = 7200 // 2 hoursError Handling
The fetcher returns empty data on failure rather than throwing:
return { reviews: [], totalRating: 0, totalReviews: 0 }Key Files
| File | Purpose |
|---|---|
lib/server/google-data.ts | Server component data fetcher |
How is this guide?
Last updated on