Welcome to the Jose Madrid Salsa developer docs — explore features, APIs, and deployment guides.
Jose Madrid SalsaJMS Docs

Google Places

Google Places API integration for location search, photos, and business details

Google Places Integration

The Google Places API is used to find retail locations by name and address, fetch business photos, and retrieve company logos. The integration supports both the new Places API (v1) and the legacy Places API as a fallback.

Architecture

The Places helper functions live in lib/google-places.ts. They are used during location data imports and enrichment to match database records with Google Places data and fetch high-quality photos.

Environment Variables

VariableDescriptionRequired
GOOGLE_PLACES_API_KEYServer-side Places API keyRecommended
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYFalls back to this if server key not setAlternative

Core Functions

findPlaceByNameAddress()

Searches for a business by name and address. Tries the v1 Text Search API first, falls back to the legacy Find Place API:

const result = await findPlaceByNameAddress({
  businessName: 'Kroger',
  address: '123 Main St',
  city: 'Columbus',
  state: 'OH',
})
// Returns: { place, photos: string[] }

v1 API request:

  • Endpoint: places.googleapis.com/v1/places:searchText
  • Fields: places.id, places.displayName, places.formattedAddress, places.location, places.photos, places.types
  • Location bias: 50km radius centered on the state

Legacy API fallback:

  • Endpoint: maps.googleapis.com/maps/api/place/findplacefromtext/json
  • Fields: place_id, name, formatted_address, photos

buildPlacesPhotoUrl()

Constructs a photo URL from either the new API photo name or a legacy photo reference:

// New API format (contains 'places/')
`${PLACES_API_BASE}/${photoReference}/media?key=${API_KEY}&maxWidthPx=${maxWidth}`

// Legacy format
`${LEGACY_PLACES_API_BASE}/place/photo?photoreference=${photoReference}&key=${API_KEY}&maxwidth=${maxWidth}`

getBestPhotoUrlForPlace()

Selects the best photo from a place's photo array:

  • Filters out photos without dimensions
  • Prefers horizontal orientation (wider aspect ratio)
  • Caps width at 1200px to avoid oversized images
  • Returns null if no suitable photos exist

getCompanyLogoFromWebsite()

Attempts to find a company logo from a website URL:

  1. Tries Clearbit logo API first (higher quality): logo.clearbit.com/{domain}
  2. Falls back to Google favicon API: google.com/s2/favicons?sz=256&domain={domain}
  3. Validates each URL with a HEAD request before returning

Retry Logic

All API calls use fetchWithRetry() with exponential backoff:

  • 3 retry attempts
  • Backoff: 1s, 2s, 4s
  • Retries on HTTP 429 (rate limit) and 5xx (server errors)
  • Non-retryable errors return immediately

A 100ms delay is added between place search results to respect rate limits.

Key Files

FilePurpose
lib/google-places.tsPlaces API helper functions
app/api/places/Places API route handler
lib/server/google-data.tsServer-side Places data fetcher (reviews)

How is this guide?

Edit on GitHub

Last updated on

On this page