Guides / Building Search UI

Send click and conversion events with Vue InstantSearch

Events are actions that users take on your app or website. They unlock powerful features, such as recommendations, personalization, smarter search results, and analytics that help you optimize your user experience. For more information, see Get started with click and conversion events.

Working example

This code has been specifically created for Vue 2. Some modifications may be required for it to work correctly in Vue 3.

How to send events

To send events from your Vue InstantSearch app, follow these steps:

  1. Set the insights option to true. This loads the search-insights for you and sends default events when viewing and clicking search results, or when selecting filters.
  2. Add additional click events when users click search results.
  3. Track conversions that start in your Vue InstantSearch app.

This guide works with Vue InstantSearch version v4.9.0 or later.

Set the insights option to true

The insights option enables sending events to Algolia.

In your Vue InstantSearch options, set insights to true.

1
2
3
4
5
6
7
8
9
<template>
  <ais-instant-search
    :index-name="<index-name>"
    :search-client="searchClient"
    :insights="true"
  >
    <!-- widgets -->
  </ais-instant-search>
</template>

Turning on the insights option achieves the following:

To change the event properties, send events from custom widgets, or send events to third-party tools, see the insights API reference.

Manage the Insights library

Vue 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 Vue 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)

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

Set the userToken

Vue InstantSearch automatically sets an anonymous user token for you and stores it in memory. To identify users across sessions, explicitly set the userToken yourself:

1
window.aa('setUserToken', 'user-id');

For example, you can use the account ID after users sign in on your website.

Don’t use personally identifiable information as a user ID.

Authenticated user token

If you’re using an authentication system for your users, use the setAuthenticatedUserToken method to set the authenticated user token as the authenticatedUserToken parameter for the Insights client.

1
2
const authenticatedUserToken = getAuthenticatedUserTokenAfterLogIn();
aa('setAuthenticatedUserToken', authenticatedUserToken);

Your authentication system usually provides an API for getting the user token, which is represented by the getAuthenticatedUserTokenAfterLogin() function.

It is important to set the authenticatedUserToken parameter for authenticated users rather than userToken, which is intended to be used for anonymous tokens. If a user initially visits a site without signing in, they’re assigned an anonymous ID. If they later sign in and receive an authenticated user ID, setting the userToken to the authenticated user ID would overwrite the anonymous ID, meaning their previous activity as an anonymous user won’t be associated with the authenticated user. By sending the anonymous and authenticated user tokens in separate parameters, you can ensure continuity of user activity and prevent data loss during the transition from anonymous to authenticated status.

If you’re not using user authentication, use a cookie to persist the anonymous user token in the userToken parameter.

Persist an anonymous userToken across sessions

The search-insights library can generate an anonymous user token and store it in the first-party _ALGOLIA cookie. To enable this, you can set the useCookie option to true.

1
2
3
4
5
6
7
8
9
10
11
12
<template>
  <ais-instant-search
    :insights="{
      // …
      insightsInitParams: {
        useCookie: true,
      },
    }"
  >
    <!-- widgets -->
  </ais-instant-search>
</template>

If you must abide by legal requirements like GDPR that prohibit usage of non-essential cookies without consent, leave useCookie as false and only update its value dynamically once the user grants or withdraws consent.

For example, your code could look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
document.getElementById('cookie-accept').addEventListener('click', () => {
  window.aa('init', {
    useCookie: true,
    partial: true,
  });
});

[
  document.getElementById('cookie-reject'),
  document.getElementById('cookie-withdraw'),
].forEach((button) => {
  button.addEventListener('click', (event) => {
    window.aa('init', {
      useCookie: false,
      partial: true,
    });
  });
});

If you’re using a cookie consent service like OneTrust or TrustArc, refer to their documentation to properly react to cookie consent updates.

Default events

Vue InstantSearch widgets use the insights middleware to send default events. To check the default events, go to the Events Debugger. For more information, see Validate your events.

Default click events for refinement widgets

The following widgets send click events (“Filter Applied”) when users select a refinement. Custom widgets use connectors to send the same events.

Widget Connector
ais-hierarchical-menu connectHierarchicalMenu
ais-menu connectMenu
ais-menu-select connectMenu
ais-numeric-menu connectNumericMenu
ais-range-input connectRange
ais-rating-menu connectRatingMenu
ais-refinement-list connectRefinementList
ais-toggle-refinement connectToggleRefinement

Default view events for results widgets

The following widgets send view events (“Hits Viewed”) for the visible items in the search results. Custom widgets using the connectors send the same events.

Widget Connector
ais-autocomplete connectAutocomplete
ais-hits connectHits
ais-infinite-hits connectInfiniteHits

Default click events for results widgets

The following widgets send click events (“Hit Clicked”) when users click a search result.

Widget Connector
hits ais-hits
infiniteHits ais-infinite-hits

Because of technical limitations, the default click events aren’t sent when using ais-hits or ais-infinite-hits. If you’re using connectors, make sure to set up click events on them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
  <ul>
    <li v-for="item in items" :key="item.value">
      <button @click="state.sendEvent('click', item, 'Hit Clicked');">
        {{ item.label }}
      </button>
    </li>
  </ul>
</template>

<script>
import { createWidgetMixin } from 'vue-instantsearch';
import { connectHitsWithInsights } from 'instantsearch.js/es/connectors';
// or
import { connectInfiniteHitsWithInsights } from 'instantsearch.js/es/connectors';

export default {
  mixins: [createWidgetMixin({ connector: connectHitsWithInsights })], // or connectInfiniteHitsWithInsights
};
</script>

Send click events

The ais-hits and ais-infinite-hits 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
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <div @click="sendEvent('click', item, 'Product Clicked')">
      <h2>
        <ais-highlight attribute="name" :hit="item" />
      </h2>
      <p>{{ item.description }}</p>
    </div>
  </template>
</ais-hits>

You can set more events on specific parts of your template. In the following example, when clicking on the Add to cart 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” (using event propagation)
1
2
3
4
5
6
7
8
9
10
11
12
13
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <div @click="sendEvent('click', item, 'Product Clicked')">
      <h2>
        <ais-highlight attribute="name" :hit="item" />
      </h2>
      <p>{{ item.description }}</p>
      <button @click="sendEvent('click', item, 'Product Added to Favorites')">
        Add to cart
      </button>
    </div>
  </template>
</ais-hits>

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
  <ais-hits>
    <template v-slot:item="{ item, sendEvent }">
      <div @click="sendEvent('click', item, 'Product Clicked')">
        <!-- … -->
        <button @click="(event) => {
+         event.stopPropagation();

          sendEvent('click', item, 'Product Added to Favorites')
        }">
          Add to favorites
        </button>
      </div>
    </template>
  </ais-hits>

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
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <h2>
      <ais-highlight attribute="name" :hit="item" />
    </h2>
    <p>{{ item.description }}</p>
    <button @click="sendEvent('click', item, 'Product Added to Favorites')">
      Add to favorites
    </button>
  </template>
</ais-hits>

Check your click events in the Events Debugger. For more information, see Validate your events. For more information, see Validate your events.

Send conversion events

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

1
2
3
4
5
6
7
8
9
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <h2><ais-highlight attribute="name" :hit="item" /></h2>
    <p>{{ item.description }}</p>
    <button @click="sendEvent('conversion', item, 'Purchase With One-Click')">
      One-Click Purchase
    </button>
  </template>
</ais-hits>

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

Conversions often happen outside your search results page. For example, an “Order Completed” event for a successful purchase happens in the shopping cart. To capture these conversions, keep track of the query ID across your site.

Then, send the conversion event with convertedObjectIDsAfterSearch from the search-insights library using window.aa.

Check your conversion events in the Events Debugger. For more information, see Validate your events.

Add-to-cart events

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
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <h2>
      <ais-highlight attribute="name" :hit="item" />
    </h2>
    <p>{{ item.description }}</p>
    <button
      @click="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: item.discount || 0,
            // The price value for this item (minus the discount)
            price: item.price,
            // How many of this item were added
            quantity: 2,
            // The per-item `queryID` for the query preceding this event
            queryID: item.__queryID,
          },
        ],
        // The total value of all items
        value: item.price * 2,
        // The currency code
        currency: 'USD',
      })"
    >
      Add to cart
    </button>
  </template>
</ais-hits>

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.

Purchase events

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
<ais-hits>
  <template v-slot:item="{ item, sendEvent }">
    <h2>
      <ais-highlight attribute="name" :hit="item" />
    </h2>
    <p>{{ item.description }}</p>
    <button
      @click="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: item.discount || 0,
            // The price value for this item (minus the discount)
            price: item.price,
            // How many of this item were added
            quantity: 2,
          },
        ],
        // The total value of all items
        value: item.price * 2,
        // The currency code
        currency: 'USD',
      })"
    >
      Purchase
    </button>
  </template>
</ais-hits>

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.

Did you find this page helpful?