Android SDK
With the Kameleoon Android SDK, you can run activate feature flags on native mobile Android applications. The Android SDK is compatible with both Kotlin and Java. The SDK is easy to integrate into your applications, and its memory and network usage are low.
Getting started: For help getting started, see the developer guide.
Changelog: Latest version of the Android SDK: 4.5.0 Changelog
SDK methods: For the full reference documentation of the Android SDK methods, see the reference section.
Developer guide
Follow this section to install and configure the Android SDK in your Android app as well as learn about advanced features.
Getting started
Follow these steps to install and configure the Kameleoon Android SDK in your application for the first time.
Installation
You can install the Android SDK by adding the following dependency to the build.gradle
file in your Android app:
dependencies {
implementation 'com.kameleoon:kameleoon-client-android:4.5.0'
}
Additional configuration
To customize the SDK behavior, create a .properties
configuration file. The name and location of the properties file are important:
- Create the file in the
assets/
directory of your app. - Name the file
kameleoon-client.properties
.
You can also download a sample configuration file.
These are the available properties that you can set:
refresh_interval_minute
(optional): Specifies the frequency, in minutes, that active experiments and feature flags are fetched from the Kameleoon servers. The initial fetch is performed on the first application launch and subsequent fetches are processed at the defined refresh interval. Once you launch an experiment, pause the experiment, or stop the experiment, the change won't propagate to each of your visitors' iOS devices until their next refresh. This means if you set the refresh interval to 30 minutes, it may take up to 30 minutes before all devices receive the update. If not specified, the default interval is 60 minutes.data_expiration_interval_minute
(optional): Designates the predefined time period, in minutes, that the SDK stores the visitor and their associated data. Each data instance is evaluated individually. This allows you to set the amount of time the SDK saves the data before automatically deleting it. If no interval is specified, the SDK does not automatically delete data from the device. The default value isInteger.MAX_VALUE
.default_timeout_millisecond
(optional): Specifies the time interval, in milliseconds, that it takes for network requests from the SDK to time out. Set the value to 30000 milliseconds (30 seconds) or more if you do not have a stable connection. The default value is 10000 milliseconds. Some methods have additional parameters for method-specific timeouts, but if you do not specify them explicitly, the default value is used.tracking_interval_millisecond
(optional): Specifies the interval for tracking requests, in milliseconds. All visitors who were evaluated for any feature flag or had data flushed will be included in this tracking request, which is performed once per interval. The minimum value is100
ms and the maximum value is1000
ms, which is also the default value.environment
(optional): For customers using multi-environment feature flagging, this option specifies which feature flag configuration to use. By default, each feature flag has the optionsproduction
,staging
,development
. If not specified, the default value isproduction
. More informationis_unique_identifier
(optional): Indicates that the specifiedvisitorCode
is a unique identifier. If not provided, the default value is false.
If you specify a visitorCode
and set the isUniqueIdentifier
parameter to true
, the SDK methods use the visitorCode
value as the unique visitor identifier, which is useful for cross-device experimentation. The SDK links the flushed data with the visitor that is associated with the specified identifier.
The isUniqueIdentifier
can be useful in other edge-case scenarios, such as when you can't access the anonymous visitorCode
that was originally assigned to the visitor, but you do have access to an internal ID that is connected to the anonymous visitor using session merging capabilities.
Initialize the Kameleoon Client
After installing the SDK in your application and setting up the app properties, the next step is to create the Kameleoon Client. A Client is a singleton object that acts as a bridge between your application and the Kameleoon platform. It includes all the methods and properties you need to run an feature flag.
- Java
- Kotlin
import com.kameleoon.KameleoonClient;
import com.kameleoon.KameleoonClientFactory;
public class MyApplication extends Application
{
private KameleoonClient kameleoonClient;
@Override
public void onCreate() {
super.onCreate();
try {
KameleoonClientConfig config = new KameleoonClientConfig.Builder()
.refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
.defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
.trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
.dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
.environment("staging") // optional
.isUniqueIdentifier(false) // false by default, optional
.build();
String siteCode = "a8st4f59bj";
String visitorCode = "yourVisitorCode";
kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
// or if you want that visitor code will be generated automatically
kameleoonClient = KameleoonClientFactory.create(siteCode, config, getApplicationContext());
} catch (SiteCodeIsEmpty | VisitorCodeInvalid exception) {
// Exceptions indicate that provided siteCode is empty or visitorCode is invalid
} catch (Throwable exception) {
// Any other error
}
}
public KameleoonClient getKameleoonClient() {
return kameleoonClient;
}
}
import com.kameleoon.KameleoonClient
import com.kameleoon.KameleoonClientFactory
class MyApplication : Application() {
var kameleoonClient: KameleoonClient? = null
private set
override fun onCreate() {
super.onCreate()
try {
val config = new KameleoonClientConfig.Builder()
.refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
.defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
.trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
.dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
.environment("staging") // optional
.build();
val siteCode = "a8st4f59bj"
val visitorCode = "yourVisitorCode"
kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext)
// or if you want that visitor code will be generated automatically
kameleoonClient = KameleoonClientFactory.create(siteCode, config, applicationContext);
} catch (e: SiteCodeIsEmpty, VisitorCodeInvalid) {
// Exceptions indicate that provided siteCode is empty or visitor code is invalid
} catch (e: Throwable) {
// Any other error
}
}
}
While executing, the KameleoonClientFactory.create()
method initializes the client, but it is not immediately ready for use. This is because the Kameleoon Client must retrieve the current configuration of feature flags (along with their traffic repartition) from a Kameleoon remote server. This requires network access, which is not always available. Until the Kameleoon Client is fully ready, you should not attempt to run other methods in the Kameleoon Android SDK. Note that once the first configuration of feature flags is fetched, it is then periodically refreshed, but even if the refresh fails for any reason, the Kameleoon client will continue to function using the previous configuration.
You can use the isReady()
method to check if the Kameleoon client initialization is finished.
Alternatively, you can use a helper callback to encapsulate the logic of feature flag triggering and variation implementation. The best approach (isReady()
or callback) depends on your own preferences and on the exact use case. As a rule of thumb, we recommend using isReady()
when you expect that the SDK will be ready for use. For example, when you are running an feature flag on a dialog that users likely wouldn't access for the first few seconds or minutes of navigating within the app. We recommend using the callback when there is a high probability that the SDK is still in the process of initialization. For example, an feature flag that would appear on screen at the application launch would be better suited to a callback that makes the application wait until either the SDK is ready or a specified timeout has expired.
It's your responsibility as the app developer to ensure the logic of your application code is correct within the context of A/B testing using Kameleoon. A good practice is to always assume that the application user can be left out of the feature flag when the Kameleoon client is not yet ready. This is easy to implement, because this corresponds to the implementation of the default or reference variation logic. The code samples in the next paragraph show examples of this approach.
You're now ready to implement feature management and features flags. See the Reference section for details about additional methods.
Activating a feature flag
Retrieving a flag configuration
To implement a feature flag in your code, you must first create the feature flag in your Kameleoon account.
To determine the status or variation of a feature flag for a specific user, you should use the getVariation()
or isFeatureActive()
method to retrieve the configuration based on the featureKey
.
The getVariation()
method handles both simple feature flags with ON/OFF states and more complex flags with multiple variations. The method retrieves the appropriate variation for the user by checking the feature rules, assigning the variation, and returning it based on the featureKey
and visitorCode
.
The isFeatureActive()
method can be used if you want to retrieve the configuration of a simple feature flag that has only an ON or OFF state, as opposed to more complex feature flags with multiple variations or targeting options.
If your feature flag has associated variables (such as specific behaviors tied to each variation) getVariation()
also enables you to access the Variation
object, which provides details about the assigned variation and its associated experiment. This method checks whether the user is targeted, finds the visitor’s assigned variation, and saves it to storage. When track=true
, the SDK will send the exposure event to the specified experiment on the next tracking request, which is automatically triggered based on the SDK’s tracking_interval_millisecond
. By default, this interval is set to 1000 milliseconds (1 second).
The getVariation()
method allows you to control whether tracking is done. If track=false
, no exposure events will be sent by the SDK. This is useful if you prefer not to track data through the SDK and instead rely on client-side tracking managed by the Kameleoon engine, for example. Additionally, setting track=false
is helpful when using the getVariations()
method, where you might only need the variations for all flags without triggering any tracking events. If you want to know more about how tracking works, view this article
Adding data points to target a user or filter / breakdown visits in reports
To target a user, ensure you've added relevant data points to their profile before retrieving the feature variation or checking if the flag is active. Use the addData()
method to add these data points to the user's profile.
To retrieve data points that have been collected on other devices, use the getRemoteVisitorData()
method. This method asynchronously fetches data from our servers. However, it is important you call getRemoteVisitorData()
before retrieving the variation or checking if the feature flag is active, as this data might be required to assign a user to a given variation of a feature flag.
To learn more about available targeting conditions, read our detailed article on the subject.
Additionally, the data points you add to the visitor profile will be available when analyzing your experiments, allowing you to filter and break down your results by factors like device. See the complete list here.
If you need to track additional data points beyond what's automatically collected, you can use Kameleoon's Custom Data feature. Custom Data allows you to capture and analyze specific information relevant to your experiments. Don't forget to call the flush()
method to send the collected data to Kameleoon servers for analysis.
Tracking goal conversions
When a user completes a desired action (such as making a purchase), it is recorded as a conversion. To track conversions, use the trackConversion()
method and provide the required goalId
parameter.
The conversion tracking request will be sent along with the next scheduled tracking request, which the SDK sends at regular intervals (defined by tracking_interval_millisecond
). If you prefer to send the request immediately, use the flush()
method with the parameter instant=true
.
Cross-device experimentation
To support visitors who access your app from multiple devices, Kameleoon allows you to synchronize previously collected visitor data across each of the visitor's devices and reconcile their visit history across devices through cross-device experimentation. We recommend reading our article on cross-device experimentation for more information on how Kameleoon handles data across devices and detailed use cases.
Synchronizing custom data across devices
Although custom mapping synchronization is used to align visitor data across devices, it is not always necessary. Below are two scenarios where custom mapping sync is not required:
Same user ID across devices
If the same user ID is used consistently across all devices, synchronization is handled automatically without a custom mapping sync. It is enough to call the getRemoteVisitorData()
method when you want to sync the data collected between multiple devices.
Multi-server instances with consistent IDs
In complex setups involving multiple servers (for example, distributed server instances), where the same user ID is available across servers, synchronization between servers (with getRemoteVisitorData()
) is sufficient without additional custom mapping sync.
Customers who need additional data can refer to the getRemoteVisitorData()
method description for further guidance. In the below code, it is assumed that the same unique identifier (in this case, the visitorCode
, which can also be referred to as userId
) is used consistently between the two devices for accurate data retrieval.
If you want to sync collected data in real time, you need to choose the scope Visitor for your custom data.
- Java
- Kotlin
// In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
final int VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90;
kameleoonClient.addData(new CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"));
kameleoonClient.flush();
// Before working with the data, call the `getRemoteVisitorData` method.
kameleoonClient.getRemoteVisitorData(result -> {
// After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
// So "your data" will be available for targeting and tracking for the visitor.
});
// In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
val VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90
kameleoonClient.addData(CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"))
kameleoonClient.flush()
// Before working with the data, call the `getRemoteVisitorData` method.
kameleoonClient.getRemoteVisitorData { result ->
// After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
// So "your data" will be available for targeting and tracking for the visitor.
}
Using custom data for session merging
Cross-device experimentation allows you to combine a visitor's history across each of their devices (history reconciliation). History reconciliation allows you to merge different visitor sessions into one. To reconcile visit history, you can use CustomData
to provide a unique identifier for the visitor. For more information, see our dedicated documentation.
After cross-device reconciliation is enabled, calling getRemoteVisitorData()
with the parameter userId
retrieves all known data for a given user.
Sessions with the same identifier will always be shown the same variation in an experiment. In the Visitor view of your experiment's results pages, these sessions will appear as a single visitor.
The SDK configuration ensures that associated sessions always see the same variation of the experiment. However, there are some limitations regarding cross-device variation allocation. We've outlined these limitations here.
Follow the activating cross-device history reconciliation guide to set up your custom data on the Kameleoon platform.
Afterwards, you can use the SDK normally. The following methods that may be helpful in the context of session merging:
getRemoteVisitorData()
with passedisUniqueIdentifier=true
toKameleoonClientConfig
- to retrieve data for all linked visitors.trackConversion()
orflush()
with passedisUniqueIdentifier=true
toKameleoonClientConfig
- to track some data for specific visitor that is associated with another visitor.
As the custom data you use as the identifier must be set to Visitor scope, you need to use cross-device custom data synchronization to retrieve the identifier with the getRemoteVisitorData()
method on each device.
Here's an example of how to use custom data for session merging.
- Java
- Kotlin
// In this example, `91` represents the index of the Custom Data
// configured as a unique identifier on Kameleoon Platform.
final int MAPPING_INDEX = 91;
final String FEATURE_KEY = "ff123";
// 0. Initializing anonymous KameleoonClient
// Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
KameleoonClient anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode);
anonymousKameleoonClient.runWhenReady(result -> {
// ...
});
// 1. Before the visitor is authenticated
// Retrieve the variation for an unauthenticated visitor.
Variation anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY);
// 2. After the visitor is authenticated
// Assume `userId` is the visitor code of the authenticated visitor.
anonymousKameleoonClient.addData(new CustomData(MAPPING_INDEX, userId));
anonymousKameleoonClient.flush(true);
KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
siteCode, userId,
(new KameleoonClientConfig.Builder())
.isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
.build()
);
userKameleoonClient.runWhenReady(result -> {
// ...
});
// 3. After the visitor has been authenticated
// Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
Variation userVariation = userKameleoonClient.getVariation(FEATURE_KEY);
boolean isSameVariation = userVariation.getKey().equals(anonymousVariation.getKey()); // true
// The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
kameleoonClient.trackConversion(123, 10.0);
// Also, the linked visitors will share all fetched remote visitor data.
kameleoonClient.getRemoteVisitorData(result -> {
// ...
});
// In this example, `91` represents the index of the Custom Data
// configured as a unique identifier on Kameleoon Platform.
val MAPPING_INDEX = 91
val FEATURE_KEY = "ff123"
// 0. Initializing anonymous KameleoonClient
// Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
val anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode)
anonymousKameleoonClient.runWhenReady { result ->
// ...
}
// 1. Before the visitor is authenticated
// Retrieve the variation for an unauthenticated visitor.
val anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY)
// 2. After the visitor is authenticated
// Assume `userId` is the visitor code of the authenticated visitor.
anonymousKameleoonClient.addData(CustomData(MAPPING_INDEX, userId))
anonymousKameleoonClient.flush(true)
val userKameleoonClient = KameleoonClientFactory.create(
siteCode, userId,
KameleoonClientConfig.Builder()
.isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
.build()
);
userKameleoonClient.runWhenReady { result ->
// ...
}
// 3. After the visitor has been authenticated
// Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
val userVariation = userKameleoonClient.getVariation(FEATURE_KEY)
val isSameVariation = userVariation.getKey() == anonymousVariation.getKey() // true
// The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
kameleoonClient.trackConversion(123, 10.0)
// Also, the linked visitors will share all fetched remote visitor data.
kameleoonClient.getRemoteVisitorData { result ->
// ...
}
In this example, we have an application with a login page. Since we don't know the user ID at the moment of login, we use an anonymous visitor automatically generated by SDK. Visitor code can be retrieved with getVisitorCode()
method. After the user logs in, we can associate the anonymous visitor with the user ID and use it as a unique identifier for the visitor.
Targeting conditions
The Kameleoon SDKs support a variety of predefined targeting conditions that you can use to target users in your campaigns. For the list of conditions this SDK supports, see use visit history to target users.
You can also use your own external data to target users.
Error Handling
Handling errors is considered a good practice to make your application more stable and avoid technical issues. Most KameleoonClient
methods can throw a KameleoonException
error.
Since it can be difficult to patch the SDK version on the Android client side, we recommended that you enclose every SDK method in a try
clause that catches the KameleoonException
as well as the Throwable
error type to prevent other fatal errors.
For example:
- Java
- Kotlin
try {
// Calling a method of the SDK
} catch (KameleoonException e) {
// Handling expected exceptions
} catch (Throwable e) {
// Any other error
}
try {
// Calling a method of the SDK
} catch (e: KameleoonException) {
// Handling expected exceptions
} catch (e: Throwable) {
// Any other error
}
Logging
The SDK generates logs to reflect various internal processes and issues.
Log levels
The SDK supports configuring limiting logging by a log level.
- Java
- Kotlin
// The `NONE` log level allows no logging.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE);
// The `ERROR` log level allows to log only issues that may affect the SDK's main behaviour.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR);
// The `WARNING` log level allows to log issues which may require an attention.
// It extends the `ERROR` log level.
// The `WARNING` log level is a default log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING);
// The `INFO` log level allows to log general information on the SDK's internal processes.
// It extends the `WARNING` log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO);
// The `DEBUG` log level allows to log extra information on the SDK's internal processes.
// It extends the `INFO` log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG);
// The `NONE` log level allows no logging.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE)
// The `ERROR` log level allows to log only issues that may affect the SDK's main behaviour.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR)
// The `WARNING` log level allows to log issues which may require an attention.
// It extends the `ERROR` log level.
// The `WARNING` log level is a default log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING)
// The `INFO` log level allows to log general information on the SDK's internal processes.
// It extends the `WARNING` log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO)
// The `DEBUG` log level allows to log extra information on the SDK's internal processes.
// It extends the `INFO` log level.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG)
Custom handling of logs
The SDK writes its logs to the console output by default. This behaviour can be overridden.
Logging limiting by a log level is performed apart from the log handling logic.
- Java
- Kotlin
public class CustomLogger implements com.kameleoon.logging.Logger {
// `log` method accepts logs from the SDK
@Override
public void log(com.kameleoon.logging.LogLevel level, String message) {
// Custom log handling logic here. For example:
switch (level) {
case ERROR:
android.util.Log.e("your-log-tag", message);
break;
case WARNING:
android.util.Log.w("your-log-tag", message);
break;
case INFO:
android.util.Log.i("your-log-tag", message);
break;
case DEBUG:
android.util.Log.d("your-log-tag", message);
break;
default:
}
}
}
// Log level filtering is applied separately from log handling logic.
// The custom logger will only accept logs that meet or exceed the specified log level.
// Ensure the log level is set correctly.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG); // Optional, defaults to `LogLevel.WARNING`.
com.kameleoon.logging.KameleoonLogger.setLogger(new CustomLogger());
class CustomLogger : com.kameleoon.logging.Logger {
override fun log(level: com.kameleoon.logging.LogLevel, message: String) {
// Custom log handling logic here. For example:
when (level) {
com.kameleoon.logging.LogLevel.ERROR -> android.util.Log.e("your-log-tag", message)
com.kameleoon.logging.LogLevel.WARNING -> android.util.Log.w("your-log-tag", message)
com.kameleoon.logging.LogLevel.INFO -> android.util.Log.i("your-log-tag", message)
com.kameleoon.logging.LogLevel.DEBUG -> android.util.Log.d("your-log-tag", message)
else -> {
// Optional: handle default case if needed
}
}
}
}
// Log level filtering is applied separately from log handling logic.
// The custom logger will only accept logs that meet or exceed the specified log level.
// Ensure the log level is set correctly.
com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG) // Optional, defaults to `LogLevel.WARNING`.
com.kameleoon.logging.KameleoonLogger.setLogger(CustomLogger())
Reference
This is the full reference documentation for the Kameleoon Android SDK.
Initialization
Once you have installed the SDK in your application, the first step is to initialize Kameleoon. All of your application's interactions with the SDK, such as triggering an experiment, are accomplished using this Kameleoon client object.
create()
Call this method before any others to initialize the SDK. This method is in com.kameleoon.KameleoonClientFactory
. Your app conducts all interactions with the SDK using the resulting KameleoonClient
object that this method creates.
You can customize the behavior of the SDK (for example, the environment, the credentials, and so on) by providing a configuration object. Otherwise, the SDK tries to find your configuration file and uses it instead.
- Java
- Kotlin
String siteCode = "a8st4f59bj";
try {
// pass client configuration and visitorCode as arguments
KameleoonClientConfig config = new KameleoonClientConfig.Builder()
.refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
.defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
.dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
.environment("staging") // optional
.build();
String visitorCode = "yourVisitorCode";
KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
} catch (SiteCodeIsEmpty | VisitorCodeInvalid exception) {
// Exception indicates that the provided siteCode is empty or the visitorCode is invalid
} catch (Throwable exception) {
// Any other error
}
try {
// generate visitorCode automatically and read client configuration from a file 'kameleoon-client.properties'
KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, getApplicationContext());
} catch (SiteCodeIsEmpty exception) {
// Exception indicates that the provided siteCode is empty or the visitorCode is invalid
} catch (Throwable exception) {
// Any other error
}
val siteCode = "a8st4f59bj"
try {
// pass client configuration and visitor code as arguments
val config = KameleoonClientConfig.Builder()
.refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
.defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
.dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
.environment("staging") // optional
.build();
val visitorCode = "yourVisitorCode"
val kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext);
} catch (e: SiteCodeIsEmpty) {
// Exception indicates that the provided siteCode is empty
} catch (e: VisitorCodeInvalid) {
// Exception indicate that the provided visitorCode is invalid
} catch (e: Throwable) {
// Any other error
}
try {
// generate visitorCode automatically and read client configuration from the 'kameleoon-client.properties' file
val kameleoonClient = KameleoonClientFactory.create(siteCode, applicationContext);
} catch (e: SiteCodeIsEmpty) {
// Exception indicates that the provided siteCode is empty
} catch (e: VisitorCodeInvalid) {
// Exception indicates that the provided visitorCode is invalid
} catch (e: Throwable) {
// Any other error
}
isReady()
For mobile SDKs, the Kameleoon Client can't initialize immediately as it needs to perform a server call to retrieve the current configuration for the active feature flags. Use this method to check if the SDK is ready by calling this method before triggering any feature flags.
Alternatively, you can use a callback (see the runWhenReady()
method for details).
- Java
- Kotlin
Boolean ready = kameleoonClient.isReady();
val ready = kameleoonClient.isReady
Return value
Type | Description |
---|---|
boolean | Boolean representing the status of the SDK. true if client is fully initialized and false if it is not yet ready to be used. |
runWhenReady()
For mobile SDKs, the Kameleoon Client can't initialize immediately as it needs to perform a server call to retrieve the current configuration for all active feature flags. Use the runWhenReady()
method of the KameleoonClient
class to pass a callback that will be executed as soon as the SDK is ready for use. It also allows you to set a timeout.
The callback given as the first argument to this method must be an instance of a class that implements the ResultCompletion<Boolean, TimeoutException>
interface. If the result.get()
equals true
, the Kameleoon client is ready and should contain code that triggers a feature flags and implements variations. Otherwise, the specified timeout will occur before the client is initialized. The callback should contain code that implements the reference variation, as the user will be excluded from the feature flag if a timeout occurs.
- Java
- Kotlin
kameleoonClient.runWhenReady(1000, result -> {
int variationID;
int recommendedProductsNumber;
try {
if (result.get().equals(true)) {
variationID = kameleoonClient.getFeatureVariationKey("featureKey");
} else {
variationID = 0;
}
} catch (Throwable exception) {
// The user will not be included in the experiment results and should see the reference variation
variationID = 0;
}
if (variationID == 0) {
// This is the default / reference number of products to display
recommendedProductsNumber = 5;
}
else if (variationID == 148382) {
// We are changing number of recommended products for this variation to 10
recommendedProductsNumber = 10;
}
else if (variationID == 187791) {
// We are changing number of recommended products for this variation to 8
recommendedProductsNumber = 8;
}
applyVariation();
});
private void applyVariation()
{
mTextMessage.setText("Number of recommended products displayed: " + recommendedProductsNumber + " product");
}
client.runWhenReady(1000) { result ->
var variationID = 0
var recommendedProductsNumber = 0
variationID = try {
if (result.get().equals(true)) {
variationID = kameleoonClient.getFeatureVariationKey("featureKey");
} else {
variationID = 0;
}
} catch (exception: Exception) {
// The user will not be included in the experiment results and should see the reference variation
variationID = 0;
}
when (variationID) {
0 -> {
// This is the default / reference number of products to display
recommendedProductsNumber = 5
}
148382 -> {
// We are changing number of recommended products for this variation to 10
recommendedProductsNumber = 10
}
187791 -> {
// We are changing number of recommended products for this variation to 8
recommendedProductsNumber = 8
}
}
applyVariation()
}
private fun applyVariation() {
mTextMessage!!.text = "Number of recommended products displayed: $recommendedProductsNumber products."
}
Feature flags and variations
isFeatureActive()
- 📨 Sends Tracking Data to Kameleoon (depending on the
track
parameter)
This method was previously named activateFeature
, which was removed in SDK version 4.0.0
release.
To activate a feature toggle, call this method. This method accepts a featureKey
as required argument to check if the specified feature will be active for a visitor.
If the visitor has never been associated with this feature flag, this method returns a random boolean value (true
if the visitor should be shown this feature, otherwise false
). If the visitor is already registered with this feature flag, this method returns the previous featureFlag
value.
Make sure to set up proper error handling as shown in the example code to catch potential exceptions.
- Java
- Kotlin
String featureKey = "new_checkout";
try {
hasNewCheckout = kameleoonClient.isFeatureActive(featureKey);
// disabling tracking
hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false);
} catch (SDKNotReady e) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (FeatureNotFound e) {
// SDK not initialized or feature toggle not yet activated on Kameleoon's side - we consider the feature inactive
} catch (Throwable exception) {
// Any other error
}
if (hasNewCheckout)
{
// Implement new checkout code here
}
val featureKey = "new_checkout"
var hasNewCheckout = false
try {
hasNewCheckout = kameleoonClient.isFeatureActive(featureKey)
// disabling tracking
hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false)
} catch (e: SDKNotReady) {
// Exception indicating that the SDK has not completed its initialization yet.
hasNewCheckout = false
} catch (e: FeatureNotFound) {
// SDK not initialized or feature toggle not yet activated on Kameleoon's side - we consider the feature inactive
hasNewCheckout = false
} catch (e: Throwable) {
// Any other error
hasNewCheckout = false
}
if (hasNewCheckout) {
// Implement new checkout code here
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | Unique key of the feature you want to expose to a user. This field is required. |
track | boolean | An optional parameter to enable or disable tracking of the feature evaluation (true by default). |
Return value
Type | Description |
---|---|
Boolean | Value of the feature that is registered for a visitor. |
Exceptions thrown
Type | Description |
---|---|
SDKNotReady | Exception indicating that the SDK has not completed its initialization yet. |
FeatureNotFound | Exception indicating that the requested feature ID was not found in the internal configuration of the SDK. This usually means the feature flag has not been activated on the Kameleoon side (but code implementing the feature is already deployed in the application). |
getVariation()
- 📨 Sends Tracking Data to Kameleoon (depending on the
track
parameter)
Retrieves the Variation
assigned to a given visitor for a specific feature flag.
This method takes featureKey
as a mandatory argument and track
as an optional argument. The track
argument is optional and defaults to true
.
It returns the assigned Variation
for the visitor. If the visitor is not associated with any feature flag rules, the method returns the default Variation
for the given feature flag.
Ensure that proper error handling is implemented in your code to manage potential exceptions.
The default variation refers to the variation assigned to a visitor when they do not match any predefined delivery rules for a feature flag. In other words, it is the fallback variation applied to all users who are not targeted by specific rules. It's represented as the variation in the "Then, for everyone else..." section in a management interface.
- Java
- Kotlin
final String featureKey = "featureKey";
Variation variation;
try {
variation = kameleoonClient.getVariation(featureKey);
// disabling tracking
variation = kameleoonClient.getVariation(featureKey, false);
} catch (SDKNotReady ex) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (FeatureNotFound ex) {
// The feature key is not yet in the configuration file that has been fetched by the SDK.
} catch (FeatureEnvironmentDisabled ex) {
// The feature flag is disabled for the environment
}
String title = (String) variation.getVariables().get("title").getValue();
switch (variation.getKey()) {
case "on":
// Main variation key is selected for visitorCode
break;
case "alternative_variation":
// Alternative variation key
break;
default:
// Default variation key
break;
}
val featureKey = "featureKey"
val variation = null
try {
variation = kameleoonClient.getVariation(featureKey)
// disabling tracking
variation = kameleoonClient.getVariation(featureKey, false)
} catch (e: SDKNotReady) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (e: FeatureNotFound) {
// The feature key is not yet in the configuration file that has been fetched by the SDK.
} catch (e: FeatureEnvironmentDisabled) {
// The feature flag is disabled for the environment
}
val title = variation.variables["title"].value as String
when (variation.key) {
"on" -> {
// Main variation key is selected for visitorCode
}
"alternative_variation" -> {
// Alternative variation key
}
else -> {
// Default variation key
}
}
Arguments
Name | Type | Description | Default |
---|---|---|---|
featureKey (required) | String | Key of the feature you want to expose to a user. | |
track (optional) | boolean | An optional parameter to enable or disable tracking of the feature evaluation. | true |
Return value
Type | Description |
---|---|
Variation | An assigned variation to a given visitor for a specific feature flag. |
Exceptions thrown
Type | Description |
---|---|
SDKNotReady | Exception indicating that the SDK is not fully initialized yet. |
FeatureNotFound | Exception indicating that the requested feature key wasn't found in the internal configuration of the SDK. This usually means that the feature flag is not activated in the Kameleoon app (but code implementing the feature is already deployed on your application). |
FeatureEnvironmentDisabled | Exception indicating that feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
getVariations()
- 📨 Sends Tracking Data to Kameleoon (depending on the
track
parameter)
Retrieves a map of Variation
objects assigned to a given visitor across all feature flags.
This method iterates over all available feature flags and returns the assigned Variation
for each flag associated with the specified visitor. It takes onlyActive
and track
as optional arguments.
- If
onlyActive
is set totrue
, the methodgetVariations()
will return feature flags variations provided the user is not bucketed with theoff
variation. - The
track
parameter controls whether or not the method will track the variation assignments. By default, it is set totrue
. If set tofalse
, the tracking will be disabled.
The returned map consists of feature flag keys as keys and their corresponding Variation
as values. If no variation is assigned for a feature flag, the method returns the default Variation
for that flag.
Proper error handling should be implemented to manage potential exceptions.
The default variation refers to the variation assigned to a visitor when they do not match any predefined delivery rules for a feature flag. In other words, it is the fallback variation applied to all users who are not targeted by specific rules. It's represented as the variation in the "Then, for everyone else..." section in a management interface.
- Java
- Kotlin
try {
Map<String, Variation> variations = kameleoonClient.getVariations();
// only active variations
Map<String, Variation> variations = kameleoonClient.getVariations(true);
// disable tracking
Map<String, Variation> variations = kameleoonClient.getVariations(false, false);
} catch (SDKNotReady ex) {
// Exception indicating that the SDK has not completed its initialization yet.
}
try {
val variations = kameleoonClient.getVariations()
// only active variations
val variations = kameleoonClient.getVariations(true)
// disable tracking
val variations = kameleoonClient.getVariations(false, false)
} catch (e: SDKNotReady) {
// Exception indicating that the SDK has not completed its initialization yet.
}
Arguments
Name | Type | Description | Default |
---|---|---|---|
onlyActive (optional) | boolean | An optional parameter indicating whether to return variations for active (true ) or all (false ) feature flags. | false |
track (optional) | boolean | An optional parameter to enable or disable tracking of the feature evaluation. | true |
Return value
Type | Description |
---|---|
Map<String, Variation> | Map that contains the assigned Variation objects of the feature flags using the keys of the corresponding features. |
Exceptions thrown
Type | Description |
---|---|
SDKNotReady | Exception indicating that the SDK is not fully initialized yet. |
getFeatureVariationKey()
- 📨 Sends Tracking Data to Kameleoon
This method is deprecated and will be removed in SDK version 5.0.0
. Use getVariation()
instead.
Use this method to get the feature variation key for a visitor. This method takes a featureKey
as required argument to retrieve the variation key for the specified user.
If the visitor has never been associated with this feature flag, the SDK returns a randomly assigned variation key (according to the feature flag rules). If the visitor is already registered with this feature flag, this method returns the previous variation key. If the user does not match any of the rules, the default value will be returned, which is defined in your customer's account.
Make sure you set up proper error handling as shown in the example code to catch potential exceptions.
- Java
- Kotlin
String featureKey = "new_checkout";
String variationKey = "";
try {
variationKey = kameleoonClient.getFeatureVariationKey(featureKey);
} catch (SDKNotReady e) {
// Exception indicates that the SDK has not completed its initialization yet.
} catch (FeatureNotFound e) {
// The error is happened, feature flag isn't found in current configuration
} catch (FeatureEnvironmentDisabled e) {
// The feature flag is disabled for the environment
} catch (Throwable e) {
// Any other error
}
switch (variationKey) {
case "on":
//main variation key is selected for visitorCode
break;
case "alternative_variation":
//alternative variation key
break;
default:
//default variation key
break;
}
val featureKey = "new_checkout"
var variationKey = ""
try {
variationKey = kameleoonClient.getFeatureVariationKey(featureKey)
} catch (e: SDKNotReady) {
// Exception indicates that the SDK has not completed its initialization yet.
} catch (e: FeatureNotFound) {
// Exception indicates that the SDK not initialized or the feature toggle is not yet activated on Kameleoon's side. We consider the feature inactive.
} catch (e: FeatureEnvironmentDisabled) {
// The feature flag is disabled for the environment
} catch (e: Throwable) {
// Any other error
}
when (variationKey) {
"on" -> {}
"alternative_variation" -> {}
else -> {}
}
getFeatureList()
This method was previously named obtainFeatureList
, which was removed in SDK version 4.0.0
release.
Returns a list of feature flag keys currently available for the SDK.
Return value
Type | Description |
---|---|
List<String> | List of feature flag keys |
Example code
- Java
- Kotlin
List<String> allFeatureFlagListId = kameleoonClient.getFeatureList();
val allFeatureFlagListId = kameleoonClient.getFeatureList();
getActiveFeatures()
- This method is deprecated and will be removed in SDK version
5.0.0
. UsegetVariations()
instead. - Previously named:
getFeatureListForVisitorCode
which was removed in SDK version4.0.0
release.
getActiveFeatures
method retrieves information about the active feature flags that are available for the visitor.
Return value
Type | Description |
---|---|
Map<String, Variation> | A dictionary that contains the assigned variations of the active features using the keys of the corresponding active features. |
Example code
- Java
- Kotlin
Map<String, Variation> listActiveFeatureFlags = kameleoonClient.getActiveFeatures();
val listActiveFeatureFlags = kameleoonClient.getActiveFeatures();
Variables
getFeatureVariable()
- 📨 Sends Tracking Data to Kameleoon
This method is deprecated and will be removed in SDK version 5.0.0
. Use getVariation()
instead.
This method gets a variable value of variation key for a specific user. It takes a featureKey
, and variableKey
as required arguments.
If the visitor has never been associated with the featureKey
, the SDK returns a randomly assigned variable value for the specified variation key (according to the feature flag rules). If the visitor is already registered with this feature flag, this method returns the variable value for previously registered variation. If the user does not match any of the rules, the default variable value is returned.
Make sure you set up proper error handling as shown in the example code to catch potential exceptions.
- Java
- Kotlin
String featureKey = "feature_key";
String variableKey = "variableKey";
try {
var variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey);
// your custom code depending of variableValue
} catch (SDKNotReady e) {
// Exception indicates that the SDK has not completed its initialization yet.
} catch (FeatureNotFound e) {
// The error is happened, feature flag isn't found in current configuration
} catch (FeatureVariableNotFound e) {
// Requested variable not defined on Kameleoon's side
} catch (FeatureEnvironmentDisabled e) {
// The feature flag is disabled for the environment
} catch (Throwable e) {
// Any other error
}
val featureKey = "new_checkout"
val variableKey = "var"
try {
val variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey)
// your custom code depending of variableValue
} catch (e: SDKNotReady) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (e: FeatureNotFound) {
// The error is happened, feature flag isn't found in current configuraiton
} catch (e: FeatureVariableNotFound) {
// Requested variable not defined on Kameleoon's side
} catch (e: FeatureEnvironmentDisabled) {
// The feature flag is disabled for the environment
} catch (e: Throwable) {
// Any other error
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | string | Key of the feature you want to display to a user. This field is required. |
variableName | string | Name of the variable you want to get a value for. This field is required. |
Return value
Type | Description |
---|---|
object | Value of variable of variation that is registered for the specified visitorCode for this feature flag. Valid types: bool , int , double , string , JObject , JArray |
Exceptions thrown
Type | Description |
---|---|
SDKNotReady | Exception indicating that the SDK has not completed its initialization yet. |
FeatureNotFound | Exception indicating that the requested feature key was found in the internal configuration of the SDK. This usually means that the feature flag has not been activated on Kameleoon's side (but code implementing the feature is already deployed in the application). |
FeatureVariableNotFound | Exception indicating that the specified variable was not found. Check that the variable key in the Kameleon app matches the one in your code. |
FeatureEnvironmentDisabled | Exception indicating that feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
getFeatureVariationVariables()
- This method is deprecated and will be removed in SDK version
5.0.0
. UsegetVariation()
instead. - This method was previously named:
getFeatureAllVariables
, which was removed in SDK version4.0.0
release.
To retrieve all of the variables for a feature, call this method. You can modify your feature variables in the Kameleoon app.
This method takes one input parameter: featureKey
. It returns the data as a Map<String, Object>
type, as defined in the Kameleoon app. It throws an exception (FeatureNotFound
) if the requested feature was not found in the internal configuration of the SDK.
- Java
- Kotlin
String featureKey = "myFeature";
try {
Map<String, Object> variables = kameleoonClient.getFeatureVariationVariables(featureKey);
} catch (SDKNotReady e) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (FeatureNotFound e) {
// The feature is not yet activated on Kameleoon's side
} catch (FeatureEnvironmentDisabled e) {
// The feature flag is disabled for the environment
} catch (Exception e) {
// This is a generic Exception handler which will handle all exceptions.
System.out.println("Exception occurred");
}
val featureKey = "myFeature"
try {
val variables = kameleoonClient.getFeatureVariationVariables(featureKey)
} catch (e: SDKNotReady) {
// Exception indicating that the SDK has not completed its initialization yet.
} catch (e: FeatureNotFound) {
// The feature is not yet activated on Kameleoon's side
} catch (e: FeatureEnvironmentDisabled) {
// The feature flag is disabled for the environment
} catch (e: Exception) {
// This is a generic Exception handler which will handle all exceptions.
println("Exception occurred")
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | Unique identifier of the feature you need to obtain. This field is required. |
Return value
Type | Description |
---|---|
Map<String,Object> | Data representing the variables associated with this feature flag. The values can be int , string , boolean , JSONObject or JSONArray (depending on the types defined on the web interface). |
Exceptions thrown
Type | Description |
---|---|
SDKNotReady | Exception indicating that the SDK has not completed its initialization yet. |
FeatureNotFound | Exception indicating that the requested feature was not found in the internal configuration of the SDK. This usually means that the feature flag has not yet been activated on Kameleoon's side. |
FeatureVariableNotFound | Exception indicating that the specified variable was not found. Check that the variable key in the Kameleoon app matches the one in your code. |
FeatureEnvironmentDisabled | Exception indicating that feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
Goals
trackConversion()
- 📨 Sends Tracking Data to Kameleoon
This asynchronous method tracks conversions in your application. This method requires goalID
to track conversion for a particular goal. In addition, this method also accepts revenue
as a second optional argument to track revenue.
This method doesn't return any values. This method is non-blocking as the server call is made asynchronously.
- Java
- Kotlin
int goalID = 83023;
kameleoonClient.trackConversion(goalID); // default revenue
kameleoonClient.trackConversion(goalID, 10); // provided revenue == 10
val goalID = 83023
kameleoonClient.trackConversion(goalID) // default revenue
kameleoonClient.trackConversion(goalID, 10); // provided revenue == 10
Arguments
Name | Type | Description |
---|---|---|
goalId | int | ID of the goal. This field is mandatory. |
revenue | double | Revenue of the conversion. This field is optional. |
Events
onUpdateConfiguration()
This method was previously named updateConfigurationHandler
, which was removed in SDK version 4.0.0
release.
The onUpdateConfiguration()
method allows you to handle the event when configuration has updated data. It takes one input parameter, completion. The completion that will be called when the configuration is updated using a real-time configuration event.
Arguments
Name | Type | Description |
---|---|---|
completion | ResultCompletion<Long, Exception> | The handler that will be called when the configuration is updated using a real-time configuration event. |
Example code
- Java
- Kotlin
kameleoonClient.onUpdateConfiguration(result -> {
if (result.isSuccess()) {
// result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
}
});
kameleoonClient.onUpdateConfiguration { result ->
if (result.isSuccess) {
// result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
}
};
Visitor data
getVisitorCode()
Returns unique visitor code used in SDK.
- Java
- Kotlin
String visitorCode = kameleoonClient.getVisitorCode()
val visitorCode = kameleoonClient.getVisitorCode()
Return value
Type | Description |
---|---|
String | String representing a unique visitor code used in SDK. |
addData()
The addData()
method adds targeting data to storage so other methods can use the data to decide whether or not to target the current visitor.
The addData()
method does not return any value and does not interact with Kameleoon back-end servers on its own. Instead, all the declared data is saved for future transmission using the flush()
method. This approach reduces the number of server calls made, as the data is typically grouped into a single server call that is triggered the flush()
.
The trackConversion()
method also sends out any previously associated data, just like the flush()
. The same holds true for getVariation()
and getVariations()
methods if an experimentation rule is triggered.
Each visitor can only have one instance of associated data for most data types. However, CustomData
is an exception. Visitors can have one instance of associated CustomData
per index.
- Java
- Kotlin
kameleoonClient.addData(new Data.Custom(1, "some custom value"), Data.Device.TABLET);
kameleoonClient.addData(new Data.Conversion(32, 10f, false));
kameleoonClient.addData(Data.CustomData(1, "some custom value"), Data.Device.TABLET);
kameleoonClient.addData(Data.Conversion(32, 10f, false))
Arguments
Name | Type | Description |
---|---|---|
data (required) | Data... | Collection of Kameleoon data types. |
flush()
- 📨 Sends Tracking Data to Kameleoon
flush()
takes the Kameleoon data associated with the visitor, then sends a tracking request along with all of the data that were added previously using the addData()
method, that has not yet been sent when calling one of these methods. flush()
is non-blocking as the server call is made asynchronously.
flush()
allows you to control when the data associated with the visitor is sent to our servers. For instance, if you call addData()
a dozen times, it would be inefficient to send data to the server after each time addData()
is invoked, so all you have to do is call flush()
once at the end.
The flush()
method uses the visitorCode
as the unique visitor identifier, which is useful for cross-device experimentation. If you set the isUniqueIdentifier
configuration parameter to true
, the SDK links the flushed data with the visitor associated with the specified identifier.
- Java
- Kotlin
kameleoonClient.addData(Data.Device.PHONE);
kameleoonClient.addData(new Data.Conversion(32, 10f, false));
kameleoonClient.flush(); // Interval tracking (most performant way for tracking)
kameleoonClient.flush(true); // Instant tracking
kameleoonClient.addData(Data.Device.PHONE)
kameleoonClient.addData(Data.Conversion(32, 10f, false))
kameleoonClient.flush() // Interval tracking (most performant way for tracking)
kameleoonClient.flush(true) // Instant tracking
Arguments
Name | Type | Description |
---|---|---|
instant | boolean | Boolean flag indicating whether the data should be sent instantly (true ) or according to the scheduled tracking interval (false ). This field is optional; the default value is false . |
getRemoteData()
This method was previously named retrieveDataFromRemoteSource
, which was removed in SDK version 4.0.0
release.
Use this method to retrieve data from a remote Kameleoon server based on your active siteCode
and the key
argument (or the active visitorCode
if you omit the key
). The visitorCode
and siteCode
are specified in KameleoonClientFactory.create()
. You can quickly and conveniently store data on our highly scalable remote servers using the Kameleoon Data API. Your application can then retrieve the data using this method.
Note that since a server call is required, this mechanism is asynchronous, and you must pass a Result<JSONObject, Exception>
object as an argument to the method.
- Java
- Kotlin
kameleoonClient.getRemoteData("test", result -> {
try {
JSONObject jsonObject = result.get();
// jsonObject contains result of request
} catch (Exception ex) {
// request failed with an exception
}
});
kameleoonClient.getRemoteData("test") { result ->
try {
val jsonObject = result.get()
// jsonObject contains result of request
} catch (e: Exception) {
// request failed with exception
}
}
Arguments
Name | Type | Description |
---|---|---|
key | String | The key that the data you try to get is associated with. This field is optional. |
completion | ResultCompletion<JSONObject, Exception> | The callback that processes the received data. This field is required. |
getRemoteVisitorData()
getRemoteVisitorData()
is an asynchronous method for retrieving Kameleoon Visits Data for the visitorCode
from the Kameleoon Data API. The method adds the data to storage for other methods to use when making targeting decisions.
Data obtained using this method plays an important role when you want to:
- use data collected from other devices.
- access a user's history, such as custom data collected during previous visits.
Read this article for a better understanding of possible use cases.
By default, getRemoteVisitorData()
automatically retrieves the latest stored custom data with scope=Visitor
and attaches them to the visitor without the need to call the method addData()
. It is particularly useful for synchronizing custom data between multiple devices.
- Java
- Kotlin
// Visitor data will be fetched and automatically added for `visitorCode`
kameleoonClient.getRemoteVisitorData(result -> {
try {
List<Data> visitorData = result.get();
// visitorData contains fetched visitor data from the Kameleoon servers
} catch (Exception ex) {
// request failed with exception
}
});
// If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
kameleoonClient.getRemoteVisitorData(false, result -> {
try {
List<Data> visitorData = result.get();
// visitorData contains fetched visitor data from the Kameleoon servers
} catch (Exception ex) {
// request failed with exception
}
});
// If you want to fetch custom list of data types
RemoteVisitorDataFilter filter = RemoteVisitorDataFilter.builder()
.previousVisitAmount(25)
.experiments(true)
.conversion(true)
.build();
kameleoonClient.getRemoteVisitorData(filter, true, result -> {
try {
List<Data> visitorData = result.get();
// visitorData contains fetched visitor data from the Kameleoon servers
} catch (Exception ex) {
// request failed with exception
}
});
// Visitor data will be fetched and automatically added for `visitorCode`
kameleoonClient.getRemoteVisitorData { result ->
try {
val visitorData = result.get()
// visitorData contains fetched visitor data from our servers
} catch (e: Exception) {
// request failed with exception
}
}
// If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
kameleoonClient.getRemoteVisitorData(false) { result ->
try {
val visitorData = result.get()
// visitorData contains fetched visitor data from the Kameleoon servers
} catch (e: Exception) {
// request failed with exception
}
}
val filter = RemoteVisitorDataFilter.builder()
.previousVisitAmount(25)
.experiments(true)
.conversion(true)
.build()
kameleoonClient.getRemoteVisitorData(false) { result ->
try {
val visitorData = result.get()
// visitorData contains fetched visitor data from the Kameleoon servers
} catch (e: Exception) {
// request failed with exception
}
}
Using parameters in getRemoteVisitorData()
The getRemoteVisitorData()
method offers flexibility by allowing you to define various parameters when retrieving data on visitors. Whether you're targeting based on goals, experiments, or variations, the same approach applies across all data types.
For example, let's say you want to retrieve data on visitors who completed a goal "Order transaction". You can specify parameters within the getRemoteVisitorData()
method to refine your targeting. For instance, if you want to target only users who converted on the goal in their last five visits, you can set the previousVisitAmount
parameter to 5 and conversions
to true.
The flexibility shown in this example is not limited to goal data. You can use parameters within the getRemoteVisitorData()
method to retrieve data on a variety of visitor behaviors.
Arguments
Name | Type | Description |
---|---|---|
filter | RemoteVisitorDataFilter | Filter that selects which data should be retrieved from visit history. By default, getRemoteVisitorData retrieves CustomData from the current and latest previous visit (RemoteVisitorDataFilter.builder().build() or new RemoteVisitorDataFilter() ). All other filters parameters default to false . This field is optional. |
shouldAddData | boolean | A boolean indicating whether the method should automatically add retrieved data for a visitor. If not specified, the default value is true. This field is optional. |
completion | ResultCompletion<List<Data>, Exception> | The callback that processes the received visitor data.This field is required. |
Here is the list of available RemoteVisitorDataFilter
options:
Name | Type | Description | Default |
---|---|---|---|
previousVisitAmount (optional) | int | Number of previous visits to retrieve data from. Number between 1 and 25 | 1 |
currentVisit (optional) | boolean | If true, current visit data will be retrieved | true |
customData (optional) | boolean | If true, custom data will be retrieved. | true |
geolocation (optional) | boolean | If true, geolocation data will be retrieved. | false |
conversions (optional) | boolean | If true, conversion data will be retrieved. | false |
experiments (optional) | boolean | If true, experiment data will be retrieved. | false |
kcs (optional) | boolean | If true, Kameleoon Conversion Score (KCS) will be retrieved. Requires the AI Predictive Targeting add-on | false |
visitorCode (optional) | boolean | If true, Kameleoon will retrieve the visitorCode from the most recent visit and use it for the current visit. This is necessary if you want to ensure that the visitor, identified by their visitorCode , always receives the same variant across visits for Cross-device experimentation. | true |
getVisitorWarehouseAudience()
Retrieves all audience data associated with the visitor in your data warehouse. The optional warehouseKey
parameter is typically your internal user ID. The customDataIndex
parameter corresponds to the Kameleoon custom data that Kameleoon uses to target your visitors. You can refer to the warehouse targeting documentation for additional details. The method passes the result to the completion
as a CustomData
object, confirming that the data has been added to the visitor and is available for targeting purposes.
Since a server call is required, this mechanism is asynchronous, and you must pass a completion
as an argument to the method.
- Java
- Kotlin
kameleoonClient.getVisitorWarehouseAudience(customDataIndex, result -> {
// As a result of the method before this callback is called, data was automatically added to the visitor.
// In general, we recommended that you check only when the request fails.
if (result.isFailure()) {
Exception exception = result.failure();
// Request failed with an exception.
}
});
// If you need to specify warehouse key
kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex, result -> {
// As a result of the method before this callback is called, data was automatically added to the visitor
// but you can evaluate the added data if you need to check it.
try {
CustomData data = result.get();
} catch (Exception exception) {
// request failed with exception
}
});
// Visitor data will be fetched and automatically added for `visitorCode`
kameleoonClient.getVisitorWarehouseAudience(customDataIndex) { result ->
// As a result of the method before this callback is called, data was automatically added to the visitor
// In general, we recommend you check only the request fails.
if (result.isFailure()) {
val exception = result.failure();
// Request failed with an exception
}
}
// If you need to specify warehouse key
kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex) { result ->
// As a result of the method before this callback is called, data was automatically added to the visitor
// but you can evaluate the added data if you need to check it.
try {
val data = result.get();
} catch (e: Exception) {
// Request failed with an exception
}
}
Arguments
Name | Type | Description |
---|---|---|
warehouseKey | String | A unique key to identify the warehouse data (usually, your internal user ID). This field is optional. |
customDataIndex | int | An integer representing the index of the custom data you want to use to target your BigQuery Audiences. |
completion | ResultCompletion<CustomData, Exception> | The callback that processes the received data. This field is required. |
Return value
Type | Description |
---|---|
Task<CustomData> | A CustomData instance confirming that the data has been added to the visitor. |
Exceptions thrown
Type | Description |
---|---|
HttpRequestException | Exception indicating that the request was failed for any reason. |
Exception | Exception indicating that the request timed out or any other reason of failure. |
setLegalConsent()
You must use this method to specify whether the visitor has given legal consent to use their personal data. Setting the legalConsent
parameter to false
limits the types of data that you can include in tracking requests. This helps you adhere to legal and regulatory requirements while responsibly managing visitor data. You can find more information on personal data in the consent management policy.
Arguments
Name | Type | Description |
---|---|---|
legalConsent | boolean | A boolean value representing the legal consent status. true indicates the visitor has given legal consent, false indicates the visitor has never provided, or has withdrawn, legal consent. This field is required. |
Example code
- Java
- Kotlin
kameleoonClient.setLegalConsent(true);
kameleoonClient.setLegalConsent(true)
Data types
This section lists the com.Kameleoon.Data
types supported by Kameleoon. We provide several standard data types as well as the CustomData
type that allows you to define custom data types.
Conversion
Store information about conversion events.
Field name | Type | Description |
---|---|---|
goalID | int | ID of the goal. This file is required. |
revenue | float | Conversion revenue. This field is optional. |
negative | boolean | Defines if the revenue is positive or negative. This field is optional. |
- Java
- Kotlin
kameleoonClient.addData(new Data.Conversion(32, 10f, false));
kameleoonClient.addData(Data.Conversion(32, 10f, false))
Device
Store information about the user's device.
Field name | Type | Description |
---|---|---|
device | Device | List of devices: PHONE, TABLET, DESKTOP. This field is required. |
- Java
kameleoonClient.addData(Data.Device.DESKTOP);
Geolocation
Geolocation
contains the visitor's geolocation details.
- Each visitor can have only one
Geolocation
. Adding a secondGeolocation
overwrites the first one.
- Java
- Kotlin
kameleoonClient.addData(new Geolocation("France", "Île-de-France", "Paris"));
kameleoonClient.addData(Geolocation("France", "Île-de-France", "Paris"))
Name | Type | Description |
---|---|---|
country (required) | String | The country of the visitor. |
region (optional) | String | The region of the visitor. |
city (optional) | String | The city of the visitor. |
postalCode (optional) | String | The postal code of the visitor. |
latitude (optional) | float | The latitude coordinate representing the location of the visitor. Coordinate number represents decimal degrees. |
longitude (optional) | float | The longitude coordinate representing the location of the visitor. Coordinate number represents decimal degrees. |
CustomData
Define your own custom data types in the Kameleoon app or the Data API and use them from the SDK.
Name | Type | Description |
---|---|---|
index | int | An index or unique ID of the custom data to be stored. This field is required. |
values | String... or String[] or List<String> | Value(s) of the custom data to be stored. This field is optional. |
The index (ID) of the custom data is available in the Kameleoon app, in the Custom data configuration page. Be careful: this index starts at 0, so the first custom data you create for a given site would have the ID 0, not 1.
- Java
- Kotlin
kameleoonClient.addData(new CustomData(1, "some custom value"));
kameleoonClient.addData(new CustomData(1, "first value", "second value"));
kameleoonClient.addData(new CustomData(1, new String[]{ "first value", "second value" }));
kameleoonClient.addData(CustomData(1, "some custom value"))
kameleoonClient.addData(CustomData(1, "first value", "second value"))
kameleoonClient.addData(CustomData(1, arrayOf("first value", "second value")))
Returned Types
Variation
Variation
contains information about the assigned variation to the visitor (or the default variation, if no specific assignment exists).
Name | Type | Description |
---|---|---|
key | String | The unique key identifying the variation. |
id | Integer | The ID of the assigned variation (or null if it's the default variation). |
experimentId | Integer | The ID of the experiment associated with the variation (or null if default). |
variables | Map<String, Variable> | A map containing the variables of the assigned variation, keyed by variable names. This could be an empty collection if no variables are associated. |
- The
Variation
object provides details about the assigned variation and its associated experiment, while theVariable
object contains specific details about each variable within a variation. - Ensure that your code handles the case where
id
orexperimentId
may benull
, indicating a default variation. - The
variables
map might be empty if no variables are associated with the variation.
Example code
- Java
- Kotlin
// Retrieving the variation key
String variationKey = variation.getKey();
// Retrieving the variation id
Integer variationId = variation.getId();
// Retrieving the experiment id
Integer experimentId = variation.getExperimentId();
// Retrieving the variables map
Map<String, Variable> variables = variation.getVariables();
// Retrieving the variation key
val variationKey: String = variation.key
// Retrieving the variation id
val variationId: Int? = variation.id
// Retrieving the experiment id
val experimentId: Int? = variation.experimentId
// Retrieving the variables map
val variables: Map<String, Variable> = variation.variables
Variable
Variable
contains information about a variable associated with the assigned variation.
Name | Type | Description |
---|---|---|
key | String | The unique key identifying the variable. |
type | String | The type of the variable. Possible values: BOOLEAN, NUMBER, STRING, JSON. |
value | Object | The value of the variable, which can be of the following types: boolean, int, long, double, String, JSONObject, JSONArray, null. |
Example code
- Java
- Kotlin
// Retrieving the variables map
Map<String, Variable> variables = variation.getVariables();
// Variable type can be retrieved for further processing
String type = variables.get("isDiscount").getType();
// Retrieving the variable value by key
Boolean isDiscount = (Boolean) variables.get("isDiscount").getValue();
// Variable value can be of different types
String title = (String) variables.get("title").getValue();
// Retrieving the variables map
val variables: Map<String, Variable> = variation.variables
// Variable type can be retrieved for further processing
val type: String = variables["isDiscount"].type
// Retrieving the variable value by key
val isDiscount: Boolean = variables["isDiscount"].value as Boolean
// Variable value can be of different types
val title: String = variables["title"].value as String