Documentation
NAV Navbar
Java Node.js C# Python PHP Swift Android React Native
  • Kameleoon SDKs
  • Kameleoon SDKs

    Introduction

    Our SDKs give you the possibility of running experiments on server-side applications, or on native mobile platforms such as Android or iOS.

    Integrating our SDK into your applications is easy. It comes with full documentation and sample code to ensure it can be seamlessly plugged into apps. Our team has already done the heavy lifting, thus your developers can simply reap the benefits. In this article, we will show how you can run a simple A/B test to change the number of recommended products based on different variations.

    You can refer to the SDK reference to check out all possible features of the SDK. Also make sure you check out our Getting started tutorial which we have prepared to walk you through the installation and implementation.

    Getting started

    Welcome to the developer documentation for the Kameleoon Server-side SDK! This hands on Getting started guide is designed to help you integrate our SDK in a few minutes and start running experiments in your apps.

    Creating an experiment

    Create an experiment you want to use in your application and make sure that server-side type is chosen as shown below:

    Server-side experiment

    Open the Kameleoon editor and login with your credentials. If it is already created click on OPEN AN EXISTING EXPERIMENT and select the experiment you need from a list.

    Upon successful creation of the experiment you will need to get its ID to use in the SDK when triggering an experiment. To get ID of an experiment, you need to click on the name of the experiment which will open a pop up with experiment details as well as its ID.

    Installing the SDK

    npm install kameleoon-ssx
    
    npm install kameleoon-client-react-native
    

    You can install Kameleoon SDK using npm as shown in the example to the right.

    You can install Kameleoon SDK using npm as shown in the example to the right.

    Initializing Kameleoon client

    var kameleoonSsx = require("kameleoon-ssx");
    var siteCode = "uzguihqmj7";
    
    var client = new kameleoonSsx(siteCode);
    
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    var siteCode = "uzguihqmj7";
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    

    After installing the server-side SDK and setting up an experiment, the next step is to create the Kameleoon client.

    The code on the right gives a clear example. A Client is a singleton object that will be a bridge between your application and the Kameleoon platform. It includes all the methods and properties you will need to run an experiment.

    While running the KameleoonClientFactory.create() method initializes the client, on Android it is not immediately ready for use. This is because the current configuration of experiments (along with their traffic repartition) has to be retrieved from a Kameleoon remote server. This requires network access, which is not always available. Until the Kameleoon client is fully ready, you should not try to run any other method in our SDK. Note that once the first configuration of experiments is fetched, it is then periodically refreshed, but even if the refresh fails for any reason, the Kameleoon client will still be ready and working (but on an outdated / previous configuration).

    We provide the isReady() method to know if the Kameleoon client initialization completed. Alternatively, you can provide a callback to the KameleoonClientFactory.create() method.

    Triggering an experiment

    //We are using cookies package, you can use any other library for managing cookies
    var Cookies = require("cookies");
    var http = require("http");
    var KameleoonClient = require("kameleoon-client");
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var experimentID = "43492";
    var recommendedProductsNo = 5;
    var params = { browser: "Google Chrome 60", device: "desktop" };
    var kameleoonClient = new KameleoonClient(siteCode);
    
    server = http.createServer(function(req, res) {
        var cookies = new Cookies(req, res, {"keys": keys});
        var foundUserID = cookies.get("userID");
    
        if (foundUserID) {
            userID = foundUserID;
        }
        kameleoonClient.triggerExperiment(userID, experimentID, params, 180, function(variationID){
            //this ID (148382) should be taken from the Kameleoon Editor
            if (variationID == "148382") {
            //We are changing number of recommended products for this variation to 10
                recommendedProductsNo = 10;
            }
            else if (variationID == "187791") {
                //We are changing number of recommended products for this variation to 8
                recommendedProductsNo = 8;
            }
        }, function(){
            console.log("Exception occurred");
        });
    });
    function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    
    //We are using cookies package, you can use any other library for managing cookies
    var Cookie  = require("react-native-cookie");
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var experimentID = "43492";
    var recommendedProductsNo = 5;
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    var Data = KameleoonClientReactNative.data;
    var foundUserID = Cookie.get("http://myurl", "userID");
    
    if (foundUserID) {
        userID = foundUserID;
    }
    kameleoonClient.addData(userID, [new Data.Custom(12, "some custom data")]);
    kameleoonClient.triggerExperiment(userID, experimentID, function(variationID){
        //this ID (148382) should be taken from the Kameleoon Editor
        if (variationID == "148382") {
        //We are changing number of recommended products for this variation to 10
            recommendedProductsNo = 10;
        }
        else if (variationID == "187791") {
            //We are changing number of recommended products for this variation to 8
            recommendedProductsNo = 8;
        }
    }, function(){
        console.log("Exception occurred");
    });
    
    function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using static KameleoonClient;
    
    namespace WebApplication
    {
        public class Startup
        {
            public void Main()
            {
                string siteCode = "uzguihqmj7";
                KameleoonClient kameleoonClient = new KameleoonClient(siteCode);
                string userID = Guid.NewGuid().toString();
                string experimentID = "43492";
                int recommendedProductsNo = 5;
                Dictionary<string, string> parameters = new Dictionary<string, string>();
                parameters.Add("browser", "Google Chrome 60");
                parameters.Add("device", "desktop");
    
                if (Request.Cookies["userID"] != null)
                {
                    userID = Request.Cookies["userID"].Value;
                }
                else
                {
                    HttpCookie userCookie = new HttpCookie("userID", userID.ToString());
                    Response.Cookies.Add(userCookie);
                }
                try {
                    string variationID = kameleoonClient.triggerExperiment(
                        userID,
                        experimentID,
                        parameters
                    );
                    if (variationID == "148382") {
                        //We are changing number of recommended products for this variation to 10
                        recommendedProductsNo = 10;
                    }
                    else if (variationID == "187791") {
                        //We are changing number of recommended products for this variation to 8
                        recommendedProductsNo = 8;
                    }
                }
                catch (Exception e) {
                    System.Diagnostics.Debug.WriteLine("Exception occurred")
                }
            }
        }
    }
    

    To run an experiment effectively we need to split the traffic for an experiment into different segments. By running split tests we get qualitative feedback on user experience to help you identify barriers and optimize your conversion tunnel.

    Triggering an experiment by calling the triggerExperiment() method will register a random variation for a given userID. If this userID is already associated with a variation (most likely a returning visitor that has already been exposed to the experiment previously), then it will return the variation associated with a given experiment.

    You can generate a user ID randomly and then save it in a cookie as shown in our example. A better approach would be to use something more unique, like an email or a phone number.

    The triggerExperiment() method can be called asynchronously as well as synchronously. If called asynchronously, a call will be made to our servers for tracking purposes, but the association of a variation with the userID for this experiment (this operation is also called the bucketing of the visitors) will be made directly in the SDK code, and thus the method will instantly return the variationID. If it is called synchronously, both the tracking and the bucketing is done on our servers, via a blocking server call, and you will have to wait the return of the call to obtain the variationID. This is not recommended for performance and stability reasons.

    Implementing variation code

    To execute different code paths depending on the variation assigned to the visitor, you will need the list of all the experiment's variation IDs. You can find these variation IDs by going into the Kameleoon Editor as shown below.

    Once you have the IDs of the different variations, you can implement a different action for each variation, and one of the code paths will be executed, based on the associated variationID for the current visitor. Generally this can be done using a simple if / else or switch mechanism. In our example, we just change the number of recommended products based on two different variations.

    Get variationID

    Tracking conversion

    //We are using cookies package, you can use any other library for managing cookies
    var Cookies = require("cookies");
    var http = require("http");
    var KameleoonClient = require("kameleoon-client");
    
    var userID = getRandomInt(10000, 99999);
    var goalID = "83023";
    var kameleoonClient = new KameleoonClient(siteCode);
    
    server = http.createServer(function(req, res) {
        var cookies = new Cookies(req, res, {"keys": keys});
        var foundUserID = cookies.get("userID");
    
        if (foundUserID) {
            userID = foundUserID;
        }
    
        kameleoonClient.trackConversion(userID, goalID);
    });
    
    //We are using cookies package, you can use any other library for managing cookies
    var Cookie  = require("react-native-cookie");
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var userID = getRandomInt(10000, 99999);
    var goalID = "83023";
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    var foundUserID = Cookie.get("http://myurl", "userID");
    var Data = KameleoonClientReactNative.data;
    
    if (foundUserID) {
        userID = foundUserID;
    }
    
    kameleoonClient.addData(userID, [new Data.Custom(12, "some custom data")]);
    kameleoonClient.trackConversion(userID, goalID);
    

    After you are done with triggering an experiment, the next step is usually to start tracking conversions. This is done to measure performance characteristics according to the goals defined while setting up the experiment.

    For this purposes use trackConversion() method of the SDK as shown in the example. We need to pass userID and goalID so we can correctly track conversion for the associated variation.

    Get goalID

    Further reading

    If you have reached this point, this means you have successfully integrated our SDK and done some basic experimenting. To get more in-depth information on the other options you can use to integrate our SDK, please refer to the SDK Reference.

    Reference

    This is a full reference documentation of our SDKs.

    Our SDKs are still evolving. The Python and PHP versions are still in development.

    If this is your first time working with the Kameleoon SDK, we strongly recommend you go over our Getting started tutorial to integrate the SDK and start experimenting in a few minutes.

    Initialization: creating the Kameleoon Client

    var KameleoonClient = require("kameleoon-client");
    
    var kameleoonClient = new KameleoonClient("uzguihqmj7");
    
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var kameleoonClient = new KameleoonClientReactNative.client("uzguihqmj7", true);
    

    The starting point for using Server-side SDK is the initialization step. All interaction with the SDK is done through an object called Client, therefore you need to create this object.

    Arguments
    NameTypeDescription
    siteCodestringCode of the website you want to run experiments on. This code can be found in the back office of our platform. Click here to see a tutorial for site installation and configuration.
    blockingbooleanThis parameter defines if the triggerExperiment() method is called asynchronously or synchronously. Value true will set it to be a synchronous call. This parameter is optional and set to false by default.

    Triggering experiments

    var KameleoonClient = require("kameleoon-client");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var experimentID = "43492";
    var params = { browser: "Google Chrome 60", device: "desktop" };
    
    var kameleoonClient = new KameleoonClient(siteCode);
    
    kameleoonClient.triggerExperiment(userID, experimentID, params, 180, function(variationID){
        console.log("Experiment triggered");
    }, function(){
        console.log("Exception occurred");
    });
    
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }
    
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var experimentID = "43492";
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    var Data = KameleoonClientReactNative.data;
    
    kameleoonClient.addData(userID, [new Data.Custom(12, "some custom data")]);
    kameleoonClient.triggerExperiment(userID, experimentID, function(variationID
        ){
        console.log("Experiment triggered");
    }, function(){
        console.log("Exception occurred");
    });
    
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }
    

    To trigger an experiment call the triggerExperiment() method of our SDK.

    This method takes userID and experimentId as mandatory arguments to register a variation for a given user.

    If such a user has never been associated with any variation and meets all the requirements of the experiment, the SDK returns a randomly selected variation. In case a user with a given userID is already registered with a variation it will detect the previously registered variation and return the variationID.

    You have to make sure that proper error handling is set up in your code as shown in the example to the right to catch errors if something goes wrong.

    Arguments
    NameTypeDescription
    userIDstringUnique identifier of the user. This field is mandatory.
    experimentIDstringID of the experiment you want to expose to a user. This field is mandatory.
    timeoutlongThe value must be submitted in seconds. This constant limits the execution time of the method. If the server does not respond within the specified time frame, the execution of the method will be terminated. This field is not mandatory. The default value is 3
    Return value
    NameTypeDescription
    variationIDstringID of the variation that is registered for a given user.

    Tracking Conversion

    var KameleoonClient = require("kameleoon-client");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var goalID = "83023";
    
    var kameleoonClient = new KameleoonClient(siteCode);
    
    kameleoonClient.trackConversion(userID, goalID);
    
    function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    
    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    var goalID = "83023";
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    
    kameleoonClient.trackConversion(userID, goalID);
    
    function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    

    To track conversion use the trackConversion method. This method requires userID and goalID to track conversion and measure performance according to the goal. In addition, this method also accepts revenue as third argument to track revenue. The userID must be identical to the one that was used when triggering the experiment.

    Since triggerExperiment() doesn't send any stored data, you will need to call the flush method to send available data. This is done to ensure that you can track all available data even when an experiment is not triggered.

    The trackConversion method doesn't return any value. This method is called through asynchronous method invocation making sure that it will not be blocked while the method is being executed.

    Arguments
    NameTypeDescription
    userIDstringUnique identifier of the user. This field is mandatory.
    goalIDstringID of the goal. This field is mandatory.
    revenuefloatRevenue of the conversion. This field is optional.

    Saving data

    kameleoonClient.addData(userID, Data.Browser.CHROME);
    kameleoonClient.addData(
        userID,
        new Data.PageView("http://url.com", "title", 3),
        new Data.Interest(0, true)
    );
    kameleoonClient.addData(userID, new Data.Conversion(32, 0, false));
    

    To save various data about user we use addData method. It accepts several parameters and serves to declare data to be sent to the server with the next call of the flush method.

    This method requires userID and different data types to store, allowing the data to be sent later on, when needed.

    The addData method doesn't return any value and doesn't interact with the server. Therefore all the data that was stored using this method should be send to the server either by calling the flush or the trackConversion methods.

    Arguments
    NameTypeDescription
    userIDstringUnique identificator of the user. This field is mandatory.
    dataTypesobjectCustom data types which may be passed separated by a comma

    Data Types

    Browser Data Type
    kameleoonClient.addData(userID, Data.Browser.CHROME);
    
    NameTypeDescription
    browserenumList of browsers: CHROME, INTERNET_EXPLORER, FIREFOX, SAFARI, OPERA, OTHER. This field is mandatory.
    PageView Data Type
    kameleoonClient.addData(
        userID,
        new Data.PageView("http://url.com", "title", 3),
    );
    
    NameTypeDescription
    urlstringURL of the page viewed. This field is mandatory.
    titlestringTitle of the page viewed. This field is mandatory.
    referrerintegerReferrer of the page viewed. This field is optional.
    Interest Data Type
    kameleoonClient.addData(
        userID,
        new Data.Interest(0, true)
    );
    
    NameTypeDescription
    indexintegerIndex of interest. This field is mandatory.
    freshbooleanIndicates whether the interest is new. This field is mandatory.
    Conversion Data Type
    kameleoonClient.addData(userID, new Data.Conversion(32, 0, false));
    
    NameTypeDescription
    goalIDstringID of the goal. This field is mandatory.
    revenuefloatConversion revenue. This field is optional.
    negativebooleanDefines if the revenue is positive or negative. This field is optional.
    Custom Data Type
    kameleoonClient.addData(
        userID,
        new Data.Custom(1, "some custom value")
    );
    
    NameTypeDescription
    keystringKey of the custom data to be stored. This field is mandatory.
    valuestringValue of the custom data to be stored. This field is mandatory.

    Flushing saved data

    var KameleoonClientReactNative = require("kameleoon-client-react-native");
    
    var siteCode = "uzguihqmj7";
    var userID = getRandomInt(10000, 99999);
    
    var kameleoonClient = new KameleoonClientReactNative.client(siteCode, true);
    var Data = KameleoonClientReactNative.data;
    
    kameleoonClient.addData(userID, Data.Browser.CHROME);
    kameleoonClient.addData(
        userID,
        new Data.PageView("http://url.com", "title", 3),
        new Data.Interest(0, true)
    );
    kameleoonClient.addData(userID, new Data.Conversion(32, 0, false));
    
    kameleoonClient.flush(userID);
    
    function getRandomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
    }
    

    To send stored data to the Kameleoon server without conversion we need to use the flush method. This method accepts userID to send data stored for a given user.

    If you need to send all the data stored, then you can use flush method without any parameters passed.

    The flush method doesn't return any value. This method is called through an asynchronous method invocation making sure that it will not be blocked while the method is being executed.

    Arguments
    NameTypeDescription
    userIDstringUnique identificator of the user. This field is mandatory.