Introduction
One thing that quietly never gets done on a property website is information about nearby businesses. You'd like to list "the closest supermarket" and "places we recommend for dinner," but opening hours change and shops close down. Hand-written information is usually stale within six months.
In this article, we share how we built an area guide page by combining the Google Places API with our own data. Freshness is maintained automatically, while the question of what to recommend stays firmly a decision of the property.
"Why we recommend it" is ours; "how it is right now" is Google's
Drawing a clear line between the two
The first thing we decided was who owns which piece of information. Which places to list and why we recommend them: the property decides. Changing details like opening hours and ratings: pull from Google. Holding that line without wavering became the starting point for every other design choice.
In the admin panel, each place has individual toggles for whether to show opening hours and whether to show ratings. That lets you hide ratings for categories where they aren't useful, like convenience stores.
What you may store, and what you may not
The Google Places API comes with an important rule in its terms of service: of the data you fetch, the only thing you may store indefinitely is the Place ID (the identifier for a business). Opening hours and ratings may only be held temporarily as a cache.
Don't save ratings or opening hours to your database
Saving ratings and opening hours to your own database because "calling the API every time is wasteful" puts you in violation of the terms. We stuck to the principle that the database holds Place IDs only, and everything else stays in a short-lived cache.
So our database stores nothing but the Place ID, and we fetch from the API each time we render. Results are cached for just six hours, so repeated visits to the same page don't multiply API calls.
Keep the page intact even when things break
External APIs go down eventually — that's a given. If the whole area guide page errors out because Google didn't respond, we've defeated the purpose.
So the fetch logic never throws on failure; it returns "no information" instead. Only the opening hours and ratings disappear, while the descriptions and directions written by the property keep showing. The page always holds together. That principle applies to every feature that depends on an external service.
How you use the API changes the bill enormously
Don't fetch what you won't use
The Places API charges differently depending on which fields you request. In one real incident, a screen that doesn't display photos was still fetching photo data, generating more than 2,000 wasted calls a month.
So we added an option on the calling side to explicitly say "no photos needed," and stopped fetching them in contexts where they aren't used — like when the AI assistant looks up nearby information. Fetch only what you use. Simple, but it goes straight to the bill.
Being smarter about how results are sorted
Search for nearby businesses and you'll sometimes find a place with a perfect score from a single review sitting at the top. That's not much help to anyone.
So we implemented our own sorting: prioritize places with at least 15 reviews, then order by rating within that group. Note that we only lower the priority of places with few reviews — we don't exclude them.
Keeping API keys in separate places
We split the Google Maps-related keys by what they're used for.
Place details, photos, text search. Never handed to the browser
Embedded map display only, restricted by referring domain
Photos are served after the server resolves the URL, so the server key never leaks into the browser. For the embedded-map key, which has to be exposed to the browser, we always apply a restriction that only allows calls from our own site.
Embedding place cards in blog posts too
Keep only the Place ID in the article
When you write about a business on the blog, putting the name and opening hours into the body of the post means it goes stale, same as anywhere else. So we built a "search for a place and insert it" feature into the admin panel's editor, and what actually gets embedded in the article is just the Place ID.
The moment the article renders, it pulls the current name and rating from the API and shows them alongside the property's own comment. Even in a five-year-old post, the name and rating are today's. The only thing that persists as an asset of the article is the recommendation the operator wrote.
Preventing rapid-fire searches
If the place search in the admin panel called the API on every keystroke, the charges would pile up. So we set a rate limit of a little over a second between searches, cutting out wasted calls from rapid typing. It's not "the admin panel is safe" — it's that the admin panel is exactly where costs creep up without you noticing.
Wrapping up
Three things mattered most in designing the area guide page.
- Decide who owns what — the reason to recommend is ours, the current state is Google's. Don't mix them
- Respect the terms and the budget — store Place IDs only, and don't fetch what you won't use
- Hold together when things break — during an API outage, keep the page running on our own information
This nearby-places data also feeds the answers given by the AI assistant for staying guests. See "The big picture of an AI assistant for staying guests" for more.
The Big Picture of an AI Assistant for Staying Guests
The design of an AI concierge that also answers questions about the surrounding area.
Blog and Announcements Run In-House — A Custom CMS for a Vacation Rental Site
How we built a blog admin panel that can insert place cards.
Building a Direct-Booking Platform for a Vacation Rental
For the structure and thinking behind the whole direct-booking site, start with this hub article.