Concepts / Getting insights and analytics / Implement click and conversion Analytics
May. 10, 2019

Implement Click and Conversion Analytics

Install the Search-Insights Library

To make use of analytics, the search-insights library has to be added to your application. We support two ways to achieve this.

  • Bundling (with npm or yarn)
  • CDN

For both ways, we will create a queue proxy method so that every captured event will eventually be sent to Algolia, even when the javascript is not loaded yet.

Bundling

Install the search-insights library:

$
$
$
npm i search-insights
# or
yarn add search-insights

Then add it to the code:

1
2
3
4
5
6
7
8
  // Create the queue proxy method with `require('search-insights')`
  !function(e,a,t,n,s,i,c){e.AlgoliaAnalyticsObject=s,e.aa=e.aa||function(){(e.aa.queue=e.aa.queue||[]).push(arguments)},i=a.createElement(t),c=a.getElementsByTagName(t)[0],i.async=1,i.html=require('search-insights'),c.parentNode.insertBefore(i,c)}(window,document,"script",0,"aa");

  // Initialize library
  aa('init', {
    appId: 'YourApplicationID',
    apiKey: 'YourSearchOnlyAPIKey'
  });

CDN

Add the search-insights library by using jsDelivr CDN, and start using it immediately.

jsDelivr is a third-party CDN. We are not able to provide support regarding third party services.

1
2
3
4
5
6
7
8
9
10
11
<script>
  // Create the queue proxy method
  !function(e,a,t,n,s,i,c){e.AlgoliaAnalyticsObject=s,e.aa=e.aa||function(){(e.aa.queue=e.aa.queue||[]).push(arguments)},i=a.createElement(t),c=a.getElementsByTagName(t)[0],i.async=1,i.src="https://cdn.jsdelivr.net/npm/search-insights@1.1.1",c.parentNode.insertBefore(i,c)}(window,document,"script",0,"aa");


  // Initialize library
  aa('init', {
    appId: 'YourApplicationID',
    apiKey: 'YourSearchOnlyAPIKey'
  });
</script>

Prepare the Event

Retrieving the query ID from the response

When sending an event to Algolia, you need to include the queryID of the most recent search. However, by default, the search response does not contain a queryID. Therefore, in order to retrieve it, the custom search parameter clickAnalytics must be set to true and needs to be added when instantiating the search.

1
2
3
4
5
6
7
const search = instantsearch({
  searchClient,
  indexName: 'INDEX_NAME',
  searchParameters: {
    clickAnalytics: true,
  },
});

Adding the query ID and click position to the Hit object

By default, a hit object does not include the position or the queryID attributes. In order to include them, we need to transform our data before it’s passed to our template. This can be achieved by passing a transformItems callback to the setup of our hits widget.

The following code will append a _queryID and _hitPosition attribute to every hit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
search.addWidget(
  instantsearch.widgets.hits({
    container: '#hits',
    transformItems(items) {
      const result = search.helper.lastResults;
      const offset = result.hitsPerPage * result.page;

      return items.map((item, index) => ({
        ...item,
        _queryID: result.queryID,
        _hitPosition: offset + index + 1,
      }));
    },
  })
);

The _queryID and the _hitPosition should be extractable from the template. We suggest that you make use of data attributes in the hit template to simplify the extraction of this data.

In this example, we add the data-query-id and data-position from the hit object into the template.

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
search.addWidget(
  instantsearch.widgets.hits({
    container: '#hits',
    templates: {
      item(hit) {
        return `
          <article>
            <h3>
              ${instantsearch.highlight({
                attribute: 'name',
                hit,
              })}
            </h3>

            <button
              class="button-click"
              data-query-id="${hit._queryID}"
              data-object-id="${hit.objectID}"
              data-position="${hit._hitPosition}"
            >
              Details
            </button>
            <button
              class="button-convert"
              data-query-id="${hit._queryID}"
              data-object-id="${hit.objectID}"
            >
              Add to cart
            </button>
          <article>
        `;
      },
    }
  })
);

Sending click events does not always take immediate effect, it depends on the situation. On the other hand, personalization events always take immediate effect. See our page on when click events take effect.

Send the event

Now for the payoff, sending the event.

If you’re sending these events with our Personalization feature, it’s important to decide which events to send, and when to send them. Please read our guide if you’re unsure about how event-sending works.

Click and Conversion events

Based on the type of event you send, you need different data. For example, a conversion event does not need the position attribute, but the click event does, because position determines the average click position.

1
2
3
4
5
6
7
8
9
10
11
12
document.addEventListener('click', event => {
  if (event.target.matches('.button-click')) {
    aa('clickedObjectIDsAfterSearch', {
      eventName: 'CLICK_HIT',
      index: 'INDEX_NAME',
      queryID: event.target.getAttribute('data-query-id'),
      objectIDs: [event.target.getAttribute('data-object-id')],
      // We call `parseInt()` because `getAttribute()` returns a string
      positions: [parseInt(event.target.getAttribute('data-position'), 10)],
    });
  }
});
1
2
3
4
5
6
7
8
9
10
document.addEventListener('click', event => {
  if (event.target.matches('.button-convert')) {
    aa('convertedObjectIDsAfterSearch', {
      eventName: 'CONVERT_HIT',
      index: 'INDEX_NAME',
      queryID: event.target.getAttribute('data-query-id'),
      objectIDs: [event.target.getAttribute('data-object-id')],
    });
  }
});

When sending a conversion event, you’re not always on the search page (such as a product detail page). Therefore, you need to pass the queryID to the detail page. We wrote a guide to show you how to use localStorage to pass the queryID.

Did you find this page helpful?