Skip to main content
This page shows ecommerce-specific click and conversion patterns for InstantSearch apps. For the concepts behind event tracking, see Click and conversion events. For other implementation paths, see Choose how to send events.

Enable events collection

To follow this guide, build search results or category pages with one of these UI libraries: InstantSearch loads the search-insights library for you from jsDelivr. You don’t need to install or initialize it yourself. If you’re using a Content Security Policy and you want to let InstantSearch load search-insights, add https://cdn.jsdelivr.net to your list of trusted JavaScript sources.
script-src https://cdn.jsdelivr.net/
If you prefer self-hosting search-insights, 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. You can enable automatic collection in the Algolia dashboard or in your InstantSearch app. Enabling automatic events collection does the following: 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 .
  2. On the left sidebar, select Data sources > Events > Settings.
  3. Click Enable automatic events collection.

Code

Enable the insights option:
const search = instantsearch({
  searchClient,
  indexName: "YourIndexName",
  insights: true, 
});
// Add your InstantSearch widgets here
search.start();
For more on tracking queryID and userToken, see Keep track of query IDs and User token.

Map your ecommerce journey to events

Map the steps users take through your website and add events that aren’t automatically captured by InstantSearch widgets. Focus on the actions that lead to the final goal: the product purchase.
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 actionMethod nameAutomatically collected?
User clicks search resultclickedObjectIDsAfterSearchYes
User adds product to shopping cartaddedToCartObjectIDsAfterSearchNo
User clicks categories/filtersclickedFiltersYes
User views search resultsviewedObjectIDsYes

Product listing and category pages

User actionMethod nameAutomatically collected?
User clicks productclickedObjectIDsAfterSearchYes
User adds product to shopping cartaddedToCartObjectIDsAfterSearchNo
User views category pageviewedObjectIDsYes

Product details page

User actionMethod nameAutomatically collected?
User adds product to cartaddedToCartObjectIDsAfterSearchNo
User views productviewedObjectIDsNo

Checkout page

User actionEventAutomatically collected?
User buys productpurchasedObjectIDsAfterSearchNo

Track query IDs across pages

Conversion events often happen outside the search results page.
  • A query ID is returned by the when a user performs a search.
  • To associate a conversion with the correct , save this query ID and include it in your conversion events.
  • To link conversion events back to the originating search request on your search results or category pages, track query IDs across your pages.

Track add-to-cart events

Send events from InstantSearch widgets

When your users add an item to their cart, send a special conversion event with the addToCart subtype.
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:
JavaScript
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 window.aa object is the API client for the Insights API and is globally available if you enabled automatic events collection. When all objects in the event are attributed to the same query, set the queryID parameter at the root level as shown above. However, when objects have different query IDs (for example, items added to cart from different searches), specify the queryID for each object in the objectData array:
JavaScript
window.aa("addedToCartObjectIDsAfterSearch", {
  eventName: "Product Added To Cart",
  index: "YourIndexName",
  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",
});
You should store the query ID with other product details when updating a user’s shopping cart. This helps you record query IDs for each item for any following purchase events. 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, you don’t need to specify queryID:
JavaScript
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

Send events from InstantSearch widgets

When your users purchase an item, send a special conversion event with the purchase subtype.
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. When all objects in the purchase are attributed to the same query, you can set the queryID parameter at the root level:
JavaScript
window.aa("purchasedObjectIDsAfterSearch", {
  eventName: "Products Purchased",
  index: "YourIndexName",
  queryID: "queryID-1",
  objectIDs: ["objectID-1", "objectID-2"],
  objectData: [
    {
      price: 19.99,
      discount: 3.99,
      quantity: 3,
    },
    {
      price: 59.99,
      quantity: 2,
    },
  ],
  currency: "USD",
});
However, users often purchase items that were added to the cart in response to different queries. For example, a user might search for “shoes” and add a pair of shoes to their cart. Then, they search for “lamp” and add a lamp to their cart. Then, they check out and complete the purchase of both items. In this case, there would be a single purchase event, but each item should be attributed to its originating query. Specify the queryID for each object in the objectData array:
JavaScript
window.aa("purchasedObjectIDsAfterSearch", {
  userToken: "anonymous-123456", // required for Node.js
  authenticatedUserToken: "user-123456",
  eventName: "your_event_name",
  index: "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.

Send events from InstantSearch widgets

You can use the sendEvent function to send conversion events from your InstantSearch app.
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>
      `;
    },
  },
});
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:
JavaScript
// 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.
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 users click 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” (through event propagation).
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.
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 users click the Add to favorites button, only the “Product Added to Favorites” event is sent:
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 more 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.
JavaScript
window.aa("clickedObjectIDs", {
  index: "YourIndexName",
  eventName: "Product Clicked",
  objectIDs: ["objectID-1"],
});

Optional: identify known users for Personalization

For effective personalization, identify users across sessions. It’s best to use an identifier from your authentication system after users sign in. After getting the identifier from your system, set it as the authenticatedUserToken parameter.
JavaScript
// 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.
JavaScript
// If user consented
aa("init", {
  partial: true,
  useCookie: true,
});
If you don’t use persistent user identifiers, a new anonymous user token is generated on every page refresh. For more on identity strategy and persistence, see User token. InstantSearch automatically sends view events for search results and category pages. Send additional view events for experiences outside InstantSearch widgets, such as homepage carousels or recommendation modules.

Optional: send view events for Personalization

Personalization benefits from the same click and conversion events, plus it can use view events to enrich each . Use the following code snippet to track view events, such as when a user views search results.
JavaScript
window.aa("viewedObjectIDs", {
  index: "YourIndexName",
  eventName: "Item Viewed",
  objectIDs: ["objectID-1"],
});
You don’t need to send a queryID when tracking view events.

Examples

Add events to a React InstantSearch application

Last modified on April 22, 2026