Icon search ui white

Building a Search UI

Last updated 03 July 2017

Overview

Beyond just Algolia’s search engine, we also provide several libraries to ease the development of full-featured, customized user interfaces.

  • InstantSearch.js: minimal configuration necessary; provides drop-in UI widgets for the most common search design patterns, including result display, pagination, filtering and faceting.
  • JS Helper: provides robust functions and event handling to keep track of and modify search state at a deeper level
  • Autocomplete.js provides an as-you-type, autocomplete search experience for text inputs

Using any of the above libraries typically removes the need to work with the API at a lower level. However, to understand how search UI is built, it’s helpful to understand the structure of API responses.

Leveraging the API Response

Algolia search responses look something like:

{
  "hits": [
    {
      "firstname": "Jimmie",
      "lastname": "Barninger",
      "objectID": "433",
      "_highlightResult": {
        "firstname": {
          "value": "<em>Jimmie</em>",
          "matchLevel": "partial"
        },
        "lastname": {
          "value": "Barninger",
          "matchLevel": "none"
        },
        "company": {
          "value": "California <em>Paint</em> & Wlpaper Str",
          "matchLevel": "partial"
        }
      }
    }
  ],
  "page": 0,
  "nbHits": 1,
  "nbPages": 1,
  "hitsPerPage": 20,
  "processingTimeMS": 1,
  "query": "jimmie paint"
}

Hits

The most important field in the search response is hits, an array of objects matching the currently active search state.

Each hit contains the object’s retrievable attributes, those attributes that have been configured to be returned in search responses. Two additional fields may be present if highlighting and snippeting have been enabled:

  • _highlightResult: an object keyed on the hit’s retrievable attributes; each key’s value returns a highlighted version of the original attribute, as well as information describing the quality of the match.
  • _snippetResult: an object keyed on the hit’s retrievable attributes; each key’s value returns a snippeted version of the original attribute, as well as information describing the quality of the match.

If highlighting or snippeting have been enabled, the highlighted and snippeted values of firstname, for example, will be available as _highlightResult.firstname.value and _snippetResult.firstname.value, respectively. These values can then be used, instead of their original values, to support highlighting and snippeting in a results interface.

Pagination

Note that a single response does not return all hits — the hits are paginated, with the current pagination state reflected by a few response fields:

  • nbHits: the total number of hits matching the search state
  • nbPages: the total number of pages in the search response
  • hitsPerPage: configurable; indicates how many hits are presented per page
  • page: the current, zero-indexed page of responses

In a search interface, these fields can be used to render appropriate pagination controls. Roughly:

  • Increment the desired page when a “Next” button is clicked, or a specific page when a numeral is clicked.
  • Don’t show a “Next” button if page == nbPages.
  • Don’t show a “Back” button if page == 0.

Keep in mind that this is only necessary when building a very customized experience; Algolia’s InstantSearch.js handles most use cases with minimal configuration.

Templating

You have complete flexibility when it comes to which templating library you use to render results — you could use a robust framework, a simple templating library, or plain JavaScript.

Here’s a simple example using jQuery and Algolia’s Helper.js. Each time a result set is returned, we simply iterate through the result’s hits and append the hit’s name attribute to a #results container:

helper.on('result', function(result) {
  result.hits.forEach((hit) =>
  	 $('#results').append('<p>' + hit.name + '</p>');
  );
});

If results needed highlighting or snippeting, the approach is largely the same. The only difference is that, instead of the original attributes, _highlightResult or _snippetResult would be used:

helper.on('result', function(result) {
  result.hits.forEach((hit) =>
    // with highlighting:
  	 $('#results').append('<p>' + hit._highlightResult.name.value + '</p>');
  	
  	 // with snippeting:
  	 // $('#results').append('<p>' + hit._snippetResult.name.value + '</p>');
  );
});

What’s Next

Continue building your Algolia knowledge with these concepts:

If you want to get started building a search UI, we have a few tutorials you might find helpful:

© Algolia - Privacy Policy