Skip to main content
Displays search results on a Google Map and provides geographic search capabilities based on map interactions.

Usage

import instantsearch from 'instantsearch.js';
import { geoSearch } from 'instantsearch.js/es/widgets';

const search = instantsearch({
  indexName: 'instant_search',
  searchClient
});

search.addWidgets([
  geoSearch({
    container: '#geo-search',
    googleReference: window.google
  })
]);

search.start();

Requirements

  • Your hits must have a _geoloc attribute with lat and lng properties.
  • You must load the Google Maps JavaScript API library separately.
  • Set explicit height on the map container (e.g., .ais-GeoSearch-map).

Parameters

container
string | HTMLElement
required
CSS selector or HTMLElement to insert the widget.
googleReference
typeof window.google
required
Reference to the global window.google object. See Google Maps documentation.
initialZoom
number
default:"1"
Default zoom level when no markers are displayed.
initialPosition
object
default:"{ lat: 0, lng: 0 }"
Default position when no markers are displayed.
{ lat: number; lng: number }
enableRefine
boolean
default:"true"
If true, the map is used to search. If false, it’s for display purposes only.
enableClearMapRefinement
boolean
default:"true"
If true, a button is displayed to remove map refinement.
enableRefineControl
boolean
default:"true"
If true, users can toggle the enableRefineOnMapMove option directly from the map.
mapOptions
google.maps.MapOptions
Options forwarded to the Google Maps constructor. See MapOptions documentation.
builtInMarker
object
Options to customize the built-in Google Maps marker.
customHTMLMarker
object | boolean
Options to customize HTML markers (alternative to built-in markers).
templates
object
Templates to use for the widget.
cssClasses
object
CSS classes to add to the widget elements.

Examples

geoSearch({
  container: '#geo-search',
  googleReference: window.google,
  initialZoom: 12,
  initialPosition: {
    lat: 48.8566,
    lng: 2.3522
  }
});

Custom marker

geoSearch({
  container: '#geo-search',
  googleReference: window.google,
  builtInMarker: {
    createOptions(item) {
      return {
        title: item.name,
        label: item.price
      };
    },
    events: {
      click({ item, marker, map }) {
        console.log('Clicked item:', item);
      }
    }
  }
});

HTML marker with template

geoSearch({
  container: '#geo-search',
  googleReference: window.google,
  customHTMLMarker: true,
  templates: {
    HTMLMarker(item) {
      return `
        <div class="custom-marker">
          <img src="${item.image}" />
          <span>${item.name}</span>
        </div>
      `;
    }
  }
});
geoSearch({
  container: '#geo-search',
  googleReference: window.google,
  enableRefine: false,
  enableClearMapRefinement: false,
  enableRefineControl: false
});

Custom map options

geoSearch({
  container: '#geo-search',
  googleReference: window.google,
  mapOptions: {
    streetViewControl: false,
    mapTypeControl: false,
    fullscreenControl: false,
    styles: [
      {
        featureType: 'poi',
        elementType: 'labels',
        stylers: [{ visibility: 'off' }]
      }
    ]
  }
});

CSS setup

.ais-GeoSearch-map {
  height: 500px;
}

HTML output

<div class="ais-GeoSearch">
  <div class="ais-GeoSearch-map">
    <!-- Google Map -->
  </div>
  <div class="ais-GeoSearch-control">
    <label class="ais-GeoSearch-label">
      <input class="ais-GeoSearch-input" type="checkbox" />
      Search when moving the map
    </label>
    <button class="ais-GeoSearch-redo">Redo search here</button>
    <button class="ais-GeoSearch-reset">Clear the map refinement</button>
  </div>
</div>

Build docs developers (and LLMs) love