iOS SDK
With the Kameleoon iOS (Swift) SDK, you can run experiments and activate feature flags on native mobile iOS applications. Integrating our SDK into your Swift apps is easy, and its footprint (memory and network usage) is low.
Getting started: For help getting started, see the developer guide.
Changelog: Latest version of the Swift SDK: 4.6.0 Changelog.
SDK methods: For the full reference documentation of the iOS SDK methods, see the reference section.
Developer guide
Follow these steps to install and configure the Kameleoon iOS SDK in your application for the first time.
Getting started
Starter kit
If you're just getting started with Kameleoon, we provide a starter kit and a demo application to test out the SDK and learn how it works. The starter kit includes a fully configured app with examples that demonstrate how you might use the SDK methods in your app. You can find the starter kit, the demo application and detailed instructions on how to use it at Starter-Kit for iOS.
Prerequisites
- Use Swift version 5.0 or higher on the iOS platform. There is no planned support for earlier iOS applications (including earlier Swift versions and Objective-C apps). We provide a Universal Framework version compatible both with x86_64 (for the iOS Simulator) and ARM (for production deployment into the App Store).
Installation
You can install the iOS SDK using CocoaPods or Swift Package Manager:
- CocoaPods
- Swift Package Manager
With CocoaPods, paste the following code in your Podfile and replace YOUR_TARGET_NAME
with the value for your app:
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'kameleoonClient'
end
Then, in a command prompt, in the Podfile
directory, run the install command:
pod install
With Swift Package Manager, add a package dependency to your Xcode project. Select File > Swift Packages > Add Package Dependency and enter the repository URL: https://github.com/Kameleoon/client-swift
.
Alternatively, you can modify your Package.swift
file directly:
dependencies: [
.package(url: "https://github.com/Kameleoon/client-swift.git", from("3.0.3"))
]
Additional configuration
To customize the SDK behavior, create a kameleoon-client-swift.plist
configuration file in the root directory of your Xcode project. You can also download a sample configuration file.
These are the keys 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
: 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 isDate.distantFuture
.default_timeout_millisecond
: Specifies the timeout, in milliseconds, for network requests from the SDK. Set the value to 30000 ms (30 seconds) or more if you do not have a stable connection. The default value is 10000 ms. Some methods have an additional parameter that you can use to override the default timeout for that particular method. If you do not specify the timeout for a method explicitly, the SDK uses this default value.tracking_interval_millisecond
: this 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 experimentation and 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 information.is_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 you've the SDK in your application and set 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 experiment.
import kameleoonClient
let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
// pass client configuration as an argument
let config = try KameleoonClientConfig(
clientId: "clientId", // optional
clientSecret: "clientSecret", // optional
refreshIntervalMinute: 15, // optional, 60 minutes by default
dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
environment: "production", // optional
isUniqueIdentifier: true, // optional, false by default
)
let kameleoonClient = try KameleoonClientFactory.create(
siteCode: siteCode,
visitorCode: visitorCode, // optional
config: config // optional
)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
do {
// read client configuration from a file 'kameleoon-client-swift.plist'
// visitor code isn't provided, so SDK generates a random visitor code which will be used in the future
let kameleoonClient = try KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch {
// Unexpected error occurred
}
The KameleoonClientFactory.create()
method initializes the client, but the client is not immediately ready for use. The client must retrieve the current configuration of experiments and feature flags (along with their traffic repartition) from a Kameleoon remote server. This requires the client to have 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 iOS SDK. After the client fetches the first configuration of feature flags, it periodically refreshes the configuration. If the refresh fails for any reason, the Kameleoon client continues to function using the previous configuration.
You can use the .ready
public getter to check if the Kameleoon client initialization is finished.
Alternatively, you can use a helper callback to encapsulate the logic of experiment triggering and variation implementation. The best approach (.ready
or callback) depends on your preferences and use case. We recommend using .ready
when you expect that the SDK will already be ready for use. For example, if you are running an experiment on a dialog that would be accessible only after a few seconds or minutes of navigation within the app. We recommend using the callback when there is a high probability that the SDK is still initializing when the experiment is accessible. For example, an experiment that is visible at the launch of the app should use 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 client is ready before calling any methods. A good practice is to always assume that the app user should be left out of the experiment if the Kameleoon client is not yet ready. This is actually easy to do, because this corresponds to the implementation of the default reference variation logic. For example, as shown in the code sample above.
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 a feature flag in your Kameleoon account.
To determine if a feature flag is active for a specific user, you need to retrieve its configuration. Use the getFeatureVariationKey()
or isFeatureActive()
method to retrieve the configuration based on the featureKey
.
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.
The getFeatureVariationKey()
method retrieves the configuration of a feature experiment with several feature variations. You can use the method to get a variation key for a given user by providing the visitorCode
and featureKey
as mandatory arguments.
Feature flags can have associated variables that are used to customize their behavior. To retrieve these variables, use the getFeatureVariationVariables()
method after calling getFeatureVariationKey()
, as you will need to obtain the variationKey
for the user.
To check if a feature flag is active, you only need to use one method. Choose isFeatureFlagActive
if you simply want to know if a feature flag is on or off. For more complex scenarios, like dynamically changing the feature's behavior, use getFeatureFlagVariables
.
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 or to access past data points about a user (which would have been collected client-side if you are using Kameleoon in Hybrid mode), 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 and browser. Remember to call the flush()
method to send saved data to the Kameleoon servers.
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. To ensure your results are accurate, it's recommended to filter out bots by using the userAgent
data type. You can learn more about this here. Don't forget to call the flush()
method to send the collected data to Kameleoon servers for analysis.
Tracking flag exposition and goal conversions
Kameleoon will automatically track visitors’ exposition to flags as soon as you call one of these methods:
getFeatureVariationKey()
getFeatureVariable()
isFeatureActive()
When a user completes a desired action (for example, making a purchase), it counts as a conversion. To track conversions, you must use the trackConversion()
method, and provide the visitorCode
and goalId
parameters.
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 supported by this SDK, see use visit history to target users.
You can also use your own external data to target users.
Logging
The SDK generates logs to reflect various internal processes and issues.
Log levels
The SDK supports configuring limiting logging by a log level.
// The `none` log level allows no logging.
KameleoonLogger.logLevel = .none
// The `ERROR` log level allows to log only issues that may affect the SDK's main behaviour.
KameleoonLogger.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.
KameleoonLogger.logLevel = .warning
// The `INFO` log level allows to log general information on the SDK's internal processes.
// It extends the `WARNING` log level.
KameleoonLogger.logLevel = .info
// The `DEBUG` log level allows to log extra information on the SDK's internal processes.
// It extends the `INFO` log level.
KameleoonLogger.logLevel = .debug
Custom handling of logs
The SDK writes sends uses the Logger
(since iOS 14) / print
(prior to iOS 14) by default. This behaviour can be overridden.
Logging limiting by a log level is performed apart from the log handling logic.
public struct CustomLogger: Logging {
let customLogger = Logger(subsystem: "com.yourcompany.app", category: "app")
public func log(level: LogLevel, message: String) {
switch level {
case .error:
customLogger.error("\(message)")
case .warning:
customLogger.warning("\(message)")
case .info:
customLogger.info("\(message)")
case .debug:
customLogger.debug("\(message)")
default:
break
}
}
}
// 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.
KameleoonLogger.logLevel = .debug // Optional, defaults to `LogLevel.WARNING`.
KameleoonLogger.logger = CustomLogger()
Apple privacy compliance
Starting May 1st, 2024, Apple requires apps that include a third-party SDK, such as the Kameleoon iOS SDK, to have a privacy manifest file for that SDK. The latest version of the SDK is code-signed, compliant, and includes a valid manifest file with the SDK. No action is required if you're using the Kameleoon iOS SDK version 4.2 or later.
Reference
This is the full reference documentation for the Kameleoon iOS (Swift) 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 KameleoonClientFactory
. This creates an instance of KameleoonClient
to manage all interactions between the SDK and your app.
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.
let visitorCode = "visitorCode"
let siteCode = "a8st4f59bj"
do {
// pass client configuration as an argument
let config = try KameleoonClientConfig(
clientId: "clientId", // optional
clientSecret: "clientSecret", // optional
refreshIntervalMinute: 15, // optional, 60 minutes by default
dataExpirationIntervalMinute: 60*24*365, // optional, `Data.distantFuture` by default
defaultTimeoutMillisecond: 10_000, // optional, 10_000 milliseconds by default
trackingIntervalMillisecond: 500, // optional, 1000 milliseconds by default
environment: "production", // optional
isUniqueIdentifier: true, // optional, false by default
)
let kameleoonClient = try KameleoonClientFactory.create(
sitecode: siteCode,
visitorCode: visitorCode, // optional
config: config // optional
)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
do {
// read client configuration from a file 'kameleoon-client-swift.plist'
// visitor code isn't provided, so SDK generates a random visitor code which will be used in the future
let kameleoonClient = KameleoonClientFactory.create(siteCode: siteCode)
} catch KameleoonError.visitorCodeInvalid {
// Provided visitor code is invalid
} catch KameleoonError.siteCodeIsEmpty {
// Indicates that provided site code is empty
} catch {
// Unexpected error occurred
}
ready
For mobile SDKs, the initialization of the Kameleoon Client is not immediate. The SDK needs to perform a server call to retrieve the current configuration for all active experiments. Check if the SDK is ready by calling this method before triggering an experiment. Alternatively, you can use the runWhenReady()
method with a callback.
let ready = kameleoonClient.ready
Return value
Name | Type | Description |
---|---|---|
ready | Bool | Boolean representing the status of the SDK (true if fully initialized, false if not ready to be used). |
runWhenReady()
For mobile SDKs, the initialization of the Kameleoon Client is not immediate. The SDK needs to perform a server call to retrieve the current configuration for all active experiments. The runWhenReady()
method of the KameleoonClient class allows you to pass a callback that will be executed as soon as the SDK is ready for use. It also allows you to specify a timeout.
The lambda given as the second argument to this method must have the signature (Bool) -> Void
. The lambda will be called with the value true
once the Kameleoon client is ready, and should contain code that triggers an experiment and implements variations. The lambda will be called with the value false
if the specified timeout happens before the client is fully initialized. When this occurs, you can implement the "reference" variation, as the user will be excluded from the experiment entirely if a timeout takes place.
kameleoonClient.runWhenReady(1000) { success in
if (success)
{
let variationKey = try? kameleoonClient.getFeatureVariationKey(my_feature_key)
if variationKey == "off" {
// This is the default / reference number of products to display
recommendedProductsNumber = 2
} else if variationKey == "on" {
// We are changing number of recommended products for this variation to 8
recommendedProductsNumber = 8
}
}
else
{
variationKey = "off"
recommendedProductsNumber = 2
}
}
Feature flags and variations
Arguments
Name | Type | Description |
---|---|---|
timeout | Int | Timeout (in milliseconds). This field is optional. If not provided, it will use the default value of 10000 milliseconds. |
callback | (Bool) -> Void | Callback object. This field is required. It is a lambda expression that will get a Bool argument representing whether the Kameleoon Client became ready before the timeout was reached. |
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
.
To activate a feature toggle, call this method. This method accepts featureKey
as a required argument to check if the specified feature will be active for a visitor.
If a visitor has never been associated with this feature flag, this method returns a random boolean value (true
if the user 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 implement error handling as shown in the example code to catch potential exceptions.
let featureKey = "new_checkout"
var hasNewCheckout = false
do {
hasNewCheckout = try kameleoonClient.isFeatureActive(featureKey: featureKey)
// disabling tracking
hasNewCheckout = kameleoonClient.isFeatureActive(featureKey: featureKey, track: false);
} catch {
switch error {
case KameleoonError.sdkNotReady:
// Exception indicating that the SDK has not completed its initialization yet.
hasNewCheckout = false
case KameleoonError.Feature.notFound:
// The feature key is not yet in the configuration file that has been fetched by the SDK.
hasNewCheckout = false
default:
// Any other error
hasNewCheckout = false
}
}
if hasNewCheckout
{
// Implement new checkout code here
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | The key of the feature you want to expose to a user. This field is required. |
track | Bool | An optional parameter to enable or disable tracking of the feature evaluation (true by default). |
Return value
Type | Description |
---|---|
Bool | Value of the feature that is registered for the visitor. |
Exceptions thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |
KameleoonError.Feature.notFound | Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This usually means that the feature flag has not yet been activated on Kameleoon's side (but code implementing the feature is already deployed in the web-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. 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.
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | Key of the feature that you want to check the status of for the user. This field is required. |
track | Bool | An optional parameter to enable or disable tracking of the feature evaluation (Defaults to true ). |
Return value
Type | Description |
---|---|
Variation | An assigned variation to a given visitor for a specific feature flag. |
Exceptions thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |
KameleoonError.Feature.notFound | Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This usually means that the feature flag has not yet been activated on Kameleoon's side (but code implementing the feature is already deployed in the web-application). |
KameleoonError.Feature.environmentDisabled | Exception indicating that the feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
Example code
let featureKey = "featureKey"
var variation: Types.Variation?
do {
variation = try kameleoonClient.getVariation(featureKey: featureKey)
// disabling tracking
variation = kameleoonClient.getVariation(featureKey: featureKey, track: false);
} catch {
switch error {
case KameleoonError.sdkNotReady:
// Exception indicating that the SDK has not completed its initialization yet.
case KameleoonError.Feature.notFound:
// The feature key is not yet in the configuration file that has been fetched by the SDK.
case KameleoonError.Feature.environmentDisabled:
// The feature flag is disabled for the environment
default:
// Any other error
}
}
let title = variation?.variables["title"].value
switch variation?.key {
case "on":
// Main variation key is selected for visitorCode
case "alternative_variation":
// Alternative variation key
default:
// Default variation key
}
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 method will only return variations for active feature flags. By default, this parameter is set tofalse
, meaning variations for both active and inactive flags will be returned. - 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.
Arguments
Name | Type | Description |
---|---|---|
onlyActive | Bool | An optional parameter indicating whether to return variations for active (true ) or all (false ) feature flags (Defaults to false ). |
track | Bool | An optional parameter to enable or disable tracking of the feature evaluation (Defaults to true ). |
Return value
Type | Description |
---|---|
[String: Variation] | Dictionary that contains the assigned [Variations ] of the feature flags using the keys of the corresponding features. |
Exceptions thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |
do {
let variations = kameleoonClient.getVariations();
// only active variations
let variations = kameleoonClient.getVariations(onlyActive: true);
// disable tracking
let variations = kameleoonClient.getVariations(track: false);
} catch KameleoonError.sdkNotReady {
// Exception indicating that the SDK has not completed its initialization 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 specific user. 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 visitor does not match any of the rules, the default variation you defined in the Kameleoon app will be returned.
Make sure you set up proper error handling as shown in the example code to catch potential exceptions.
let featureKey = "new_checkout"
var variationKey = ""
do {
variationKey = try kameleoonClient.getFeatureVariationKey(featureKey: featureKey)
switch variationKey {
case "variation 1":
// The visitor has been bucketed with variation 1 key
case "variation 2":
// The visitor has been bucketed with variation 1 key
default:
//The visitor has been bucketed with the default variation or is part of the unallocated traffic sample
}
} catch {
switch error {
case KameleoonError.sdkNotReady:
// Exception indicating that the SDK has not completed its initialization yet.
case KameleoonError.Feature.notFound:
// The feature key is not yet in the configuration file that has been fetched by the SDK. Trigger the old checkout for this visitor.
case KameleoonError.Feature.environmentDisabled:
// The feature flag is disabled for the environment
default:
// Any other error
}
}
getFeatureList()
To get the list of feature flag keys that are currently available to the SDK, call this method.
Return value
Type | Description |
---|---|
[String] | List of feature flag keys |
Example code
let allFeatureList = kameleoonClient.getFeatureList()
getActiveFeatureList()
This method is deprecated and will be removed in SDK version 5.0.0
. Use getVariations()
instead.
To get the list of feature flag keys currently available and active for the visitor.
Return value
Type | Description |
---|---|
[String] | List of feature flag keys which are active for the visitor |
Example code
let activeFeatureFlags = kameleoonClient.getActiveFeatureList()
getActiveFeatures()
This method is deprecated and will be removed in SDK version 5.0.0
. Use getVariations()
instead.
getActiveFeatures
method retrieves information about the active feature flags that are available for the specified visitor code.
Return value
Type | Description |
---|---|
[String: Types.Variation] | A dictionary that contains the visitor's assigned variations for each active feature using the keys of the corresponding active features. |
Example code
let activeFeatures = kameleoonClient.getActiveFeatures()
Feature variables
getFeatureVariable()
- 📨 Sends Tracking Data to Kameleoon
- This method is deprecated and will be removed in SDK version
5.0.0
. UsegetVariation()
instead. - This method was previously named
obtainFeatureVariable()
, which was removed in SDK version4.0.0
.
Call this method to get the feature variable of a variation key associated with a user.
This method takes featureKey
, and variableKey
as required arguments to get the variable of the variation key for a given user.
If a visitor has never been associated with this feature flag, the SDK returns a variable value for the variation key that it randomly assigns according to the feature flag rules. If the user is already registered with this feature flag, the SDK returns the variable value for previously associated variation. If the user does not match any of the rules, the default variable is returned.
String featureKey = "myFeature"
String variableKey = "myVariable"
try {
let variable = kameleoonClient.getFeatureVariable(featureKey: featureKey, variableKey: variableKey)
// your custom code depending of variableValue
} catch {
switch error {
case KameleoonError.sdkNotReady:
// Exception indicating that the SDK has not completed its initialization yet.
case KameleoonError.Feature.notFound:
// The Feature Key is not yet in the configuration file that has been fetched by the SDK. Trigger the old checkout for this visitor.
case KameleoonError.Feature.environmentDisabled:
// The feature flag is disabled for the environment
case KameleoonError.Feature.variableNotFound:
// Exception indicating that the requested variable has not been found. Check that the variable's key matches the one in your code.
default:
// Any other error
}
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | Identification key of the feature you want to retrieve. This field is required. |
variableKey | String | Name of the variable you want to get a value for. This field is required. |
Return value
Type | Description |
---|---|
Any | Data associated with this feature flag. The values can be Int , String , Bool or Dictionary (depending on the type defined on the web interface). |
Exceptions thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |
KameleoonError.Feature.notFound | Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This usually means that the feature flag has not yet been activated on Kameleoon's side (but code implementing the feature is already deployed in the web-application). |
KameleoonException.Feature.environmentDisabled | Exception indicating that the feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
KameleoonError.Feature.variableNotFound | Exception indicating that the requested variable wasn't found. Check that the variable's key in the Kameleoon app matches the one in your code. |
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 argument, featureKey
. It returns the data with the [String: Any]
type, as defined on the web interface. It will throw an exception (KameleoonError.Feature.notFound
) if the requested feature has not been found in the internal configuration of the SDK.
let featureKey = "myFeature"
let variationKey = "on"
do {
allVariables = try kameleoonClient.getFeatureVariationVariables(featureKey: featureKey, variationKey: variationKey);
} catch KameleoonError.Feature.notFound {
// The feature is not yet activated on Kameleoon's side
} catch KameleoonError.Feature.environmentDisabled {
// The feature flag is disabled for the environment
} catch {
// This is a generic Exception handler that will handle all exceptions.
}
Arguments
Name | Type | Description |
---|---|---|
featureKey | String | Identification key of the feature you want to retrieve. This field is required. |
variationKey | String | The key of the variation you want to retrieve. This field is required. |
Return value
Type | Description |
---|---|
[String: Any] | Data associated with this feature flag. The values can be Int , String , Bool or Dictionary (depending on the type defined on the web interface). |
Exceptions thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Exception indicating that the SDK is not fully initialized yet. |
KameleoonError.Feature.notFound | Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This usually means that the feature flag has not been activated in the Kameleoon app (but code implementing the feature is already deployed in the web application). |
KameleoonException.Feature.environmentDisabled | Exception indicating that the feature flag is disabled for the visitor's current environment (for example, production, staging, or development). |
KameleoonError.Feature.variationNotFound | Exception indicating that the requested variation key has not been found in the internal configuration of the SDK. This means that the feature flag has not yet been retrieved by the SDK. This may happen if the SDK is in polling mode. |
Example code
let featureKey = "myFeature"
let variationKey = "on"
do {
allVariables = try kameleoonClient.getFeatureVariationVariables(featureKey: featureKey, variationKey: variationKey);
} catch KameleoonError.Feature.notFound {
// The feature is not yet activated on Kameleoon's side
} catch KameleoonError.Feature.environmentDisabled {
// The feature flag is disabled for the environment
} catch {
// This is a generic Exception handler that will handle all exceptions.
}
Goals
trackConversion()
- 📨 Sends Tracking Data to Kameleoon
Use this method to track conversions. This method requires goalId
to track conversion on this particular goal. In addition, this method also accepts revenue
as a third optional argument to track revenue.
The trackConversion()
method doesn't return any value. This method is non-blocking as the server call is made asynchronously.
let goalId = 83023
kameleoonClient.trackConversion(goalId: goalId, revenue: 10.0)
Arguments
Name | Type | Description |
---|---|---|
goalId | Int | ID of the goal. This field is required. |
revenue | Float | Revenue of the conversion. This field is optional. |
Errors thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Error indicating that the SDK has not completed its initialization yet. |
Example code
let goalId = 83023
kameleoonClient.trackConversion(goalId: goalId, revenue: 10.0)
Events
updateConfigurationHandler()
The updateConfigurationHandler()
method allows you to handle the event when configuration has updated data. It takes one input argument handler
. The handler that will be called when the configuration is updated using a real-time configuration event.
kameleoonClient.addData(CustomData(id: 20, values: "true", "20"))
kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))
kameleoonClient.flush()
Arguments
Name | Type | Description |
---|---|---|
handler | Optional<(() -> Void)> | The handler that will be called when the configuration is updated using a real-time configuration event. |
kameleoonClient.updateConfigurationHandler {
// configuration was updated
}
Visitor data
visitorCode
Unique visitor code used in SDK.
let visitorCode = kameleoonClient.visitorCode
Return value
Type | Description |
---|---|
String | String representing a unique visitor code used in SDK. |
getRemoteData()
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.
Since a server call is required, this mechanism is asynchronous, and you must pass a completionHandler
as an argument to the method.
struct Test1: Decodable {
let value: String
private enum CodingKeys: String, CodingKey {
case value = "json_value"
}
}
kameleoonClient.getRemoteData(key: "test") { (result: Result<Test1, Error>) in
switch result {
case .success(let test1):
// test1 is a decoded value for Test1 type
case .failure:
// error represents with informaion about request's failure
}
}
kameleoonClient.getRemoteData(key: "test") { (data: Result<Data, Error>) in
switch result {
case .success(let data):
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
print(json)
}
case .failure:
// error represents with informaion about request's failure
}
}
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.
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 | Types.RemoteVisitorDataFilter | Filter that selects which data (see table below) should be retrieved from visit history. By default, getRemoteVisitorData retrieves CustomData from the current and latest previous visit (new RemoteVisitorDataFilter(1, true, true, false, false, false) or new RemoteVisitorDataFilter() ). All other filters parameters default to false . This field is optional. |
addData | Bool | A boolean indicating whether the method should automatically add the retrieved data for a visitor. This field is optional. The default value is true . |
completion | (Result<[KameleoonData], Error>) -> Void | A closure that takes an Result<[KameleoonData], Error> parameter to handle the result. Confirms that the data has been added to the visitor. If addData is false, it only indicates the value was retrieved. |
Here is the list of available Types.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) | Bool | If true, current visit data will be retrieved | true |
customData (optional) | Bool | If true, custom data will be retrieved. | true |
conversions (optional) | Bool | If true, conversion data will be retrieved. | false |
experiments (optional) | Bool | If true, experiment data will be retrieved. | false |
geolocation (optional) | Bool | If true, geolocation data will be retrieved. | false |
kcs (optional) | Bool | If true, Kameleoon Conversion Score (KCS) will be retrieved. Requires the AI Predictive Targeting add-on | false |
Example code
// Visitor data will be fetched and automatically added
kameleoonClient.getRemoteVisitorData { result in
switch result {
case .success(let visitorData):
// visitorData represents all data which was retrieved and added for the visitor
case .failure:
// error contains information about the reason for the request failure
}
}
// If you only want to fetch data and add it yourself manually, set addData == `false`
kameleoonClient.getRemoteVisitorData(addData: false) { result in
switch result {
case .success(let visitorData):
// visitorData represents all data which was retrieved but not added for the visitor
case .failure:
// error contains information about the reason for the request failure
}
}
// If you want to fetch custom list of data types
let filter = Types.RemoteVisitorDataFilter(
previousVisitAmount: 25, currentVisit: true, conversions: true, experiments: true, geolocation: true
)
kameleoonClient.getRemoteVisitorData(filter: filter) { result in
switch result {
case .success(let visitorData):
// visitorData represents all data which was retrieved and added for the visitor
case .failure:
// error contains information about the reason for the request failure
}
}
Arguments
Name | Type | Description |
---|---|---|
filter | Types.RemoteVisitorDataFilter | Filter that selects which data should be retrieved from visit history. By default, getRemoteVisitorData retrieves CustomData from the current and latest previous visit (new RemoteVisitorDataFilter(1, true, true, false, false, false) or new RemoteVisitorDataFilter() ). All other filters parameters default to false . This field is optional. |
addData | Bool | A boolean indicating whether the method should automatically add the retrieved data for a visitor. This field is optional. The default value is true . |
completion | (Result<[KameleoonData], Error>) -> Void | A closure that takes an Result<[KameleoonData], Error> parameter to handle the result. Confirms that the data has been added to the visitor. If addData is false, it only indicates the value was retrieved. |
Here is the list of available Types.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) | Bool | If true, current visit data will be retrieved | true |
customData (optional) | Bool | If true, custom data will be retrieved. | true |
conversions (optional) | Bool | If true, conversion data will be retrieved. | false |
experiments (optional) | Bool | If true, experiment data will be retrieved. | false |
geolocation (optional) | Bool | If true, geolocation data will be retrieved. | false |
kameleoonClient.getVisitorWarehouseAudience(customDataIndex: 10) { result in
switch result {
case .success(let customData):
// Data was added. You can access the data from the `customData` value.
case .failure:
// error contains information about failure of request
}
}
// If you need to specify a warehouse key
kameleoonClient.getVisitorWarehouseAudience(
warehouseKey: "warehouseKey",
customDataIndex: 10)
{ result in
switch result {
case .success(let customData):
// Data was added. You can access the data from the `customData` value.
case .failure:
// error contains information about failure of request
}
}
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. Note that the trackConversion method also sends out any previously associated data, just like the flush method. The same is true for getFeatureVariationKey and getFeatureVariable 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 customDataIndex
.
Arguments
Name | Type | Description |
---|---|---|
data | KameleoonData... or [KameleoonData] | One or more values conforming to the KameleoonData protocol. |
Errors thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Error indicating that the SDK is not fully initialized yet. |
Example code
kameleoonClient.addData(CustomData(id: 20, values: "true", "20"))
kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))
kameleoonClient.addData([
CustomData(id: 20, values: "true", "20"),
Conversion(goalId: 32)
])
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 a 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.
Arguments
Name | Type | Description |
---|---|---|
instant | boolean | Boolean flag indicating whether the data should be sent instantly (true ) or according to the default tracking interval (false ) set with the SDK parameter trackingIntervalMillisecond in KameleoonClientConfig or tracking_interval_millisecond . This field is optional. |
Errors thrown
Type | Description |
---|---|
KameleoonError.sdkNotReady | Error indicating that the SDK has not completed its initialization yet. |
kameleoonClient.addData(CustomData(id: 20, values: "true", "20"))
kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))
kameleoonClient.flush() // Interval tracking (most performant way for tracking)
kameleoonClient.flush(instant: true) // Instant tracking
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
kameleoonClient.setLegalConsent(true)
Data types
This section lists the 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.
Name | Type | Description |
---|---|---|
goalID | String | ID of the goal. This field is required. |
revenue | Float | Conversion revenue. This field is optional. |
negative | Bool | Defines if the revenue is positive or negative. This field is optional. |
Example code
try? kameleoonClient.addData(Conversion(goalId: 32, revenue: 10.0, negative: false))
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 | The index a (a unique ID) of the custom data to store. This field is required. |
value | String | Value of the custom data to store. This field is required. |
values | String... or [String] | Value(s) of the custom data to store. |
You can find the index (ID) for your custom data 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 has an ID value of 0, not 1.
Example code
try? kameleoonClient.addData(CustomData(id: 1, value: "some custom value"))
try? kameleoonClient.addData(CustomData(id: 1, value: "first value", "second value"))
try? kameleoonClient.addData(CustomData(id: 1, values: ["first value", "second value"]))
Device
Store information about the user's device.
Name | Type | Description |
---|---|---|
device | Device | List of devices: phone , tablet , desktop . This field is required. |
Example code
try? kameleoonClient.addData(Device.desktop);
Geolocation
Geolocation
contains the visitor's geolocation details.
Each visitor can only have one Geolocation
. Adding a second Geolocation
instance overwrites the first one.
Name | Type | Description |
---|---|---|
country | string | The country of the visitor. This field is required. |
region | string | The region of the visitor. This field is optional. |
city | string | The city of the visitor. This field is optional. |
postalCode | string | The postal code of the visitor. This field is optional. |
latitude | float | The latitudinal coordinate for the position of the visitor. Coordinate number represents decimal degrees (a double that can be negative). This field is optional. |
longitude | float | The longitudinal coordinate for the position of the visitor. Provide the coordinate number in decimal degrees (a double that can be negative). This field is optional. |
kameleoonClient.addData(Geolocation(country: "France", region: "Île-de-France", city: "Paris"));
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 | Int | The ID of the assigned variation (or -1 if it's the default variation). |
experimentId | Int | The ID of the experiment associated with the variation (or -1 if default). |
variables | [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 be-1
, indicating a default variation. - The
variables
map might be empty if no variables are associated with the variation.
Example code
// Retrieving the variation key
let variationKey: String = variation.key
// Retrieving the variation id
let variationId: Int = variation.id
// Retrieving the experiment id
let experimentId: Int = variation.experimentId
// Retrieving the variables map
let variables: [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 | Any? | The value of the variable, which can be of the following types: Bool, Int, Double, String, [String: Any] (json object), [Any] (json array). |
Example code
// Retrieving the variables map
let variables: [String: Variable] = variation.variables
// Variable type can be retrieved for further processing
let type: String = variables["isDiscount"]?.type ?? ""
// Retrieving the variable value by key
let isDiscount: Bool = variables["isDiscount"]?.value as? Bool ?? false
// Variable value can be of different types
let title: String = variables["title"]?.value as? String ?? ""