Icon search ui white

Building an instant search result page

Last updated 13 November 2017

Before starting

Make sure you understand the following Algolia concepts before starting this tutorial:

See this tutorial in video

Introduction

Instant search 1

In this tutorial, you will use Algolia to create an instant search results page where the whole page (results, filters and pagination) is updated as you type, to provide end-users with a lightning fast search experience.

Dataset

[
  {
    "name": "3-Year Unlimited Cloud Storage Service Activation Card - Other",
    "description": "Enjoy 3 years of unlimited Cloud storage service with [...]",
    "brand": "Pogoplug",
    "categories": [
      "Best Buy Gift Cards",
      "Entertainment Gift Cards"
    ],
    "hierarchicalCategories": {
      "lvl0": "Best Buy Gift Cards",
      "lvl1": "Best Buy Gift Cards > Entertainment Gift Cards"
    },
    "type": "Online data backup",
    "price": 69,
    "price_range": "50 - 100",
    "image": "https://cdn-demo.algolia.com/bestbuy/1696302_sc.jpg",
    "url": "http://www.bestbuy.com/site/3-year-unlimited-cloud-storage-service-activation-card-other/1696302.p?id=1219066776306&skuId=1696302&cmp=RMX&ky=1uWSHMdQqBeVJB9cXgEke60s5EjfS6M1W",
    "free_shipping": true,
    "popularity": 10000,
    "rating": 2,
    "objectID": "1696302"
  },
  [...]
]

The sample dataset can be downloaded here here. Learn how to import data into Algolia here here.

Index configuration

This tutorial will teach you how to configure the dataset properly to use in a search UI.

Or, if you already understand index configuration, you can quickly configure your data using the following code:

<?php
// composer autoload
require __DIR__ . '/vendor/autoload.php';

// if you are not using composer
// require_once 'path/to/algoliasearch.php';

$client = new \AlgoliaSearch\Client('YourApplicationID', 'YourAdminAPIKey');

$index = $client->initIndex('your_index_name');
require 'rubygems'
require 'algoliasearch'

Algolia.init application_id: 'YourApplicationID',
             api_key:        'YourAPIKey'
index = Algolia::Index.new("your_index_name")
// var algoliasearch = require('algoliasearch');
// var algoliasearch = require('algoliasearch/reactnative');
// var algoliasearch = require('algoliasearch/lite');
// import algoliasearch from 'algoliasearch';
//
// or just use algoliasearch if you are using a <script> tag
// if you are using AMD module loader, algoliasearch will not be defined in window,
// but in the AMD modules of the page

var client = algoliasearch('YourApplicationID', 'YourAPIKey');
var index = client.initIndex('your_index_name');
from algoliasearch import algoliasearch

client = algoliasearch.Client("YourApplicationID", 'YourAPIKey')
index = client.init_index('your_index_name')
import "github.com/algolia/algoliasearch-client-go/algoliasearch"

func main() {
    client := algoliasearch.NewClient("YourApplicationID", "YourAPIKey")
    index := client.InitIndex("your_index_name")
}
<?php
$index->setSettings(array(
  "searchableAttributes" => [
    "brand",
    "name",
    "categories",
    "unordered(description)"
  ],
  "customRanking" => [
    "desc(popularity)"
  ]
));
index.setSettings({
  searchableAttributes: [
    'brand',
    'name',
    'categories',
    'unordered(description)',
  ],
  customRanking: ['desc(popularity)'],
});

HTML

To begin with HTML, first create the necessary DOM elements to contain the search results.

<!doctype html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.css">
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <header>
    <div>
       <input id="search-input" placeholder="Search for products">
       <!-- We use a specific placeholder in the input to guides users in their search. -->
    </div>
  </header>
  <main>
      <div id="hits"></div>
      <div id="pagination"></div>
  </main>
  <script src="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.js"></script>
  <script src="app.js"></script>
</body>

In this HTML page we included:

  • instantsearch.js javascript and css
  • the app.js file where we’ll put all javascript
  • a search input
  • a container for search results
  • a container for pagination of search results

Out of the box, instantsearch.js’s CSS file only contains the bare minimum rules to make it usable, but has no strong styling. To reproduce the tutorial theme, copy the content of the CSS file to your style.css.

Initialize instantsearch.js

Before beginning, be sure you have the following information:

  • Your search credentials: the Application ID and Search only API Key found in the credentials page in your Algolia Dashboard
  • The name of the index you want to query
var search = instantsearch({
  // Replace with your own values
  appId: 'latency',
  apiKey: '6be0576ff61c053d5f9a3225e2a90f76', // search only API key, no ADMIN key
  indexName: 'instant_search',
  urlSync: true
});

The urlSync option is now activated. This will keep the browser url in sync and allow users to copy paste urls corresponding to the current search state.

Binding the search input

In the HTML there’s an input to bind to the Algolia index. This means that when a query is made, instantsearch.js will fetch results from Algolia.

To implement this, you’ll use the searchBox widget, just be certain to specify the search input id in the container option of the widget.

search.addWidget(
  instantsearch.widgets.searchBox({
    container: '#search-input'
  })
);

Displaying results

search.addWidget(
  instantsearch.widgets.hits({
    container: '#hits',
    hitsPerPage: 10,
    templates: {
      item: document.getElementById('hit-template').innerHTML,
      empty: "We didn't find any results for the search <em>\"{{query}}\"</em>"
    }
  })
);

You can see here that up to 10 search results will be rendered inside the <div id="hits">.

Instantsearch will use default templates if none are specified. In this case we want to use custom templates. The template can be specified directly (as with the empty template) or can be fetched from the DOM (as with the item template)

<script type="text/html" id="hit-template">
  <div class="hit">
    <div class="hit-image">
      <img src="{{image}}" alt="{{name}}">
    </div>
    <div class="hit-content">
      <h3 class="hit-price">${{price}}</h3>
      <h2 class="hit-name">{{{_highlightResult.name.value}}}</h2>
      <p class="hit-description">{{{_highlightResult.description.value}}}</p>
    </div>
  </div>
</script>

A few things to note about this hit template:

  • The item template will be used for every hit, using the hit’s data as the rendering context.
  • The special attribute, _higlightResult, contains the same attributes with HTML highlights on the matched words.
  • By default, the API returns the highlighted part between <em> tags (like <em>smart</em>phone}) so that they can be easily styled.
  • You must disable escaping on highlighted values, which can be easily done using three curly-braces {{{html}}}.
  • Our template is wrapped in a <script type="text/html"> tag, so you can “store” some HTML code without rendering it on the page.

Pagination

To add pagination, simply add a pagination widget, again specifying where to display it in the DOM.

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

Start instantsearch

Now that all widgets have been added, let’s start the whole interface:

search.start();

Going further

This is only the beginning of what can be done with instantsearch.js. Remember that you can always go further with instant search through a variety of customizations and additional widgets.

Below is the documentation of the widget used in this tutorial

And here you can find a list of additional interesting widgets

What’s Next

Continue building your Algolia knowledge with these tutorials:

© Algolia - Privacy Policy