Implementing geosearch

Hello, we are implementing geosearch to find products within a certain distance of the customer. We are not displaying results on a map, but rather just listing the products on the page.

Initially we ran into issues using the ais-search-box component as it is tied to the search query. In our case, queries are things like zip codes, cities, and states so this will break the search as our products do not contain these terms.

Implementing our own input for the search box, we listen for a key press to execute the refinement using our custom search function. The custom search function is responsible for taking the “query” i.e. location and converting that to a lat/lng pair that can be used to search around.

This was the only way we could figure out how to prevent 2 things from happening:

  1. search being executed before the complete location is entered
  2. removing the “query” as parameter from search
<ais-instant-search
  index-name="dev_VARIANTS"
  :search-client="searchClient"
  :search-function="searchFunction"
>

<ais-search-box
  class="mb-8 flex justify-between"
  placeholder="Search by city, state, or zip code..."
  autofocus
  show-loading-indicator
  submit-title="Search by city, state, or zip code..."
>
  <template v-slot="{ currentRefinement, isSearchStalled, refine }">
      <div class="w-full sm:mx-auto sm:text-center lg:text-left lg:mx-0 sm:flex relative">
          <label for="location" class="sr-only">Location</label>
          <input
            type="search"
            @search="refine"
            @keyup.enter="refine($event.currentTarget.value)"
            class="block w-full pl-10 py-3 text-base rounded-md placeholder-gray-500 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:flex-1 border-gray-300"
            placeholder="Search by city, state or zip code..."
            required
          >
      </div>
      <span :hidden="!isSearchStalled">Loading...</span>
  </template>
</ais-search-box>

</ais-instant-search>

Custom search function:

const searchFunction = (helper) => {
const page = helper.getPage(); // Retrieve the current page

if (query !== '') {
  helper.state.query = query
}

if (!helper.state.query) {
    helper.setQueryParameter('query')
      .setQueryParameter('aroundLatLng')
      .setPage(page)
      .search()
    return;
}

this.geocoder.send({
  address_line_1: helper.state.query,
}, (response) => {
    if (!response.results.length) {
      return;
    }
    const result = response.results[0]

    if (result.geometry === undefined) {
      return
    }

    const { lat, lng } = result.geometry.location
    const latLng = lat + ', ' + lng;

    helper.setQueryParameter('query')
      .setQueryParameter('aroundLatLng', latLng)
      .setQueryParameter('aroundRadius', 80467)
      .setPage(page)
      .search();
});
return;
}

The problem were having now is the search function is being executed multiple times each time something is clicked in the search UI. Specifically, on mobile, when the filters drawer is opened/closed, the search function is executed twice.

What is happening though is on the 2nd call, the refinements are being cleared so the search is reset. As a result, when users are filtering the results on mobile and try to close the drawer to see the results, the filters are cleared.

This is a very similar problem to maintaining the page state when implementing a custom search function so my thought was to capture the current refinements, and then reapply them the same way the page is applied.

However, we have been unable to find a way to determine the current refinements.

What is the best way to implement geosearch without a map, as well as use the “query” as a location rather than search terms?