---
title: Headless tracking
related:
  - https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md
  - https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/contact-configuration.md
  - https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities.md
  - https://docs.kentico.com/documentation/developers-and-admins/data-protection/consent-management.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

> **License:** Advanced license required.
>
> Features described on this page require the Xperience by Kentico **Advanced** license tier.

Websites running in Xperience by Kentico can [track visitors as contacts](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/contact-configuration.md) and [log their activities](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities.md). Headless tracking allows you to extend these features to the audience of other content channels, such as mobile apps, external services, single-page applications, etc. Xperience then serves as a central hub where you can monitor contacts and analyze activities for all connected websites and channels.

For example, headless tracking is suitable for applications that retrieve and display content from Xperience through [headless channels](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md).

> **Info:** **Relationship of headless channels and tracking**
>
> Applications where you wish to use headless tracking must be represented in Xperience by a [headless channel](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md).
>
> The channel allows you to [manage headless content](https://docs.kentico.com/documentation/business-users/headless-content.md) and [retrieve it via the GraphQL API](https://docs.kentico.com/documentation/developers-and-admins/development/content-retrieval/retrieve-headless-content.md). However, content retrieval is not a prerequisite, and you can use headless tracking in external applications that do not retrieve content from Xperience. For example, if you have an Xperience website channel and a mobile app that loads content from a different source, you can use headless tracking to synchronize the app's user activity with your contacts in Xperience.

Headless tracking works as a REST API. The Xperience application provides endpoints to which you send HTTP requests from your external applications.

> **Info:** **Prerequisite**
>
> Make sure the `Enable` and `EnableTracking` configuration keys or options are enabled for your Xperience application. See [Configure the headless API](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md#configure-the-headless-api) for details.

The following steps outline the typical process for setting up headless tracking in an external application:

- [Ensure authentication and CORS for your requests](#authentication-and-cors)
- [Display one or more tracking consents from Xperience to your application's users](#get-the-text-of-consents-from-xperience)
- [Allow users to accept or revoke the consents](#add-or-revoke-a-consent-agreement)
- For users who have given a consent agreement to be tracked:
  - [Create contacts in Xperience to represent individual users](#create-contacts)
  - [Log activities for the contacts](#log-activities)
    - Use the _Data input_ [activity](#log-activities) to send or update information about contacts
    - You can set up [custom activity types](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities/custom-activities.md) for any actions that you wish to track in your application.

## Authentication and CORS

To authenticate headless tracking requests, you need to:

1. Set up a [headless channel](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md) in Xperience.
2. Create at least one [API key](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md#manage-api-keys) with the **[Access type](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md#access-types-of-api-keys)** set to _Tracking API_.

For each tracking API request, add the [Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) header containing an **enabled tracking API key**.

```text title="HTTP Authorization header"
Authorization: Bearer <ApiKey>
```

> **Note:** **Authorizaton header security recommendations**
>
> If you set the _Authorization_ header directly when sending requests from a client API on a public web page, it can be seen by anyone. To ensure the security of your API keys, we recommend that you use a backend proxy server to add the _Authorization_ header and forward the requests to a headless tracking API endpoint.

If sending tracking requests directly from the client-side code of a web application (without additional header processing on a proxy server), you also need to ensure [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).

Follow the instructions in [Cross-origin resource sharing](https://docs.kentico.com/documentation/developers-and-admins/development/content-retrieval/retrieve-headless-content.md#cross-origin-resource-sharing) — the CORS configuration options are shared for headless tracking endpoints and headless channel GraphQL endpoints.

## Get the text of consents from Xperience

To comply with [data protection regulations](https://docs.kentico.com/documentation/developers-and-admins/data-protection.md), most applications can only collect personal data and track activities for users who explicitly give consent.

Set up your [consents](https://docs.kentico.com/documentation/developers-and-admins/data-protection/consent-management.md) in Xperience, and retrieve their text by sending requests:

- **HTTP method**: GET
- **Endpoint**: /Kentico.Tracking/consents/{consent\_code\_name}?languageName={language\_code\_name}
- **URI example**: https://domain.com/Kentico.Tracking/consents/TrackingConsent?languageName=en
- **Response body**: Consent text strings in the `shortText` and `fullText` fields

  ```json
  {
      "shortText": "...",
      "fullText": "..."
  }
  ```

  > **Info:** **Consent text format**
  >
  > The returned consent text strings contain HTML tags – text formatting elements, `<p>` tags for paragraphs, etc.

Create an appropriate UI in your application that displays the retrieved texts and allows users to give consent agreements.

## Create contacts

Your application's users are represented as [contacts](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-management.md) in Xperience. When a user gives consent to be tracked, you can create a new contact in Xperience by sending the following request:

- **HTTP method**: POST
- **Endpoint**: /Kentico.Tracking/contacts
- **Response body**: GUID of the new contact in the `contact` field

  ```json
  {
      "contact": "06b035b8-6658-4a1b-b1de-5994e4975fb1"
  }
  ```

The returned contact GUID is an identifier that you need to **store in your application**. Link the identifier with any other data that you have about the user. This allows you to keep track of the user in your application, identify them whenever they return, and pair them with the same contact.

The GUID is a required parameter whenever you need to [manage the contact's consent agreements](#add-or-revoke-a-consent-agreement) or [log activities](#log-activities).

## Add or revoke a consent agreement

To add or revoke a [consent agreement](#get-the-text-of-consents-from-xperience) for a [contact](#create-contacts), send the following request:

- **HTTP method**: POST
- **Endpoint**: /Kentico.Tracking/contacts/{contact\_guid}/consents/{consent\_name}
- **URI example**: https://domain.com/Kentico.Tracking/contacts/06b035b8-6658-4a1b-b1de-5994e4975fb1/consents/TrackingConsent
- **Request headers**: The [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) header must be set to _application/json_.
- **Request body**: Set the `agree` field to `true` (agree) or `false` (revoke)

  ```json
  {
      "agree": true
  }
  ```

## Check whether a contact has given a consent agreement

To check whether a [contact](#create-contacts) currently has a valid agreement for a [consent](#get-the-text-of-consents-from-xperience), send the following request:

- **HTTP method**: GET
- **Endpoint**: /Kentico.Tracking/contacts/{contact\_guid}/consents/{consent\_name}
- **URI example**: https://domain.com/Kentico.Tracking/contacts/06b035b8-6658-4a1b-b1de-5994e4975fb1/consents/TrackingConsent
- **Response body**: `true` or `false` value in the `isAgreed` field

  ```json
  {
      "isAgreed": true
  }
  ```

## Log activities

The headless tracking API allows you to log the following types of [activities](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities.md):

- **Page visit** – represents a single view of a "page" in your application.
- **Click** – represents a "click" action performed by a user.
- **Data input** – allows you to update the data of [contacts](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-management.md) using information submitted by the user.
- [Custom activity types](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities/custom-activities.md) – can represent any action that you wish to track.

> **Note:** The headless endpoint for activity logging does not automatically evaluate whether the specified contact has given consent to be tracked. Such conditions need to be implemented on the side of your external application before you log activities (see [Check whether a contact has given a consent agreement](#check-whether-a-contact-has-given-a-consent-agreement)).

Log activities by sending the following requests:

- **HTTP method**: POST
- **Endpoint**: /Kentico.Tracking/activities
- **Request headers**: The [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) header must be set to _application/json_.
- **Request body**:
  - `channel` – the GUID identifier of the [headless channel](https://docs.kentico.com/documentation/developers-and-admins/configuration/headless-channel-management.md) under which the activity will be logged.

    - Find the identifier in the Xperience administration: **Channel management** → edit channel → **General** → **Channel identifier for Tracking API**
    - The identifier must match the parent channel of the API key used to [authenticate](#authentication-and-cors) the logging request.
  - `contact` – the GUID of the contact who performed the activity (see [Create contacts](#create-contacts)).
  - `activities` – an array of activity objects. You can log any number of activities within a single request. See below to learn about the data structure of activity objects.

For each activity object in the `activities` array, set the following fields:

- `type` – the _code name_ of the activity type that you wish to log. Use the following values:

  - pagevisit
  - click
  - datainput
  - __ for custom activities
- `value` – a value logged with the activity. Required for _Click_ and _Data input_ activities.
- `url` – optional for all activity types (except _Page visit_). Currently not displayed in the activity log within the Xperience administration.
- `referrer` – an optional [URL referrer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) value. Currently not displayed in the activity log within the Xperience administration.

Additionally, individual activity types have additional requirements:

| Activity type     | Instructions                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Page visit        | The `url` field is required for page visit activities (for potential use in [Contact group](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-groups.md) conditions).<br>Set the `value` field to the title/name of the visited page.<br>The title of the resulting activity is in format: _Page visit ''_                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| Click             | The `Value` field is required for _Click_ activites. We recommend setting the value to the name, label or identifier of the clicked UI element.<br>The title of the resulting activity is in format: _Clicked ''_                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| Data input        | Populate `contactFields` with a JSON object containing fields matching the names of contact fields that you wish to set. The following contact fields are available:<br>**ContactEmail**<br>Note: For security reasons, the _Data input_ activity cannot be used to change a contact's existing email value. If the contact already has an email address stored in Xperience that doesn't match the new email value, the _Data input_ activity and all related field updates are performed for a different contact. Either an existing contact that matches the submitted email value is used, or a new contact is created.<br>**ContactFirstName**<br>**ContactMiddleName**<br>**ContactLastName**<br>**ContactBirthday**<br>**ContactMobilePhone** (_Private phone_ in the Xperience _Contact management_ application)<br>**ContactBusinessPhone**<br>**ContactCompanyName**<br>**ContactJobTitle**<br>**ContactAddress1**<br>**ContactCity**<br>**ContactZIP**<br>**ContactCountry** (accepts [3 letter ISO country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3))<br>**ContactState** (accepts 2 letter state codes, currently only [USA state codes (ANSI)](https://en.wikipedia.org/wiki/List_of_U.S._state_and_territory_abbreviations) are supported)<br>**ContactNotes**<br>Only `string` values are supported for the contact fields.<br>The `value` field is required for _Data input_ activities. For example, you can set the value to describe the source of the contact data.<br>The title of the resulting activity is in format: _Data input ''_<br>You can view the collected contact data in the Xperience **Contact management** application and use it to build [contact group](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-groups.md) conditions. |
| Custom activities | The `type` field must match the **Code name** of an enabled [custom activity type](https://docs.kentico.com/documentation/developers-and-admins/digital-marketing-setup/set-up-activities/custom-activities.md).<br>The title of the resulting activity is the custom activity type's name, followed by _''_ if the `value` field was specified.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

```json title="Request body example"
{
    "channel": "a3f4bc8b-6d84-454f-8215-cbec70bfaadd",
    "contact": "06b035b8-6658-4a1b-b1de-5994e4975fb1",
    "activities": [
        {
            "type": "pagevisit",
            "url": "https://example.com/mypage"
        },
        {
            "type": "click",
            "value": "MyClickableElement"
        },
        {
            "type": "datainput",
            "value": "Registration form",
            "contactFields": 
            {
                "ContactFirstName": "Luke",
                "ContactLastName" : "Smith",
                "ContactEmail" : "lsmith@domain.com"
            }
        },
        {
            "type": "custom_loan_calculator",
            "value": "5000"
        }
    ]
}
```

Activity logging requests return an [HTTP 207 Multi-Status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/207) response. The response body contains a `results` array where you can find the HTTP status code for individual submitted activities.

```json title="Response example"
{
    "results": [
        {
            "status": 202,
        },
        {
            "status": 202
        }
    ]
}
```
