Getting started

Edit this page

Welcome to InstantSearch.js

InstantSearch.js is a JavaScript library that lets you create an instant search results experience using Algolia’s REST API.

In this tutorial, you’ll learn how to:

  • import instantsearch.js on your website
  • display results from Algolia
  • add widgets to filter the results

Before we start

InstantSearch.js is meant to be used with Algolia.

Therefore, you’ll need the credentials to an Algolia index. To ease this getting started, here are credentials to an already configured index:

  • appId: latency
  • searchKey: 3d9875e51fbd20c7754e65422f7ce5e1
  • indexName: bestbuy

It contains sample data for an e-commerce website.

This guide also expects you to have a working website. You can also use our bootstrapped project by clicking this link.

Install InstantSearch.js

From a CDN

Use a built version of InstantSearch.js from the jsDeliver CDN:

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@3.0.0-beta.2/dist/instantsearch.min.css">
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@3.0.0-beta.2"></script>

We also provide you a default Algolia theme for the widgets to be effectively styled:

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@3.0.0-beta.2/dist/instantsearch-theme-algolia.min.css">

You will then have access to the instantsearch function in the global scope (window).

We recommend using jsDelivr only for prototyping, not for production applications. Whenever possible, you should host your assets yourself or use a premium CDN service. jsDelivr is a free service and isn’t operated by Algolia, so we won’t be able to provide support if it fails.

From NPM/Yarn

If you have a JavaScript build system, you can install InstantSearch.js from NPM:

// `npm install instantsearch.js algoliasearch` OR
// `yarn add instantsearch.js algoliasearch`

const algoliasearch = require('algoliasearch/lite');
const instantsearch = require('instantsearch.js');

You need to manually load the companion CSS file. You can load it by adding this to your page <head>:

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@3.0.0-beta.2/dist/instantsearch.min.css">

You will also need to load manually the default Algolia theme for the widgets to be effectively styled:

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@3.0.0-beta.2/dist/instantsearch-theme-algolia.min.css">

Initialization

To initialize InstantSearch.js, you need an Algolia account with a configured and non-empty index.

To initialize with the credentials proposed at the beginning:

const search = instantsearch({
  indexName: 'instant_search',
  searchClient: algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'),
  routing: true
});

search.start();

appId, apiKey and indexName are mandatory. Those values are the credentials of your application in Algolia. They can be found in your Algolia dashboard.

You can synchronise the current search with the browser url. It provides two benefits:

  • Working back/next browser buttons
  • Copy and share the current search url

To configure this feature, pass routing: true option to instantsearch(). The routing option has more parameters.

Congrats 🎉 ! Your website is now connected to Algolia.

Display results

The core of a search experience is to display results. By default, InstantSearch.js will do a query at the start of the page and will retrieve the most relevant hits.

To display results, the hits widget will be used. This widget will display all the results returned by Algolia, and it will update when there are new results.

A key aspect of InstantSearch.js, is that you need to provide a container for each widget. This will tell instantsearch where to display the widget. Here, we need to define first the container of our results:

<div id="hits">
  <!-- Hits widget will appear here -->
</div>

Once you’ve set the place where the widget will be rendered, you need to add it to your instantsearch instance, using addWidget:

<script>
  const search = instantsearch(options);

  search.addWidget(
    instantsearch.widgets.hits({
      container: '#hits'
    })
  );

  search.start();
</script>

All the widgets provided by the library can be found in the namespace instantsearch.widgets.

You should now be able to see the results without any styling. This view lets you inspect the values that are retrieved from Algolia, in order to build your custom view.

In order to customize the view for each product, we can use a special option of the hit widget: templates. This option accepts a Mustache template string or a function returning a string.

<div id="hits">
  <!-- Hits widget will appear here -->
</div>

<script>
  const search = instantsearch(options);

  search.addWidget(
    instantsearch.widgets.hits({
      container: '#hits',
      templates: {
        empty: 'No results',
        item: '<em>Hit {{objectID}}</em>: {{{_highlightResult.name.value}}}'
      }
    })
  );

  search.start();
</script>

In this example, we have used the _highlightResult that contains the attributes highlighted based on the current query. This is a very important aspect of search, as it gives the user a feedback on the matching parts of the results.

In this section we’ve seen:

  • how to define containers for the widgets
  • how to display the results from Algolia
  • how to customize the display of those results
  • how to leverage highlighting in results

Now that we’ve added the results, we can start querying our index. To do this, we are going to use the Searchbox widget. Let’s add it in the html page that we created before:

<div id="search-box">
  <!-- SearchBox widget will appear here -->
</div>

<div id="hits">
  <!-- Hits widget will appear here -->
</div>

<script>
  const search = instantsearch(options);

  // initialize SearchBox
  search.addWidget(
    instantsearch.widgets.searchBox({
      container: '#search-box',
      placeholder: 'Search for products'
    })
  );

  // initialize hits widget
  search.addWidget(
    instantsearch.widgets.hits({
      container: '#hits'
    })
  );

  search.start();
</script>

The search is now interactive and we see what matched in each of the products. Good thing for us, Algolia computes the matching part. For better control over what kind of data is returned, you should configure the attributeToRetrieve and attributeToHighlight of your index

In this part, we’ve seen:

  • How to use the searchbox to query Algolia with text

Add a RefinementList

While the SearchBox is the way to go when it comes to textual search, you may also want to provide filters based on the structure of the records.

Algolia provides a set of parameters for filtering by facets, numbers or geo location. InstantSearch.js packages those into a set of widgets and connectors.

Since the dataset used here is an e-commerce one, let’s add a RefinementList to filter the products by categories:

<div id="search-box">
  <!-- SearchBox widget will appear here -->
</div>

<div id="refinement-list">
  <!-- RefinementList widget will appear here -->
</div>

<div id="hits">
  <!-- Hits widget will appear here -->
</div>

<script>
  const search = instantsearch(options);

  // initialize RefinementList
  search.addWidget(
    instantsearch.widgets.refinementList({
      container: '#refinement-list',
      attributeName: 'categories'
    })
  );

  // initialize SearchBox
  search.addWidget(
    instantsearch.widgets.searchBox({
      container: '#search-box',
      placeholder: 'Search for products'
    })
  );

  // initialize hits widget
  search.addWidget(
    instantsearch.widgets.hits({
      container: '#hits'
    })
  );

  search.start();
</script>

The attributeName option specifies the faceted attribute to use in this widget. This attribute should be declared as a facet in the index configuration as well.

The values displayed are computed by Algolia from the results.

In this part, we’ve seen that:

  • there are components for different types of filters
  • the refinementList works with facets
  • facets are computed from the results

Going further

We now miss two elements in our search interface:

  • the ability to browse beyond the first page of results
  • the ability to reset the filters

Those two features are implemented respectively with the pagination, clearAll and currentRefinements widgets. Both have nice defaults which means that we can use them directly without further configuration.

<div id="current-refinements">
  <!-- CurrentRefinements widget will appear here -->
</div>

<div id="clear-all">
  <!-- ClearAll widget will appear here -->
</div>

[ ... ]

<div id="pagination">
  <!-- Pagination widget will appear here -->
</div>

<script>
  const search = instantsearch(options);

  // initialize currentRefinements
  search.addWidget(
    instantsearch.widgets.currentRefinements({
      container: '#current-refinements',
    })
  );

  // initialize clearAll
  search.addWidget(
    instantsearch.widgets.clearAll({
      container: '#clear-all',
      templates: {
        link: 'Reset everything'
      },
      autoHideContainer: false
    })
  );

  // initialize pagination
  search.addWidget(
    instantsearch.widgets.pagination({
      container: '#pagination',
      totalPages: 20,
      // default is to scroll to 'body', here we disable this behavior
      scrollTo: false
    })
  );

  [...]

  search.start();
</script>

Current filters will display all the filters currently selected by the user. This gives the user a synthetic way of understanding the current search. clearAll displays a button to remove all the filters.

In this part, we’ve seen:

  • how to clear the filters
  • how to paginate the results

Wrapping up

Congratulations, you now have a fully featured InstantSearch result page. But this is only the beginning! If you want to dig further into InstantSearch.js, we suggest reading:


Can't find what you are looking for? Open an issue, we'll get back to you.