-
Tutorials
- 0: Environment Setup
- 1: Basic Configuration, Options, and Markup
- 2: Interact With the Search Interface and Component Instances
- 3: Understanding the Event System
- 4: Modify the Query
- 5: Result Templates
- 6: Usage Analytics
- 7: Interact With Component States
- 8: Configure Your Own Search Endpoint
- 9: Advanced Integration With Custom TypeScript Component (Configuration)
- 10: Advanced Integration With Custom TypeScript Component (Implementation)
JavaScript Search Framework Tutorial 6: Usage Analytics
Coveo Usage Analytics (Coveo UA) is a very important part of any Coveo implementation. Without it, a large part of the Coveo technology stack can’t function properly.
For example, the Coveo Machine Learning (Coveo ML) service won’t be able to work correctly if it can’t access the usage analytics data about your search page (see Coveo Machine Learning).
In this tutorial, you’ll learn more about the Analytics
component and its options. You’ll also learn how to log analytics events programmatically and modify standard analytics events.
-
For more detailed information on Coveo UA, see Analyze Data and Usage Analytics Concepts.
-
If you significantly modified the
./bin/index.html
page in previous tutorials, you can undo these changes by rebuilding the project. To do so, run the following command line from the root of the tutorial project folder:
npm run build
The Analytics Component
To allow your search page to log usage analytics events, you need to insert an Analytics
component in your search interface as shown in the following code excerpt:
<div id="search" class="CoveoSearchInterface">
<!-- ... -->
<div class="CoveoAnalytics"></div>
<!-- ... -->
</body>
If your Coveo organization is in the HIPAA environment, set the endpoint
option of your Analytics
component to https://usageanalyticshipaa.cloud.coveo.com
.
<div class="CoveoAnalytics" data-endpoint="https://usageanalyticshipaa.cloud.coveo.com"></div>
The Analytics
component can be inserted anywhere inside the search interface. It doesn’t provide any visual aspect to your search page. Therefore, moving it around will have no impact on the rendering of your search interface.
After it has been added, the Analytics
component will take care of logging all search and click events triggered by basic components.
It’s important to note that the Analytics
component doesn’t decide which event data or metadata needs to be logged. Each component will individually do an explicit call to the Analytics
component to signal its need to log an event.
About the searchHub Option
The searchHub
option is a very important parameter which is used to determine from what page the analytics events originated.
This parameter is essential to many concepts, such as the query pipeline (see What’s a Query Pipeline?).
There are two ways to specify the searchHub
:
-
Client side, by setting the
data-search-hub
option on theCoveoAnalytics
component in the markup.This means the property isn’t “enforced”, but rather set client side with JavaScript code. You can still use the property to create conditions in query pipelines, but you shouldn’t use it for features that require the
searchHub
to be set securely (such as providing query suggestions based on thesearchHub
). -
Enforced by the search token (see Search Token Authentication).
This is more complicated to setup, but is much more secure. This is discussed in JavaScript Search Framework Tutorial 8: Configure Your Own Search Endpoint).
Whenever possible, you should use a searchHub
enforced by the search token.
In some scenarios, for example when inside the Coveo for Salesforce application, the Analytics
component is properly configured out of the box with a valid searchHub
enforced in the token.
You should refer to your specific Coveo product documentation for more specific information.
Troubleshooting Analytics Requests
The following steps detail the requests and responses of a very basic search event when the Analytics
component present in a search page.
You can actively follow these steps by inspecting the requests and responses from your web browser.
-
Make sure there’s an
Analytics
component in your page. It can be placed anywhere inside the search interface. -
Type something in the search box, then send the request.
-
You should see that your browser sends an
OPTIONS
request tohttps://platform.cloud.coveo.com/rest/ua/v15/analytics/searches
.This is called a CORS preflight request (see HTTP access control (CORS)).
Very simply speaking, the browser is making sure that the back-end service supports CORS correctly.
-
You should then see that your browser sends a
POST
request tohttps://platform.cloud.coveo.com/rest/ua/v15/analytics/searches
Here is the important information you should look for in that request:
-
Authorization header
This will normally use the same search token or API key that you used to perform the query, unless you specified a different one in the
Analytics
component. -
Visitor query string parameter
This is an ID that the UI retrieves from your cookies to track a single visit.
The first time someone visits a Coveo-powered search page in which the
Analytics
component is enabled, the ID of this visitor will be sent from Coveo UA and stored in your cookie.Each event belonging to the same visit will send the same visitor ID.
-
The request payload
This is the body of the request. It’s different for each event type. Feel free to investigate the data that the framework sends to Coveo UA.
The
actionType
andactionCause
parameters specify which component triggered the event.The
customData
parameter is a simple key-value pair which can be used to create customized dashboards and reports in Coveo UA.The
originLevel1
,originLevel2
, andoriginLevel3
parameters should specify where the event was triggered from.originLevel1
should be a general name for your search interface (e.g., the location of the search page or a string that describes the purpose of the page). If not set, it will fallback to"default"
.originLevel2
will try to match the currentTab
component, if available. If not set, it will fallback to an empty string.originLevel3
is set to thedocument.referrer
value.
-
-
You should then see a response from
https://platform.cloud.coveo.com/rest/ua/v15/analytics/searches
.-
If the request was successful, you should see a
200 OK
response with the content being a JSON containing the visitor ID and query ID. -
If the request was not successful, you should inspect the response content. It will normally be a detailed response describing what the problem is. Usually, this will be a privilege related error. Concretely, this means that if you used an API key to log a search event, you need to make sure that this API key has the privilege to push analytics data (i.e., the Push access level on the Analytics data domain) (see Manage Privileges and Analytics Data Domain).
-
Log Search Events Programmatically
All out of the box components take care of logging their own events in Coveo UA. However, it’s important that your implementation takes care of logging search events correctly, since you can create your own components and execute queries using JavaScript code (see JavaScript Search Framework Tutorial 2: Interact With the Search Interface and Component Instances). Logging search events correctly can be done with the logSearchEvent
function.
Consider the following code:
<head>
<script class="coveo-script" src="https://static.cloud.coveo.com/searchui/v2.5395/js/CoveoJsSearch.Lazy.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
Coveo.SearchEndpoint.configureSampleEndpointV2();
const root = document.getElementById("search");
Coveo.init(root);
Coveo.executeQuery(root);
})
</script>
</head>
<body id="search" class="CoveoSearchInterface" data-auto-trigger-query="false">
<div class="CoveoAnalytics"></div>
</body>
The script would produce a warning such as:
This is because a search was triggered without any related search event while the Analytics
component was active on the page.
To log a search event correctly, you would need to modify the script like this:
const eventCause = { name: "searchEventName", type: "searchEventType" };
const metadata = { key1: "value1", key2: "value2" };
Coveo.logSearchEvent(root, eventCause, metadata);
Coveo.executeQuery(root);
Q: Is it necessary to make the logSearchEvent call before the executeQuery call?
A: Yes, because it allows the Analytics
component to queue the search event and wait for the query to successfully complete before sending the event.
If you were to only call logSearchEvent
without any query, you wouldn’t see the search event being sent from the browser.
Q: What’s the customEventCause parameter ?
A: This parameter accepts a JSON with the following two properties: name
and type
.
Both of these properties can be set to any arbitrary string value. However, you should respect the following guidelines:
-
The
name
property should uniquely identify the precise action that caused the search event to be triggered. -
The
type
property should describe the general category of the event. This value can be used by more than one event or component.
The basic Searchbox
component can log the following search events:
-
The user “submits” the query by pressing
Enter
:{name: "searchboxSubmit", type: "search box"}
-
The user “clears” the query by pressing the clear button in the
Searchbox
component:{name: "searchboxClear", type: "search box"}
-
The search-as-you-type feature is used to trigger queries:
{name: "searchboxAsYouType", type: "search box"}
It’s not useful to memorize the individual name
and type
values logged by each out of the box component. However, it’s important to understand that the name
value should uniquely identify the action itself whereas the type
value should be a general concept for a given component.
If you were to implement a calendar component which would trigger queries, you could log search events with customEventCause
parameters such as these:
-
The user clicks on a day in the calendar:
{name: "selectDay", type: "calendar"}
-
The user clicks on the next month button:
{name: "nextMonth", type: "calendar"}
Q: What’s the metaData parameter?
A: This parameter can be used to send any arbitrary data to the Coveo Analytics service to create custom dimensions (see Manage Dimensions on Custom Data).
The metaData
parameter needs to be a key-value pair, with the value being a string containing no more than 255 characters.
This parameter is optional. If you don’t want to log any metadata, you can pass an empty JSON: {}
.
Logging Click Events Programmatically
Click events can be associated to any action resulting in the end user viewing an item, such as a ResultLink
click or a Quickview
click.
Logging click events can be done using the logClickEvent
function as shown in the following code excerpt:
const eventCause = { name: "clickEventName", type: "clickEventType" };
const metadata = { key1: "value1", key2: "value2" };
const result = getTheResult();
Coveo.logClickEvent(root, eventCause, metadata, result)
Q: How can I get the result?
A: The result can be retrieved in many ways. One way is to use the querySuccess
event (see JavaScript Search Framework Tutorial 3: Understanding the Event System).
Most of the time, a function that needs to log a click event will be executed inside the scope of a result template. The result object is always available inside a result template (see JavaScript Search Framework Tutorial 5: Result Templates).
Logging Search-As-You-Type Events Programmatically
Logging search-as-you-type events follows the exact same logic as logging normal search events, with the exception that those types of event are handled with a bit of extra logic.
Search-as-you-type events will wait until one of the following conditions is met before logging the actual event after it has been queued up:
-
Five seconds have passed since the search-as-you-type event was queued up.
If a new search-as-you-type event is queued up, the countdown is reset. Only the last search-as-you-type event queued up in this manner will be logged.
-
Another search event which isn’t a search-as-you-type event is queued up.
For example, a facet value is selected. In that case, the search-as-you-type event is logged, followed by the standard search event.
This is done to avoid logging many partial queries. Only the last “valid” query will be logged.
Search-as-you-type events can be logged programmatically using the logSearchAsYouTypeEvent
function as shown in the following code excerpt:
const eventCause = { name: "searchAsYouTypeEventName", type: "searchAsYouTypeEventType" };
const metadata = { key1: "value1", key2: "value2" };
Coveo.logSearchAsYouTypeEvent(root, eventCause, metadata);
Coveo.executeQuery(root);
Logging Custom Events Programmatically
A custom event can be any event that doesn’t trigger a search and doesn’t result in the end user viewing an item.
For example, a Case Deflection form powered by Coveo search could log a custom event when a Cancel or Submit button is pressed.
Custom events can be logged programmatically using the logCustomEvent
function as shown in the following code excerpt:
const eventCause = { name: "customEventName", type: "customEventType" };
const metadata = { key1: "value1", key2: "value2" };
Coveo.logCustomEvent(root, eventCause, metadata);
Modifying Standard Analytics Events
Sometimes, it can be useful to tweak and modify the standard usage analytics events logged by the Coveo JavaScript Search Framework.
For example, you could want to add the end-user profile name to all usage analytics events for a given implementation.
You can do so by using adding a changeAnalyticsCustomData
event handler as shown in the following code excerpt:
document.addEventListener("DOMContentLoaded", () => {
// ...
const root = document.getElementById("search");
Coveo.$$(root).on("changeAnalyticsCustomData", (e, args) => {
// See https://coveo.github.io/search-ui/interfaces/ichangeanalyticscustomdataeventargs.html
args.originLevel1 = "myOriginLevel1";
args.metaObject["foo"] = "bar";
});
// ...
Coveo.init(root);
})
Binding event handlers was explained in JavaScript Search Framework Tutorial 3: Understanding the Event System.
Other Useful Reference Documentation
What’s Next?
You should now proceed to JavaScript Search Framework Tutorial 7: Interact With Component States.