Skip to main content
Provides AI-powered filter suggestions based on the current search context and user behavior.

Usage

import instantsearch from 'instantsearch.js';
import { filterSuggestions } from 'instantsearch.js/es/widgets';

const search = instantsearch({
  indexName: 'instant_search',
  searchClient
});

search.addWidgets([
  filterSuggestions({
    container: '#filter-suggestions',
    agentId: 'YOUR_AGENT_ID',
    attributes: ['brand', 'category', 'color']
  })
]);

search.start();

Parameters

container
string | HTMLElement
required
CSS selector or HTMLElement to insert the widget.
agentId
string
required
The agent ID for the AI filter suggestions.
attributes
string[]
required
Array of attribute names to get filter suggestions for.
maxSuggestions
number
Maximum number of filter suggestions to display.
debounceMs
number
Debounce time in milliseconds before requesting suggestions.
hitsToSample
number
Number of hits to sample for generating suggestions.
transformItems
function
Function to transform the suggestions before rendering.
(items: FilterSuggestion[]) => FilterSuggestion[]
transport
object
Custom transport configuration for the suggestions API.
templates
object
Templates to use for the widget.
cssClasses
object
CSS classes to add to the widget elements.

Examples

Basic usage

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category', 'color'],
  maxSuggestions: 5
});

Custom item template

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category'],
  templates: {
    item({ suggestion, refine }) {
      return `
        <button 
          class="filter-chip"
          onclick="${() => refine(suggestion)}"
        >
          ${suggestion.label}
          <span class="count">${suggestion.count}</span>
        </button>
      `;
    }
  }
});

With header

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category', 'color'],
  templates: {
    header({ suggestions, isLoading }) {
      if (isLoading) {
        return '<h3>Loading suggestions...</h3>';
      }
      return `<h3>Suggested Filters (${suggestions.length})</h3>`;
    },
    item({ suggestion, refine }) {
      return `
        <div class="suggestion" onclick="${() => refine(suggestion)}">
          <strong>${suggestion.attribute}</strong>: ${suggestion.value}
        </div>
      `;
    }
  }
});

Empty state

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category'],
  templates: {
    item({ suggestion, refine }) {
      return `<button onclick="${() => refine(suggestion)}">${suggestion.label}</button>`;
    },
    empty() {
      return '<p class="no-suggestions">No filter suggestions available.</p>';
    }
  }
});

Hide header

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category'],
  templates: {
    header: false,
    item({ suggestion, refine }) {
      return `<button onclick="${() => refine(suggestion)}">${suggestion.label}</button>`;
    }
  }
});

With debounce

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category', 'color'],
  debounceMs: 300,
  maxSuggestions: 8
});

Transform suggestions

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category', 'price'],
  transformItems(suggestions) {
    // Filter out low-count suggestions
    return suggestions.filter(s => s.count > 5);
  },
  templates: {
    item({ suggestion, refine }) {
      return `
        <button onclick="${() => refine(suggestion)}">
          ${suggestion.label} (${suggestion.count})
        </button>
      `;
    }
  }
});

Styled as chips

filterSuggestions({
  container: '#filter-suggestions',
  agentId: 'filter-agent-123',
  attributes: ['brand', 'category', 'color', 'size'],
  templates: {
    header: 'Refine by',
    item({ suggestion, refine }, { html }) {
      return html`
        <button 
          class="chip"
          onclick=${() => refine(suggestion)}
        >
          <span class="chip-label">${suggestion.value}</span>
          <span class="chip-count">${suggestion.count}</span>
        </button>
      `;
    }
  }
});

HTML output

<div class="ais-FilterSuggestions">
  <div class="ais-FilterSuggestions-header">
    Suggested Filters
  </div>
  
  <ul class="ais-FilterSuggestions-list">
    <li class="ais-FilterSuggestions-item">
      <!-- Item template content -->
    </li>
    <!-- More suggestions -->
  </ul>
</div>

Loading state

<div class="ais-FilterSuggestions">
  <div class="ais-FilterSuggestions-header">
    Loading suggestions...
  </div>
  
  <ul class="ais-FilterSuggestions-list">
    <li class="ais-FilterSuggestions-item ais-FilterSuggestions-item--skeleton">
      <!-- Skeleton loader -->
    </li>
  </ul>
</div>

Notes

  • Requires Algolia AI to be enabled on your account.
  • Suggestions are generated based on search context and user behavior.
  • The widget automatically handles loading and empty states.
  • Clicking a suggestion applies the corresponding filter.
  • Perfect for helping users discover relevant filters.
  • Works best with query-based search interfaces.