The widgets for displaying recommendations are part of InstantSearch.js,
starting with version 4.69.0.
The Algolia JavaScript API client supports the Recommend API starting with version 4.23.2.
With this, you can integrate recommendations seamlessly into your InstantSearch app,
without having to install additional packages.
Packages
Add the instantsearch.js and algoliasearch packages to your project,
and remove the @algolia/recommend and @algolia/recommend-js packages:
1
2
3
4
5
| yarn add algoliasearch instantsearch.js
yarn remove @algolia/recommend-js @algolia/recommend
# or
npm install algoliasearch instantsearch.js
npm uninstall @algolia/recommend-js @algolia/recommend
|
Imports
Import the Recommend widgets from InstantSearch.js:
1
2
| - import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
|
The trendingFacets function is no longer available.
To replace it, see widgets.
Usage
Add the Recommend widgets to the instantsearch component.
Pass the API client and index name to the instantsearch widget:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| - import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import instantsearch from 'instantsearch.js';
+ import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
- import recommend from '@algolia/recommend';
+ import algoliasearch from 'algoliasearch/lite';
- const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const search = instantsearch({
+ searchClient,
+ indexName: 'YOUR_INDEX_NAME',
+ }).addWidgets([
frequentlyBoughtTogether({
container: '#frequentlyBoughtTogether',
- recommendClient,
- indexName: 'YOUR_INDEX_NAME',
objectIDs: ['5723537'],
});
+ ]);
+ search.start();
|
Changes for frequentlyBoughtTogether
Move recommendClient and indexName to instantsearch
The frequentlyBoughtTogether widget no longer needs recommendClient and indexName props.
Instead, pass a searchClient and the ìndexName to instantsearch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| - import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import instantsearch from 'instantsearch.js';
+ import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
- import recommend from '@algolia/recommend';
+ import algoliasearch from 'algoliasearch/lite';
- const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const search = instantsearch({
+ searchClient,
+ indexName: 'YOUR_INDEX_NAME',
+ }).addWidgets([
frequentlyBoughtTogether({
container: '#frequentlyBoughtTogether',
- recommendClient,
- indexName: 'YOUR_INDEX_NAME',
objectIDs: ['5723537'],
});
+ ]);
+ search.start();
|
Replace view with the layout template or the connectFrequentlyBoughtTogether connector
The frequentlyBoughtTogether widget no longer provides a view prop.
To fully customize the UI, use either the layout template or the connectFrequentlyBoughtTogether connector instead.
Layout template
1
2
3
4
5
6
7
8
9
10
11
12
| - import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
frequentlyBoughtTogether({
container: '#frequentlyBoughtTogether',
- view: (props) => { /* ... */ },
+ templates: {
+ layout({ items }, { html }) {
+ // …
+ },
+ }
});
|
Connector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import {
+ connectFrequentlyBoughtTogether,
+ } from 'instantsearch.js/es/connectors';
+ const customFrequentlyBoughtTogether = connectFrequentlyBoughtTogether(({ items, widgetParams }) => {
+ const container = document.querySelector(widgetParams.container);
+ container.innerHTML = `/* ... */`;
+ });
- frequentlyBoughtTogether({
+ customFrequentlyBoughtTogether({
container: '#frequentlyBoughtTogether',
- view: (props) => { /* ... */ },
}),
|
Replace component props with templates
The frequentlyBoughtTogether widget uses templates to customize specific parts of its UI.
| Recommend JS |
InstantSearch.js |
headerComponent |
header |
itemComponent |
item |
fallbackComponent |
empty |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| frequentlyBoughtTogether({
- headerComponent({ classNames, recommendations, html }) {
- return html`<h2 class=${classNames.title}>
- Recommendations (${recommendations.length})
- </h2>`;
- },
+ templates: {
+ header({ cssClasses, items }, { html }) {
+ return html`<h2 class=${cssClasses.title}>
+ Recommendations (${items.length})
+ </h2>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
9
10
| frequentlyBoughtTogether({
- itemComponent({ item, html }) {
- return html`<p>${item.name}</p>`;
- },
+ templates: {
+ item(recommendation, { html }) {
+ return html`<p>${recommendation.name}</p>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
| frequentlyBoughtTogether({
- fallbackComponent({ html }) {
+ templates: {
+ empty(_, { html }) {
return html`<p>No recommendations.</p>`;
+ }
},
});
|
Replace translations with templates
The frequentlyBoughtTogether widget uses templates to provide translations to the header.
1
2
3
4
5
6
7
8
9
10
| frequentlyBoughtTogether({
- translations: {
- title: 'Recommendations',
- },
+ templates: {
+ header: ({ cssClasses }, { html }) {
+ return html`<h2 class=${cssClasses.title}>Recommendations</h2>`;
+ },
+ },
});
|
Replace maxRecommendations with limit
The limit prop replaces the maxRecommendations prop.
1
2
3
4
| frequentlyBoughtTogether({
- maxRecommendations: 3,
+ limit: 3,
});
|
Remove environment
The environment prop is no longer needed.
1
2
3
| frequentlyBoughtTogether({
- environment: global,
});
|
Replace classNames with cssClasses
The cssClasses prop replaces the classNames prop.
1
2
3
4
5
6
7
8
9
10
11
| frequentlyBoughtTogether({
- classNames: {
+ cssClasses: {
root: 'MyCustomFrequentlyBoughtTogether',
+ emptyRoot: 'MyCustomFrequentlyBoughtTogether-emptyRoot',
title: 'MyCustomFrequentlyBoughtTogether-title',
container: 'MyCustomFrequentlyBoughtTogether-container',
list: 'MyCustomFrequentlyBoughtTogether-list',
item: 'MyCustomFrequentlyBoughtTogether-item',
},
});
|
Move recommendClient and indexName to instantsearch
The relatedProducts widget no longer needs recommendClient and indexName props.
Instead, pass a searchChlient and the ìndexName to instantsearch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| - import { relatedProducts } from '@algolia/recommend-js';
+ import instantsearch from 'instantsearch.js';
+ import { relatedProducts } from 'instantsearch.js/es/widgets';
- import recommend from '@algolia/recommend';
+ import algoliasearch from 'algoliasearch/lite';
- const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const search = instantsearch({
+ searchClient,
+ indexName: 'YOUR_INDEX_NAME',
+ }).addWidgets([
relatedProducts({
container: '#relatedProducts',
- recommendClient,
- indexName: 'YOUR_INDEX_NAME',
objectIDs: ['5723537'],
});
+ ]);
+ search.start();
|
The relatedProducts widget no longer provides a view prop.
To fully customize the UI, use either the layout template or the connectRelatedProducts connector instead.
Layout template
1
2
3
4
5
6
7
8
9
10
11
12
| - import { relatedProducts } from '@algolia/recommend-js';
+ import { relatedProducts } from 'instantsearch.js/es/widgets';
relatedProducts({
container: '#relatedProducts',
- view: (props) => { /* ... */ },
+ templates: {
+ layout({ items }, { html }) {
+ // …
+ },
+ }
});
|
Connector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - import { relatedProducts } from '@algolia/recommend-js';
+ import {
+ connectRelatedProducts,
+ } from 'instantsearch.js/es/connectors';
+ const customRelatedProducts = connectRelatedProducts(({ items, widgetParams }) => {
+ const container = document.querySelector(widgetParams.container);
+ container.innerHTML = `/* ... */`;
+ });
- relatedProducts({
+ customRelatedProducts({
container: '#relatedProducts',
- view: (props) => { /* ... */ },
}),
|
Replace component props with templates
The relatedProducts widget uses templates to customize specific parts of its UI.
| Recommend JS |
InstantSearch.js |
headerComponent |
header |
itemComponent |
item |
fallbackComponent |
empty |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| relatedProducts({
- headerComponent({ classNames, recommendations, html }) {
- return html`<h2 class=${classNames.title}>
- Recommendations (${recommendations.length})
- </h2>`;
- },
+ templates: {
+ header({ cssClasses, items }, { html }) {
+ return html`<h2 class=${cssClasses.title}>
+ Recommendations (${items.length})
+ </h2>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
9
10
| relatedProducts({
- itemComponent({ item, html }) {
- return html`<p>${item.name}</p>`;
- },
+ templates: {
+ item(recommendation, { html }) {
+ return html`<p>${recommendation.name}</p>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
| relatedProducts({
- fallbackComponent({ html }) {
+ templates: {
+ empty(_, { html }) {
return html`<p>No recommendations.</p>`;
+ }
},
});
|
Replace translations with templates
The relatedProducts widget uses templates to provide translations to the header.
1
2
3
4
5
6
7
8
9
10
| relatedProducts({
- translations: {
- title: 'Recommendations',
- },
+ templates: {
+ header: ({ cssClasses }, { html }) {
+ return html`<h2 class=${cssClasses.title}>Recommendations</h2>`;
+ },
+ },
});
|
Replace maxRecommendations with limit
The limit prop replaces the maxRecommendations prop.
1
2
3
4
| relatedProducts({
- maxRecommendations: 3,
+ limit: 3,
});
|
Remove environment
The environment prop is no longer needed.
1
2
3
| relatedProducts({
- environment: global,
});
|
Replace classNames with cssClasses
The cssClasses prop replaces the classNames prop.
1
2
3
4
5
6
7
8
9
10
11
| relatedProducts({
- classNames: {
+ cssClasses: {
root: 'MyCustomRelatedProducts',
+ emptyRoot: 'MyCustomRelatedProducts-emptyRoot',
title: 'MyCustomRelatedProducts-title',
container: 'MyCustomRelatedProducts-container',
list: 'MyCustomRelatedProducts-list',
item: 'MyCustomRelatedProducts-item',
},
});
|
Changes for trendingItems
Move recommendClient and indexName to instantsearch
The trendingItems widget no longer needs recommendClient and indexName props.
Instead, pass a searchClient and the ìndexName to instantsearch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| - import { trendingItems } from '@algolia/recommend-js';
+ import instantsearch from 'instantsearch.js';
+ import { trendingItems } from 'instantsearch.js/es/widgets';
- import recommend from '@algolia/recommend';
+ import algoliasearch from 'algoliasearch/lite';
- const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const search = instantsearch({
+ searchClient,
+ indexName: 'YOUR_INDEX_NAME',
+ }).addWidgets([
trendingItems({
container: '#trendingItems',
- recommendClient,
- indexName: 'YOUR_INDEX_NAME',
});
+ ]);
+ search.start();
|
Replace view with the layout template or the connectTrendingItems connector
The trendingItems widget no longer provides a view prop.
To fully customize the UI, use either the layout template or the connectTrendingItems connector instead.
Layout template
1
2
3
4
5
6
7
8
9
10
11
12
| - import { trendingItems } from '@algolia/recommend-js';
+ import { trendingItems } from 'instantsearch.js/es/widgets';
trendingItems({
container: '#trendingItems',
- view: (props) => { /* ... */ },
+ templates: {
+ layout({ items }, { html }) {
+ // …
+ },
+ }
});
|
Connector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - import { trendingItems } from '@algolia/recommend-js';
+ import {
+ connectTrendingItems,
+ } from 'instantsearch.js/es/connectors';
+ const customTrendingItems = connectTrendingItems(({ items, widgetParams }) => {
+ const container = document.querySelector(widgetParams.container);
+ container.innerHTML = `/* ... */`;
+ });
- trendingItems({
+ customTrendingItems({
container: '#trendingItems',
- view: (props) => { /* ... */ },
}),
|
Replace component props with templates
The trendingItems widget uses templates to customize specific parts of its UI.
| Recommend JS |
InstantSearch.js |
headerComponent |
header |
itemComponent |
item |
fallbackComponent |
empty |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| trendingItems({
- headerComponent({ classNames, recommendations, html }) {
- return html`<h2 class=${classNames.title}>
- Recommendations (${recommendations.length})
- </h2>`;
- },
+ templates: {
+ header({ cssClasses, items }, { html }) {
+ return html`<h2 class=${cssClasses.title}>
+ Recommendations (${items.length})
+ </h2>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
9
10
| trendingItems({
- itemComponent({ item, html }) {
- return html`<p>${item.name}</p>`;
- },
+ templates: {
+ item(recommendation, { html }) {
+ return html`<p>${recommendation.name}</p>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
| trendingItems({
- fallbackComponent({ html }) {
+ templates: {
+ empty(_, { html }) {
return html`<p>No recommendations.</p>`;
+ }
},
});
|
Replace translations with templates
The trendingItems widget uses templates to provide translations to the header.
1
2
3
4
5
6
7
8
9
10
| trendingItems({
- translations: {
- title: 'Recommendations',
- },
+ templates: {
+ header: ({ cssClasses }, { html }) {
+ return html`<h2 class=${cssClasses.title}>Recommendations</h2>`;
+ },
+ },
});
|
Replace maxRecommendations with limit
The limit prop replaces the maxRecommendations prop.
1
2
3
4
| trendingItems({
- maxRecommendations: 3,
+ limit: 3,
});
|
Remove environment
The environment prop is no longer needed.
1
2
3
| trendingItems({
- environment: global,
});
|
Replace classNames with cssClasses
The cssClasses prop replaces the classNames prop.
1
2
3
4
5
6
7
8
9
10
11
| trendingItems({
- classNames: {
+ cssClasses: {
root: 'MyCustomTrendingItems',
+ emptyRoot: 'MyCustomTrendingItems-emptyRoot',
title: 'MyCustomTrendingItems-title',
container: 'MyCustomTrendingItems-container',
list: 'MyCustomTrendingItems-list',
item: 'MyCustomTrendingItems-item',
},
});
|
Alternative for trendingFacets
InstantSearch.js doesn’t include a widget for trendingFacets.
If you need it, use the trendingFacets function
from the deprecated Recommend JS library.
Changes for lookingSimilar
Move recommendClient and indexName to instantsearch
The lookingSimilar widget no longer needs recommendClient and indexName props.
Instead, pass a searchChlient and the ìndexName to instantsearch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| - import { lookingSimilar } from '@algolia/recommend-js';
+ import instantsearch from 'instantsearch.js';
+ import { lookingSimilar } from 'instantsearch.js/es/widgets';
- import recommend from '@algolia/recommend';
+ import algoliasearch from 'algoliasearch/lite';
- const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const searchClient = algoliasearch('YourApplicationID', 'YourSearchOnlyAPIKey');
+ const search = instantsearch({
+ searchClient,
+ indexName: 'YOUR_INDEX_NAME',
+ }).addWidgets([
lookingSimilar({
container: '#lookingSimilar',
- recommendClient,
- indexName: 'YOUR_INDEX_NAME',
objectIDs: ['5723537'],
});
+ ]);
+ search.start();
|
Replace view with the layout template or the connectLookingSimilar connector
The lookingSimilar widget no longer provides a view prop.
To fully customize the UI, use either the layout template or the connectLookingSimilar connector instead.
Layout template
1
2
3
4
5
6
7
8
9
10
11
12
| - import { lookingSimilar } from '@algolia/recommend-js';
+ import { lookingSimilar } from 'instantsearch.js/es/widgets';
lookingSimilar({
container: '#lookingSimilar',
- view: (props) => { /* ... */ },
+ templates: {
+ layout({ items }, { html }) {
+ // …
+ },
+ }
});
|
Connector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - import { lookingSimilar } from '@algolia/recommend-js';
+ import {
+ connectLookingSimilar,
+ } from 'instantsearch.js/es/connectors';
+ const customLookingSimilar = connectLookingSimilar(({ items, widgetParams }) => {
+ const container = document.querySelector(widgetParams.container);
+ container.innerHTML = `/* ... */`;
+ });
- lookingSimilar({
+ customLookingSimilar({
container: '#lookingSimilar',
- view: (props) => { /* ... */ },
}),
|
Replace component props with templates
The lookingSimilar widget uses templates to customize specific parts of its UI.
| Recommend JS |
InstantSearch.js |
headerComponent |
header |
itemComponent |
item |
fallbackComponent |
empty |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| lookingSimilar({
- headerComponent({ classNames, recommendations, html }) {
- return html`<h2 class=${classNames.title}>
- Recommendations (${recommendations.length})
- </h2>`;
- },
+ templates: {
+ header({ cssClasses, items }, { html }) {
+ return html`<h2 class=${cssClasses.title}>
+ Recommendations (${items.length})
+ </h2>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
9
10
| lookingSimilar({
- itemComponent({ item, html }) {
- return html`<p>${item.name}</p>`;
- },
+ templates: {
+ item(recommendation, { html }) {
+ return html`<p>${recommendation.name}</p>`;
+ }
+ },
});
|
1
2
3
4
5
6
7
8
| lookingSimilar({
- fallbackComponent({ html }) {
+ templates: {
+ empty(_, { html }) {
return html`<p>No recommendations.</p>`;
+ }
},
});
|
Replace translations with templates
The lookingSimilar widget uses templates to provide translations to the header.
1
2
3
4
5
6
7
8
9
10
| lookingSimilar({
- translations: {
- title: 'Recommendations',
- },
+ templates: {
+ header: ({ cssClasses }, { html }) {
+ return html`<h2 class=${cssClasses.title}>Recommendations</h2>`;
+ },
+ },
});
|
Replace maxRecommendations with limit
The limit prop replaces the maxRecommendations prop.
1
2
3
4
| lookingSimilar({
- maxRecommendations: 3,
+ limit: 3,
});
|
Remove environment
The environment prop is no longer needed.
1
2
3
| lookingSimilar({
- environment: global,
});
|
Replace classNames with cssClasses
The classNames keys have changed and are defined through the cssClasses prop.
1
2
3
4
5
6
7
8
9
10
11
| lookingSimilar({
- classNames: {
+ cssClasses: {
root: 'MyCustomLookingSimilar',
+ emptyRoot: 'MyCustomLookingSimilar-emptyRoot',
title: 'MyCustomLookingSimilar-title',
container: 'MyCustomLookingSimilar-container',
list: 'MyCustomLookingSimilar-list',
item: 'MyCustomLookingSimilar-item',
},
});
|
horizontalSlider
The horizontalSlider view is now available in InstantSearch.js as a carousel template.
For carousel options, check the API reference:
1
2
3
4
5
6
7
8
9
| import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
import { carousel } from 'instantsearch.js/es/templates';
frequentlyBoughtTogether({
// ...
templates: {
layout: carousel(),
},
});
|