UI Libraries / Autocomplete / Sending Algolia Insights events

Sending Algolia Insights events

Using this plugin requires an Algolia application with the Event Analytics feature enabled.

If you’re using Algolia indices as sources in your autocomplete, Algolia provides Search Analytics out-of-the-box. Search Analytics includes metrics like top searches, top searches with no results, overall search counts, etc.

You may also want to capture Click and Conversion Analytics. These analytics take Algolia’s out-of-the-box Search Analytics further by providing insights into actions users take after performing a search. They’re useful to better understand your user’s behavior and what they need from your app. This information can ultimately drive your business.

Capturing these analytics requires sending events to Algolia when your users view, click, or convert on results. This tutorial explains how to automatically send events from your autocomplete using the autocomplete-plugin-algolia-insights package.

Prerequisites

This tutorial assumes that you have:

  • an autocomplete using one or more Algolia indices for your sources
  • front-end development proficiency with HTML, CSS, and JavaScript

If you haven’t implemented an autocomplete using Algolia as a source yet, follow the Getting Started guide first. For learning purposes, you can use the demo application credentials and index provided in this tutorial.

Getting started

First, begin with some boilerplate for the autocomplete implementation. Create a file called index.js in your src directory, and add the boilerplate below:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { h, Fragment } from 'preact';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';
import algoliasearch from 'algoliasearch';

const appId = 'latency';
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76';
const searchClient = algoliasearch(appId, apiKey);

autocomplete({
  container: '#autocomplete',
  openOnFocus: true,
  plugins: [],
  getSources({ query }) {
    return [
      {
        sourceId: 'products',
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: 'instant_search',
                query,
                params: {
                  clickAnalytics: true,
                },
              },
            ],
          });
        },
        templates: {
          item({ item, components, html }) {
            return html`<div class="aa-ItemWrapper">
              <div class="aa-ItemContent">
                <div class="aa-ItemIcon">
                  <img
                    src="${item.image}"
                    alt="${item.name}"
                    width="40"
                    height="40"
                  />
                </div>
                <div class="aa-ItemContentBody">
                  <div class="aa-ItemContentTitle">
                    ${components.Highlight({ hit: item, attribute: 'name' })}
                  </div>
                  <div class="aa-ItemContentDescription">
                    ${components.Snippet({
                      hit: item,
                      attribute: 'description',
                    })}
                  </div>
                </div>
              </div>
              <button
                class="aa-ItemActionButton aa-DesktopOnly aa-ActiveOnly"
                type="button"
              >
                <svg
                  fill="currentColor"
                  viewBox="0 0 24 24"
                  width="20"
                  height="20"
                >
                  <path
                    d="M18.984 6.984h2.016v6h-15.188l3.609 3.609-1.406 1.406-6-6 6-6 1.406 1.406-3.609 3.609h13.172v-4.031z"
                  ></path>
                </svg>
              </button>
            </div>`;
          },
        },
      },
    ];
  },
});

This boilerplate assumes you want to insert the autocomplete into a DOM element with autocomplete as an id. You should change the container to match your markup. Setting openOnFocus to true ensures that the dropdown appears as soon as a user focuses the input.

The autocomplete searches into an Algolia index of ecommerce products using the getAlgoliaResults function. Refer to the example in the Getting Started guide for more information.

You must set the clickAnalytics query parameter to true to send click and conversion events from your autocomplete.

For now, plugins is an empty array, but you’ll learn how to add the Insights plugin next.

Sending Algolia Insights events

The autocomplete-plugin-algolia-insights package provides the createAlgoliaInsightsPlugin function for creating an Insights plugin out-of-the-box.

It requires an Algolia Insights client initialized with an Algolia application ID and Search API key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ...
import { createAlgoliaInsightsPlugin } from '@algolia/autocomplete-plugin-algolia-insights';
import insightsClient from 'search-insights';

const appId = 'latency';
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76';
const searchClient = algoliasearch(appId, apiKey);

insightsClient('init', { appId, apiKey });
const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({ insightsClient });

autocomplete({
  container: '#autocomplete',
  placeholder: 'Search products',
  openOnFocus: true,
  plugins: [algoliaInsightsPlugin],
  getSources({ query }) {
    // ...
  },
});

// ...

If you’re using search-insights >= 2.0.0, the library no longer sets an anonymous token automatically. You can either set the user token, or re-enable the cookie-based anonymous token.

1
2
3
4
5
6
insightsClient('init', { appId, apiKey });
insightsClient('setUserToken', yourUserToken);

// or

insightsClient('init', { appId, apiKey, useCookie: true });

Now, whenever the autocomplete shows products in the dropdown, the plugin sends view events with the eventName “Items Viewed” for these products. If a user clicks a product, the plugin sends a click event, with the eventName “Item Selected” for that product. By default, the plugin doesn’t send any conversion events.

Customizing events

You can change any of the plugin’s default behavior by using the onItemsChange, onSelect, or onActive hooks. For example, you may want to customize the eventName to match your naming conventions or send a different events on these actions.

Changing the eventName

This snippet shows how to instantiate a plugin that sends a click event with “Product Selected from Autocomplete” as the eventName whenever a user selects an item. You may want to do this to differentiate between click events sent from your Autocomplete compared with other parts of your search implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const appId = 'latency'
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76'
const searchClient = algoliasearch(appId, apiKey)

insightsClient('init', { appId, apiKey })

const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({
  insightsClient,
  onSelect({ insights, insightsEvents }) {
    const events = insightsEvents.map((insightsEvent) => ({
      ...insightsEvent,
      eventName: 'Product Selected from Autocomplete',
    }))
    insights.clickedObjectIDsAfterSearch(...events)
  },
})

Sending different events for different result types

If you’re using multiple different Algolia indices in the same autocomplete, for example one for products and one for suggestions, you may want to use different eventNames for each section. You can change this (and other parts of the event) conditionally based on the source index name:

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
const appId = 'latency'
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76'
const searchClient = algoliasearch(appId, apiKey)

insightsClient('init', { appId, apiKey })

const algoliaInsightsPlugin = createAlgoliaInsightsPlugin({
  insightsClient,
  onSelect({ insights, insightsEvents }) {
    const events = insightsEvents.map((insightsEvent) => {
      switch (insightsEvent.index) {
        case 'instant_search_demo_query_suggestions': {
          return {
            ...insightsEvent,
            eventName: 'Suggestion Selected from Autocomplete',
          }
        }
        case 'instant_search': {
          return {
            ...insightsEvent,
            eventName: 'Product Selected from Autocomplete',
          }
        }
        default: {
          return {
            ...insightsEvent,
            eventName: 'Item Selected from Autocomplete',
          }
        }
      }
    })
    insights.clickedObjectIDsAfterSearch(...events)
  },
})

Sending events from templates

Though the default Insights plugin doesn’t send any conversion events, you may want to. For example, you may have created a template with an “Add to cart” button.

Autocomplete with add to cart button

If a user adds an item to their shopping cart directly from the autocomplete, you can send a conversion event from your template. This is possible since the Insights plugin stores the Insights client in context. You can pass it to your templates like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
autocomplete({
  // ...
  plugins: [algoliaInsightsPlugin],
  templates: {
    item({ item, components, state, html }) {
      return createProductItemTemplate({
        hit: item,
        components,
        insights: state.context.algoliaInsightsPlugin.insights,
        html,
      });
    },
  },
});

function createProductItemTemplate() {
  // ...
}

Once available to your templates, you can use it to send events using Insights client methods. In this example, clicking the “Add to cart button” fires the convertedObjectIDsAfterSearch method, sending a conversion event.

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
39
40
41
42
43
44
45
46
function createProductItemTemplate({ hit, insights, components, html }) {
  return html`<div class="aa-ItemWrapper">
    <div class="aa-ItemIcon">
      <img src="${hit.image}" alt="${hit.name}" width="40" height="40" />
    </div>
    <div class="aa-ItemContent">
      <div class="aa-ItemContentTitle">
        ${components.Highlight({ hit, attribute: 'name' })}
      </div>
      <div class="aa-ItemContentDescription">
        ${components.Snippet({ hit, attribute: 'description' })}
      </div>
    </div>
    <div class="aa-ItemActions">
      <button
        class="aa-ItemActionButton"
        type="button"
        onClick="${(event) => {
          event.preventDefault();
          event.stopPropagation();
          insights.convertedObjectIDsAfterSearch({
            eventName: 'Added to cart',
            index: hit.__autocomplete_indexName,
            objectIDs: [hit.objectID],
            queryID: hit.__autocomplete_queryID,
          });
        }}"
      >
        <svg
          viewBox="0 0 24 24"
          width="20"
          height="20"
          fill="none"
          stroke="currentColor"
        >
          <path
            d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
          />
        </svg>
      </button>
    </div>
  </div>`;
}

For more information on the methods and event types you can send using the Insights API, consult the Algolia Insights documentation.

Validating events

To ensure that you’re sending events as you expect, you can check the Algolia Events Hub, or the Algolia Events Debugger.

Did you find this page helpful?