Helper for implementing advanced search features with Algolia
Switch branches/tags
V1 chore/esm chore/jest chore/use-version-js-not-json develop doc/searchParameters fea/newHeader feat/add-remove-facet feat/middlewares feat/pending-search feat/public-shortener feat/toggleRefinementForState feat/unqiue-identifier feature/fix-184 fix/92 fix/540 gh-pages greenkeeper-algoliasearch-3.18.1 greenkeeper-algoliasearch-3.19.0 greenkeeper-algoliasearch-3.19.1 greenkeeper-algoliasearch-3.19.2 greenkeeper-algoliasearch-3.20.0 greenkeeper-algoliasearch-3.20.1 greenkeeper-algoliasearch-3.20.2 greenkeeper-algoliasearch-3.20.3 greenkeeper-babel-core-6.14.0 greenkeeper-babel-core-6.16.0 greenkeeper-babel-core-6.17.0 greenkeeper-babel-core-6.18.0 greenkeeper-babel-core-6.18.1 greenkeeper-babel-core-6.18.2 greenkeeper-babel-core-6.20.0 greenkeeper-babel-core-6.21.0 greenkeeper-babel-loader-6.2.6 greenkeeper-babel-loader-6.2.7 greenkeeper-babel-loader-6.2.8 greenkeeper-babel-loader-6.2.9 greenkeeper-babel-preset-es2015-6.14.0 greenkeeper-babel-preset-es2015-6.16.0 greenkeeper-babel-preset-es2015-6.18.0 greenkeeper-benchmark-2.1.2 greenkeeper-benchmark-2.1.3 greenkeeper-browserify-13.1.1 greenkeeper-browserify-13.2.0 greenkeeper-browserify-13.3.0 greenkeeper-dateformat-2.0.0 greenkeeper-dmd-2.0.3 greenkeeper-dmd-2.1.0 greenkeeper-envify-4.0.0 greenkeeper-eslint-3.4.0 greenkeeper-eslint-3.5.0 greenkeeper-eslint-3.6.1 greenkeeper-eslint-3.7.0 greenkeeper-eslint-3.7.1 greenkeeper-eslint-3.8.0 greenkeeper-eslint-3.9.0 greenkeeper-eslint-3.9.1 greenkeeper-eslint-3.10.0 greenkeeper-eslint-3.10.1 greenkeeper-eslint-3.10.2 greenkeeper-eslint-3.11.0 greenkeeper-eslint-3.11.1 greenkeeper-eslint-3.12.0 greenkeeper-eslint-3.12.1 greenkeeper-eslint-config-airbnb-11.0.0 greenkeeper-eslint-config-airbnb-11.2.0 greenkeeper-eslint-config-airbnb-13.0.0 greenkeeper-handlebars-4.0.6 greenkeeper-jsdoc-parse-2.0.5 greenkeeper-jsdoc-to-markdown-1.3.7 greenkeeper-jsdoc-to-markdown-1.3.9 greenkeeper-jsdoc-to-markdown-2.0.0 greenkeeper-lodash-4.16.0 greenkeeper-lodash-4.16.1 greenkeeper-lodash-4.16.2 greenkeeper-lodash-4.16.3 greenkeeper-lodash-4.16.4 greenkeeper-lodash-4.16.5 greenkeeper-lodash-4.16.6 greenkeeper-lodash-4.17.0 greenkeeper-lodash-4.17.1 greenkeeper-lodash-4.17.2 greenkeeper-lodash-4.17.3 greenkeeper-lodash-4.17.4 greenkeeper-metalsmith-2.2.1 greenkeeper-metalsmith-2.2.2 greenkeeper-metalsmith-2.3.0 greenkeeper-metalsmith-changed-3.1.0 greenkeeper-metalsmith-layouts-1.7.0 greenkeeper-metalsmith-metallic-2.0.1 greenkeeper-metalsmith-packagejson-1.1.0 greenkeeper-onchange-3.0.1 greenkeeper-onchange-3.0.2 greenkeeper-onchange-3.1.0 greenkeeper-onchange-3.2.0 greenkeeper-onchange-3.2.1 greenkeeper-phantomjs-prebuilt-2.1.13 greenkeeper-phantomjs-prebuilt-2.1.14 greenkeeper-qs-6.3.0 greenkeeper-sinon-1.17.6 greenkeeper-sinon-1.17.7 greenkeeper-tape-4.6.1 greenkeeper-tape-4.6.2 greenkeeper-tape-4.6.3 greenkeeper-uglify-js-2.7.4 greenkeeper-uglify-js-2.7.5 greenkeeper-update-all greenkeeper-vinyl-2.0.0 greenkeeper-vinyl-2.0.1 greenkeeper-webpack-1.13.2 greenkeeper-webpack-1.13.3 greenkeeper-webpack-1.14.0 greenkeeper-zuul-3.11.1 master poc/flow-type renovate/algoliasearch-3.x renovate/colors-1.x renovate/conventional-changelog-cli-1.x renovate/eslint-config-airbnb-0.x renovate/gh-pages-1.x renovate/gulp-cli-1.x renovate/handlebars-4.x renovate/marked-0.x renovate/metalsmith-discover-partials-0.x renovate/metalsmith-headings-0.x renovate/metalsmith-in-place-digest renovate/metalsmith-markdown-0.x renovate/metalsmith-sass-1.x renovate/mversion-1.x renovate/onchange-3.x renovate/pin-dependencies renovate/rimraf-2.x renovate/semver-5.x renovate/shelljs-0.x renovate/watchify-3.x revert-330-feat/add-remove-facet test/geo-search vvo-patch-1
Nothing to show
Clone or download
Haroenv chore(deps): update st (#625)
* chore: update lockfile to add integrity

* chore: upgrade st to 1.2.2 (fix possible vuln)
Latest commit 5d7d915 Oct 8, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
dist 2.26.1 - 2018-06-19 Jun 19, 2018
documentation-src chore(docs): fix interpolation Aug 2, 2018
examples feat(derive) Let the user create a derivation of an helper (#374) Dec 22, 2016
scripts fix(release-script): actually build the library (#559) Dec 14, 2017
src feat(sffv): throw an error if it's called and the client doesn't have… Oct 8, 2018
test feat(sffv): throw an error if it's called and the client doesn't have… Oct 8, 2018
.eslintignore chore(build): Provide an ES module build Mar 8, 2017
.eslintrc feat(client): Adds methods to set/get the client. (#460) Jan 10, 2017
.gitignore chore(docs): remove folder in `develop` (#616) Aug 2, 2018
.jsdoc chore: code style change, lint using modified eslint-config-airbnb Jul 6, 2015
.nvmrc chore(ci): fix build so that tests can be executed (tests are still f… Jul 20, 2017
.travis.yml chore(ci): fix build so that tests can be executed (tests are still f… Jul 20, 2017
CHANGELOG 2.26.1 - 2018-06-19 Jun 19, 2018 test: first pass at full CI browser/node/iojs testing Jul 1, 2015
LICENSE Initial commit Mar 20, 2015 doc(params): Add filters to query parameters (#604) May 16, 2018
bower.json 2.26.1 - 2018-06-19 Jun 19, 2018
index.html docs(jsdoc): fix spelling Jun 1, 2017
index.js docs(init): use toggleFacetRefinement instead (#622) Oct 5, 2018
package.json chore(deps): update st (#625) Oct 8, 2018
renovate.json build: Configure Renovate (#579) Apr 25, 2018
yarn.lock chore(deps): update st (#625) Oct 8, 2018
zuul.config.js test(chore) Update browsers list Aug 22, 2016

Coming from V1 (or js client v2)? Read the migration guide to the new version of the Helper.

The JavaScript helper is an advanced library we provide to our users. If you are looking to build a complete search interface, we recommend you to use instantsearch.js. If you want to build an autocomplete menu, see autocomplete.js.


This module is the companion of the algolia/algoliasearch-client-js. It helps you keep track of the search parameters and provides a higher level API.

This is the library you will need to easily build a good search UX like our instant search demo.

See the helper in action

Version Build Status License Downloads jsDelivr Hits


  • Search parameters management
  • Facets exclusions
  • Pagination
  • Disjunctive faceting (search on two or more values of the same facet)


Vanilla JavaScript

A small example that uses Browserify to manage modules.

var algoliasearch = require('algoliasearch');
var algoliasearchHelper = require('algoliasearch-helper');

var client = algoliasearch('appId', 'apiKey');

var helper = algoliasearchHelper(client, 'indexName', {
  facets: ['mainCharacterFirstName', 'year'],
  disjunctiveFacets: ['director']

helper.on('result', function(data){

helper.addDisjunctiveFacetRefinement('director', 'Clint Eastwood');
helper.addDisjunctiveFacetRefinement('director', 'Sofia Coppola');

helper.addNumericRefinement('year', '=', 2003);

// Search for any movie filmed in 2003 and directed by either C. Eastwood or S. Coppola;

See more examples in the examples folder

AngularJS module

<script src=""></script>
<script src="dist/algoliasearch.helper.min.js"></script>

<script type="text/javascript">
angular.module('searchApp', ['ngSanitize', 'algoliasearch'])
.controller('searchController', ['$scope', '$sce', 'algolia', function($scope, $sce, algolia) {
  var algolia = algolia.Client('applicationId', 'apiKey');
  $scope.q = '';
  $scope.content = null;
  $scope.helper = algoliasearchHelper(algolia, 'indexName', {
    facets: ['type', 'shipping'],
    disjunctiveFacets: ['category', 'manufacturer'],
    hitsPerPage: 5,
  $scope.helper.on('result', function(content) {
    $scope.$apply(function() {
      $scope.content = content;
  $scope.toggleRefine = function($event, facet, value) {
    $scope.helper.toggleRefine(facet, value).search();
  $scope.$watch('q', function(q) {

You can see the full Angular example here

Helper cheatsheet

There is also a complete JSDoc

Add the helper in your project

Regular <script> tag

Use our jsDelivr build:

<script src=""></script>

With NPM

npm install algoliasearch-helper

With bower

bower install algoliasearch-helper

Init the helper

var helper = algoliasearchHelper(client, 'indexName'/*, parameters*/);

Helper lifecycle

  1. modify the parameters of the search (usually through user interactions)
    helper.setQuery('iphone').addFacetRefinement('category', 'phone')

  2. trigger the search (after all the modification have been applied)

  3. read the results (with the event "result" handler) and update the UI with the results
    helper.on('result', function(results) { updateUI(results); });

  4. go back to 1


AlgoliasearchHelper: the helper. Keeps the state of the search, makes the queries and calls the handlers when an event happen.

SearchParameters: the object representing the state of the search. The current state is stored in helperInstance.state.

SearchResults: the object in which the Algolia answers are transformed into. This object is passed to the result event handler. An example of SearchResults in JSON is available at the end of this readme


The search is triggered by the search() method.

It takes all the previous modifications to the search and uses them to create the queries to Algolia. The search parameters are immutable.


var helper = algoliasearchHelper(client, indexName);

// Let's monitor the results with the console
helper.on('result', function(content) {

// Let's make an empty search
// The results are all sorted using the dashboard configuration;

// Let's search for "landscape"

// Let's add a category "photo"
// Will make a search with "photo" tag and "landscape" as the query


The helper is a Node.js EventEmitter instance.

result: get notified when new results are received. The handler function will receive two objects (SearchResults and SearchParameters).

error: get notified when errors are received from the API.

change: get notified when a property has changed in the helper

search : get notified when a request is sent to Algolia

Listen to the result event

helper.on('result', updateTheResults);

Listen to a result event once

helper.once('result', updateTheResults);

Remove a result listener

helper.removeListener('result', updateTheResults);

Remove all result listeners


All the methods from Node.js EventEmitter class are available.


Do a search with the query "fruit"


Filtering results

Facets are filters to retrieve a subset of an index having a specific value for a given attribute. First you need to define which attribute will be used as a facet in the dashboard:

Regular (conjunctive) facets

Refinements are ANDed by default (Conjunctive selection).

Facet definition
var helper = algoliasearchHelper(client, indexName, {
	facets: ['ANDFacet']
Add a facet filter
helper.addFacetRefinement('ANDFacet', 'valueOfANDFacet').search();
Remove a facet filter
helper.removeFacetRefinement('ANDFacet', 'valueOfANDFacet').search();

Disjunctive facets

Refinements are ORed by default (Disjunctive selection).

Facet definition
var helper = algoliasearchHelper(client, indexName, {
	disjunctiveFacets: ['ORFacet']
Add a facet filter
helper.addDisjunctiveFacetRefinement('ORFacet', 'valueOfORFacet').search();
Remove a facet filter
helper.removeDisjunctiveFacetRefinement('ORFacet', 'valueOfORFacet').search();

Negative facets

Filter so that we do NOT get a given facet

Facet definition (same as "AND" facet)
var helper = algoliasearchHelper(client, indexName, {
	facets: ['ANDFacet']
Exclude a value for a facet
helper.addFacetExclusion('ANDFacet', 'valueOfANDFacetToExclude');
Remove an exclude from the list of excluded values
helper.removeFacetExclusion('ANDFacet', 'valueOfANDFacetToExclude');

Numeric facets

Filter over numeric attributes with math operations like =, >, <, >=, <=. Can be used for numbers and dates (if converted to timestamp)

Facet definition
var helper = algoliasearchHelper(client, indexName, {
  disjunctiveFacets: ['numericAttribute']
Add numeric refinements
helper.addNumericRefinement('numericAttribute', '=', '3').search();
// filter to only the results that match numericAttribute=3
helper.addNumericRefinement('numericAttribute', '=', '4').search();
// filter to only the results that match numericAttribute=3 AND numericAttribute=4

// On another numeric with no previous filter
helper.addNumericRefinement('numericAttribute2', '=', ['42', '56', '37'] ).search();
// filter to only the results that match numericAttribute2=42 OR numericAttribute2=56 OR numericAttribute2=37
Remove a numeric refinement
helper.removeNumericRefinement('numericAttribute', '=', '3').search();
Batch numeric filter removal
// for the single operator = on numericAttribute
helper.removeNumericRefinement('numericAttribute', '=').search();
// for all the refinements on numericAttribute

Hierarchical facets

Hierarchical facets are useful to build such navigation menus:

| products
  > fruits
    > citrus
    | strawberries
    | peaches
    | apples

Here, we refined the search this way:

  • click on fruits
  • click on citrus

To build such menu, you need to use hierarchical faceting:

var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1']

Requirements: All the specified attributes must be defined in your Algolia settings as attributes for faceting.

Given your objects looks like this:

  "objectID": "123",
  "name": "orange",
  "categories": {
    "lvl0": "fruits",
    "lvl1": "fruits > citrus"

And you refine products:

helper.toggleFacetRefinement('products', 'fruits > citrus');

You will get a hierarchical presentation of your facet values: a navigation menu of your facet values.

helper.on('result', function(data){
  // {
  //   'name': 'products',
  //   'count': null,
  //   'isRefined': true,
  //   'path': null,
  //   'data': [{
  //     'name': 'fruits',
  //     'path': 'fruits',
  //     'count': 1,
  //     'isRefined': true,
  //     'data': [{
  //       'name': 'citrus',
  //       'path': 'fruits > citrus',
  //       'count': 1,
  //       'isRefined': true,
  //       'data': null
  //     }]
  //   }]
  // }

To ease navigation, we always:

  • provide the root level categories
  • provide the current refinement sub categories (fruits > citrus > *: n + 1)
  • provide the parent refinement (fruits > citrus => fruits: n -1) categories
  • refine the search using the current hierarchical refinement
Multiple values per level

Your records can also share multiple categories between one another by using arrays inside your object:

  "objectID": "123",
  "name": "orange",
  "categories": {
    "lvl0": ["fruits", "color"],
    "lvl1": ["fruits > citrus", "color > orange"]
  "objectID": "456",
  "name": "grapefruit",
  "categories": {
    "lvl0": ["fruits", "color", "new"],
    "lvl1": ["fruits > citrus", "color > yellow", "new > citrus"]
Specifying another separator
var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1'],
    separator: '|'

helper.toggleFacetRefinement('products', 'fruits|citrus');

Would mean that your objects look like so:

  "objectID": "123",
  "name": "orange",
  "categories": {
    "lvl0": "fruits",
    "lvl1": "fruits|citrus"
Specifying a different sort order for values

The default sort for the hierarchical facet view is: isRefined:desc (first show refined), name:asc (then sort by name).

You can specify a different sort order by using:

var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1'],
    sortBy: ['count:desc', 'name:asc'] // first show the most common values, then sort by name

The available sort tokens are:

  • count
  • isRefined
  • name
  • path
Restrict results and hierarchical values to non-root level

Let's say you have a lot of levels:

- fruits
  - yellow
    - citrus
      - spicy

But you only want to get the values starting at "citrus", you can use rootPath

You can specify an root path to filter the hierarchical values

var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1', 'categories.lvl2', 'categories.lvl3'],
    rootPath: 'fruits > yellow > citrus'

Having a rootPath will refine the results on it automatically.

Hide parent level of current parent level

By default the hierarchical facet is going to return the child and parent facet values of the current refinement.

If you do not want to get the parent facet values you can set showParentLevel to false

var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1'],
    showParentLevel: false
Asking for the current breadcrumb
var helper = algoliasearchHelper(client, indexName, {
  hierarchicalFacets: [{
    name: 'products',
    attributes: ['categories.lvl0', 'categories.lvl1'],
    separator: '|'

helper.toggleFacetRefinement('products', 'fruits|citrus');
var breadcrumb = helper.getHierarchicalFacetBreadcrumb('products');

// ['fruits', 'citrus']

console.log(breadcrumb.join(' | '));
// 'fruits | citrus'

Clearing filters

Clear all the refinements for all the refined attributes
Clear all the refinements for a specific attribute
[ADVANCED] Clear only the exclusions on the "ANDFacet" attribute
helper.clearRefinements(function(value, attribute, type) {
  return type === 'exclude' && attribute === 'ANDFacet';

Facet utilities

Get the values of a facet with the default sort

helper.on('result', function(result) {
  // Get the facet values for the attribute age
  // It will be ordered :
  //  - refined facets first
  //  - then ordered by number of occurence (bigger count -> higher in the list)
  //  - then ordered by name (alphabetically)

Get the values of a facet with a custom sort

helper.on('result', function(result) {
  // Get the facet values for the attribute age
  result.getFacetValues('age', {sortBy: ['count:asc']});
  // It will be ordered by number of occurence (lower number => higher position)
  // Elements that can be sorted : count, name, isRefined
  // Type of sort : 'asc' for ascending order, 'desc' for descending order

Get the facet stats

This only apply on numeric based facets/attributes.

helper.on('result', function(result) {
  // Get the facet values for the attribute age


Tags are an easy way to do filtering. They are based on a special attribute in the records named _tags, which can be a single string value or an array of strings.

Add a tag filter for the value "landscape"


Remove a tag filter for the value "landscape"


Clear all the tags filters



Get the current page


Change page


Automatic reset to page 0

During a search, changing the parameters will update the result set, which can then change the number of pages in the result set. Therefore, the behavior has been standardized so that any operation that may change the number of page will reset the pagination to page 0.

This may lead to some unexpected behavior. For example:

helper.getPage(); // 4
helper.getPage(); // 0

Non exhaustive list of operations that trigger a reset:

  • refinements (conjunctive, exclude, disjunctive, hierarchical, numeric)
  • tags
  • index (setIndex)
  • setQuery
  • setHitsPerPage
  • setTypoTolerance


Index can be changed. The common use case is when you have several slaves with different sort order (sort by relevance, price or any other attribute).

Change the current index


Get the current index

var currentIndex = helper.getIndex();

One time query

Sometime it's convenient to reuse the current search parameters with small changes without changing the state stored in the helper. That's why there is a function called searchOnce. This method does not trigger change or error events.

In the following, we are using searchOnce to fetch only a single element using all the other parameters already set in the search parameters.

Using searchOnce with a callback

var state = helper.searchOnce(
  {hitsPerPage: 1},
  function(error, content, state) {
    // if an error occured it will be passed in error, otherwise its value is null
    // content contains the results formatted as a SearchResults
    // state is the instance of SearchParameters used for this search

Using searchOnce with a promise

var state1 = helper.searchOnce({hitsPerPage: 1})
                   .then(function(res) {
  // res contains
  // {
  //   content : SearchResults
  //   state : SearchParameters (the one used for this specific search)
  // }

URL Helpers

Set the state from a query string


Get a plain object with a subset of the state

// to an object with the query and all the refinements
helper.getState(['query', 'attribute:*']);

Get an object for the helper configuration in the query string

var state = algoliasearchHelper.url.getStateFromQueryString(qs);

Get the configuration contained in the query string that is not for the helper

var otherConf = algoliasearchHelper.url.getUnrecognizedParametersInQueryString(qs);

Get the query string of any state

var state = helper.getState();
var qs = algoliasearchHelper.url.getQueryStringFromState(state);

Query parameters

There are lots of other parameters you can set.

Set a parameter at the initialization of the helper

var helper = algoliasearchHelper(client, indexName, {
	hitsPerPage: 50

Set a parameter later

helper.setQueryParameter('hitsPerPage', 20).search();

List of parameters that can be set






Enable the advanced syntax.

advancedSyntax on



Should the engine allow typos on numerics.

allowTyposOnNumericTokens on



Enable the analytics

analytics on



Tag of the query in the analytics.

analyticsTags on



Center of the geo search.

aroundLatLng on



Center of the search, retrieve from the user IP.

aroundLatLngViaIP on



Precision of the geo search.

aroundPrecision on



Radius of the geo search.

aroundRadius on



Minimum radius of the geo search.

minimumAroundRadius on



List of attributes to highlight

attributesToHighlight on



List of attributes to retrieve

attributesToRetrieve on



List of attributes to snippet

attributesToSnippet on



All the declared disjunctive facets



Remove duplicates based on the index setting attributeForDistinct

distinct on



All the facets that will be requested to the server



Add filters to the query (similar to WHERE clauses)

filters on



Enable the ranking informations in the response

getRankingInfo on



Number of hits to be returned by the search API

hitsPerPage on



Should the plurals be ignored

ignorePlurals on



Geo search inside a box.

insideBoundingBox on



Geo search inside a polygon.

insidePolygon on



Number of values for each facetted attribute

maxValuesPerFacet on



Number of characters to wait before doing one character replacement.

minWordSizefor1Typo on



Number of characters to wait before doing a second character replacement.

minWordSizefor2Typos on



Add some optional words to those defined in the dashboard

optionalWords on



The current page number

page on



Query string of the instant search. The empty string is a valid query.

query on



How the query should be treated by the search engine. Possible values: prefixAll, prefixLast, prefixNone

queryType on



Possible values are "lastWords" "firstWords" "allOptional" "none" (default)

removeWordsIfNoResults on



Should the engine replace the synonyms in the highlighted results.

replaceSynonymsInHighlight on



Restrict which attribute is searched.

restrictSearchableAttributes on



Enable the synonyms

synonyms on



Contains the tag filters in the raw format of the Algolia API. Setting this parameter is not compatible with the of the add/remove/toggle methods of the tag api.

tagFilters on



How the typo tolerance behave in the search engine. Possible values: true, false, min, strict

typoTolerance on

Results format

Here is an example of a result object you get with the result event.

   "hitsPerPage": 10,
   "processingTimeMS": 2,
   "facets": [
         "name": "type",
         "data": {
            "HardGood": 6627,
            "BlackTie": 550,
            "Music": 665,
            "Software": 131,
            "Game": 456,
            "Movie": 1571
         "exhaustive": false
         "exhaustive": false,
         "data": {
            "Free shipping": 5507
         "name": "shipping"
   "hits": [
         "thumbnailImage": "",
         "_highlightResult": {
            "shortDescription": {
               "matchLevel": "none",
               "value": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
               "matchedWords": []
            "category": {
               "matchLevel": "none",
               "value": "Computer Security Software",
               "matchedWords": []
            "manufacturer": {
               "matchedWords": [],
               "value": "Webroot",
               "matchLevel": "none"
            "name": {
               "value": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
               "matchedWords": [],
               "matchLevel": "none"
         "image": "",
         "shipping": "Free shipping",
         "bestSellingRank": 4,
         "shortDescription": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
         "url": "…d=1219060687969&skuId=1688832&cmp=RMX&ky=2d3GfEmNIzjA0vkzveHdZEBgpPCyMnLTJ",
         "name": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
         "category": "Computer Security Software",
         "salePrice_range": "1 - 50",
         "objectID": "1688832",
         "type": "Software",
         "customerReviewCount": 5980,
         "salePrice": 49.99,
         "manufacturer": "Webroot"
   "nbHits": 10000,
   "disjunctiveFacets": [
         "exhaustive": false,
         "data": {
            "5": 183,
            "12": 112,
            "7": 149,
         "name": "customerReviewCount",
         "stats": {
            "max": 7461,
            "avg": 157.939,
            "min": 1
         "data": {
            "Printer Ink": 142,
            "Wireless Speakers": 60,
            "Point & Shoot Cameras": 48,
         "name": "category",
         "exhaustive": false
         "exhaustive": false,
         "data": {
            "> 5000": 2,
            "1 - 50": 6524,
            "501 - 2000": 566,
            "201 - 500": 1501,
            "101 - 200": 1360,
            "2001 - 5000": 47
         "name": "salePrice_range"
         "data": {
            "Dynex™": 202,
            "Insignia™": 230,
            "PNY": 72,
         "name": "manufacturer",
         "exhaustive": false
   "query": "",
   "nbPages": 100,
   "page": 0,
   "index": "bestbuy"

Browser support

This project works on any ES5 browser, basically >= IE9+.