Algolia DevCon
Oct. 2–3 2024, virtual.
Guides / Sending events / InstantSearch

Capturing real-time user interactions as events gives you actionable insights via click and conversion metrics, and they help you increase your customer engagement and conversions. Events are used to activate Algolia features and products like NeuralSearch, Dynamic Re-Ranking, Query Categorization, Recommend, and Personalization.

Before you begin

To follow this guide, you need to build both search results and category pages with one of these UI libraries:

For other methods of collecting events, see Get started with events.

Manage the Insights library

InstantSearch loads the search-insights library for you from jsDelivr. You don’t need to install it or set it up yourself.

If you’re using a Content Security Policy to protect your site and you want to let InstantSearch load search-insights for you, make sure to add https://cdn.jsdelivr.net in your list of trusted sources for JavaScript.

1
script-src https://cdn.jsdelivr.net/

If you prefer hosting your own version of search-insights, you can add it to your project:

  1. Install the Insights client
  2. Initialize the Insights client (optional)

InstantSearch doesn’t load search-insights when it detects it on the page.

Enable events collection

You can enable the automatic collection of events from your InstantSearch apps in the Algolia dashboard (without coding), or when setting up your InstantSearch app (with coding).

Enabling automatic events collection takes care of the following:

  • Add the search-insights library to your project and make it globally available as window.aa
  • Set an anonymous userToken for sending events to the Insights API and for search requests
  • Include the queryID parameter in the search response
  • Send default click and view events for your InstantSearch widgets

Go to the Events hub in the Algolia dashboard to check the default events arriving from your website or app. For more information, see Validate your events.

No code

  1. Go to the Algolia dashboard and select your Algolia application.
  2. On the left sidebar, select Data sources > Events > Settings.
  3. Click Enable automatic events collection.

Code

Enable the insights option:

1
2
3
4
5
6
7
const search = instantsearch({
    searchClient,
    indexName: "YourIndexName",
+   insights: true,
  });
  // Add your InstantSearch widgets here
  search.start();

Understand which events to track

You may want to send events that are not automatically captured by InstantSearch widgets. To understand which events you should send, think about the different steps a user takes through your website to reach the final goal: the product purchase.

Events for search

Starting with a search on any of your pages, a user might take the following actions:

  1. Select a product from the search results to open the product details page.
  2. Add a product to the shopping cart.
  3. Buy the product.

Search and search results pages

User action Method name Automatically collected?
User clicks search result clickedObjectIDsAfterSearch Yes
User adds product to shopping cart addedToCartObjectIDsAfterSearch No
User clicks categories/filters clickedFilters Yes
User views search results viewedObjectIDs Yes

Product listing and category pages

User action Method name Automatically collected?
User clicks product clickedObjectIDsAfterSearch Yes
User adds product to shopping cart addedToCartObjectIDsAfterSearch No
User views category page viewedObjectIDs Yes

Product details page

User action Method name Automatically collected?
User adds product to cart addedToCartObjectIDsAfterSearch No
User views product viewedObjectIDs No

Checkout page

User action Event Automatically collected?
User buys product purchasedObjectIDsAfterSearch No

Keep track of query IDs

Conversion events are often triggered on pages that aren’t covered by InstantSearch, such as your product details pages, or the checkout page.

To relate the conversion events back to the search request made on your search results or category pages, you need to keep track of the query IDs across your pages.

Track add-to-cart events

Using InstantSearch widgets

When your users add an item to their cart, send a special conversion event with the addToCart subtype.

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
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <h2>${components.Highlight({ attribute: "name", hit })}</h2>
        <p>${hit.description}</p>
        <button
          onClick=${() =>
            sendEvent("conversion", hit, "Added To Cart", {
              // Special subtype
              eventSubtype: "addToCart",
              // An array of objects representing each item added to the cart
              objectData: [
                {
                  // The discount value for this item, if applicable
                  discount: hit.discount || 0,
                  // The price value for this item (minus the discount)
                  price: hit.price,
                  // How many of this item were added
                  quantity: 2,
                },
              ],
              // The total value of all items
              value: hit.price * 2,
              // The currency code
              currency: "USD",
            })}
        >
          Add to cart
        </button>
      `;
    },
  },
});

Fields representing monetary values accept both numbers and strings, in major currency units (for example, 5.45 or '5.45'). To prevent floating-point math issues, use strings, especially if you’re performing calculations.

On pages without InstantSearch widgets

Add the following code to all components and pages where users can add products to their shopping cart.

For add-to-cart events associated with a search:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
window.aa("addedToCartObjectIDsAfterSearch", {
  eventName: "Product Added To Cart",
  index: "YourIndexName",
  queryID: "queryID-1",
  objectIDs: ["objectID-1"],
  objectData: [
    {
      price: 19.99,
      discount: 3.99,
      quantity: 3,
    },
  ],
  currency: "USD",
});

The windows.aa object is the API client for the Insights API and is globally available if you enabled automatic events collection. The queryID parameter is used by Algolia to relate the event to a prior search or browse event.

For add-to-cart events not related to a search query, for example, after a user clicks on a ‘Recommended for you’ or ‘Buy again’ carousel on the home page:

1
2
3
4
5
6
7
8
9
10
11
12
window.aa("addedToCartObjectIDs", {
  eventName: "Recommended Product Added To Cart",
  index: "YourIndexName",
  objectIDs: ["objectID-1"],
  objectData: [
    {
      price: 68.5,
      quantity: 2,
    },
  ],
  currency: "USD",
});

Track purchase events

Using InstantSearch widgets

When your users purchase an item, send a special conversion event with the purchase subtype.

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
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <h2>${components.Highlight({ attribute: "name", hit })}</h2>
        <p>${hit.description}</p>
        <button
          onClick=${() =>
            sendEvent("conversion", hit, "Purchased", {
              // Special subtype
              eventSubtype: "purchase",
              // An array of objects representing each purchased item
              objectData: [
                {
                  // The discount value for this item, if applicable
                  discount: hit.discount || 0,
                  // The price value for this item (minus the discount)
                  price: hit.price,
                  // How many of this item were added
                  quantity: 2,
                  // The per-item `queryID` for the query preceding this event
                  queryID: hit.__queryID,
                },
              ],
              // The total value of all items
              value: hit.price * 2,
              // The currency code
              currency: "USD",
            })}
        >
          Purchase
        </button>
      `;
    },
  },
});

Fields representing monetary values accept both numbers and strings, in major currency units (for example, 5.45 or '5.45'). To prevent floating-point math issues, use strings, especially if you’re performing calculations.

On pages without InstantSearch widgets

Add the following code to your checkout flow:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
window.aa("purchasedObjectIDsAfterSearch", {
  userToken: "anonymous-123456", // required for Node.js
  authenticatedUserToken: "user-123456",
  eventName: "your_event_name",
  index: "your_index_name",
  objectIDs: ["objectID-1", "objectID-2"],
  objectData: [
    {
      queryID: "queryID-1",
      price: 19.99,
      discount: 3.99,
      quantity: 3,
    },
    {
      queryID: "queryID-2",
      price: 59.99,
      quantity: 2,
    },
  ],
  currency: "USD",
});

Track other conversion events

You can track other conversions in addition to add-to-cart and purchase events.

Using InstantSearch widgets

You can use the sendEvent function to send conversion events from your InstantSearch app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <h2>${components.Highlight({ attribute: "name", hit })}</h2>
        <p>${hit.description}</p>
        <button
          onClick="${() =>
            sendEvent("conversion", hit, "Product Added To Wishlist")
          }"
        >
          Add to wishlist
        </button>
      `;
    },
  },
});

Unlike click events, setting custom conversion events doesn’t prevent the custom click event from being sent.

On pages without InstantSearch widgets

This is an example of a conversion that may occur on a page without InstantSearch:

1
2
3
4
5
6
// A user added a product to their wishlist from the homepage
window.aa("convertedObjectIDs", {
  eventName: "Product Added To Wishlist",
  index: "YourIndexName",
  objectIDs: ["objectID-1"],
});

Track click events

Override default click events

The hits and infiniteHits widgets expose a sendEvent function. Use it to send click events when users interact with your search results.

1
2
3
4
5
6
7
8
9
10
11
12
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <div onClick="${() => sendEvent("click", hit, "Product Clicked")}">
          <h2>${components.Highlight({ attribute: "name", hit })}</h2>
          <p>${hit.description}</p>
        </div>
      `;
    },
  },
});

You can set more events on specific parts of your template. In the following example, when clicking on the Add to favorites button, two events are sent to the Insights API:

  • A click event with the eventName “Product Added to Favorites”
  • A click event with the eventName “Product Clicked” (via event propagation)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <div onClick="${() => sendEvent("click", hit, "Product Clicked")}">
          <h2>${components.Highlight({ attribute: "name", hit })}</h2>
          <p>${hit.description}</p>
          <button
            onClick="${() =>
              sendEvent("click", hit, "Product Added to Favorites")
            }"
          >
            Add to favorites
          </button>
        </div>
      `;
    },
  },
});

To only send the most specific event per clicked element, you can use Event.stopPropagation in your event handler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <div onClick="${() => sendEvent("click", hit, "Product Clicked")}">
          <!-- ... -->
          <button
            onClick="${(event) => {
+             event.stopPropagation();

              sendEvent("click", hit, "Product Added to Favorites");
            }}"
          >
            Add to favorites
          </button>
        </div>
      `;
    },
  },
});

When InstantSearch captures a custom click event that you defined, it doesn’t send the default click event. In the following example, when clicking the Add to favorites button, only the “Product Added to Favorites” event is sent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
hits({
  templates: {
    item(hit, { html, components, sendEvent }) {
      return html`
        <h2>${components.Highlight({ attribute: "name", hit })}</h2>
        <p>${hit.description}</p>
        <button
          onClick="${() =>
            sendEvent("click", hit, "Product Added to Favorites")
          }"
        >
          Add to favorites
        </button>
      `;
    },
  },
});

Track additional click events

For Algolia Recommend and Personalization, capture additional click events when users select individual products:

  • On your home page
  • From product recommendations

To send click events with the Insights client, add the following code whenever a user clicks on a product—for example, on your homepage.

1
2
3
4
5
window.aa("clickedObjectIDs", {
  index: "YourIndexName",
  eventName: "Product Clicked",
  objectIDs: ["objectID-1"],
});

(Optional) Set up Personalization

For effective personalization, you need to identify users across sessions. It’s best to use an identifier from your authentication, user profile, or ecommerce service after users signed in. For more information, see User token.

After getting the identifier from your system, set it as authenticatedUserToken parameter.

1
2
3
// Get a unique, pseudonymous identifier for signed-in users
const authenticatedUserToken = getUserTokenAfterSignIn();
window.aa("setAuthenticatedUserToken", authenticatedUserToken);

If you can’t get persistent user identifiers from your system, you can store the anonymous user token in a cookie after obtaining user consent.

1
2
3
4
5
// If user consented
aa("init", {
  partial: true,
  useCookies: true,
});

If you don’t use persistent user identifiers, a new anonymous user token is generated on every page refresh.

Personalization benefits from the same click and conversion events, plus it can use view events to enrich user profiles.

Your InstantSearch components for the search results and category pages automatically collect view events.

To capture additional view events, such as on your homepage, add this code:

1
2
3
4
5
window.aa("viewedObjectIDs", {
  index: "YourIndexName",
  eventName: "Products Viewed",
  objectIDs: ["objectID-1"],
});

Working examples

Adding events to a React InstantSearch application

Did you find this page helpful?