React Native SDK
Introduction
Welcome to the developer documentation for the Kameleoon React SDK! Our SDK gives you the possibility of running experiments and activating feature flags on your front-end web and mobile application. Integrating our SDK into your web and mobile application is easy, and its footprint (in terms of memory and network usage) is low.
Before you begin installing our React SDK, we recommend that you read our technical considerations article to gain an understanding of the fundamental technological concepts behind our SDKs. This will help you to better understand the SDK and ensure a successful integration.
The React SDK offers versatile functionality that can be leveraged for both React and React Native applications. While the majority of the hooks function in a consistent manner across both platforms, it should be noted that React Native employs a distinct mechanism for storing feature flag related data. Specifically, React Native utilizes the MMKV
storage mechanism rather than the localStorage
approach utilized by browsers.
To ensure seamless integration between your React Native
application and the React SDK
, it is highly recommended to review the React Native Considerations section. This section provides essential guidance for optimizing compatibility and ensuring proper functionality.
Changelog
Latest version description of React SDK can be found here.
Requirements
React SDK requires React 16.8.0+
Installation
Use preferred package manager to install React SDK from npm repository.
Npm:
npm install @kameleoon/react-sdk
Yarn:
yarn add @kameleoon/react-sdk
Pnpm:
pnpm add @kameleoon/react-sdk
Contents
To configure your React application and start running feature experiments and deploying new features to your users, please follow the instructions provided in the Main usage section. This section contains all the main steps for proper Kameleoon React SDK configuration as well as main tools for development.
- Create Kameleoon Client
- Wrap application in Kameleoon Provider
- Await for client initialization
- Getting access to feature flags and variations
- Using Kameleoon CLient hooks
We highly recommend that you take a look at the Additional Tools section, which includes useful information on every hook that is introduced in React SDK.
- Get Visitor Code / Use Own Visitor ID
- Initialize Kameleoon Client
- Add associated client data
- Track Conversion
- Flush tracking data
- Get list of all experiments
- Get list of experiments for certain visitor
- Get a certain experiment variation data
- Get list of all feature flags
- Get list of feature flags for certain visitor
- Check if the feature is active for visitor
- Get variation key for a certain feature flag
- Get a variable of a certain feature flag
- Obtain data from Kameleoon remote source
- Obtain custom data from Kameleoon Data API
- Define an action for real time configuration update
- Sending exposure events to external tools
Explore additional sections with some useful information on Kameleoon:
- Data types
- React Native Consideration
- List of supported targeting conditions
- Synchronizing custom data across devices
- Error handling
Migration
We have introduced new version of React SDK with the breaking changes.
Migration considerations
- All
HOCs
,Feature
render props,compose
were removed. - All data types hooks were removed:
useDevice
,useConversion
,useCustomData
,usePageView
,useBrowser
.
Removed hooks:
useRunWhenReady
(no longer needed, useuseInitialize
instead)useFeature
Renamed hooks:
useActivateFeature
->useFeatureFlagActive
useVisitorCode
->useBrowserVisitorCode
useAsyncVisitorCode
->useNativeVisitorCode
useRetrieveDataFromRemoteSource
->useRemoteData
useVariationAssociatedData
->useExperimentVariationData
Added hooks:
useInitialize
useConfigurationUpdate
useFeatureFlags
useVisitorFeatureFlags
useExperiments
useVisitorExperiments
useFeatureFlagVariationKey
useEngineTrackingCode
useRemoteVisitorData
Main Usage
Here is a step by step guide for configuring React JS SDK for your application.
1. Create Kameleoon Client
createClient
- Typescript / Javascript
import { createClient, Environment } from '@kameleoon/react-sdk';
const client = createClient('my_site_code', {
updateInterval: 60,
environment: Environment.Production,
});
For the start developers will need to create an entry point for React SDK by creating Kameleoon Client on the top level of your application which is done by using createClient()
function imported from kameleoon package.
An instance of KameleoonClient
is created using createClient()
function.
Parameters
Name | Type | Description |
---|---|---|
siteCode (required) | string | client's siteCode defined on Kameleoon platform |
configuration (optional) | Partial<SDKConfigurationType> | client's configuration |
configuration
consists of following parameters:
Name | Type | Description | Default Value |
---|---|---|---|
updateInterval (optional) | number | update interval in minutes for sdk configuration, minimum value is 1 minute | 60 |
environment (optional) | Environment | feature flag environment | Environment.Production |
targetingDataCleanupInterval (optional) | number or undefined | interval in minutes for cleaning up targeting data, minimum value is 1 minute | undefined (no cleanup will be performed) |
Returns
KameleoonClient
- an instance of KameleoonClient.
Make sure not to use several client instances in one application as it is not fully supported yet, which may lead to local storage configuration being overwritten and cause bugs.
2. Wrap application in Kameleoon Provider
The second step is connecting previously created Kameleoon Client to KameleoonProvider
. It can be done by passing configured client to KameleoonProvider
as follows.
- Typescript
- Javascript
import {
createClient,
Environment,
KameleoonProvider,
} from '@kameleoon/react-sdk';
const client = createClient('my_site_code', {
updateInterval: 60,
environment: Environment.Production,
});
function AppWrapper(): JSX.Element {
return (
<KameleoonProvider client={client}>
<App />
</KameleoonProvider>
);
}
import {
createClient,
Environment,
KameleoonProvider,
} from '@kameleoon/react-sdk';
const client = createClient('my_site_code', {
updateInterval: 60,
environment: Environment.Production,
});
function AppWrapper() {
return (
<KameleoonProvider client={client}>
<App />
</KameleoonProvider>
);
}
KameleoonProvider
Use this provider on root level by wrapping your app to gain an access to KameleoonClient
. This ensures your app does not flicker due to flag changes at startup time.
Props
Name | Type | Description |
---|---|---|
children (required) | ReactNode | child elements of the provider |
client (required) | KameleoonClient | KameleoonClient instance created by createClient() |
3. Await for the client initialization
KameleoonClient
initialization is done asynchronously in order to make sure that Kameleoon API call was successful for that hook useInitialize
is used. You can use async/await
, Promise.then()
or any other method to handle asynchronous client initialization.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useInitialize } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
// -- Waiting for the client initialization using `async/await`
const init = useCallback(async (): Promise<void> => {
await initialize();
}, [initialize]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import { useInitialize } from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
// -- Waiting for the client initialization using `async/await`
const init = useCallback(async () => {
await initialize();
}, [initialize]);
useEffect(() => {
init();
}, [init]);
}
4. Getting access to feature flags and variations
To implement a feature flag in your code, you must first create a feature flag in your Kameleoon account.
After the SDK has been initialized, you can obtain a feature flag configuration. Subsequently, all hooks will require you to specify the User ID or visitor code associated with the request.
If you are using Kameleoon in Hybrid mode with mixed front-end and back-end environments, you can call the useBrowserVisitorCode hook to obtain the Kameleoon visitorCode for the current visitor. Alternatively, if you provide your own User ID, you must ensure its uniqueness on your end.
5. Using Kameleoon Client hooks
Now that KameleoonClient
is created, configured and added to a KameleoonProvider
it is possible to communicate with your feature flag and experiments from the inside of React Components.
To associate various data points with the current user, you can use the useAddData hook. This hook returns addData
function which requires the visitorCode as the first parameter and accepts several additional parameters. These additional parameters represent the various Data Types allowed in Kameleoon.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useAddData,
useBrowserVisitorCode,
useTriggerExperiment,
useTrackConversion,
useFeatureFlagActive,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { triggerExperiment } = useTriggerExperiment();
const { trackConversion } = useTrackConversion();
const { isFeatureFlagActive } = useFeatureFlagActive();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Trigger an experiment
const experimentId = 100;
const variationId = triggerExperiment(visitorCode, experimentId);
// -- Add user data
const customDataIndex = 0;
addData(visitorCode, new CustomData(customDataIndex, 'my_data'));
// -- Check if the feature is active for visitor
const isMyFeatureActive = isFeatureFlagActive(
visitorCode,
'my_feature_key',
);
// -- Track conversion
trackConversion({ visitorCode, revenue: 20000, goalId: 123 });
}, [
initialize,
visitorCode,
triggerExperiment,
isFeatureFlagActive,
trackConversion,
]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useAddData,
useBrowserVisitorCode,
useTriggerExperiment,
useTrackConversion,
useFeatureFlagActive,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { triggerExperiment } = useTriggerExperiment();
const { trackConversion } = useTrackConversion();
const { isFeatureFlagActive } = useFeatureFlagActive();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Trigger an experiment
const experimentId = 100;
const variationId = triggerExperiment(visitorCode, experimentId);
// -- Add user data
const customDataIndex = 0;
addData(visitorCode, new CustomData(customDataIndex, 'my_data'));
// -- Check if the feature is active for visitor
const isMyFeatureActive = isFeatureFlagActive(
visitorCode,
'my_feature_key',
);
// -- Track conversion
trackConversion({ visitorCode, revenue: 20000, goalId: 123 });
}, [
initialize,
visitorCode,
triggerExperiment,
isFeatureFlagActive,
trackConversion,
]);
useEffect(() => {
init();
}, [init]);
}
Feature flags can be very useful for implementing ON/OFF switches with optional but advanced user targeting rules. However, you can also use feature flags to run feature experiments with several variations of your feature flag. Check out our documentation on creating feature experiments for more information.
See Additional Tools section for detailed guide for each KameleoonClient
hook available.
Additional Tools
Get Visitor Code / Use Own Visitor ID
React SDK provides dedicated hooks for React useBrowserVisitorCode and React Native useNativeVisitorCode.
useBrowserVisitorCode
A hook that returns getBrowserVisitorCode
function which obtains visitor code from browser cookie, if the visitor code doesn't yet exist generates a random visitor code (or uses a provided default) and sets a new visitor code to cookie.
- Typescript
- Javascript
import { useBrowserVisitorCode } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
// -- Pass default visitorCode, save and retrieve it
const visitorCode = getBrowserVisitorCode(
'www.example.com',
'default_visitor_code',
);
}
import { useBrowserVisitorCode } from '@kameleoon/react-sdk';
function MyComponent() {
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
// -- Pass default visitorCode, save and retrieve it
const visitorCode = getBrowserVisitorCode(
'www.example.com',
'default_visitor_code',
);
}
Callback Parameters
Name | Type | Description |
---|---|---|
domain (required) | string | domain which cookie belongs to |
defaultVisitorCode (optional) | string | visitor code to be used in case there is no visitor code in cookies |
If defaultVisitorCode
wasn't provided and there is no visitor code stored in cookie it will be randomly generated
Callback Returns
string
- result visitor code.
Initialize Kameleoon Client
useInitialize
A hook that returns an asynchronous initialize
function which is used for KameleoonClient initialization by fetching Kameleoon SDK related data from server or by retrieving data from local source if data is up-to-date or update interval has not been reached.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useInitialize } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const init = useCallback(async (): Promise<void> => {
await initialize();
}, [initialize]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import { useInitialize } from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const init = useCallback(async () => {
await initialize();
}, [initialize]);
useEffect(() => {
init();
}, [init]);
}
Client initialization has an optional offline mode.
It is activated by setting optional useCache
parameter to true
. Offline mode allows for silent polling fails.
If the SDK successfully initializes and then loses internet connection, the SDK still tries to fetch the configuration at the next updateInterval
, which results in initialize
errors. If initialized in offline mode, the SDK will continue to function using the most recently fetched experiment and feature flag configuration from its cache. Activating offline mode doesn't prevent initialization from failing if there is no cached data available.
If tracking requests from returned functions of the following hooks fail due to internet connectivity issues, the SDK automatically resends the request as soon as it detects that the internet connection has been re-established:
Callback Parameters
Name | Type | Description | Default Value |
---|---|---|---|
useCache (optional) | boolean or undefined | parameter for activating SDK offline mode, if true is passed failed polls will not return error and will use cached data if such data is available | false |
Callback Returns
Promise<boolean>
- a promise resolved to a boolean indicating a successful sdk initialization. Generally initialize will throw an error if the something that can not be handled will happen, so the boolean
value will almost always be true
and won't give as much useful information.
Throws
Type | Description |
---|---|
KameleoonException.StorageWrite | Couldn't update storage data |
KameleoonException.ClientConfiguration | Couldn't retrieve client configuration from Kameleoon API |
KameleoonException.MaximumRetriesReached | Maximum retries reached, request failed |
Add associated client data
useAddData
A hook that returns addData
function which adds targeting data to the storage so that other hooks could decide whether the current visitor is targeted or not.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
Browser,
BrowserType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Create Kameleoon Data Types
const customData = new CustomData(0, 'my_data');
const browserData = new Browser(BrowserType.Chrome);
// -- Add one Data item to Storage
addData(visitorCode, browserData);
// -- Add Data to Storage using variadic style
addData(visitorCode, browserData, customData);
// -- Add Data to Storage in array
addData(visitorCode, ...[browserData, customData]);
}, [initialize, visitorCode, addData]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
Browser,
BrowserType,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Create Kameleoon Data Types
const customData = new CustomData(0, 'my_data');
const browserData = new Browser(BrowserType.Chrome);
// -- Add one Data item to Storage
addData(visitorCode, browserData);
// -- Add Data to Storage using variadic style
addData(visitorCode, browserData, customData);
// -- Add Data to Storage in array
addData(visitorCode, ...[browserData, customData]);
}, [initialize, visitorCode, addData]);
useEffect(() => {
init();
}, [init]);
}
The addData()
function 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 via the useFlush hook .This approach helps reduce the number of server calls made, as the data is typically grouped into a single server call triggered by the execution of useFlush.
The useTrackConversion hook also sends out any previously associated data, just like the useFlush. The same holds true for useFeatureVariationKey and useFeatureVariable hooks if an experimentation rule is triggered. :::
userAgent
data will not be stored in storage like other data, and it will be sent with every tracking request for bot filtration.
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
.
Check the list of supported conditions to know what data types can be used for targeting
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
kameleoonData (optional) | KameleoonDataType[] | number of instances of any type of KameleoonData , can be added solely in array or as sequential arguments |
kameleoonData
is variadic argument it can be passed as one or several arguments (see the example)
The index or ID of the custom data can be found in your Kameleoon account. It is important to note that this index starts at 0
, which means that the first custom data you create for a given site will be assigned 0
as its ID, not 1
.
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.StorageWrite | Couldn't update storage data |
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Check Data Types reference for more details of how to manage different data types
Trigger an Experiment (without feature flags)
useTriggerExperiment
The useTriggerExperiment()
method will be deprecated as part of sunsetting the SDK/Hybrid experimentation in September 2023. Use feature experimentation methods instead.
A hook that returns the triggerExperiment
function which triggers an experiment by assigning the specified variation to the user with the specified visitorCode
. If the variation is already assigned, the function returns the variation ID and sends the tracking request.
The triggerExperiment
function allows you to run server-side or hybrid experiments without the need to configure feature flags.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useTriggerExperiment,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { triggerExperiment } = useTriggerExperiment();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
const experimentId = 123;
// -- Trigger Experiment and obtain variation id
const variationId = triggerExperiment(visitorCode, experimentId);
}, [initialize, visitorCode, triggerExperiment]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useTriggerExperiment,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { triggerExperiment } = useTriggerExperiment();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
const experimentId = 123;
// -- Trigger Experiment and obtain variation id
const variationId = triggerExperiment(visitorCode, experimentId);
}, [initialize, visitorCode, triggerExperiment]);
useEffect(() => {
init();
}, [init]);
}
Returned id 0
indicates default variation.
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
experimentId (required) | number | id of experiment running for the current visitor. |
Callback Returns
number
- associated variationId which is successfully found in storage or newly assigned.
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.ExperimentConfigurationNotFound | No configuration found for provided experimentId |
KameleoonException.StorageRead | Couldn't find associated experiment by provided experimentId and visitorCode inside the storage |
KameleoonException.NotTargeted | Current visitor is not targeted |
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Track Conversion
useTrackConversion
A hook that returns trackConversion
function which creates and adds Conversion data to the visitor with specified parameters and executes flush
.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useTrackConversion,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { trackConversion } = useTrackConversion();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Track conversion
trackConversion({ visitorCode, revenue: 2000, goalId: 123 });
}, [initialize, trackConversion, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useTrackConversion,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { trackConversion } = useTrackConversion();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Track conversion
trackConversion({ visitorCode, revenue: 2000, goalId: 123 });
}, [initialize, trackConversion, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
It's a helper hook for the quick and convenient conversion tracking, however creating and adding Conversion manually allows more flexible Conversion
with negative
parameter
Callback Parameters
Parameters object consisting of:
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
goalId (required) | number | goal to be sent in tracking request |
revenue (optional) | number | revenue to be sent in tracking request |
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.StorageWrite | Couldn't update storage data |
Flush tracking data
useFlush
A hook that returns flush
function which takes the Kameleoon data associated with the visitor and sends the data tracking request along with all of the data that's been added previously using the useAddData.
If a visitorCode
isn't provided, the SDK flushes all of its stored data to the remote Kameleoon servers.
If any previously failed tracking requests were stored locally during offline mode, the SDK attempts to send the stored requests before executing the latest request.
Previously, the hook was named useFlushData
, which has been deprecated since 7.4.0
.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
useFlush,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
const { flush } = useFlush();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Create instance of CustomData
const customData = new CustomData(0, 'my_data');
addData(visitorCode, customData);
// -- Flush added custom data
flush(visitorCode);
}, [initialize, visitorCode, addData, flush]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
useFlush,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
const { flush } = useFlush();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Create instance of CustomData
const customData = new CustomData(0, 'my_data');
addData(visitorCode, customData);
// -- Flush added custom data
flush(visitorCode);
}, [initialize, visitorCode, addData, flush]);
useEffect(() => {
init();
}, [init]);
}
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (optional) | string | unique visitor identification string, can't exceed 255 characters length, if not passed all the data will be flushed (sent to the remote Kameleoon servers) |
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Get list of all experiments
useExperiments
The useExperiments()
method will be deprecated as SDK and Hybrid type experiments are being merged with feature experimentation in September 2023. Use feature experimentation methods instead.
A hook that returns getExperiments
function which returns a list of experiments stored in the client configuration.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useInitialize, useExperiments } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getExperiments } = useExperiments();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get experiment list
const experiments = getExperiments();
}, [initialize, getExperiments]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import { useInitialize, useExperiments } from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getExperiments } = useExperiments();
const init = useCallback(async () => {
await initialize();
// -- Get experiment list
const experiments = getExperiments();
}, [initialize, getExperiments]);
useEffect(() => {
init();
}, [init]);
}
Callback Returns
ExperimentType[]
- list of experiments, each experiment item contains id
and name
.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Get list of experiments for a certain visitor
useVisitorExperiments
The useVistorExperiments()
method will be deprecated as SDK and Hybrid type experiments are being merged with feature experimentation in September 2023. Use feature experimentation methods instead.
A hook that returns getVisitorExperiments
function which returns a list of experiments that the visitor with visitorCode
is targeted by and that are active for the visitor.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useVisitorExperiments,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getVisitorExperiments } = useVisitorExperiments();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get all visitor experiments
const experiments = getVisitorExperiments(visitorCode, false);
// -- Get only allocated visitor experiments
const allocatedExperiments = getVisitorExperiments(visitorCode);
}, [initialize, visitorCode, getVisitorExperiments]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useVisitorExperiments,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getVisitorExperiments } = useVisitorExperiments();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Get all visitor experiments
const experiments = getVisitorExperiments(visitorCode, false);
// -- Get only allocated visitor experiments
const allocatedExperiments = getVisitorExperiments(visitorCode);
}, [initialize, visitorCode, getVisitorExperiments]);
useEffect(() => {
init();
}, [init]);
}
Visitor will have one of the variations allocated if the experiment was triggered
Callback Parameters
Name | Type | Description | Default Value |
---|---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length | - |
isAllocated (optional) | boolean | boolean value indicating that only experiments allocated for visitor will be returned. | true |
Callback Returns
ExperimentType[]
- list of experiments, each experiment item contains id
and name
.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
Get a certain experiment variation data
useExperimentVariationData
A hook that returns getExperimentVariationData
function which returns variation data in JSON format for the variation with variationId
.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useExperimentVariationData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getExperimentVariationData } = useExperimentVariationData();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get experiment variation data
const variationId = 100;
const variationDataJson = getExperimentVariationData(variationId);
}, [initialize, visitorCode, getVisitorExperiments]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useExperimentVariationData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getExperimentVariationData } = useExperimentVariationData();
const init = useCallback(async () => {
await initialize();
// -- Get experiment variation data
const variationId = 100;
const variationDataJson = getExperimentVariationData(variationId);
}, [initialize, visitorCode, getVisitorExperiments]);
useEffect(() => {
init();
}, [init]);
}
Callback Parameters
Name | Type | Description |
---|---|---|
variationId (required) | number | id of a variation |
Callback Returns
JSONType
- variation data in JSON format.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.JSONParse | Couldn't parse retrieved data to JSON format |
KameleoonException.VariationNotFound | No variation found for provided variationId |
Get list of all feature flags
useFeatureFlags
A hook that returns getFeatureFlags
function which returns a list of feature flags stored in the client configuration.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useInitialize, useFeatureFlags } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getFeatureFlags } = useFeatureFlags();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get list of all feature flags
const featureFlags = getFeatureFlags();
}, [initialize, getFeatureFlags]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import { useInitialize, useFeatureFlags } from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getFeatureFlags } = useFeatureFlags();
const init = useCallback(async () => {
await initialize();
// -- Get list of all feature flags
const featureFlags = getFeatureFlags();
}, [initialize, getFeatureFlags]);
useEffect(() => {
init();
}, [init]);
}
Callback Returns
FeatureFlagType[]
- list of feature flags, each experiment item contains id
and key
.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Get list of feature flags for a certain visitor
useVisitorFeatureFlags
A hook that returns getVisitorFeatureFlags
function which returns a list of feature flags that the visitor with visitorCode
that is targeted by and that are active for the visitor (visitor will have one of the variations allocated).
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useVisitorFeatureFlags,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getVisitorFeatureFlags } = useVisitorFeatureFlags();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get active feature flags for visitor
const featureFlags = getVisitorFeatureFlags(visitorCode);
}, [initialize, visitorCode, getVisitorFeatureFlags]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useVisitorFeatureFlags,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getVisitorFeatureFlags } = useVisitorFeatureFlags();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Get active feature flags for visitor
const featureFlags = getVisitorFeatureFlags(visitorCode);
}, [initialize, visitorCode, getVisitorFeatureFlags]);
useEffect(() => {
init();
}, [init]);
}
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
Callback Returns
FeatureFlagType[]
- list of feature flags, each experiment item contains id
and key
.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.NotTargeted | Current visitor is not targeted |
Check if the feature is active for visitor
useFeatureFlagActive
A hook that returns a callback function isFeatureFlagActive()
which indicates whether the visitor with visitorCode
has featureKey
active for him, this includes targeting check, finding the according variation exposed to the visitor and saving it to storage along with sending tracking request.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useAddData,
useFeatureFlagActive,
useBrowserVisitorCode,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { isFeatureFlagActive } = useFeatureFlagActive();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code using `getBrowserVisitorCode` function
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
const featureKey = 'my_feature_key';
// -- Add CustomData with index `0` containing visitor id to check the targeting
addData(visitorCode, new CustomData(0, 'visitor_id'));
// -- Get the status of feature flag
const isActive = isFeatureFlagActive(visitorCode, featureKey);
}, [initialize, visitorCode, isFeatureFlagActive]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useAddData,
useFeatureFlagActive,
useBrowserVisitorCode,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { isFeatureFlagActive } = useFeatureFlagActive();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code using `getBrowserVisitorCode` function
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
const featureKey = 'my_feature_key';
// -- Add CustomData with index `0` containing visitor id to check the targeting
addData(visitorCode, new CustomData(0, 'visitor_id'));
// -- Get the status of feature flag
const isActive = isFeatureFlagActive(visitorCode, featureKey);
}, [initialize, visitorCode, isFeatureFlagActive]);
useEffect(() => {
init();
}, [init]);
}
Visitor must be targeted to has feature flag active
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
featureKey (required) | string | a unique key for feature flag |
Callback Returns
boolean
- indicator of whether the feature flag with featureKey
is active for visitor with visitorCode
.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.NotTargeted | Current visitor is not targeted |
KameleoonException.FeatureFlagConfigurationNotFound | No feature flag was found for provided visitorCode and featureKey |
KameleoonException.DataInconsistency | Allocated variation was found but there is no feature flag with according featureKey |
Get variation key for a certain feature flag
useFeatureFlagVariationKey
A hook that returns a callback function getFeatureFlagVariationKey()
which returns variation key for the visitor under visitorCode
in the found feature flag, this includes targeting check, finding the according variation exposed to the visitor and saving it to storage along with sending tracking request.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useFeatureFlagVariationKey,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getFeatureFlagVariationKey } = useFeatureFlagVariationKey();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code using `getBrowserVisitorCode` function
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
const featureKey = 'my_feature_key';
// -- Get the variationKey for the visitor under `visitorCode` in the found feature flag
const variationKey = getFeatureFlagVariationKey(visitorCode, featureKey);
}, [initialize, visitorCode, getFeatureFlagVariationKey]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useFeatureFlagVariationKey,
useBrowserVisitorCode,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getFeatureFlagVariationKey } = useFeatureFlagVariationKey();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
// -- Get visitor code using `getBrowserVisitorCode` function
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
const featureKey = 'my_feature_key';
// -- Get the variationKey for the visitor under `visitorCode` in the found feature flag
const variationKey = getFeatureFlagVariationKey(visitorCode, featureKey);
}, [initialize, visitorCode, getFeatureFlagVariationKey]);
useEffect(() => {
init();
}, [init]);
}
If the user has never been associated with the feature flag, the SDK returns a variation key randomly, following the feature flag rules. If the user is already registered with the feature flag, the SDK detects the previous variation key value. If the user doesn't match any of the rules, the default value defined in Kameleoon's feature flag delivery rules will be returned. It's important to note that the default value may not be a variation key, but a boolean value or another data type, depending on the feature flag configuration.
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
featureKey (required) | string | a unique key for feature flag |
Callback Returns
string
- a string containing variable key for the allocated feature flag variation for the provided visitor.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.NotTargeted | Current visitor is not targeted |
KameleoonException.FeatureFlagConfigurationNotFound | No feature flag was found for provided visitorCode and featureKey |
Get a variable of a certain feature flag
useFeatureVariable
A hook that returns getFeatureFlagVariable
function which returns a variable for the visitor under visitorCode
in the found feature flag, this includes targeting check, finding the according variation exposed to the visitor and saving it to storage along with sending tracking request.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useFeatureVariable,
VariableType,
JSONType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getFeatureFlagVariable } = useFeatureVariable();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Get feature variable
const result = getFeatureFlagVariable({
visitorCode,
featureKey: 'my_feature_key',
variableKey: 'my_variable_key',
});
// -- Infer the type of variable by it's `type`
switch (result.type) {
case VariableType.BOOLEAN:
const myBool: boolean = result.value;
break;
case VariableType.NUMBER:
const myNum: number = result.value;
break;
case VariableType.JSON:
const myJson: JSONType = result.value;
break;
case VariableType.STRING:
const myStr: string = result.value;
break;
default:
break;
}
}, [initialize, getFeatureFlagVariable, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useFeatureVariable,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { getFeatureFlagVariable } = useFeatureVariable();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Get feature variable
const variableResult = getFeatureFlagVariable({
visitorCode,
featureKey: 'my_feature_key',
variableKey: 'my_variable_key',
});
const { type, value } = variableResult;
}, [initialize, getFeatureFlagVariable, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
Callback Parameters
Parameters object of a type GetFeatureFlagVariableParamsType
containing the following fields:
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
featureKey (required) | string | a unique key for feature flag |
variableKey (required) | string | key of the variable to be found for a feature flag with provided featureKey , can be found on Kameleoon Platform |
Callback Returns
FeatureVariableResultType
- a variable object containing type
and value
fields, type
can be checked against FeatureVariableType
enum, if the type
is FeatureVariableType.BOOLEAN
then the value
type will be boolean
and so on.
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.NotTargeted | Current visitor is not targeted |
KameleoonException.FeatureFlagConfigurationNotFound | No feature flag was found for provided visitorCode and featureKey |
KameleoonException.FeatureFlagVariableNotFound | No feature variable was found for provided visitorCode and variableKey |
KameleoonException.JSONParse | Couldn't pass JSON value |
KameleoonException.NumberParse | Couldn't pass Number value |
Obtain data from Kameleoon remote source
useRemoteData
A hook that returns asynchronous getRemoteData
function which returns a data stored for specified site code on a remote Kameleoon server.
For example, you can use this function to retrieve user preferences, historical data, or any other data relevant to your application's logic. By storing this data on our highly scalable servers using our Data API, you can efficiently manage massive amounts of data and retrieve it for each of your visitors or users.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useRemoteData } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { getRemoteData } = useRemoteData();
const getData = useCallback(async (): Promise<void> => {
// -- Get remote data
const jsonData = await getRemoteData('my_data_key');
const data = JSON.parse(jsonData);
}, [getRemoteData]);
useEffect(() => {
getData();
}, [getData]);
}
import { useEffect, useCallback } from 'react';
import { useRemoteData } from '@kameleoon/react-sdk';
function MyComponent() {
const { getRemoteData } = useRemoteData();
const getData = useCallback(async () => {
// -- Get remote data
const jsonData = await getRemoteData('my_data_key');
const data = JSON.parse(jsonData);
}, [getRemoteData]);
useEffect(() => {
getData();
}, [getData]);
}
Callback Parameters
Name | Type | Description |
---|---|---|
key (required) | string | unique key that the data you try to get is associated with |
Callback Returns
JSONType
- promise with data retrieved for specific key.
Throws
Type | Description |
---|---|
KameleoonException.RemoteData | Couldn't retrieve data from Kameleoon server |
Obtain custom data from Kameleoon Data API
useRemoteVisitorData
A hook that returns asynchronous getRemoteVisitorData
function which retrieves custom data from Kameleoon server and optionally adds it to storage.
getRemoteVisitorData
automatically attaches the latest custom data entry with scope=Visitor
to the visitor without calling addData
. You can use this data for Synchronizing custom data across devices.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useRemoteVisitorData, KameleoonDataType } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { getRemoteVisitorData } = useRemoteVisitorData();
const getData = useCallback(async (): Promise<void> => {
// -- Get remote visitor data and add it to storage
const customDataList: KameleoonDataType[] = await getRemoteVisitorData(
'my_visitor_code',
);
// -- Get remote visitor data without adding to storage
const customDataList: KameleoonDataType[] = await getRemoteVisitorData(
'my_visitor_code',
false,
);
}, [getRemoteData]);
useEffect(() => {
getData();
}, [getData]);
}
import { useEffect, useCallback } from 'react';
import { useRemoteVisitorData } from '@kameleoon/react-sdk';
function MyComponent() {
const { getRemoteVisitorData } = useRemoteVisitorData();
const getData = useCallback(async () => {
// -- Get remote visitor data and add it to storage
const customDataList = await getRemoteVisitorData('my_visitor_code');
// -- Get remote visitor data without adding to storage
const customDataList = await getRemoteVisitorData('my_visitor_code', false);
}, [getRemoteData]);
useEffect(() => {
getData();
}, [getData]);
}
Callback Parameters
Name | Type | Description | Default Value |
---|---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length | - |
shouldAddData (optional) | boolean | boolean flag identifying whether the retrieved custom data should be set to the storage like addData method does | true |
Callback Returns
KameleoonDataType[]
- promise with list of custom data retrieved
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
KameleoonException.RemoteData | Couldn't retrieve data from Kameleoon server |
Define an action for real time configuration update
useConfigurationUpdate
A hook that returns onConfigurationUpdate
function which fires a callback on client configuration update.
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import { useInitialize, useConfigurationUpdate } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { onConfigurationUpdate } = useConfigurationUpdate();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Define logic to be executed on client configuration update
onConfigurationUpdate(() => {
// -- My Logic
});
}, [initialize, onConfigurationUpdate]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import { useInitialize, useConfigurationUpdate } from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { onConfigurationUpdate } = useConfigurationUpdate();
const init = useCallback(async () => {
await initialize();
// -- Define logic to be executed on client configuration update
onConfigurationUpdate(() => {
// -- My Logic
});
}, [initialize, onConfigurationUpdate]);
useEffect(() => {
init();
}, [init]);
}
This hook only works for server sent events of real time update
Callback Parameters
Name | Type | Description |
---|---|---|
callback (required) | () => void | callback function with no parameters that will be called upon configuration update |
Throws
Type | Description |
---|---|
KameleoonException.Initialization | Method was executed before initialize was done for kameleoonClient |
Sending exposure events to external tools
Kameleoon offers built-in integrations with various analytics and CDP solutions, such as Mixpanel, GA4, Segment.... To ensure that you can track and analyze your server-side experiments, Kameleoon provides a method getEngineTrackingCode()
that returns the JavasScript code to be inserted in your page to automatically send the exposure events to the analytics solution you are using. For more information about hybrid experimentation, please refer to this documentation.
To benefit from this feature, you will need to implement both the React SDK and our Kameleoon JavaScript tag. We recommend you implement the Kameleoon Asynchronous tag, which you can install before your closing <body>
tag in your HTML page, as it will be only used for tracking purposes.
useEngineTrackingCode
A hook that returns getEngineTrackingCode()
function which obtains Kameleoon tracking code for the current visitor. Tracking code is built based the experiments that were triggered during the last 5 seconds
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useTriggerExperiment,
useEngineTrackingCode,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { triggerExperiment } = useTriggerExperiment();
const { getEngineTrackingCode } = useEngineTrackingCode();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Trigger an experiment
const experimentId = 100;
// -- E.g. result `variationId` is `200`
const variationId = triggerExperiment('visitor_code', experimentId);
// -- Get tracking code
const engineCode = getEngineTrackingCode('visitor_code');
// -- Result engine code will look like this
// `
// window.kameleoonQueue = window.kameleoonQueue || [];
// window.kameleoonQueue.push(['Experiments.assignVariation', 100, 200]);
// window.kameleoonQueue.push(['Experiments.trigger', 100, true]);
// `
}, [initialize, triggerExperiment, getEngineTrackingCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useTriggerExperiment,
useEngineTrackingCode,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { triggerExperiment } = useTriggerExperiment();
const { getEngineTrackingCode } = useEngineTrackingCode();
const init = useCallback(async () => {
await initialize();
// -- Trigger an experiment
const experimentId = 100;
// -- E.g. result `variationId` is `200`
const variationId = triggerExperiment('visitor_code', experimentId);
// -- Get tracking code
const engineCode = getEngineTrackingCode('visitor_code');
// -- Result engine code will look like this
// `
// window.kameleoonQueue = window.kameleoonQueue || [];
// window.kameleoonQueue.push(['Experiments.assignVariation', 100, 200]);
// window.kameleoonQueue.push(['Experiments.trigger', 100, true]);
// `
}, [initialize, triggerExperiment, getEngineTrackingCode]);
useEffect(() => {
init();
}, [init]);
}
Result tracking code can be inserted directly into html <script>
tag
For example:
<!DOCTYPE html>
<html lang="en">
<body>
<script>
const engineTrackingCode = `
window.kameleoonQueue = window.kameleoonQueue || [];
window.kameleoonQueue.push(['Experiments.assignVariation', 100, 200]);
window.kameleoonQueue.push(['Experiments.trigger', 100, true]);
`;
const script = document.createElement('script');
script.textContent = engineTrackingCode;
document.body.appendChild(script);
</script>
</body>
</html>
Callback Parameters
Name | Type | Description |
---|---|---|
visitorCode (required) | string | unique visitor identification string, can't exceed 255 characters length |
Callback Returns
string
containing engine tracking code
Throws
Type | Description |
---|---|
KameleoonException.VisitorCodeMaxLength | The visitor code length was exceeded |
KameleoonException.VisitorCodeEmpty | The visitor code is empty |
Data Types
Kameleoon Data types are helper classes used for storing data in storage in predefined forms. During the flush execution, the SDK collects all the data and sends it along with the tracking request.
Browser
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Browser,
BrowserType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Add new browser data to client
const browser = new Browser(BrowserType.Chrome, 86.1);
addData(visitorCode, browser);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Browser,
BrowserType,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Add new browser data to client
const browser = new Browser(BrowserType.Chrome, 86.1);
addData(visitorCode, browser);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
Browser contains browser information.
Parameters
Name | Type | Description |
---|---|---|
browser (required) | BrowserType | predefined browser type (Chrome , InternetExplorer , Firefox , Safari , Opera , Other ) |
version (optional) | number | version of the browser, floating point number represents major and minor version of the browser |
Conversion
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Conversion,
ConversionParametersType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Defined conversion parameters
const conversionParameters: ConversionParametersType = {
goalId: 123,
revenue: 10000,
negative: true,
};
// -- Add new conversion data to client
const conversion = new Conversion(conversionParameters);
addData(visitorCode, conversion);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Conversion,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Defined conversion parameters
const conversionParameters = {
goalId: 123,
revenue: 10000,
negative: true,
};
// -- Add new conversion data to client
const conversion = new Conversion(conversionParameters);
addData(visitorCode, conversion);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
Conversion contains information about your conversion.
goalId
can be found on Kameleoon Platform
Parameters
ConversionParametersType
conversionParameters - an object with conversion parameters described below
Name | Type | Description | Default Value |
---|---|---|---|
goalId (required) | number | an id of a goal to track | - |
revenue (optional) | number | an optional parameter for revenue | 0 |
negative (optional) | boolean | an optional parameter identifying whether the conversion should be removed | false |
CustomData
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Defined conversion parameters
const dataItemOne = 'abc';
const dataItemTwo = JSON.stringify(100);
const dataItemThree = JSON.stringify({ a: 200, b: 300 });
const customDataIndex = 0;
// -- Create custom data using single parameter
const customData = new CustomData(customDataIndex, dataItemOne);
// -- Create custom data using variadic number of parameters
const customData = new CustomData(
customDataIndex,
dataItemOne,
dataItemTwo,
);
// -- Create custom data using an array of values
const dataList = [dataItemOne, dataItemTwo, dataItemThree];
const customData = new CustomData(customDataIndex, ...dataList);
// -- Add new custom data to client
addData(visitorCode, customData);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Defined conversion parameters
const dataItemOne = 'abc';
const dataItemTwo = JSON.stringify(100);
const dataItemThree = JSON.stringify({ a: 200, b: 300 });
const customDataIndex = 0;
// -- Create custom data using single parameter
const customData = new CustomData(customDataIndex, dataItemOne);
// -- Create custom data using variadic number of parameters
const customData = new CustomData(
customDataIndex,
dataItemOne,
dataItemTwo,
);
// -- Create custom data using an array of values
const dataList = [dataItemOne, dataItemTwo, dataItemThree];
const customData = new CustomData(customDataIndex, ...dataList);
// -- Add new custom data to client
addData(visitorCode, customData);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
CustomData is usually used together with custom data targeting condition on Kameleoon Platform to determine whether the visitor is targeted or not
The index or ID of the custom data can be found in your Kameleoon account. It is important to note that this index starts at 0, which means that the first custom data you create for a given site will be assigned 0 as its ID, not 1.
To prevent the SDK from flushing the data with the selected index to the Kameleoon servers, check the Only save this data in Local Storage on the user's device, not on a server option when creating a new custom data entry on the Custom Data dashboard.
It's a useful option if you only want to utilize your private custom data for targeting.
Parameters
Name | Type | Description |
---|---|---|
index (required) | number | an index of custom data to be stored under in a state, an index of custom data can be specified in Advanced Tools section of Kameleoon Application |
value (optional) | string[] | custom value to store under the specified id, value can be anything but has to be stringified to match the string type. Note value is variadic parameter and can be used as follows |
Device
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Device,
DeviceType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Add new device data to client
const device = new Device(DeviceType.Desktop);
addData(visitorCode, device);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
Device,
DeviceType,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Add new device data to client
const device = new Device(DeviceType.Desktop);
addData(visitorCode, device);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
Device contains information about your device.
Parameters
Name | Type | Description |
---|---|---|
deviceType (required) | DeviceType | possible variants for device type (PHONE , TABLET , DESKTOP ) |
PageView
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
PageView,
PageViewParametersType,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Define page view parameters
const pageViewParameters: PageViewParametersType = {
urlAddress: 'www.example.com',
title: 'my example',
referrers: [123, 456],
};
// -- Add new page view data to client
const pageView = new PageView(pageViewParameters);
addData(visitorCode, pageView);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
PageView,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Define page view parameters
const pageViewParameters = {
urlAddress: 'www.example.com',
title: 'my example',
referrers: [123, 456],
};
// -- Add new page view data to client
const pageView = new PageView(pageViewParameters);
addData(visitorCode, pageView);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
PageView contains information about your web page.
Parameters
PageViewParametersType
pageViewParameters - an object with page view parameters described below
Name | Type | Description |
---|---|---|
urlAddress (required) | string | url address of the page to track |
title (required) | string | title of the web page |
referrer (optional) | number[] | an optional parameter containing a list of referrers Indices, has no default value |
UserAgent
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
UserAgent,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Add new user agent data to client
const userAgent = new UserAgent('my_unique_value');
addData(visitorCode, userAgent);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
UserAgent,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode('www.example.com');
const init = useCallback(async () => {
await initialize();
// -- Add new user agent data to client
const userAgent = new UserAgent('my_unique_value');
addData(visitorCode, userAgent);
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
UserAgent has a special meaning, if added to client it will be used provided value for filtering out bots during tracking requests
Parameters
Name | Type | Description |
---|---|---|
value (required) | string | value used for comparison |
Server-side experiments are more vulnerable to bot traffic than client-side experiments. To address this, Kameleoon uses the IAB/ABC International Spiders and Bots List to identify known bots and spiders. We recommend that you pass the user agent to be filtered by Kameleoon when running server-side experiments for each visitor browsing your website, to avoid counting bots in your analytics.
If you use internal bots, we suggest that you pass the value curl/8.0 of the userAgent to exclude them from our analytics.
If you run Kameleoon in hybrid mode, your server-side experiments will be automatically protected against bot traffic. This is because Kameleoon collects the user-agent automatically on the front-end side. Therefore, you don't need to pass the user-agent or any other parameter to filter bots and spiders.
React Native Considerations
React Native on android
platform doesn't support Real Time Update
feature.
useNativeVisitorCode
React Native uses MMKV
to store feature flag data so useBrowserVisitorCode hook won't be able to obtain visitor code safely, instead there is dedicated useNativeVisitorCode hook.
A hook that returns a callback function getNativeVisitorCode()
which obtains visitor code from the storage, if no visitor code exists returns a new random visitor code (or the specified default value). This way it guarantees user identification consistency.
- Typescript
- Javascript
import { useNativeVisitorCode } from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { getNativeVisitorCode } = useNativeVisitorCode();
// -- Get visitor code
const visitorCode = getNativeVisitorCode();
// -- Pass default visitorCode, save and retrieve it
const visitorCode = getNativeVisitorCode('default_visitor_code');
}
import { useNativeVisitorCode } from '@kameleoon/react-sdk';
function MyComponent() {
const { getNativeVisitorCode } = useNativeVisitorCode();
// -- Get visitor code
const visitorCode = getNativeVisitorCode();
// -- Pass default visitorCode, save and retrieve it
const visitorCode = getNativeVisitorCode('default_visitor_code');
}
Callback Parameters
Name | Type | Description |
---|---|---|
defaultVisitorCode (optional) | string | visitor code to be used instead of randomly generated visitor code in case there is no visitor code saved in storage |
Callback Returns
string
- result visitor code.
List of supported targeting conditions
Targeting conditions can be defined in the Kameleoon App on the Segment Dashboard.
The following list of conditions are supported by the SDK along with the data checked on the SDK side:
Condition Type | Description | Associated SDK Data |
---|---|---|
Exclusive Experiment | Check if only one certain experiment was triggered for visitor | Internal data saved after some experiments were triggered |
Target Experiment | Check if certain experiment was triggered for visitor | Internal data saved after some experiments were triggered |
Browser | Check if browser type or/and version matches parameters | Browser added by useAddData() |
Device | Check if device type matches parameters | Device added by useAddData() |
Conversion | Check if conversion goalId matches parameters | Conversion added by useAddData() |
Custom Data | Check if custom data values matches parameters | CustomData added by useAddData() |
Page Title | Check if page title value matches parameters | PageView added by useAddData() |
Page Url | Check if page url value matches parameters | PageView added by useAddData() |
SDK Language | Check if the current SDK language matches parameters | A type of the current SDK (React ) |
Visitor Code | Check if visitor code matches parameters | visitorCode passed as an argument to a method |
Error Handling
- Typescript
- Javascript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
KameleoonError,
KameleoonException,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode();
const init = useCallback(async (): Promise<void> => {
try {
await initialize();
const customData = new CustomData(0, 'my_data');
addData(visitorCode, customData);
} catch (error) {
// -- Type guard for inferring error type as native JavaScript `catch`
// only infers `unknown`
if (error instanceof KameleoonError) {
switch (error.type) {
case KameleoonException.VisitorCodeMaxLength:
// -- Handle an error
break;
case KameleoonException.StorageWrite:
// -- Handle an error
break;
case KameleoonException.Initialization:
// -- Handle an error
break;
default:
break;
}
}
}
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useBrowserVisitorCode,
useAddData,
CustomData,
KameleoonException,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { getBrowserVisitorCode } = useBrowserVisitorCode();
const { addData } = useAddData();
// -- Get visitor code
const visitorCode = getBrowserVisitorCode();
const init = useCallback(async () => {
try {
await initialize();
const customData = new CustomData(0, 'my_data');
addData(visitorCode, customData);
} catch (error) {
switch (error.type) {
case KameleoonException.VisitorCodeMaxLength:
// -- Handle an error
break;
case KameleoonException.StorageWrite:
// -- Handle an error
break;
case KameleoonException.Initialization:
// -- Handle an error
break;
default:
break;
}
}
}, [initialize, addData, visitorCode]);
useEffect(() => {
init();
}, [init]);
}
Almost every React SDK callback which is returned by hooks may throw an error at some point, these errors are not just caveats but rather deliberately predefined KameleoonError
s
that extend native JavaScript Error
class providing useful messages and special type
field with a type KameleoonException
.
KameleoonException
is an enum containing all possible error variants.
To know exactly what variant of KameleoonException
the callbacks may throw, you can check Throws
section of the hooks description on this page or just hover over the callback in your IDE to see jsdocs description.
Overall handling the errors considered a good practice to make your application more stable and avoid technical issues.
Synchronizing custom data across devices
If you want to synchronize your Custom Data across multiple devices, Kameleoon provides a Custom Data synchronization mechanism.
To use this feature, in the Custom Data Dashboard, edit the custom data and set the Scope
value to Visitor
. The custom data will now be permanently associated with a specific visitor as long as getRemoteVisitorData
is called before any other actions with the visitor-associated data.
The current implementation will change in an upcoming release.
The getRemoteVisitorData method implicitly attaches the latest custom data entry with scope=VISITOR to the visitor, so make sure your app calls this method before any other actions with Kameleoon Data. See the following example:
- TypeScript
- JavaScript
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useRemoteVisitorData,
useAddData,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent(): JSX.Element {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { getRemoteVisitorData } = useRemoteVisitorData();
const init = useCallback(async (): Promise<void> => {
await initialize();
// -- Before working with data, make `getRemoteVisitorData` call
// -- That way visitor will always has latest data with `scope=VISITOR`
// associated (even without manually calling `addData`)
await getRemoteVisitorData("my_visitor_code");
// -- Let's say that only "Device 1" adds visitor data
if window.device === "Device 1" {
// -- Create custom data
// -- Let's assume index `0` is set to `scope=VISITOR` on Kameleoon Platform
const customData = new CustomData(0, "my_data");
// -- Add custom data
addData('my_visitor_code', customData);
}
// -- As a result visitor on "Device 1" and the same visitor on other devices will
// always have `CustomData(0, "my_data")` associated with them in the storage
}, [initialize, addData]);
useEffect(() => {
init();
}, [init]);
}
import { useEffect, useCallback } from 'react';
import {
useInitialize,
useRemoteVisitorData,
useAddData,
CustomData,
} from '@kameleoon/react-sdk';
function MyComponent() {
const { initialize } = useInitialize();
const { addData } = useAddData();
const { getRemoteVisitorData } = useRemoteVisitorData();
const init = useCallback(async () => {
await initialize();
// -- Before working with data, make `getRemoteVisitorData` call
// -- That way visitor will always has latest data with `scope=VISITOR`
// associated (even without manually calling `addData`)
await getRemoteVisitorData("my_visitor_code");
// -- Let's say that only "Device 1" adds visitor data
if window.device === "Device 1" {
// -- Create custom data
// -- Let's assume index `0` is set to `scope=VISITOR` on Kameleoon Platform
const customData = new CustomData(0, "my_data");
// -- Add custom data
addData('my_visitor_code', customData);
}
// -- As a result visitor on "Device 1" and the same visitor on other devices will
// always have `CustomData(0, "my_data")` associated with them in the storage
}, [initialize, addData]);
useEffect(() => {
init();
}, [init]);
}