InstantSearch / React / V6 / Guides / Injecting content between hits

Inject Hits from Algolia Rules

Deprecated content
This documentation is for a deprecated version of React InstantSearch. Some features and settings may be missing or their usage may have changed. Refer to the documentation for the latest version of React InstantSearch for up-to-date information.

Content injection consists of inserting data between search results. With React InstantSearch, you can build a custom widget to mix results from an index and custom content from Algolia Rules into a single set of hits.

This is useful to inject arbitrary content within hits—for example a banner or a video—depending on the search query, filters, or context sent to Algolia. The data would live in individual Algolia Rules, as custom JSON data.

Screenshot showing editorial content from Rules injected between regular hits

Requirements

React InstantSearch exposes a connector API that lets you reuse existing logic and plug your own. With it, you can build a custom React InstantSearch widget to mix regular Algolia results with injected content. Make sure you’re familiar with this concept before continuing to the next section.

Set up an index and Rule

To find related banners when searching for ingredients, they need to match the same queries.

For example, in your “ingredients” records, you can use a unique name to identify each ingredient. Then, you can use the same name as the Rule pattern.

1
2
3
4
5
6
7
8
[
  {
    "ingredient": "chicken",
    "title": "Chicken",
    "summary": "The chicken is a domesticated subspecies of the red junglefowl originally from Southeastern Asia...."
  },
  // ...
]

Inject custom content between hits

When a Rule that contains custom JSON matches, it’s exposed on the response under the userData property. You can return it from getHits to inject it between hits.

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
import React from 'react';
import {
  InstantSearch,
  Configure,
  Index,
  SearchBox,
} from 'react-instantsearch-dom';

import { InjectedHits } from './InjectedHits';

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="ingredients">
      <Configure hitsPerPage={8} />
      <SearchBox />
      <InjectedHits
        slots={() => [
          {
            injectAt: 3,
            getHits: ({ resultsByIndex }) => {
              const userData = resultsByIndex.products?.userData || [];
              const [item] = userData.filter(({ type }) => type === 'banner');

              return item ? [item] : [];
            },
            slotComponent: BannerHit,
          },
        ]}
        hitComponent={IngredientHit}
      />
    </InstantSearch>
  );
}

// ...

When the Rule matches, it will show up at the specified position. Regular hits use the component defined with hitComponent, while injected hits from Rules use the slotComponent.

Dynamic positioning with Rules

Instead of passing a static position to injectAt, you can store a dynamic position in Rules, along with their data, and use it in the code.

If you inject multiple slots at the same position, they’re injected in the defined slot order.

1
2
3
4
5
6
{
  "position": 3,
  "type": "banner",
  "title": "100 Delicious Chicken Recipes",
  "image": "chicken.jpg"
}
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
import React from 'react';
import {
  InstantSearch,
  Configure,
  Index,
  SearchBox,
} from 'react-instantsearch-dom';

import { InjectedHits } from './InjectedHits';

function App() {
  return (
    <InstantSearch searchClient={searchClient} indexName="ingredients">
      <Configure hitsPerPage={8} />
      <SearchBox />
      <InjectedHits
        slots={({ resultsByIndex }) => {
          const userData = resultsByIndex.products?.userData || [];
          const [item] = userData.filter(({ type }) => type === 'banner');

          return [
            {
              injectAt: item.position,
              getHits: () => (item ? [item] : []),
              slotComponent: BannerHit,
            },
          ];
        }}
        hitComponent={IngredientHit}
      />
    </InstantSearch>
  );
}

// ...
Did you find this page helpful?