Customize data tracking

Coveo’s out-of-the-box (OOTB) tracking mechanisms allow for persisting tracking identifiers across subdomains. It doesn’t, however, allow tracking across multiple top-level domains.

For example, the client ID remains the same between and, since the information is shared across the top-level domain. On the other hand, the client ID would change between and, since they are two distinct top-level domains and browser restrictions prevent them from accessing each other’s client ID.

This article provides methods to use this identifier to track customers across multiple domains.

User journey example

The example below demonstrates the differences within the user journey using different data tracking mechanisms. A user navigates through pages across three sites, two of which share the same top-level domains ( and

Client ID in user journey

When the client ID changes, a new visit is generated.

1 With the previous OOTB tracking mechanism, a user is assigned a new client ID across each domain and subdomain.

2 With the current OOTB tracking mechanism, the client ID is persisted between and, but a user is assigned a new one when they reach which is under a different domain.

3 With client-generated tracking mechanisms, a user is assigned a single client ID which persists throughout the user journey.

Set a tracking identifier based on an existing UUID

In certain cases, you may already have an existing identifier that you use for tracking users and/or you want to use this identifier to track customers across multiple domains.

You can use it to track customers across multiple domains if:

  • You’re using the library to log events and the coveoua constant is available in the browser.


    This method doesn’t apply if you’re using Coveo JavaScript Search Framework (JSUI), and it may not be available if you’re using app-specific frameworks.

  • You have access to a stable string which identifies the browser client or user:

You can then set a custom client ID using a single JavaScript command, provided that it passes a valid UUID string which is unique to the browser across domains.


Creating your own client ID may be risky if not done correctly, therefore we recommend creating one only if all other options are unavailable. If the ID isn’t created properly, it can negatively affect tracking and consequently have an impact on all downstream Coveo systems.

Set a custom clientId

This command must be called before any other Coveo API calls are executed, which in practice means immediately after the Coveo library has loaded.

coveoua('onLoad', function (args) {

Set a custom clientId from a Google clientId

If you don’t have your own client UUID string, but you do have a unique identifier from another source, you can use that string identifier to generate a consistent pseudonymous clientId, provided you also specify a unique namespace string constant.


This namespace must be identical for all the domains that you want to track and is required to ensure good randomization.

A sample namespace can be your organization_id, Google client_id, or any other string which is constant for your organization.

coveoua('onLoad', function (args) {
  gtag('get', GOOGLE_MEASUREMENT_ID, 'client_id', (google_client_id) => {
    // This will generate a UUID for the provided Google client_id. The UUID will be stable for the given namespace.
    coveoanalytics.getCurrentClient().setClientId(google_client_id, GOOGLE_MEASUREMENT_ID);

Set a custom clientId from a userId and userAgent

If you don’t have either your own cliendId nor a persistent ID from another source, but you do have a consistent user identifier, a clientId can be generated by combining the userId and the browser’s distinct userAgent string. This will ensure that the clientId is the same across domains, but is still distinct for different browsers and devices.


In this case, changes to the browser’s userAgent string (for example, browser version upgrade, userAgent override, or custom code) will affect the clientId.

coveoua('onLoad', function (args) {
  // this sets a stable v5 uuid based on the given userId and browser userAgent.
  coveoanalytics.getCurrentClient().setClientId(USER_ID + Navigator.userAgent, ORGANIZATION_ID);

The client ID and user ID shouldn’t be confused with one another as they track different things. The client ID tracks a distinct combination of browser and device, while the user ID tracks a distinct user. While basing the client ID on only the userId is technically possible, it’s not recommended since it would ultimately alter the semantic of visits and hamper tracking of different browser clients.


For clarity, the following domains will be used as examples in this section: and

When there’s no consistent user identifier available, it may still be possible to ensure the client IDs on two top-level domains are identical, by passing the client ID in a Coveo specific URL parameter.



We recommend using this method if you have experience with JavaScript.

  • Your implementation relies on v2.26.1 or higher (this includes recent versions of Headless, but excludes JSUI).

  • You have content on multiple top-level domains. For example, and are part of a single user journey and you want to track this journey as a single visit.

  • The user is fully anonymous. If you have a user ID or a third-party client ID, use the method outlined above.

  • There is a known set of links from to

  • You must be in control of both domains, and the script has to be deployed on the outgoing and landing pages of both domains.


Do not use this method if both of your domains are isolated. For example, you operate two distinct ecommerce domains, where all your users are anonymous, and there are no links from one domain to the other. In this case, Coveo can’t assign a consistent clientId to both domains.

This method works by adding a cvo_cid parameter containing the clientId to the query parameters of the link used to navigate from a page on to a target page on This link parameter will be picked up by code on if all of the following conditions apply:

  • The target page has a greater or equal version of loaded.

  • The current URL contains a cvo_cid query parameter.

  • The cvo_cid query parameter contains a valid UUID.

  • The cvo_cid query parameter contains a valid UNIX timestamp, and that timestamp is no more than 120 seconds in the past.

  • The receiving page has specified an allowlist of valid referrers and the current referrer matches that list.

Then follow the following steps to implement link decoration:

  1. Ensure that is loaded on the page on which links to

  2. Modify the JavaScript on the source page on so that whenever a link to the target page is clicked, its href is replaced by the result of coveoua('link:decorate', '').


    This last step depends highly on the exact structure of the page. It’s important that the decorated link is generated at the moment the link is clicked, as it will be valid only for a short time afterward. This means you can’t just replace all links with decorated links in static page code. As an example, for a simple hyperlink, this sample code would dynamically replace the reference on click:

        async function decorate(element) {
            element.href = await coveoua('link:decorate', element.href);
    <a onclick="decorate(this)" href="">Navigate to index</a>
  3. Ensure that is loaded on the target page (

  4. Ensure that the target page allows reception of links from the source page by adding the line coveoua('link:acceptFrom', ['']); immediately after the script loads. The second parameter is an allowlist of incoming domains.

    1. You want to list all of your domains that would send decorated links.

    2. You can use wildcards to specify subdomains (for example, or all domains (for example, ).


      If you don’t specify a list, the link parameter will be ignored.