How to Deal With Existing URL Parameters in Algolia's instantsearch.js

I searched the internet up and down to find a solution to my problem of using Algolia's instantsearch.js with their router in combination with existing GET parameters on my url. There was no example, just a hint to read the docs 🥵.

I have an URL https://website.com/page?id=50 and implemented instantsearch.js with routing: true, in order to create linkable urls for search queries.

Algolia creates an URL like this:

https://website.com/page?instant_search[query]=galaxy&instant_search[menu][categories]=All Unlocked Cell Phones&instant_search[refinementList][brand][0]=Apple&instant_search[refinementList][brand][0]=Samsung&instant_search[page]=2

As soon as I exit the search or load the page, the URL gets reset without my own query string, so https://website.com/page?id=50 just becomes https://website.com/page.

In order to preserve existing url parameters, I had to create my own URL in the router.history.

For that, I grab the current location.search, merge in the routeState when I search, or remove the routeState object when I exit the search.

This way my query parameters stay intact. If you have correction to make, add them on the two StackOverflow Issues linked below!


const algoliaAppId = 'APP_ID';
const algoliaApiKey = 'API_KEY';
const algoliaIndex = 'instant_search';

const search = instantsearch({
  indexName: algoliaIndex,
  algoliasearch(algoliaAppId, algoliaApiKey),
  routing: {
    router: instantsearch.routers.history({

      createURL({ qsModule, location, routeState }) {

        const indexState = routeState[algoliaIndex] || {};
        const { origin, pathname, hash, search } = location;
        // grab current query string, remove the trailing `?` and convert to object
        const queryParameters = qsModule.parse(search.slice(1)) || {};

        // if there is an active search
        if (Object.keys(indexState).length ){
          // merge the search params with the current query params
          Object.assign(queryParameters, routeState);
        }else{
          // remove the search params
          delete queryParameters[algoliaIndex];
        }

        let queryString = qsModule.stringify(queryParameters);

        if(queryString.length){
          queryString = `?${queryString}`;
        }

        return `${origin}${pathname}${queryString}${hash}`;
      },
    })
  }
});

search.start();