Guides / Solutions / Content navigation / Content Carousels

There are two types of carousel solutions:

  • Static, where hard-coded values defines the carousels used in the solution. This means that changes to the list of carousels require an update to your code.
  • Dynamic, where your Algolia index defines the carousels. This enables you to control the list of carousels from the Algolia dashboard, with no need to recode.

This tutorial outlines the dynamic approach.

Content carousels (also called shelves, lanes, or aisles) organize results within a media-heavy browsing experience. Rather than overwhelming users with a large grid of items, carousels group items into easily scannable rows like “most popular,” “trending,” “just for you,” etc.

Carousels are highly customizable: you can adjust their categories, order, and content.

Screenshot showing carousels for popular and trending movies

Solution requirements

Difficulty
Experienced
Plan Premium for a personalized carousel
Features Rules, Personalization
Prerequisites Instant Search 4+

Implementation guide

This guide shows you how to display movies in four different carousels: “most popular,” “trending,” “just for you,” and “fantasy and comedy.”

You need these four files:

  • index.html
  • src/main.js
  • src/carousel.js
  • src/style.css

Indices to display the carousels

You need two Algolia indices containing the movie dataset:

  • A primary index, with a custom ranking on the popularity attribute of the movies. Name this index perso_movies_carousel. You can download the JSON of the perso_movies_carousel index, located in the src/ folder.
  • A replica of the perso_movies_carousel index, with a custom ranking on the views_last_7_days attribute. Name this index perso_movies_carousel_trending.

In addition to the two indices used to store the movie dataset, the dynamic solution uses a third Algolia index to define the content of the carousels and their order on the page. By using an index, you manage your carousels directly in the dashboard without needing to change your front-end code.

This third index has the configuration information for each carousel:

  • The perso_movies_carousel_config index gives you dynamic control over how you define the carousels.

To dynamically generate the carousels, you can store each carousel’s configuration is in the perso_movies_carousel_config index. For this demo, the index has four records, one for each carousel. Each record has attributes that define the title of the carousel, the index (indexName), and any query parameters (in configure) pertinent to the carousel.

The carousel section walks you through four typical carousels. They all rely on the records in the personalized_movies_carousel_config index. Here’s an example record:

1
2
3
4
5
6
7
8
9
{
  "title": "Just for you",
  "indexName": "perso_movies_carousel",
  "configure": {
    "hitsPerPage": 10,
  },
  "objectID": "61606000",
  "order": 1
}

You need to set up order as a custom ranking attribute. Doing so orders the shelves on the front end. You learn about the other attributes as you go through the tutorial.

Adapting the HTML

In your index.html file, add the following div as a placeholder for your dynamically generated carousels.

1
<div id="carousel-container" class="carousel-container"></div>

Rendering the carousels

This section explains how to render the carousels dynamically, by creating a new index widget for each carousel.

  • Use src/main.js to render the carousel widgets.
  • Use src/carousel.js to define the carousel widget.

Define how to display the carousels

Define the display logic for every carousel in src/carousel.js. This file creates the widget that you append to the carousel-container defined in index.html.

Create a renderCarousel function that targets the containers and appends them with the hits you want to display:

  • Target the carousel container.
  • Create an <h2> header that displays the title of the carousel.
  • Add a <ul> tag in the container when you render the carousel for the first time.
  • Inside the <ul> element, add <li> tags for each movie you want to display.

Here is the full rendering code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
export const carousel = connectHits(function renderCarousel(
  { widgetParams: { container, title }, hits },
  isFirstRender
) {
  if (isFirstRender) {
    const section = document.createElement('section');
    container.appendChild(section);
    const h2 = document.createElement('h2');
    h2.innerText = title;
    section.appendChild(h2);
    const ul = document.createElement('ul');
    ul.classList.add('carousel-list-container');
    section.appendChild(ul);
  }

  container.querySelector('ul').innerHTML = hits
    .map(
      (hit) => `
        <li>
          <img src="${hit.image}" alt="${hit.title}">
          <div class="overlay">
            <h3>${hit.title}</h3>
            <ul>
              ${hit.genre
                .map(
                  (genre) => `
                <li>${genre}</li>
              `
                )
                .join('')}
            </ul>
          </div>
        </li>
      `
    )
    .join('');
});

The following function returns an array of all carousel widgets.

1
2
3
4
5
6
7
8
9
function getCarousels() {
  return searchClient
    .initIndex('perso_movies_carousel_config')
    .search('', {
      attributesToHighlight: [],
      attributesToRetrieve: ['title', 'indexName', 'configure'],
    })
    .then((res) => res.hits);
}

Next, loop through the array and do the following:

  • Execute a search on the index associated with the carousel, using any search parameters defined in the widget.
  • Create the widget with the results obtained.
  • Append the carousel widget to the carouselContainer.

Here is the full loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
getCarousels().then((carousels) => {
  const container = document.querySelector('#carousel-container');

  search.addWidgets(
    carousels.map((carouselConfig) => {
      const carouselContainer = document.createElement('div');

      const indexWidget = index({
        indexName: carouselConfig.indexName,
        indexId: carouselConfig.objectID,
      });

      if (carouselConfig.configure) {
        indexWidget.addWidgets([
          configure({
            ...carouselConfig.configure,
            // replace user token with the user's one if set by configure
            userToken: carouselConfig.configure.userToken
              ? getUserToken()
              : undefined,
          }),
        ]);
      }

      indexWidget.addWidgets([
        carousel({
          title: carouselConfig.title,
          container: carouselContainer,
        }),
      ]);

      container.appendChild(carouselContainer);

      return indexWidget;
    })
  );

This is all the coding you need to do. The rest of this solution describes how to use the records in perso_movies_carousel_config to create the different carousels.

Creating the carousels

This tutorial offers four examples of carousels. Some apply different sorting strategies. Others require Personalization and/or Rules.

You need to define each of these carousels as records in the perso_movies_carousel_config index. To do so, you can add the JSON snippets in the following sections to that index. You don’t have to do any further front-end development.

This carousel displays the most popular movies.

The carousel targets the index that sorts results by popularity (perso_movies_carousel). The code limits the number of results (8) and display the carousel in the correct container (#carousel-most-popular). You also need to provide the indexID property, because other carousels will target the same index.

You need to place the following record in the perso_movies_carousel_config index.

1
2
3
4
5
6
7
8
9
{
  "title": "Most Popular",
  "indexName": "perso_movies_carousel",
  "configure": {
    "hitsPerPage": 10,
  },
  "objectID": "popular",
  "order": 1
}

This carousel displays trending movies.

The code is similar to the carousel that displays the most popular movies. The main difference is the index you target. You have to target the replica index, which ranks movies on the number of views in the last seven days.

You need to place the following record in the perso_movies_carousel_config index.

1
2
3
4
5
6
7
8
9
{
  "title": "Trending",
  "indexName": "perso_movies_carousel_trending",
  "configure": {
    "hitsPerPage": 10,
  },
  "objectID": "trending",
  "order": 2
}

Just for you

This carousel displays movies personalized to each user’s taste. To do this, it leverages Algolia’s Personalization feature. Please make sure your plan has access to Personalization before trying to implement this.

For Personalization to work, you need to configure two extra search parameters for the carousel:

You need to place the following record in the perso_movies_carousel_config index.

1
2
3
4
5
6
7
8
9
10
11
{
  "title": "Just for you",
  "indexName": "perso_movies_carousel",
  "configure": {
    "hitsPerPage": 10,
    "enablePersonalization": true,
  },
  "objectID": "perso",
  "userToken": "123456789",
  "order": 3
}

This carousel displays movies that belong to specific genres: fantasy and comedy in the example. To accomplish this, you need to create a Rule, either in the dashboard or with the API.

Create the following Rule in the perso_movies_carousel index.

Using the dashboard

To create this Rule in the dashboard, follow these steps:

  1. Select the Rules section from the left sidebar menu in the Algolia dashboard.
  2. Under the heading Rules, select the index you are adding a Rule to.
  3. Select Create your first rule or New rule. In the dropdown, click on the Manual Editor option.
  4. In the Condition(s) section, click on Context, enter the text “comedy_fantasy.”
  5. In the Consequence(s) section:
    • Click the Add consequence button and select Add Query Parameter.
    • In the input field that appears, enter the following JSON search parameter.
      1
      2
      3
      
      {
      "filters": "genre:Comedy AND genre:Fantasy"
      }
      
    • Click the Add consequence button and select Pin an item.
    • Find the product ‘440108610’ and press Enter.
    • Find the product ‘440083670’ and press Enter.
    • Find the product ‘440149860’ and press Enter.
    • Find the product ‘439932740’ and press Enter.
  6. Don’t forget to save your changes.
Using an API client

If you use the API to create your Rule, use the saveRule method with the following Rule structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  "enabled": true,
  "tags": [
    "visual-editor"
  ],
  "condition": {
    "anchoring": "is",
    "pattern": "",
    "alternatives": false,
    "context": "comedy_fantasy"
  },
  "consequence": {
    "params": {
      "filters": "\"genre\":\"Comedy\" AND \"genre\":\"Fantasy\""
    },
    "hide": [],
    "promote": [
      {
        "objectID": "440108610",
        "position": 0
      },
      {
        "objectID": "440083670",
        "position": 1
      },
      {
        "objectID": "440149860",
        "position": 2
      },
      {
        "objectID": "439932740",
        "position": 3
      }
    ],
    "filterPromotes": true
  },
  "objectID": "qr-1593439847749"
}

Then, you have to set up the carousel with the comedy_fantasy Rule with the correct context. Do this using the ruleContexts parameter.

You need to place the following record in the perso_movies_carousel_config index.

1
2
3
4
5
6
7
8
9
10
{
  "title": "Fantasy Comedy",
  "indexName": "perso_movies_carousel",
  "configure": {
    "hitsPerPage": 8,
    "ruleContexts": "comedy_fantasy"
  },
  "order": 4,
  "objectID": "61607000"
}

Next steps

Add more carousels. Now that you know how to set up content carousels, you can create a variety of carousels for your project. This helps improve user engagement with your content.

Did you find this page helpful?