Guides / Building Search UI / Going further / Back-end search

Advanced InstantSearch users may have the need to query Algolia’s servers from their back end instead of the front end, while still being able to reuse InstantSearch widgets. Possible motivations could be for security restrictions, for SEO purposes or to enrich the data sent by the custom server, that is fetching Algolia data and data from their own servers. If this sounds appealing to you, feel free to follow this guide. Keep in mind though that Algolia recommends doing front-end search for performance and high availability reasons.

In this guide, you can learn how to leverage InstantSearch with your own back end to query Algolia.

How back-end search works

InstantSearch is the UI part on top a search client with a state managed by a JavaScript Helper. These three layers are composable and can be interchanged to leverage the InstantSearch widgets system with different search clients.

The search client that Algolia offers queries Algolia’s backends whenever the user refines the search. It’s possible to implement your own search client that queries your back end, which then queries Algolia’s backends with the Algolia search client on your server.

To create your own client, you need to implement a given interface that receives and returns formatted data that InstantSearch can understand.

On the back end: Create the necessary routes

This guide assumes that you’ve got an existing server running on http://localhost:3000 with the route POST /search that takes the default Algolia query parameters as JSON. This back end could be using the JavasScript API client to query Algolia, on top of any other operations you want to perform.

The algoliasearch package will allow you to query Algolia from your back end. Here’s an example using Express:

1
2
3
4
5
6
7
8
9
10
// Instantiate an Algolia client
const algoliasearch = require('algoliasearch');
const algoliaClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');

// Add the search endpoint
app.post('/search', async ({body}, res) => {
  const { requests } = body;
  const results = await algoliaClient.search(requests);
  res.status(200).send(results);
});

Once your new route is ready, get back to the front end and create a search client that can communicate with this server.

On the front end: Call your new back-end routes

Searching for results

A search client is an object which implements the method search(), called every time the user searches and refines results.

Since the server accepts the InstantSearch format as an input, you only need to pass these requests to your back end in this method, and return the response.

1
2
3
4
5
6
7
8
9
10
11
const customSearchClient = {
  search(requests) {
    return fetch('http://localhost:3000/search', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ requests }),
    }).then(res => res.json());
  }
};

This example uses the Fetch API to query the server. Make sure to take note of the browser compatibility before using it in production.

If you want to transform the data to be passed to your server, you can learn more about all the parameters that the search() method supports in the Algolia API reference.

Using the search client with Vue InstantSearch

Now, you need to tell InstantSearch to use the search client that you created. This is possible with the searchClient option. This parameter turns off all Algolia requests coming from the front end and proxies them to your own back end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
  <ais-instant-search
    :search-client="searchClient"
  >
  </ais-instant-search>
</template>

<script>
export default {
  data() {
    return {
      searchClient: {
        search(requests) {
          return fetch('http://localhost:3000/search', {
            method: 'post',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ requests }),
          }).then(res => res.json());
        }
      },
    };
  },
};
</script>

InstantSearch is now requesting your own back end and will display the UI accordingly.

Going further: Enriching data from the back end

Now that you’ve got InstantSearch querying your own back end before fetching results from Algolia, you could merge Algolia’s data to yours to offer your users more exhaustive results.

A recurring problem with ecommerce websites using Algolia is to manage the remaining stock for each product; it’s sometimes hard to keep track of the exact number of items. An approach made possible with a custom back end is to only store the item’s availability on each Algolia record (none, low, medium, high) and to fetch the exact stock on your database.

You need to make a few changes to your back end:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app.post('/search', async ({body}, res) => {
  const requests = body;
  const algoliaResults = await algoliaClient.search(requests);
  const results = {
    ...algoliaResults,
    results: algoliaResults.results.map(result => ({
      ...result,
      hits: result.hits.map(async hit => ({
        ...hit,
        // `getStock()` retrieves a product's exact stock from your own database
        stock: await getStock(hit.productID),
      })),
    })),
  };

  res.status(200).send(results);
});

You can now access the property stock on each hit with InstantSearch on the front end.

Conclusion

Throughout this guide, you learned:

  • How to handle Algolia requests coming from InstantSearch on your own back end
  • How to create a custom search client calling this server
  • How to plug the search client to InstantSearch

Did you find this page helpful?