Building a Store Locator with a Geocoding API

"Where is your nearest store?" is one of the oldest features on the web, and its architecture has not changed: coordinates for your stores, coordinates for the visitor, and a distance calculation between them. A geocoding API supplies the first two; a few lines of JavaScript or SQL supply the third.

Step 1: Geocode Your Stores - Once

Your store addresses rarely change, so geocode them once and save the coordinates in your database. Because ExoAPI allows storing results, this is a one-time setup cost measured in a handful of API requests:

import { ExoAPI } from "@flower-digital/exoapi-sdk";

const exoapi = new ExoAPI({ apiKey: "<your-api-key>" });

for (const store of stores) {
  const res = await exoapi.geocoding({ address: store.address });
  await db.stores.update(store.id, { lat: res.lat, lon: res.lon });
}

Step 2: Geocode the Visitor's Search

When a visitor types a city or an address, geocode it to get their reference point:

const search = await exoapi.geocoding({
  address: req.query.q, // e.g. "Manchester, United Kingdom" or a full address
  locale: "en-GB",
});

If the visitor allows browser geolocation instead, you already have their coordinates and can skip this call entirely - or use reverse geocoding (included in the same subscription) to display the detected location back to them as a readable label.

Step 3: Find the Nearest Stores

Now both sides are coordinates, and "nearest" becomes a math question: what is the distance between two points on the surface of the Earth? The standard answer is the haversine formula. You do not need to understand its trigonometry to use it - it takes two latitude/longitude pairs and returns the straight-line ("as the crow flies") distance between them, accounting for the curvature of the Earth. The 6371 you'll see in the code is simply the Earth's radius in kilometers, so the result comes out in kilometers too.

Note that this is straight-line distance, not driving distance - for a store locator that is almost always fine, since ranking by straight-line distance and ranking by driving time agree in the vast majority of cases.

Option A: Plain JavaScript

If you have up to a few thousand stores, you don't need any database features: load the stores, compute the distance to each, and sort.

function distanceKm(a, b) {
  const rad = (deg) => (deg * Math.PI) / 180;
  const h = Math.sin(rad(b.lat - a.lat) / 2) ** 2 + Math.cos(rad(a.lat)) * Math.cos(rad(b.lat)) * Math.sin(rad(b.lon - a.lon) / 2) ** 2;
  return 6371 * 2 * Math.asin(Math.sqrt(h));
}

const visitor = { lat: search.lat, lon: search.lon };
const nearest = stores
  .map((store) => ({ ...store, distanceKm: distanceKm(visitor, store) }))
  .sort((a, b) => a.distanceKm - b.distanceKm)
  .slice(0, 5);

Option B: In SQL

With a bigger store list, or when you'd rather not load every store into memory, the same formula runs directly in your database query:

SELECT
  id,
  name,
  address,
  6371 * 2 * ASIN(SQRT(
    POWER(SIN(RADIANS(:lat - lat) / 2), 2) +
    COS(RADIANS(lat)) * COS(RADIANS(:lat)) *
    POWER(SIN(RADIANS(:lon - lon) / 2), 2)
  )) AS distance_km
FROM stores
ORDER BY distance_km
LIMIT 5;

:lat and :lon are the visitor's coordinates; lat and lon are the columns you filled in step 1. If your database is PostgreSQL with the PostGIS extension installed, its built-in ST_DistanceSphere function computes the same thing - but for a store locator, the plain SQL above works on any database with no extensions at all.

Step 4: Show It on Any Map

ExoAPI returns plain JSON with no display-platform requirement, so render the results with whatever you already use - Leaflet with OpenStreetMap tiles, MapLibre, or a plain list with distances. When displaying OpenStreetMap-derived data on a map, keep the "© OpenStreetMap contributors" attribution.

What This Costs

A store locator is a light geocoding workload: the store list is geocoded once and cached forever, so you only pay for visitor searches. The 9€/month Starter plan covers 1,000 searches per day - and the same subscription includes every other ExoAPI API, from QR codes for "open in maps" links to HTML-to-PDF for printable directions.

Start a free 14-day trial - no credit card required - and have your store list geocoded before lunch.


Get started building.

Sign up today and get access to our platform's easy-to-use APIs, all with just one subscription
No credit card required