Concepts / Building Search UI / Plug analytics
Jan. 07, 2019

Plug analytics

Using Algolia Insights with InstantSearch.js

Loading and initializing the library

Insights library can be either loaded via jsDelivr CDN or directly bundled with your application. We recommend loading the library by adding the snippet below to all pages where you wish to track search analytics.

1
2
3
4
5
6
7
8
9
<script>
  !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.0.0",c.parentNode.insertBefore(i,c)}(window,document,"script",0,"aa");

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

Enabling queryID response

To enable the queryID response from the search API, InstantSearch.js enables setting custom queryParameters when you instantiate your search instance like so:

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

Reporting click and conversion events

When you actually want to trigger a click event depends on your implementation type and business logic. A good framework would be to send a click event once a user has clicked on something that indicates action inside the hit - for example, when a user clicks on a result (for click events) or when a user adds an item to a cart (for conversions).

This example covers how to obtain the objectID and position for reporting. We advise that you add data-algolia-objectid and data-algolia-position data attributes in your hitTemplate, as it greatly eases the implementation.

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
search.addWidget(
  instantsearch.widgets.hits({
    container: '#hits',
    hitsPerPage: 16,
    transformData: function(hit) {
       var result = search.helper.lastResults;
       var offset = result.hitsPerPage * result.page;

       hit._queryID = result.queryID;
       hit._hitPosition = offset + hit.__hitIndex + 1;

       return hit;
     }
    templates: {
      item(hit) {
        return `
          <div>
            ...
            <button class="button-click"
              data-query-id="${hit._queryID}"
              data-object-id="${hit.objectID}"
              data-position="${hit._hitPosition}">Click event</button>

            <button class="button-conversion"
              data-query-id="${hit._queryID}"
              data-object-id="${hit.objectID}">Conversion event</button>
            ...
          <div>
        `;
      },
    },
  })
);

After you’ve added the information to the DOM, you need to create the handlers to trigger the action. This can be done by specifying a global onclick event handler and checking the clicked element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
document.addEventListener('click', e => {
  if (e.target.matches('.button-click')) {
    window.aa('clickedObjectIDsAfterSearch', {
      index: "INDEX_NAME",
      eventName: "Add to Cart",
      queryID: e.target.getAttribute('data-query-id'),
      objectIDs: [e.target.getAttribute('data-object-id')],
      positions: [parseInt(e.target.getAttribute('data-position'))], // parseInt as getAttribute always returns a string
    });
  } else if (e.target.matches('.button-conversion')) {
    window.aa('convertedObjectIDsAfterSearch', {
      index: "INDEX_NAME",
      eventName: "Add to Cart",
      queryID: e.target.getAttribute('data-query-id'),
      objectIDs: [e.target.getAttribute('data-object-id')],
    });
  }
});

Advanced options - sending click events on right click

Sometimes - and it is often the case in ecommerce - users right-click and open the product in a new tab. To be able to report that event as a click event, you will have to bind a global contextmenu event listener similar to the click event.

1
2
3
4
5
6
7
8
9
10
11
document.addEventListener('contextmenu', e => {
  if (e.target.matches('.button-click')) {
    window.aa('clickedObjectIDsAfterSearch', {
      index: "INDEX_NAME",
      eventName: "Add to Cart",
      queryID: e.target.getAttribute('data-query-id'),
      objectIDs: [e.target.getAttribute('data-object-id')],
      positions: [parseInt(e.target.getAttribute('data-position'))], // parseInt as getAttribute always returns a string
    });
  }
});

Google Analytics with Vanilla JS InstantSearch

Even though Algolia provides an analytics tailored to your search, you might want to integrate your search into your existing analytics tools. For this purpose, InstantSearch.js provides a widget called analytics.

This widget is platform agnostic and can be used either with Google Analytics or any platform that provides an REST endpoint.

Integrate InstantSearch.js with Google Analytics

Integrating with Google Analytics requires 2 steps:

  • set up the Google Analytics library in your page
  • add and configure the analytics widget

To set up Google Analytics, the best way is to actually follow the reference guide.

Once the GA library is installed on your website, you can add the following:

1
2
3
4
5
6
7
8
9
search.addWidget(
  instantsearch.widgets.analytics({
    pushFunction: function(formattedParameters, state, results) {
      // Google Analytics
      window.ga('set', 'page', window.location.pathname + window.location.search);
      window.ga('send', 'pageView');
    },
  })
);

The logic is defined in the pushFunction. Have a look at the reference API to get more information about the parameters of this function.

Did you find this page helpful?