--- title: Log search events slug: '1502' canonical_url: https://docs.coveo.com/en/1502/ collection: build-a-search-ui source_format: adoc --- # Log search events Typically, whenever a user interacts with a [search interface](https://docs.coveo.com/en/2741/) in a way that triggers a [query](https://docs.coveo.com/en/231/) to the Search API, the search interface logs a search event. For example, a search event is logged when the user submits a query from the search box or selects a [facet](https://docs.coveo.com/en/198/) value. This is the most commonly logged category of [Coveo Analytics event](https://docs.coveo.com/en/260/). This article provides guidelines for performing HTTP requests against the [Usage Analytics (UA) Write API](https://docs.coveo.com/en/18/) to properly log search events. > **Important** > > The information in this article is only relevant when you can't (or choose not to) use one of the Coveo UI libraries ([Atomic](https://docs.coveo.com/en/lcdf0264/), [Headless](https://docs.coveo.com/en/lcdf0493/), or the [JavaScript Search Framework](https://docs.coveo.com/en/187/)) to achieve a search integration with Coveo. > These libraries can handle all of the HTTP requests for you. To log a search event, make a POST request to [source,text,subs="attributes+"] ``` https://.analytics.org.coveo.com/rest/ua/v15/analytics/search ``` where `` is the unique identifier of your [Coveo organization](https://docs.coveo.com/en/185/). In the HIPAA environment, use: [source,text,subs="attributes+"] ``` https://.analytics.orghipaa.coveo.com/rest/ua/v15/analytics/search ``` > **Note** > > In either case, under the hood, Coveo will use the [organization endpoints](https://docs.coveo.com/en/mcc80216/) to redirect your requests to the target region. Use an access token with the [privilege](https://docs.coveo.com/en/228/) to push [Coveo Analytics data](https://docs.coveo.com/en/259/) (that is, the **Allowed** [access level](https://docs.coveo.com/en/2818/) on the [**Analytics data**](https://docs.coveo.com/en/1707#analytics-data-domain) [domain](https://docs.coveo.com/en/2819/)). ## Example In the following request, only the body properties which are required by the [Coveo Analytics](https://docs.coveo.com/en/182/) and [Coveo Machine Learning (Coveo ML)](https://docs.coveo.com/en/188/) services are included. In this example, even though the `username` is required, it's not included because it's extracted from the [search token](https://docs.coveo.com/en/1346/). If another authentication method was used, the `username` field would need to be included in the request body. [source,http,subs="attributes+"] ``` POST https://myorganizationid9sd8df7s.analytics.org.coveo.com/rest/ua/v15/analytics/search HTTP/1.1 ​ Content-Type: application/json Authorization: Bearer **********-****-****-****-************ ``` Payload: ```json { "anonymous": false, "language": "en", "originLevel1": "CommunitySearchPage", "originLevel2": "All", "clientId": "489aa3e3-aed2-4563-8e81-62bb73178a56", "actionCause": "searchboxSubmit", "queryText": "coveo", "responseTime": 145, "searchQueryUid": "7bfc652a-9dea-4811-b3f9-6d24345c37ce", "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" } ``` > **Note** > > There's also a method for [logging search events in batches](https://docs.coveo.com/en/18#operation/post__v15_analytics_searches): `+POST https://.analytics.org.coveo.com/rest/ua/v15/analytics/searches+`, where `` is the unique identifier of your organization. > > Assuming that the search interface is logging usage analytics events asynchronously, it could queue up events and send them in a batch when they're ready. > This would allow the search interface to make fewer HTTP requests, especially when many search requests that log search events are performed in a short amount of time. > For example, when [search-as-you-type](https://docs.coveo.com/en/2068/) is used. ## Required request body properties The following properties are required by the UA Write API when logging a search event. ### `actionCause` (string) The identifier of the user action that triggered a query and caused the search interface to log a search event. For example, if the user submits a query from the search box, the standard `actionCause` value would be `searchboxSubmit`. Most of the actions which can be performed from a typical search interface are associated with a specific, standard `actionCause` value (that is, the one that the Coveo UI libraries would use in a similar situation). The most common of these are documented in the search interface [implementation guidelines](https://docs.coveo.com/en/1370/). To learn more about the different `actionCause` values, see [Custom metadata reference](https://docs.coveo.com/en/1522/). > **Note** > > Some `actionCause` values are expected to be accompanied by a specific set of [`customData`](https://docs.coveo.com/en/1502#search-event-customdata-key-value-pairs) key-value pairs. > Passing these expected key-value pairs is important because they're used by Coveo ML and in [Coveo Analytics reports](https://docs.coveo.com/en/266/). Coveo ML [Query Suggestion (QS)](https://docs.coveo.com/en/1015/) models will learn from a given Coveo UA Write log request when `actionCause` is set to one of the following: `omniboxAnalytics`, `searchboxSubmit`, `searchFromLink`. ```json { ... "actionCause": "facetSelect", ... } ``` ### `language` (string) The language of the search interface from which the search event originates. Maximum: 256 characters. This value must be an [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) code, and it must match the first part of the `locale` value in the request body of the corresponding query to the Search API. The Coveo ML [Automatic Relevance Tuning (ART)](https://docs.coveo.com/en/1013/) and QS models handle the query string differently depending on the `language` value. Additionally, QS models only provide suggestions in the appropriate language, and [Content Recommendation (CR)](https://docs.coveo.com/en/1016/) models are language-specific. Coveo ML builds an independent CR submodel for each `language` value. ```json { ... "language": "en", ... } ``` ### `numberOfResults` (unsigned integer) The number of results which were returned by the query that caused the search interface to log a search event. > **Note** > > The `numberOfResults` property isn't required by the UA Write API, but is required for some UA reporting purposes, such as identifying content gaps. > This dimension is used to decide whether queries return results or not, populating the `hasResults` dimension, used to identify content gaps. > Therefore, it's strongly recommended to populate this property. The `numberOfResults` value must be the same as the `totalCount` value in the response body of the corresponding Search API request. ```json { ... "numberOfResults": 1866, ... } ``` ### `queryText` (string) The original [basic query expression (`q`)](https://docs.coveo.com/en/178/) in the corresponding search request. Maximum: 1024 characters. The `queryText` value must be the same as the `q` value of the corresponding search request to the Search API. The `queryText` value is used by Coveo ML ART, QS, and CR. It's broken down and associated with relevant result [items](https://docs.coveo.com/en/210/). ```json { ... "queryText": "coveo", ... } ``` ### `responseTime` (strictly positive integer) Time (in milliseconds) between the moment the query that caused the search interface to log a search event was sent to the Search API and the moment the search interface received the results. Useful to monitor the speed of your solution. ```json { ... "responseTime": 145, ... } ``` ### `searchQueryUid` (string) The unique identifier of the query that caused the search interface to log a search event. The `searchQueryUid` value must be the same as the `searchUid` value in the response of the corresponding search request to the Search API. The Coveo ML ART and QS [models](https://docs.coveo.com/en/1012/) use `searchQueryUid` to relate click events to search events. ```json { ... "searchQueryUid": "df60b2fb-c276-49ae-b704-2ee45609f3a6", ... } ``` ## Coveo ML-required request body properties The following properties aren't required by the UA Write API when logging a search event, but they're required when using the Coveo ML service (otherwise, Coveo ML models won't function correctly). ### `originLevel1` (string) The name or identifier of the search interface from which the search event originates. Maximum: 128 characters. If `[originLevel1](https://docs.coveo.com/en/1337/)` isn't specified and the request is authenticated with a search token, the service tries to extract the `[searchHub](https://docs.coveo.com/en/1342/)` value from the access token that authenticated the request to log a search event (see [Set the Search Hub](https://docs.coveo.com/en/365#set-the-search-hub)). When logging a search event, the `originLevel1` value must be the same as the `searchHub` value in the request body of the corresponding query to the Search API. > **Important** > > Coveo ML models use the `originLevel1` value as a default filter field. > These filters don't affect how the models learn, but they must be logged correctly for recommendations to work. > When Coveo ML models make suggestions, items which don't meet the right filters are ignored (see [Get query suggestions - Troubleshooting](https://docs.coveo.com/en/1459#troubleshooting)). ```json { ... "originLevel1": "ExternalSearch", ... } ``` ### `anonymous` (Boolean) Whether the query that caused the search interface to log a search event was triggered by an anonymous user. The default value is `false`. If the user is authenticated but wants to be anonymous, set `anonymous` to `true`. The UA Write API won't extract the `name` and `userDisplayName`, if present, from the search token. As long as you don't include their identity elsewhere in your request, the user will remain anonymous. The `anonymous` value must be identical to the `isGuestUser` value of the corresponding search request to the Search API. If an authenticated user wants to be anonymous, `isGuestUser` should be set to `true` when performing a query. When `anonymous` is set to `true`, Coveo ML QS models will personalize using [`clientId` or `visitorId`](https://docs.coveo.com/en/masb0234/) instead of `username`. ```json { ... "anonymous": false, ... } ``` ### `userAgent` (string) Information about the browser and operating system of the user who triggered the query that caused the search interface to log a search event. Maximum: 1024 characters. > **Note** > > If the client performs HTTP requests directly against the UA Write API to log events (rather than performing those requests through a proxy server), the user's browser will typically include the correct information in the `User-Agent` request header. > In this case, it's not necessary to specify a value for the `userAgent` request body property. The Coveo ML ART, QS, and CR models use this value to filter out search events that were logged by bots or anonymous users. ```json { ... "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36", ... } ``` ### `username` (string) The name of the [user](https://docs.coveo.com/en/250/) [security identity](https://docs.coveo.com/en/240/) which triggered the query that caused the search interface to log a search event. Maximum: 128 characters. This can only be specified when authenticated with an API key that was created using the **Authenticated search** [template](https://docs.coveo.com/en/1718#api-key-templates) or an [OAuth2 token](https://docs.coveo.com/en/1369/) with the privilege to [impersonate](https://docs.coveo.com/en/2737/) users (that is, the **Allowed** access level on the [**Impersonate** domain](https://docs.coveo.com/en/1707#impersonate-domain-analytics)). > **Important** > > A private API key or an OAuth2 token with the privilege to impersonate users shouldn't be exposed publicly. If `username` isn't specified and the request is authenticated with a search token, the service tries to extract the `username` value from the access token that authenticated the log search event request. If this fails, `username` is left blank. If this isn't specified and the request is authenticated with an API key, `username` is set to `anonymous`. The Coveo ML service requires the `username` value to load even though it's not always used. In QS, the Coveo ML service uses the `username` to filter out irrelevant users. In CR, it uses the `username` to build user profiles and provide user-based recommendations. ```json { ... "username": "alice.smith@example.com", ... } ``` ## Coveo ML-optional request body properties The following properties aren't required by either the UA Write API or Coveo ML service when logging search events. However, specifying values for these properties may improve the effectiveness of Coveo ML. ### `originLevel2` (string) The name or identifier of the [tab](https://docs.coveo.com/en/1406/) from which the search event originates. Maximum: 128 characters. When logging a search event, the `[originLevel2](https://docs.coveo.com/en/1338/)` value must be identical to the `tab` value in the request body of the corresponding query to the Search API. If there are no tabs in your search interface, you can reuse the `searchHub` value (in other words, you can use the same value for `originLevel1` and `originLevel2`). > **Important** > > Coveo ML ART models use the `originLevel2` value as a default filter field. > Filters don't affect how Coveo ML models learn, but they must be logged correctly for recommendations to work. > When Coveo ML models make suggestions, items which don't meet the right filters are ignored. ```json { ... "originLevel2": "All", ... } ``` ### `outcome` (integer from `-5` to `5`) An indication of the quality of the outcome of this event. A value of `-5` corresponds to the worst possible outcome, a value of `0` corresponds to a neutral outcome, and a value of `5` corresponds to the best possible outcome. The `outcome` property will eventually be leveraged by the Coveo ML service. ```json { ... "outcome": 0, ... } ``` ## Optional request body properties The following properties are entirely optional when logging search events. Although they're not leveraged by the Coveo ML service, specifying values for these properties can be useful for reporting. ### `advancedQuery` (string) The original advanced query expression (`aq`) in the corresponding search request. Maximum: 3000 characters. If specified, the `advancedQuery` value must be the same as the [advanced query expression (`aq`)](https://docs.coveo.com/en/175/) value of the corresponding search request to the Search API. ```json { ... "advancedQuery": "(@objecttype==('Developer Guide', 'Developers Topic'))", ... } ``` ### `contextual` (Boolean) Indicates if the query is modified by contextual filters (for instance, a query to find similar documents). ### `indexId` (string) The unique name of the index that the search query is performed against. Can be specified if there's one or more indexes in an organization. ```json { ... "indexId": "coveodev-4rroj2cd-Indexer-1-qxqvk5o55uduzhgsqggfz6smv4", ... } ``` ### `originContext` (string) The origin of the event. This is used to specify the deployment from which the user performs the action. Maximum: 128 characters. Suggested values are `Search`, `InternalSearch`, `CommunitySearch`, or the `originLevel1` value. ```json { ... "originContext": "CommunitySearch", ... } ``` ### `[originLevel3](https://docs.coveo.com/en/1339/)` (string) The URL of the page that redirected the browser to the search interface from which the search event originates (that is, `document.referrer`). Maximum: 128 characters. ```json { ... "originLevel3": "https://connect.coveo.com/s/search/All/Home/%40uri", ... } ``` ### `queryPipeline` (string) The name of the [query pipeline](https://docs.coveo.com/en/180/) which processed the query that caused the search interface to log a search event. Maximum length of 128 characters. If specified, the `queryPipeline` value takes precedence over the one defined in the search token [`pipeline`](https://docs.coveo.com/en/56#pipeline-string-optional) parameter. If specified, the `queryPipeline` value must be the same as the `pipeline` value in the request body of the corresponding query to the Search API. > **Important** > > When performing [A/B testing](https://docs.coveo.com/en/3255/), it's mandatory to include the `queryPipeline` in the usage analytics event. ```json { ... "queryPipeline": "External Search", ... } ``` ### `splitTestRunName` (string) The name of the [A/B test](https://docs.coveo.com/en/3255/) to run, if one is active. Maximum: 128 characters. ```json { ... "splitTestRunName": "splitTest", ... } ``` ### `splitTestRunVersion` (string) The version of the A/B test to run, if one is active. Maximum: 128 characters. ```json { ... "splitTestRunVersion": "splitTestRunAlpha", ... } ``` ### `trackingId` (string) The value to identify which web property an event is related to. This is a human-readable name you can use when sending analytics events. ```json { ... "trackingId": "online_store", ... } ``` ### `userDisplayName` (string) The display name of the user performing the search event. Maximum: 128 characters. If `userDisplayName` isn't specified and the request is authenticated with a search token, the service tries to extract the `userdisplayName` value from the access token that authenticated the request to log a search event. ```json { ... "userDisplayName": "Alice", ... } ``` ### `userGroups` (string array) The groups that the end user performing the event is a member of. If the request is authenticated with a search token, the service also tries to extract the `userGroups` value from the access token that authenticated the log search event request, and logs those groups as well. ```json { ... "userGroups": ["Employee"], ... } ``` ## Search event `customData` (key-value pairs) These are custom key-value pairs which can contain all of the user-defined [dimensions](https://docs.coveo.com/en/258/) and their values, and which can be used for reporting or learning. * The `customData` section must be valid JSON. * When possible, use a string as the value. * The value can be any valid JSON, but it's handled as string over [Coveo Analytics](https://docs.coveo.com/en/182/), and the string conversion could result in the alteration of the original JSON. Keys may only contain alphanumeric or underscore characters, and all spaces in the keys are replaced with underscores. Any uppercase characters in the keys are converted to lowercase characters. **Examples** * `"key" : "value"` → This is the recommended format for [Coveo Analytics](https://docs.coveo.com/en/182/), which renders the string as `"value"` and makes it usable as any other string [dimension](https://docs.coveo.com/en/258/) type. * `"key" : [ "value_1", "value_2" ]` → This becomes the string `"[ "value_1", "value_2" ] "` within [Coveo Analytics](https://docs.coveo.com/en/182/). Although it's harder to use for reporting, this value could still be useful (for example, when using the filter `"contains"` type). * We recommend that you [create your custom dimension](https://docs.coveo.com/en/1522/) before adding `customData`. * Any [field](https://docs.coveo.com/en/200/) beginning with `context_` will be used by [Coveo Machine Learning (Coveo ML)](https://docs.coveo.com/en/188/) as user [context](https://docs.coveo.com/en/1345/) to learn and provide boosts to contextually relevant [items](https://docs.coveo.com/en/210/). * When logging a search event which involved a [large query expression (`lq`)](https://docs.coveo.com/en/214/), you can optionally include, as a custom data [field](https://docs.coveo.com/en/200/), the `refinedKeywords` (string array) returned by the Search API. These `refinedKeywords` are extracted from `[`lq`](https://docs.coveo.com/en/214/)` by the [Coveo ML](https://docs.coveo.com/en/188/) [Intelligent Term Detection (ITD)](https://docs.coveo.com/en/207/) feature. Although they aren't used by [Coveo ML](https://docs.coveo.com/en/188/) to learn, the `refinedKeywords` will be available for reporting. **Example** Case deflection (which involved `lq`) ```json { ... "customData":{ "context_usertype" : "User", "refinedKeywords": ["issue", "making", "request", "403", "api"] }, ... } ```