{"id":379229,"date":"2026-10-13T06:29:44","date_gmt":"2026-10-13T06:29:44","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/store-locator-for-openstreetmap\/"},"modified":"2026-10-13T06:44:25","modified_gmt":"2026-10-13T06:44:25","slug":"nearspot-store-finder-openstreetmap","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/nearspot-store-finder-openstreetmap\/","author":15763694,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.2","stable_tag":"1.0.2","tested":"7.1.3","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"Nearspot Store Finder for OpenStreetMap","header_author":"Asymetria","header_description":"A store locator built on Leaflet and OpenStreetMap. No Google Maps API key, no billing account, no third-party map cookies.","assets_banners_color":"","last_updated":"2026-10-13 06:44:25","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/asymetria.com.pl","rating":0,"author_block_rating":0,"active_installs":0,"downloads":55,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.2":{"tag":"1.0.2","author":"asymetria","date":"2026-10-13 06:44:25","revision":3743064}},"upgrade_notice":[],"ratings":[],"assets_icons":[],"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.2"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[4595,2909,16164,6105,6102],"plugin_category":[49],"plugin_contributors":[282776],"plugin_business_model":[],"class_list":["post-379229","plugin","type-plugin","status-publish","hentry","plugin_tags-leaflet","plugin_tags-map","plugin_tags-openstreetmap","plugin_tags-store-finder","plugin_tags-store-locator","plugin_category-maps-and-location","plugin_contributors-asymetria","plugin_committers-asymetria"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/s.w.org\/plugins\/geopattern-icon\/nearspot-store-finder-openstreetmap.svg","icon_2x":false,"generated":true},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Locations are a custom post type with an address and coordinates. A visitor\ntypes a place, picks a radius, and gets the nearest locations as pins on a map\nand as a list beside it. It ships as a shortcode and as a Bricks Builder\nelement.<\/p>\n\n<h4>What it does<\/h4>\n\n<ul>\n<li>Search by address, postcode or city, with suggestions as you type and a\nsearch button beside the field<\/li>\n<li>A radius filter in kilometres or miles, and a result-count filter<\/li>\n<li>\"Use my location\", which asks the browser for a position only when the\nvisitor presses the button<\/li>\n<li>A category filter, backed by a taxonomy<\/li>\n<li>Marker clustering, which switches itself on once a locator would draw fifty\npins, and which can be forced on or off<\/li>\n<li>A directions link from a result to OpenStreetMap or to Google Maps, or none\nat all, whichever the site chooses<\/li>\n<li>Bulk geocoding from the admin, with a report of what happened to each row<\/li>\n<li>A settings screen whose fields are a closed list of options rather than a\nfree-text box that can hold anything<\/li>\n<\/ul>\n\n<h4>How it is built<\/h4>\n\n<ul>\n<li><strong>No dependencies and no build step.<\/strong> No npm, no Composer, no bundler. What\nis in the plugin is what runs.<\/li>\n<li><strong>No jQuery.<\/strong> One frozen <code>window.SLOSM<\/code> namespace on the front end.<\/li>\n<li><strong>The REST API rather than admin-ajax.<\/strong> Four narrow, read-only routes.<\/li>\n<li><strong>Conditional assets.<\/strong> The clustering bundle downloads only when a locator\nactually needs it; a site with twenty branches never sees it.<\/li>\n<li><strong>Geocoding through a server-side proxy<\/strong>, with a thirty-day cache and a\none-request-per-second gap, so a visitor's browser never talks to the\ngeocoder itself and a failure is never cached.<\/li>\n<li>Leaflet and Leaflet.markercluster are bundled rather than loaded from a CDN.<\/li>\n<\/ul>\n\n<h4>Known limitations in this release<\/h4>\n\n<p>Worth reading before this goes on a site that matters.<\/p>\n\n<ul>\n<li><strong>The search button is new in this release, and there is no form around\nit.<\/strong> The address field has a Search button beside it now, running the same\nsearch Enter runs; with the suggestion list open, both take the highlighted\nsuggestion rather than looking the text up again. What this markup\ndeliberately does not have is a <code>&lt;form&gt;<\/code>: that would make Enter submit the\npage for anybody the plugin's JavaScript has not reached yet, and a form\ninside a page builder's own form is discarded by the browser's parser with\nits controls handed to the outer one. If your theme or builder rebuilds the\nfilter bar and drops the button, the field still searches on Enter.<\/li>\n<li><strong>The styling is two files, and you can switch one of them off.<\/strong> One holds\nthe layout \u2014 the map's box and its height floor, the results list beside or\nunder it, the suggestion popup, the dot marker \u2014 and is always loaded. The\nother is a skin: the spacing of the filter row and a border and padding on\nthe search field, the selects and the buttons, in the site's own font and\ncolour rather than the browser's. Untick \"Default styles\" on the Advanced tab\nto drop the skin and write your own; the map keeps its layout either way, so\nswitching it off cannot leave you with a map of no height, which is the usual\nway this kind of plugin appears broken.<\/li>\n<li><strong>The accessibility and translation passes are done; what is left is\nchecking them with real software.<\/strong> The search field is a combobox with a\nlistbox of suggestions, the arrow keys walk it, one status line announces\nwhat happened \u2014 including how many locations a search found \u2014 and opening a\nlocation's bubble moves the keyboard focus into it and gives it back when the\nbubble closes. The map's close button is labelled in your site's language\nrather than in English. None of that has been through NVDA, VoiceOver or\nOrca yet, and that check is listed as open rather than claimed as done.<\/li>\n<li>One thing is deliberately left alone: the name inside a location's bubble is\nbold text and not a heading, because a heading needs a level and the right\nlevel depends on the page you drop the locator into.<\/li>\n<li>Clustering at scale has not been measured on a real site either.<\/li>\n<\/ul>\n\n<h4>The free services have limits, and a busy shop will meet them<\/h4>\n\n<p>The public OpenStreetMap geocoding service allows roughly one request a second\nand asks that heavy use go elsewhere. This plugin keeps to that limit and\ncaches hard, but a shop with real traffic needs its own instance or a paid\nprovider. That is a property of a free public service rather than of this\nplugin, and the endpoints are settings so a site can point at its own.<\/p>\n\n<h4>Credits and licences<\/h4>\n\n<ul>\n<li>Leaflet 1.9.4, unmodified, BSD-2-Clause \u2014 https:\/\/leafletjs.com\/<\/li>\n<li>Leaflet.markercluster 1.5.3, unmodified, MIT \u2014\nhttps:\/\/github.com\/Leaflet\/Leaflet.markercluster<\/li>\n<li>Map data \u00a9 OpenStreetMap contributors \u2014\nhttps:\/\/www.openstreetmap.org\/copyright<\/li>\n<\/ul>\n\n<p>Both bundled libraries are GPL-compatible, and each ships with its own licence\nfile and a note recording where it came from and what its SHA-512 digest is.<\/p>\n\n<h4>A note on the name<\/h4>\n\n<p>OpenStreetMap is a trademark of the OpenStreetMap Foundation. This plugin is an\nindependent piece of software that works with OpenStreetMap data and services;\nit is <strong>not endorsed by, affiliated with, or an official product of<\/strong> the\nOpenStreetMap Foundation. The name follows the Foundation's trademark policy,\nwhich permits naming software that works specifically with OpenStreetMap data,\nand asks for exactly this disclaimer alongside it.<\/p>\n\n<p>Leaflet and Leaflet.markercluster are bundled here under their own licences and\nare likewise not affiliated with this plugin's author.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin contacts three external services. Two of them are contacted by\nyour server; the third is contacted by every visitor's browser. None of them\nis contacted until something on the site actually asks for it.<\/p>\n\n<h4>1. Nominatim, the OpenStreetMap geocoding service<\/h4>\n\n<p><strong>What it is for.<\/strong> Turning an address into coordinates.<\/p>\n\n<p><strong>When.<\/strong> When a location is saved with an address and no coordinates, when\nthe bulk geocoder is run from the admin, and when a visitor submits a search.\nA result is cached for thirty days, so the same address is sent once.<\/p>\n\n<p><strong>What is sent.<\/strong> The address or search text, normalised; an ISO country code\nwhen the site has set one; and a User-Agent naming this plugin, its version\nand your site's home URL, which the service's usage policy asks for. The\nrequest is made by your server, so the visitor's IP address and cookies are\nnot part of it.<\/p>\n\n<p><strong>Where.<\/strong> <code>https:\/\/nominatim.openstreetmap.org\/search<\/code> by default. The\nendpoint is a setting: a site may point it at its own instance or at a paid\nprovider instead.<\/p>\n\n<p><strong>Terms and privacy.<\/strong> Nominatim Usage Policy:\nhttps:\/\/operations.osmfoundation.org\/policies\/nominatim\/ . Privacy policy of\nthe OpenStreetMap Foundation, which operates the service:\nhttps:\/\/osmfoundation.org\/wiki\/Privacy_Policy .<\/p>\n\n<h4>2. Photon, the address-suggestion service<\/h4>\n\n<p><strong>What it is for.<\/strong> The suggestions that appear while a visitor types in the\nsearch field.<\/p>\n\n<p><strong>When.<\/strong> While typing, after a pause, and only when suggestions are switched\non. A suggestion list is cached for a day.<\/p>\n\n<p><strong>What is sent.<\/strong> The text typed so far and a result limit. As above, the\nrequest is made by your server rather than by the visitor's browser.<\/p>\n\n<p><strong>Where.<\/strong> <code>https:\/\/photon.komoot.io\/api<\/code> by default, and also a setting.<\/p>\n\n<p><strong>Terms and privacy.<\/strong> Photon is run by komoot. Its terms are a fair-use\nparagraph on the service's own page, https:\/\/photon.komoot.io\/ , which reads:\n\"You can use the API for your project, but please be fair - extensive usage\nwill be throttled. We do not guarantee for the availability and usage might be\nsubject of change in the future.\" The service publishes no privacy policy of\nits own, which is said here rather than papered over with a link to something\nelse. A site that needs a documented data-processing agreement for this should\npoint the setting at its own Photon instance, or switch suggestions off.<\/p>\n\n<h4>3. The OpenStreetMap tile server<\/h4>\n\n<p><strong>What it is for.<\/strong> The map images themselves.<\/p>\n\n<p><strong>When.<\/strong> Every time a page carrying a map is viewed, from the visitor's own\nbrowser.<\/p>\n\n<p><strong>What is sent.<\/strong> What any image request sends: the visitor's IP address, their\nbrowser's User-Agent, and the coordinates of the tiles being looked at. This\nplugin sets no cookie of its own and neither the geocoding nor the suggestion\nrequest carries one.<\/p>\n\n<p><strong>Where.<\/strong> <code>https:\/\/tile.openstreetmap.org\/{z}\/{x}\/{y}.png<\/code> by default, and a\nsetting, so a site may use any tile provider it has the right to use.<\/p>\n\n<p><strong>Terms and privacy.<\/strong> Map data and attribution:\nhttps:\/\/www.openstreetmap.org\/copyright . Tile Usage Policy:\nhttps:\/\/operations.osmfoundation.org\/policies\/tiles\/ . Privacy policy of the\nOpenStreetMap Foundation: https:\/\/osmfoundation.org\/wiki\/Privacy_Policy .<\/p>\n\n<h4>Not a request, but worth saying<\/h4>\n\n<p>A \"directions\" link opens OpenStreetMap, or Google Maps if the site chose\nthat, in a new tab <strong>when a visitor clicks it<\/strong>. Nothing is sent anywhere until\nthey do, and the link can be turned off in the settings.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin to <code>wp-content\/plugins\/<\/code>, or install it from the\nPlugins screen, and activate it.<\/li>\n<li>Add locations under <strong>Locations<\/strong>. Enter an address and press the button\nthat geocodes it, or type the coordinates directly.<\/li>\n<li>Put a locator on a page: use the shortcode builder under <strong>Locations \u2192\nShortcode<\/strong>, or add the <strong>Store Locator<\/strong> element in Bricks.<\/li>\n<li>Settings live under <strong>Locations \u2192 Settings<\/strong>.<\/li>\n<\/ol>\n\n<p>No API key, no account, and nothing to configure before the first map draws.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20google%20maps%20api%20key%2C%20or%20a%20billing%20account%3F\"><h3>Do I need a Google Maps API key, or a billing account?<\/h3><\/dt>\n<dd><p>No. The map, the geocoding and the suggestions all use OpenStreetMap services,\nand the plugin works with the defaults it ships with.<\/p><\/dd>\n<dt id=\"can%20i%20use%20it%20on%20a%20busy%20shop%3F\"><h3>Can I use it on a busy shop?<\/h3><\/dt>\n<dd><p>Not on the free public services alone. They allow about one request a second\nand ask that heavy use be moved elsewhere, and a shop with real traffic will\nreach that. The geocoding endpoint, the suggestion endpoint and the tile URL\nare all settings, so the answer is to point them at your own instance or at a\nprovider you pay. Please have that conversation before the traffic arrives\nrather than after.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20my%20locations%20when%20i%20delete%20the%20plugin%3F\"><h3>What happens to my locations when I delete the plugin?<\/h3><\/dt>\n<dd><p>They stay, unless you have asked for them to go.<\/p>\n\n<p>By default, deleting the plugin removes its settings, its two cache\ninvalidation counters and its own cached entries, and nothing else. Your\nlocations, their addresses and coordinates, and their categories are posts and\nterms in your database, and removing a plugin is not by itself a decision to\ndelete them.<\/p>\n\n<p>If you want them gone, the Advanced tab has a checkbox \u2014 <em>\"Delete every\nlocation, category and setting when this plugin is deleted\"<\/em>. It is <strong>off by\ndefault<\/strong>, and while it is off, uninstalling keeps every location. Tick it and\ndeleting the plugin also deletes the <code>slosm_store<\/code> posts with their meta,\nincluding any in the trash, and the location categories. Nothing else on the\nsite is touched: other post types, other taxonomies and other plugins' data are\nleft alone.<\/p>\n\n<p>That deletion cannot be undone from here, so please take a backup first if\nthere is any chance you will want the addresses back.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20bricks%20builder%3F\"><h3>Does it work with Bricks Builder?<\/h3><\/dt>\n<dd><p>Yes. The element registers itself when Bricks is present and does nothing at\nall when it is not, and it renders through the same code the shortcode uses, so\nthe two cannot drift apart. It was built against Bricks 2.4.<\/p><\/dd>\n<dt id=\"the%20buttons%20do%20not%20look%20like%20the%20rest%20of%20my%20site%27s%20buttons\"><h3>The buttons do not look like the rest of my site's buttons<\/h3><\/dt>\n<dd><p>There is a field for that: \"Button class\" on the Advanced tab, empty by\ndefault. Whatever you type is added to the Search and \"Use my location\"\nbuttons, so they can take the class your theme already styles \u2014 on Bricks that\nis <code>bricks-button<\/code>, and most themes and frameworks have one of their own. One\nlocator can override the site-wide value with <code>button_class<\/code> in the shortcode\nor in the element's own control.<\/p>\n\n<p>The plugin does not fill this in for you, deliberately. Writing another theme's\nclass name into a plugin means inheriting that theme's renames as your own\nbreakages, and a primary-button class on a secondary control is rarely what a\npage wants. The Bricks element also carries a STYLE tab, so a locator can be\nstyled in the builder without touching CSS at all.<\/p><\/dd>\n<dt id=\"can%20i%20use%20a%20different%20map%20style%20or%20tile%20provider%3F\"><h3>Can I use a different map style or tile provider?<\/h3><\/dt>\n<dd><p>Yes \u2014 the tile URL and its attribution line are settings. Please use a provider\nwhose terms allow your traffic, and keep the attribution that provider requires.<\/p><\/dd>\n<dt id=\"where%20does%20the%20plugin%20store%20anything%3F\"><h3>Where does the plugin store anything?<\/h3><\/dt>\n<dd><p>One option for the settings, two counters used to invalidate caches, two\ntimestamps that keep the plugin inside the geocoder's rate limit, and\ntransients for the cached map payload, the cached geocoding results and a few\nadmin notices. All of those go when the plugin is deleted. Locations\nthemselves are ordinary posts, and they go only if you asked for them to \u2014\nsee the question above.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Renamed, before the first release, to be distinguishable from the several\nexisting plugins whose names begin \"Store Locator\".<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>The OpenStreetMap attribution, and everything else Leaflet draws inside the\nmap, keeps a legible size on themes that set a 62.5% root font size. It was\nrendering at 7.5px there, which is not an attribution anybody can read.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First release.<\/li>\n<li>The map frames what it is showing \u2014 on load, after a search, and when a\nlocation is opened from the list \u2014 and redraws itself when its container\nchanges size inside a page builder, a tab or an accordion.<\/li>\n<li>Keyboard and screen reader: the popup takes the focus, Escape closes it and\ngives the focus back to the row that opened it, and that row says what it\nopened for as long as it is open.<\/li>\n<li>Map, search, radius and category filters, \"use my location\", clustering,\ndirections links, bulk geocoding, a settings screen, a shortcode builder and\na Bricks Builder element.<\/li>\n<li>The address field has a Search button, and carries enterkeyhint=\"search\" so\nthat a touch keyboard labels its action key. No form element is involved:\nthe button runs the same code path Enter runs.<\/li>\n<li>Changing the radius or the result count updates the results on its own.<\/li>\n<\/ul>","raw_excerpt":"A store locator built on Leaflet and OpenStreetMap. No Google Maps API key, no billing account, no third-party map cookies.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/379229","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=379229"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/asymetria"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=379229"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=379229"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=379229"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=379229"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=379229"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=379229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}