DEV Community

Cover image for Building a "Find Stores Near Me" Feature with Geolocation
Talha Khwaja
Talha Khwaja

Posted on

Building a "Find Stores Near Me" Feature with Geolocation

A "Find Stores Near Me" button looks simple: get the user's location, compare it with your stores, and show the closest results.

But once you start building it, a few questions appear. How do you request location safely? How do you calculate which store is actually closest? What happens when permission is denied? And does the same approach still work with thousands of locations?

Let's build the basic version in JavaScript and then look at what needs to change for production.

How Does "Find Stores Near Me" Work?

At its simplest, the process looks like this:

User clicks "Find Stores Near Me"
        ↓
Browser requests location permission
        ↓
Get user's latitude + longitude
        ↓
Compare with store coordinates
        ↓
Calculate + sort by distance
        ↓
Display nearest stores
Enter fullscreen mode Exit fullscreen mode

The browser doesn't actually know which store is closest. It gives us the user's coordinates; finding the nearest location is our job.

1. Get the User's Location

Modern browsers provide the Geolocation API:

navigator.geolocation.getCurrentPosition(
  (position) => {
    const userLat = position.coords.latitude;
    const userLng = position.coords.longitude;

    console.log(userLat, userLng);
  },
  (error) => {
    console.error("Location unavailable:", error.message);
  },
  {
    enableHighAccuracy: true,
    timeout: 10000,
    maximumAge: 60000
  }
);
Enter fullscreen mode Exit fullscreen mode

The browser asks the visitor for permission before returning their location. Request location when the visitor actually uses the feature, and explain why you need it rather than triggering the permission dialog immediately on page load.

Geolocation generally requires HTTPS, and users can deny permission. Your application should therefore provide another way to search, such as entering a city, ZIP/postal code, or address.

In the options above, enableHighAccuracy asks for a more precise position when available, timeout limits how long we're willing to wait, and maximumAge allows the browser to reuse a recent cached position.

For WordPress implementations, permission prompts can become part of the locator UX.

This guide covers geolocation in a WordPress store locator, including prompting visitors and triggering location detection from a custom button.

2. Prepare Your Store Coordinates

Every store needs latitude and longitude coordinates:

const stores = [
  { name: "Downtown Store", lat: 40.7128, lng: -74.0060 },
  { name: "Uptown Store", lat: 40.7831, lng: -73.9712 },
  { name: "Brooklyn Store", lat: 40.6782, lng: -73.9442 }
];
Enter fullscreen mode Exit fullscreen mode

If you only have street addresses, you'll first need to convert them into coordinates using a geocoding service.

Once both the visitor and stores have coordinates, we can compare them.

3. Calculate the Nearest Store

For a basic implementation, the Haversine formula calculates the straight-line distance between two geographic coordinates.

function calculateDistance(lat1, lon1, lat2, lon2) {
  const R = 6371; // Earth radius in kilometers
  const dLat = (lat2 - lat1) * Math.PI / 180;
  const dLon = (lon2 - lon1) * Math.PI / 180;

  const a =
    Math.sin(dLat / 2) ** 2 +
    Math.cos(lat1 * Math.PI / 180) *
    Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon / 2) ** 2;

  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
Enter fullscreen mode Exit fullscreen mode

We can calculate each store's distance and sort the results:

const nearestStores = stores
  .map(store => ({
    ...store,
    distance: calculateDistance(
      userLat, userLng, store.lat, store.lng
    )
  }))
  .sort((a, b) => a.distance - b.distance);

Enter fullscreen mode Exit fullscreen mode

nearestStores[0] is now the closest location.

Remember that Haversine gives us straight-line distance, not driving distance or travel time. Those require a routing service.

4. Put It Together: A Working "Find Stores Near Me" Button

Now let's connect the pieces.

<button id="find-nearby">Find Stores Near Me</button>
<div id="results"></div>
Enter fullscreen mode Exit fullscreen mode
document.getElementById("find-nearby").addEventListener("click", () => {
  navigator.geolocation.getCurrentPosition(
    ({ coords }) => {
      const nearest = stores
        .map(store => ({
          ...store,
          distance: calculateDistance(
            coords.latitude,
            coords.longitude,
            store.lat,
            store.lng
          )
        }))
        .sort((a, b) => a.distance - b.distance)
        .slice(0, 3);

      document.getElementById("results").innerHTML = nearest
        .map(store =>
          `<p>${store.name}${store.distance.toFixed(1)} km</p>`
        )
        .join("");
    },
    () => {
      document.getElementById("results").textContent =
        "Location unavailable. Search by city or ZIP code instead.";
    },
    {
      enableHighAccuracy: true,
      timeout: 10000,
      maximumAge: 60000
    }
  );
});
Enter fullscreen mode Exit fullscreen mode

We now have the complete basic flow: the visitor clicks the button, grants location access, and sees the three nearest stores.

A production interface could add map markers, directions, opening hours, phone numbers, and other store information.

5. Plan for Geolocation Failure

The successful path is only half the implementation.

Visitors may deny permission, location accuracy may be poor, location services may be unavailable, or no store may exist nearby.

That's why a locator should never depend entirely on geolocation.

A simple fallback could be:

Can't access your location?

[ Enter city, ZIP code, or address ] [ Search ]

Enter fullscreen mode Exit fullscreen mode

This also helps visitors who want to find stores somewhere other than their current location.

What If You Have Thousands of Stores?

Running these calculations in the browser works well for a small dataset. Sending thousands of store records to every visitor doesn't.

For larger datasets, send the user's coordinates to your backend and query only stores within a useful radius.

User coordinates
      ↓
Server / API
      ↓
Geographic radius query
      ↓
Nearest locations
      ↓
Browser
Enter fullscreen mode Exit fullscreen mode

Databases with geospatial capabilities and spatial indexes can perform this filtering efficiently. Instead of sending your entire location database to the browser, your backend might return only the 10 or 20 stores relevant to that visitor.

Building It Yourself vs. Using a Store Locator

The nearest-store calculation isn't particularly complicated. The workload grows when you add maps, markers, geocoding, address search, filters, directions, mobile layouts, store management, and hundreds of locations.

For a custom application, building those components yourself may make sense.

If this is going into WordPress and you don't need custom location infrastructure, you may not need to maintain all of this yourself. A WordPress store locator plugin such as Agile Store Locator can handle nearby-location search, maps, store data, and the management interface while leaving the custom-build approach available for projects that need complete control.

The right approach depends on how much control your project needs versus how much infrastructure you want to maintain.

Final Thoughts

"Find Stores Near Me" looks like a simple button, but there's an interesting chain behind it:

permission → coordinates → distance calculation → sorting → nearest stores

The browser Geolocation API and a little JavaScript are enough for a useful prototype. For production, permission failures, search fallbacks, data quality, routing, scalability, and mobile UX all matter.

How would you implement nearest-store search in your application: client-side calculations, database geospatial queries, or a mapping/routing service?

Top comments (0)