Skip to main content

Custom data

Custom data is one of the most powerful features offered by the Kameleoon platform. It allows for easy association of any type of data with each visitor, which can be utilized for a variety of purposes, such as building advanced targeting segments for A/B tests and personalizations based on this data, as well as filtering experiment and personalization reports by any value stored in this data.

Examples of custom data can include a wide range of information, such as age, previous purchases, current cart amount, and favorite category. Typically, custom data is closely tied to the specificities of a given business. For example, if you operate a marketplace website, you may want to create custom data that indicates whether a particular visitor is primarily a "buyer" or a "seller".

Despite the fact that custom data is primarily intended to be used in the context of a single visit, it is by default historized, meaning that its lifespan is not limited to the JavaScript environment of the current page, as is often the case with Tag Managers / Data Layers. This unlocks the possibility of implementing truly advanced use cases.

This article serves as a general guide for learning more about custom data and how to use it effectively. If you're interested in creating custom data within the Kameleoon platform, you can refer to the following user guide.

Technical Overview

Once a custom data value is set, it is stored locally on your server or on the user's device, depending on whether you use a server-side SDK or a client-side SDK, including our application file (kameleoon.js), rather than retrieving it from a remote Kameleoon server.This means that the data can be retrieved later in subsequent page views of the same visit, or in future visits. When Kameleoon is loaded, any custom data that has been written at some point will be automatically available for use later, either through the Activation API or our SDKs.


If you use Kameleoon Web Experimentation, our LocalStorage implementation is unified, which means that user journeys spanning multiple domains are automatically handled by Kameleoon as long as you follow our implementation guidelines for unified session data across subdomains. Kameleoon also takes care of saving and loading custom data, as well as handling complex issues such as concurrent access from multiple tabs on the same website.

Any value set for a custom data can also be sent to our data collection servers as part of the standard Kameleoon tracking process. This serves three purposes:

  1. The data is available for reporting purposes.
  2. The data can be used as input for our machine learning algorithms for AI Predictive Targeting.
  3. The data is stored on our backend servers and can be retrieved using our Data API.

Unfortunately, the latest version (2.3) of Intelligent Tracking Prevention (ITP) restrictions on Safari browsers clear the LocalStorage after 7 days. This means that if a returning visitor comes back after 7 days, additional synchronization server calls to retrieve the content of custom data cannot be avoided on Safari. However, we optimize these calls and only make them if necessary (i.e., if the 7-day period has elapsed). For more information about our solution, please see this article on ITP management.

General characteristics

When creating a custom data in the Kameleoon platform, you must provide several characteristics for it. These are documented below.


Custom data can have one of three types: Boolean, Number, or String of characters. Additionally, a custom data can be a list of values, such as all the categories of products seen by a visitor, or even a counted list. A counted list is a list of different values with a count of how many times each particular value was set. For example, a custom data that represents the list of categories seen by a visitor, along with how many times these categories were seen, should use a counted list.

Kameleoon.API.CurrentVisit.customData["visitedCategories"] == [{"value": "Computers", "count": 3}, {"value": "Phones", "count": 1}, {"value": "Games", "count": 7}]; // example of a Counted List custom data


The scope of a custom data is also important, with three possible values: PAGE, VISIT or VISITOR:

  • (Only applies for web experiments and personalizations) Custom data with a PAGE scope is only valid for the current page and is reset on the next page view, which can have consequences for targeting purposes.
  • Custom data with a VISIT scope retains its value for the duration of the visit but is reset on the next visit.
  • Custom data with a VISITOR scope is set forever and should be used for information that is constant or changes infrequently for a visitor/customer. To access this data via the Activation API, use Kameleoon.API.Visitor.customData.

For GDPR compliance, any data collected by Kameleoon has a maximum lifespan of 365 days and is automatically deleted when the Kameleoon application code is loaded. If a visitor returns after more than 365 days, the local storage data is erased, and the visitor is considered a new visitor.


If there is a risk that a custom data value may be obtained after Kameleoon's initialization and the associated first targeting execution, it is usually recommended to set the scope to PAGE. Without this, the current custom data value may be "late" and cause targeting problems, especially when running an experiment that targets visitors browsing a category page but moves to a product page, obtaining a new value only after a few seconds. With a scope of PAGE, this issue would not occur.


Stored only in LocalStorage

Enabling this option stores the custom data value solely on the user's device via LocalStorage and never transmits it to our servers. This feature can be beneficial for privacy or legal reasons. Some customers may require that sensitive data is not stored outside their IT systems, but still wish to personalize the visitor's experience based on that data.


Custom data should not be used to store sensitive information about your visitors, as this information can be retrieved from our servers by anyone who has access to the corresponding Kameleoon visitorCode.

Machine Learning Input

Enabling this option will allow our machine learning algorithms to use this custom data as an input. This feature is only available if you have subscribed to the AI Predictive Targeting add-on.

Cross-device history reconciliation

Enabling this option ensures consistency in variation allocation and cross-device history reconciliation. This means that a visitor will see the same variation for a given experiment even if they switch between devices. You can learn more about this feature in this article.

Acquisition Methods

Kameleoon offers various integrations out of the box, which are detailed below.

Data layers

These methods directly retrieve the value of the custom data from a given variable in the data layer for Google Tag Manager, Tealium, or Commander's Act. You only need to specify the name of the variable in your usual data layer, and integration is automatically done as soon as the data layer is loaded on your page.


We support several levels of hierarchy, as well as array variables in the data layer. For example, you can fetch a value from, cart["amount"] or purchases[3].


Kameleoon can set the custom data value only after the data layer is available on your page. As this can take several seconds (depending on when you load your tag manager), if you use the custom data as a targeting condition in an A/B test, a noticeable flicker effect can occur.

Activation API

Using our Activation API is the recommended way of setting custom data values on the browser (client-side environment). You can directly locate a particular DOM element on the page and get its content as the value for the custom data. This way, you can obtain the current cart amount value if it is displayed on the web page and fill the corresponding custom data accordingly.


The Kameleoon.API.Data.setCustomData() method always overwrites previous existing values for the custom data, except if the type is a List or Counted List, and the third argument is false, in which case it adds to the existing list.

Custom Code

This option allows you to write ad hoc custom JavaScript code. The main rule to follow when setting a custom data is that your code should return an object with two keys:value with the value you want to provide for this custom data and (optionally) override with a boolean value (false by default).

If you don't have any value to provide for this custom data yet but will obtain it later on this page, don't return any value (you can also return null or undefined). Your code will be executed again (every 100 ms for the first 3 seconds after the first invocation, then every 3 seconds). By convention, returning {"value": null} will not set the custom data but will stop the regular execution of your code.

The first execution of your code takes place before the Kameleoon targeting system is triggered, giving you the chance to set up your custom data before targeting is executed.

if (! window.myObject) return null; // custom data will not be set, but code will re-run later

if (window.myObject) return {"value": window.myObject.x, "overwrite": true}; // returning a value and setting the custom data

if (window.someObject.value == 3) return {"value": null} // stopping the periodic execution of the code, without setting the custom data

We advise against using this acquisition method if possible. It is preferable to write your JavaScript code in a different location, such as Tag Manager, an external script file, or inline script code in the HTML code, and then use the Activation API acquisition method to set the custom data.

SDK method

You need to use the SDK method addData(), which is documented in all of our SDKs. For more technical considerations regarding this method, please refer to this article.

Data API / Server to Server integration

If you are looking to set up a server to server integration, our Data API is the recommended approach. This involves implementing a REST call to our servers, where you will specify the custom data name and value, as well as the visitorCode.

Using Custom Data

Targeting condition for segments

Kameleoon segment builder will automatically add targeting conditions for any custom data that you define. Everything is done automatically here, and if the value of the custom data corresponds to your condition, this particular visitor will be included in the segment.

Via the Activation API

You can obtain the current value of a custom data via Kameleoon.API.CurrentVisit.customData (PAGE or VISIT scopes) or Kameleoon.API.Visitor.customData (VISITOR scope).

Via one of our SDKs

You can use the getRemoteVisitorData() method to retrieve all custom data collected during the previous visit by the current visitor.

Analytical Purposes

Any custom data (except those marked as local only) can be used as a filter or a breakdown option in our experiment or personalization result pages. Additionally, this information is also available in reports produced by our raw data export tool, and complex queries including those custom data can be performed (if you opted for a dedicated Kameleoon data cluster).

For a breakdown with a String type custom data, the results will be broken down with a maximum of 50 possible values for this custom data. The 50 most frequently used values for the custom data are used.

For a breakdown with a Number type custom data, the results will also be broken down with a maximum of 50 possible values. In the case of numerical custom data, this does not always make sense.

Advanced Settings

Implement a custom select box component for the targeting condition associated with this custom data

This feature simplifies the selection of custom data values in targeting conditions by presenting them in a select box instead of a plain text field. This makes it much easier for end-users to choose the appropriate value for targeting. There are two important points to consider:

  • Raw values can be associated with descriptive labels.
  • The labels and values are obtained dynamically when the targeting condition interface is displayed.

This feature is especially useful for integrating with third-party data providers like DMPs or CRMs. For example, if the custom data represents an external segment from a DMP, the user can select "Loyal customers" instead of the internal ID, which is usually a complex string of characters like "8ney4225y65a". The list of defined segments in the DMP is always up-to-date on Kameleoon's interface, so this feature handles the synchronization automatically.


The labels associated with custom data are only visible to users who have access to the Kameleoon platform. They are not included in the JavaScript application file, so website visitors will not be able to view them. The process remains transparent and hidden from the user's perspective.

To implement this feature for a specific custom data, you need to provide JavaScript code that will return an array of objects representing the possible values along with their labels synchronously. The array must meet the following requirements:

  • All elements in the array should be JavaScript objects.
  • These objects should have two keys: a value key (containing the actual possible value for the custom data), and a label key (representing the textual description for this particular value).
  • The content type for the value key should correspond to the actual type of the custom data. For the label key, you should provide a string as content.

Check out the code sample below for an example of how this feature can be used in practice. In this example, a remote call is made to a third-party server (usually a DMP or similar platform) that provides the list of available segments defined on the platform. It's important to note that this code is only used to build the selection interface for the Kameleoon end-user.

var xhr = new XMLHttpRequest();"GET", "", false);

var segments = [];
xhr.onreadystatechange = function() {

if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
var data = JSON.parse(xhr.response); (segment) {
if (segment.segment_uuid && !== "undefined") {
segments.push({"label":, "value": segment.segment_uuid});

return segments;

It is important that your code runs synchronously and returns its value with a blocking behavior. It is advised to avoid any asynchronous remote server calls, as this may cause the feature to malfunction.