Skip to main content
All articles
5 min read

Building Geo-Aware Search with Algolia and Next.js

A practical guide to implementing location-based filtering in a directory app — from Algolia geo indices to the UX decisions that actually move conversion.

Algolia
Next.js
Search
UX

I've now shipped geo-aware search for two directory platforms — Seniornicity and Estate Sales Near Me. Both use Algolia with Next.js. Here's the practical guide I wish had existed when I started.

Indexing records with geo coordinates

Algolia's geo search requires a _geoloc field on each record with lat and lng. We geocode addresses at write time (using Google's Geocoding API) and store the coordinates in our Prisma DB, then include them when syncing to Algolia:

await algoliaIndex.saveObject({
  objectID: provider.id,
  name: provider.name,
  _geoloc: {
    lat: provider.latitude,
    lng: provider.longitude,
  },
  // ...other fields
})
Geocode at write time

Geocode when the record is created or updated — not at search time. This keeps the search path fast and avoids hitting the Google API on every user query.

The search UI: aroundLatLng vs. insideBoundingBox

For a "near me" experience, aroundLatLng with aroundRadius is the right primitive. We ask for the user's location via the browser Geolocation API and pass the coordinates directly to the Algolia query:

const results = await algoliaIndex.search(query, {
  aroundLatLng: `${lat},${lng}`,
  aroundRadius: radiusMeters,
  hitsPerPage: 20,
})

For a map-driven UI (pan the map → results update), switch to insideBoundingBox with the map viewport coordinates. We found the map approach converted better for estate sales because buyers care about neighborhood, not just distance.

Faceting with geo

Combining geo with attribute facets (service type, price range, rating) is where Algolia shines. We declared all filterable attributes in the index settings upfront — Algolia won't let you filter on undeclared attributes at query time.

Set up index settings first

You must configure attributesForFaceting in your Algolia dashboard (or via the API) before filtering on those attributes. Attempting to filter on an undeclared attribute silently returns unfiltered results — it doesn't throw an error.

URL-based state for shareability

We serialised the active search state (query, location, radius, facets) into the URL using Next.js's useSearchParams. This made search results shareable and bookmarkable — a critical feature for a directory that relies on referral traffic.

The nuqs library made the bidirectional sync between URL state and React state painless. If you're building search in Next.js, it's worth adding from day one.

The one thing I'd do first

Set up Algolia Analytics (click and conversion events) from the very first deployment. The data you collect in the first month will tell you which facets matter, which queries return no results, and where to focus query rules — things you can't easily retrofit once you have real usage patterns.

Analytics tip

Enable click analytics by sending clickedObjectIDsAfterSearch events when a user selects a result. This unlocks the "Click-through rate by position" report, which shows whether your ranking is actually working as intended.