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 Google Places API (v1). Reviews are loaded server-side and cached via ISR to avoid client-side API calls.
Architecture
Two data paths serve reviews:
- Server component fetcher (
lib/server/google-data.ts) -- Used by server components with ISR caching (2-hour revalidation) - API route (
app/api/reviews/google/route.ts) -- Client-accessible endpoint with 2-hour cache
Both call the same Google Places API endpoint.
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 |
GOOGLE_PLACE_NAME | Business name for place search (defaults to "Jose Madrid Salsa") | No |
If no Place ID is configured, the API route will attempt to find it by searching for the business name via the Places Text Search API.
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
Both implementations return empty data on failure rather than throwing:
return { reviews: [], totalRating: 0, totalReviews: 0 }The API route returns HTTP 200 with empty reviews and an error message in the response body to prevent UI breakage.
Key Files
| File | Purpose |
|---|---|
lib/server/google-data.ts | Server component data fetcher |
app/api/reviews/google/route.ts | Client-accessible reviews endpoint |
How is this guide?
Last updated on