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:

Shell
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:

JavaScript
- 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:

JavaScript
- 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();

Widgets

Recommend JSInstantSearch.jsChanges
frequentlyBoughtTogetherfrequently-bought-togetherProp changes
relatedProductsrelated-productsProp changes
trendingItemstrending-itemsProp changes
trendingFacetsRemovedAlternative
lookingSimilarlooking-similarProp changes

Changes for frequentlyBoughtTogether

Move recommendClient and indexName to instantsearch

The frequently-bought-together widget no longer needs recommendClient and indexName props. Instead, pass a searchClient and the ìndexName to instantsearch.

JavaScript
- 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 frequently-bought-together widget no longer provides a view prop. To fully customize the UI, use either the layout template or the frequently-bought-together connector instead.

Layout template
JavaScript
- import { frequentlyBoughtTogether } from '@algolia/recommend-js';
+ import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';

  frequentlyBoughtTogether({
    container: '#frequentlyBoughtTogether',
-   view: (props) => { /* ... */ },
+   templates: {
+     layout({ items }, { html }) {
+       // …
+     },
+   }
  });
Connector
JavaScript
- 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 frequently-bought-together widget uses templates to customize specific parts of its UI.

Recommend JSInstantSearch.js
headerComponentheader
itemComponentitem
fallbackComponentempty
JavaScript
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>`;
+   }
+ },
});

Replace translations with templates

The frequently-bought-together widget uses templates to provide translations to the header.

JavaScript
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.

JavaScript
frequentlyBoughtTogether({
- maxRecommendations: 3,
+ limit: 3,
});

Remove environment

The environment prop is no longer needed.

JavaScript
frequentlyBoughtTogether({
- environment: global,
});

Replace classNames with cssClasses

The cssClasses prop replaces the classNames prop.

JavaScript
frequentlyBoughtTogether({
- classNames: {
+ cssClasses: {
    root: 'MyCustomFrequentlyBoughtTogether',
+   emptyRoot: 'MyCustomFrequentlyBoughtTogether-emptyRoot',
    title: 'MyCustomFrequentlyBoughtTogether-title',
    container: 'MyCustomFrequentlyBoughtTogether-container',
    list: 'MyCustomFrequentlyBoughtTogether-list',
    item: 'MyCustomFrequentlyBoughtTogether-item',
  },
});

Changes for relatedProducts

Move recommendClient and indexName to instantsearch

The related-products widget no longer needs recommendClient and indexName props. Instead, pass a searchChlient and the ìndexName to instantsearch.

JavaScript
- 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();

Replace view with the layout template or the connectRelatedProducts connector

The related-products widget no longer provides a view prop. To fully customize the UI, use either the layout template or the related-products connector instead.

Layout template
JavaScript
- import { relatedProducts } from '@algolia/recommend-js';
+ import { relatedProducts } from 'instantsearch.js/es/widgets';

  relatedProducts({
    container: '#relatedProducts',
-   view: (props) => { /* ... */ },
+   templates: {
+     layout({ items }, { html }) {
+       // …
+     },
+   }
  });
Connector
JavaScript
- 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 related-products widget uses templates to customize specific parts of its UI.

Recommend JSInstantSearch.js
headerComponentheader
itemComponentitem
fallbackComponentempty
JavaScript
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>`;
+   }
+ },
});

Replace translations with templates

The related-products widget uses templates to provide translations to the header.

JavaScript
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.

JavaScript
relatedProducts({
- maxRecommendations: 3,
+ limit: 3,
});

Remove environment

The environment prop is no longer needed.

JavaScript
relatedProducts({
- environment: global,
});

Replace classNames with cssClasses

The cssClasses prop replaces the classNames prop.

JavaScript
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 trending-items widget no longer needs recommendClient and indexName props. Instead, pass a searchClient and the ìndexName to instantsearch.

JavaScript
- 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 trending-items widget no longer provides a view prop. To fully customize the UI, use either the layout template or the trending-items connector instead.

Layout template
JavaScript
- import { trendingItems } from '@algolia/recommend-js';
+ import { trendingItems } from 'instantsearch.js/es/widgets';

  trendingItems({
    container: '#trendingItems',
-   view: (props) => { /* ... */ },
+   templates: {
+     layout({ items }, { html }) {
+       // …
+     },
+   }
  });
Connector
JavaScript
- 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 trending-items widget uses templates to customize specific parts of its UI.

Recommend JSInstantSearch.js
headerComponentheader
itemComponentitem
fallbackComponentempty
JavaScript
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>`;
+   }
+ },
});

Replace translations with templates

The trending-items widget uses templates to provide translations to the header.

JavaScript
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.

JavaScript
trendingItems({
- maxRecommendations: 3,
+ limit: 3,
});

Remove environment

The environment prop is no longer needed.

JavaScript
trendingItems({
- environment: global,
});

Replace classNames with cssClasses

The cssClasses prop replaces the classNames prop.

JavaScript
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 looking-similar widget no longer needs recommendClient and indexName props. Instead, pass a searchChlient and the ìndexName to instantsearch.

JavaScript
- 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 looking-similar widget no longer provides a view prop. To fully customize the UI, use either the layout template or the looking-similar connector instead.

Layout template
JavaScript
- import { lookingSimilar } from '@algolia/recommend-js';
+ import { lookingSimilar } from 'instantsearch.js/es/widgets';

  lookingSimilar({
    container: '#lookingSimilar',
-   view: (props) => { /* ... */ },
+   templates: {
+     layout({ items }, { html }) {
+       // …
+     },
+   }
  });
Connector
JavaScript
- 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 looking-similar widget uses templates to customize specific parts of its UI.

Recommend JSInstantSearch.js
headerComponentheader
itemComponentitem
fallbackComponentempty
JavaScript
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>`;
+   }
+ },
});

Replace translations with templates

The looking-similar widget uses templates to provide translations to the header.

JavaScript
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.

JavaScript
lookingSimilar({
- maxRecommendations: 3,
+ limit: 3,
});

Remove environment

The environment prop is no longer needed.

JavaScript
lookingSimilar({
- environment: global,
});
Replace classNames with cssClasses

The classNames keys have changed and are defined through the cssClasses prop.

JavaScript
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:

  • frequentlyBoughtTogether
  • relatedProducts
  • `trendingItems
  • lookingSimilar
JavaScript
import { frequentlyBoughtTogether } from 'instantsearch.js/es/widgets';
import { carousel } from 'instantsearch.js/es/templates';

frequentlyBoughtTogether({
    // ...
    templates: {
    layout: carousel(),
    },
});