Algolia Add Refiniting List (Faceting)

April 16, 2018
Narrow search result by tags/labels

Algolia has refinementList, which provide filters to narrow down the search results. An example would be using tags to further narrow down the search result.

Goto Algolia -> Apps -> Indices -> Display -> Display Settings -> Faceting -> Attributes for faceting, click on Add Attribute and select tags (or equivelant for your dataset) and click Save.

Click on Browse tab and you should see the tags faucet.

Algolia Browse Faucet

Edit your HTML to include the following container (probably below searchBox and above hits).

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

Edit your InstantSearch.js javascript code to add refinementList widget.

const search = instantsearch({
  appId: '***',
  apiKey: '***',
  indexName: '???',
  urlSync: true
});

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

Algolia Search Faucet

Below is the full HTML (using Bootstrap 4 classes) and JavaScript for Algolia tags fauceting with InstantSearch.js.

<ul class="list-inline">
  <li class="list-inline-item" style="width: 300px;"><div id="search-box"><!-- SearchBox widget will appear here --></div></li>
  <li class="list-inline-item"><img src="https://www.algolia.com/static_assets/images/pricing/pricing_new/algolia-powered-by-14773f38.svg"></img></li>
</ul>

<div class="row">
  <div class="col-md-3 d-none d-md-block">
    <h4 class="mt-3">Tags</h4>
    <div id="refinement-list">
      <!-- RefinementList widget will appear here -->
    </div>
  </div>
  <div class="col-md-9">
    <div id="hits">
      <!-- Hits widget will appear here -->
    </div>

    <div id="pagination">
    <!-- Pagination widget will appear here -->
    </div>
  </div>
</div>
const search = instantsearch({
  appId: '***',
  apiKey: '***',
  indexName: '???',
  urlSync: true
  // routing: true
});

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

search.addWidget(
  instantsearch.widgets.hits({
    container: '#hits',
    templates: {
      empty: 'No results',
      item: '<div class="my-3"><h3><a href="{{ permalink }}">{{{ _highlightResult.title.value }}}</a></h3><div><span class="text-secondary">{{ lastmod_date }}</span> <span class="text-secondary">∙ {{ tags_text }}</span> {{#_highlightResult.description.value}}∙ {{ _highlightResult.description.value }}{{/_highlightResult.description.value}}</div></div>'
    },
    transformData: {
      item: function(data) {
        data.lastmod_date = new Date(data.lastmod*1000).toISOString().slice(0,10)
        // https://caniuse.com/#search=MAP
        const tags = data.tags.map(function(value) {
          return value.toLowerCase().replace(' ', '-')
        })
        data.tags_text = tags.join(', ')
        return data
      }
    }
  })
);

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

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

search.start();
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.