Lite free · Pro $79 · Craft CMS 5
Find the nearest shop that has it in stock
Fold is a store locator for Craft: a map, a search box, and your shops sorted by distance, with opening hours that are right after midnight. If you run Craft Commerce, it can also filter that list to the shops that have a product available today.
One line is a working locator
The search box, radius select, results list and map, all rendered in Twig before any JavaScript runs. Without scripting it's still a complete, linkable list of your shops, and the script adds the map and live search on top. The default map is Leaflet on OpenStreetMap, so you don't need an API key.
{{ craft.fold.locator({ group: 'retail', radius: 25 }) }}
{# Or build your own: it's an ordinary element query #}
{% set stores = craft.fold.locations
.group('retail')
.nearby({ lat: 35.2271, lng: -80.8431, radius: 25 })
.limit(10)
.all() %}
{% for store in stores %}
{{ store.title }}: {{ store.distance|round(1) }} mi,
{{ store.isOpenNow() ? 'open now' : 'closed' }}
{% endfor %}
Features
Everything a store locator has to get right, built on the parts of Craft you already use.
Locations are elements
Each shop has a field layout from its group, a URL and template per site, element search, relations and the trash. A Locations relation field links entries to the shops they belong to.
- Groups, such as Retail and Service Centres, carry different fields and URLs
- Address, coordinates and hours are shared across sites; titles and fields are translated
Radius search that scales
An indexed bounding box rules out the distant shops first, then a haversine filters and sorts the rest, all in one query. It runs the same on MySQL and Postgres and doesn't need spatial types or PostGIS.
Opening hours that are actually right
A bar open 22:00 to 02:00 is still open at half past midnight. "Open now" is worked out in each shop's own timezone, not the server's, and the hours model has room for holiday exceptions.
Geocoding that respects the provider
Fold only geocodes a location again when its address changes, so editing a phone number never costs a request. Every lookup is cached, including misses. Nominatim gets one request per second across the whole site, as its usage policy asks.
- Coordinates you type are never overwritten
- Pro adds Google and Mapbox, with a separate server-only Google key
Searches that understand people
Visitors type "NoDa" and "the airport one" into a locator box. When a geocoder can't place a term, Fold matches it against your shop names. It also tells "we couldn't find that place" apart from "there's nothing near it", because they need different messages.
A JSON endpoint for your own front end
GET /fold/search.json returns the same results the built-in locator shows, from the same search code. It's anonymous, read-only and cacheable, with a per-visitor rate limit and a fixed response shape that adding a custom field won't change.
Commerce inventory, read properly
Link a location to a Commerce inventory location and its address comes from Commerce. A stock search then uses Commerce's own available quantity, not on-hand, so nobody is sent across town for an item that's already been sold.
Import the spreadsheet you already have
The CSV importer recognises the column names other systems export, such as Store Name, address_1, ZIP, Telephone and a column per weekday. It matches existing rows by slug or name, so a second run updates instead of duplicating. Export writes the same columns back out.
Learn where to open next
With search recording on, Fold lists the places people searched for and found nothing. A town that keeps turning up there is a lead for your next shop, and you won't see it in any other analytics tool. Coordinates are rounded to about a kilometre and old rows expire.
Which shop near me has this in stock?
WP Store Locator can't answer this one. Fold asks Craft Commerce, through Commerce's own inventory service, which linked locations have the item available, then sorts those shops by distance. The JSON endpoint reports in or out of stock for each shop, and exact counts only if you turn them on.
{% set stockists = craft.fold.locations
.nearby({ lat: lat, lng: lng, radius: 50 })
.inStockOf(product.defaultVariant)
.all() %}
{# At least four available, not just one #}
{% set stockists = craft.fold.locations
.inStockOf(variant, 4)
.all() %}
{# The same filter from JavaScript:
GET /fold/search.json?q=28202&radius=50&inStockOf=1234 #}
Frequently Asked Questions
Questions worth answering before you install it.
It covers the same ground: a map, a search box, a radius, opening hours and a page per shop. Fold builds it the Craft way, with locations as real elements that have field layouts, per-site URLs and relations. It also answers the question WP Store Locator can't: which shop near me has this in stock, using Craft Commerce's own inventory.
No. The default map is Leaflet on OpenStreetMap tiles and the default geocoder is Nominatim, and neither needs a key. Leaflet ships inside the plugin, so a default install doesn't load scripts from a CDN. Google Maps and Mapbox are available in Pro.
Yes. Results are rendered in Twig and the search box is an ordinary form. JavaScript adds the map and live search, and it never removes content that was already rendered. That also means search engines see a real list of your shops, with links to their pages.
No. An indexed bounding box rules out distant shops before any distance is calculated, and the haversine only runs on the shops that are left. It's all one query, on MySQL or Postgres.
Not by default. The JSON endpoint reports inStock as true or false for each shop. Exact quantities are published only if you turn on Publish exact stock counts, and a purchasable ID only resolves to products a visitor could actually buy.
The search term, where it was placed (rounded to about a kilometre), the radius, the result count and the nearest shop. It doesn't store IP addresses, user agents or cookies. Rows are deleted after 90 days by default, and reading the log needs its own permission.
No. Commerce is optional and is only needed for the stock features in Pro. Without it, nothing in Fold references Commerce.
The locator falls back to the free Leaflet map and the Nominatim geocoder instead of going blank, and the Pro-only features stop. Your settings aren't changed, so renewing brings back exactly what you had.
Lite is free for up to 10 locations in one group. It includes the map, radius search, opening hours, store pages and the JSON endpoint. Pro is $79, with an optional $59/year renewal for updates. Pro adds unlimited locations and groups, Google and Mapbox, Commerce stock filtering, CSV import and export, and search recording.
Craft CMS 5.3+ and PHP 8.2+, plus Craft Commerce 5 if you want the stock features. There's no build step and no runtime dependency beyond Craft.
Put your shops on a map
Lite is free for up to 10 locations and doesn't need an API key. Pro is $79 with a $59/year renewal, and adds unlimited locations, Google and Mapbox, import and export, and Commerce stock search.