JavaScript SDK

This guide provides detailed information about our JavaScript SDK. All of our SDKs are open source. Go to our JavaScript SDK GitHub repository to see the source code.

Language Support

The JavaScript SDK supports all versions of JavaScript.

Initialization

Set up Split in your code base with two simple steps.

1. Import the SDK into your project

You can import the SDK into your project using either of the three methods below.

<script src="//cdn.split.io/sdk/split-10.8.0.min.js"></script>

npm install --save @splitsoftware/splitio@10.8.0

bower install splitio=https://cdn.split.io/sdk/split-10.8.0.min.js

Updating to v10.2.0 - Promise

The Split SDK depends on support for a native ES6 promise implementation. Since v10.2.0, the SDK does not pollute any global variable to add ES6 promise polyfill. If your environment does not support ES6 promises, you can polyfill.

Notice for NPM version

We use the same mechanism as React and other trending libraries to facilitate using Split in development environments. For productions environments set NODE_ENV=production and minimize your code.

Updating to v10 for NPM version

If you are using the CDN package or Bower, no changes are needed on your current code. We changed our module system to ES modules and now we are exposing an object with a SplitFactory property. That property points to the same factory function that we were returning in the previous versions.

Take a look at the snippet above to see the code.

Notice for TypeScript

With the SDK package on NPM, you get the SplitIO namespace, which contains useful types and interfaces for you to use.

Feel free to dive into the declaration files if IntelliSense is not enough!

We recommend keeping only one instance of the client at all times (singleton pattern) and reusing it throughout your application.

Include the API key for the environment that you are setting up the SDK for. The API key is available on your Organization Settings page, on the APIs tab. Choose the "browser" type. This is a special type of API token with limited privileges to be used for the untrustable world of browsers or mobile clients. Learn more about API keys.

Using the SDK

Basic use

When the SDK is instantiated, it kicks off background tasks to update an in-memory cache with small amounts of data fetched from Split servers. This process can take up to a few hundred milliseconds depending on the size of data. If the SDK is asked to evaluate which treatment to show to a customer for a specific split while its in this intermediate state, it may not have the data necessary to run the evaluation. In this case, the SDK does not fail, rather, it returns the control treatment.

To make sure the SDK is properly loaded before asking it for a treatment, block until the SDK is ready, as shown below. We set the client to listen for the SDK_READY event triggered by the SDK before asking for an evaluation.

After the SDK_READY event fires, you can use the getTreatment method to return the proper treatment based on the SPLIT_NAME and the CUSTOMER_ID variables you passed when instantiating the SDK.

Then use an if-else-if block as shown below and insert the code for the different treatments that you defined in the Split UI. Remember the final else branch in your code to handle the client returning control.

Shutdown

Call the client.destroy() method before letting a process using the SDK exit, as this method gracefully shuts down the Split SDK by stopping all background threads, clearing caches, closing connections, and flushing the remaining unpublished impressions.

// You can just destroy and remove the variable reference and move on:
user_client.destroy();
user_client = null;
// destroy() returns a promise, so if you want to, for example,
// navigate to another page without loosing impressions, you
// can do that once the promise resolves.
user_client.destroy().then(function() {
user_client = null;
document.location.replace('another_page');
});

After destroy() is called and finishes, any subsequent invocations to getTreatment/getTreatments or manager methods result in control or empty list, respectively.

Important!

A call to the destroy() method also destroys the factory object. When creating new client instance, first create a new factory instance.

Multiple evaluations at once

In some instances, you may want to evaluate treatments for multiple splits at once. Use the GetTreatments method of the Split client to do this. Simply pass a list of the split names you want treatments for and the method returns an object with the results.

Attribute syntax

In the example below, we are rolling out a split to users. The provided attributes plan_type, registered_date, permissions, paying_customer, and deal_size are passed to the getTreatment call. These attributes are compared and evaluated against the attributes used in the rollout plan as defined in the Split Web console to decide whether to show the on or off treatment to this account.

The getTreatment method supports five types of attributes: strings, numbers, dates, booleans, and sets. The proper data type and syntax for each are:

Strings: Use type String.

Numbers: Use type Number.

Dates: Use type Date and express the value in milliseconds since epoch. Note: Milliseconds since epoch is expressed in UTC. If your date or date-time combination is in a different timezone, first convert it to UTC, then transform it to milliseconds since epoch.

Booleans: Use type Boolean.

Sets: Use type Array.

var attributes = {
// date attributes are handled as `millis since epoch`
registered_date: new Date('YYYY-MM-DDTHH:mm:ss.sssZ').getTime(),
// this string will be compared against a list called `plan_type`
plan_type: 'growth',
// this number will be compared agains a const value called `deal_size`
deal_size: 10000,
// this boolean will be compared against a const value called `paying_customer`
paying_customer: true,
// this array will be compared against a set called `permissions`
permissions: ["read", "write"]
};
var treatment = client.getTreatment('SPLIT_NAME', attributes);
if (treatment === 'on') {
// insert on code here
} else if (treatment === 'off') {
// insert off code here
} else {
// insert control code here
}

Get Treatments with Configurations

var TreatmentResult = {
String treatment;
String config; // or null if there is no config for the treatment
}

type TreatmentResult = {
treatment: string,
config: string | null
};

As you can see from the object structure, the config will be a stringified version of the configuration JSON defined in the Split web console. If there is no configuration defined for a treatment, the SDK will return null for the config parameter.

This method takes the exact same set of arguments as the standard getTreatment method. See below for examples on proper usage:

If you need to get multiple evaluations at once, you can also use the getTreatmentsWithConfig. The method takes the exact same arguments as the getTreatments method but just returns a mapping of split names to TreatmentResults instead of strings. Example usage below.

Track

Use the track method to record any actions your customers perform. Each action is known as an event and corresponds to an event type. Calling track through one of our SDKs or via the API is the first step to getting experimentation data into Split and allows you to measure the impact of your splits on your users' actions and metrics.

In the examples below you can see that the .track() method can take up to four arguments. The proper data type and syntax for each are:

TRAFFIC_TYPE: The traffic type of the customer ID in the track call. The expected data type is String. You can only pass values that match the names of traffic types that you have defined in your instance of Split.

EVENT_TYPE: The event type that this event should correspond to. The expected data type is String. Full requirements on this argument are:

Contains 63 characters or fewer.

Starts with a letter or number.

Contains only letters, numbers, hyphen, underscore, or period.

This is the regular expression we use to validate the value: [a-zA-Z0-9][-_\.a-zA-Z0-9]{0,62}

VALUE: (Optional) The value to be used in creating the metric. This field can be sent in as null or 0 if you intend to purely use the count function when creating a metric. The expected data type is Integer or Float.

PROPERTIES: (Optional) An object of key value pairs that can be used to filter your metrics. Learn more about event property capture here. Split currently supports three types of properties: strings, numbers, and booleans.

The track method returns a boolean value of true or false to indicate whether or not the SDK was able to successfully queue the event to be sent back to Split's servers on the next event post. The SDK will return false if the current queue size is equal to the config set by eventsQueueSize or if an incorrect input to the track method has been provided.

In the case that a bad input has been provided, you can read more about our SDK's expected behavior here

Configuration

The SDK has a number of knobs for configuring performance. Each knob is tuned to a reasonable default. However, you can override the value while instantiating the SDK. The parameters available for configuration are shown below.

Configuration

Description

Default value

startup.readyTimeout

Maximum amount of time to wait before firing the SDK_READY_TIMED_OUT event

1.5

startup.requestTimeoutBeforeReady

The SDK has two main endpoints it uses /splitChanges and /mySegments that it hits to get ready. This config sets how long the SDKs will wait for each request it makes as part of getting ready.

1.5

startup.retriesOnFailureBeforeReady

How many retries on /splitChanges and /mySegments we will do while getting the SDK ready

1

startup.eventsFirstPushWindow

Use to set a specific timer for the first push of events, starting on SDK initialization.

10

scheduler.featuresRefreshRate

The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds.

30

scheduler.segmentsRefreshRate

The SDK polls Split servers for changes to segment definitions. This parameter controls this polling period in seconds.

60

scheduler.metricsRefreshRate

The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds.

60

scheduler.impressionsRefreshRate

The SDK sends information on who got what treatment at what time back to Split servers to power analytics. This parameter controls how often this data is sent to Split servers. The parameter should be in seconds.

60

scheduler.eventsPushRate

The SDK sends tracked events to Split servers. This setting controls that flushing rate in seconds.

60

scheduler.eventsQueueSize

The max amount of events we queue. If the queue is full, the SDK flushes the events and reset the timer.

500

core.trafficType

Use to bind a client to a traffic type, and we use this when you are tracking events, along with the client key.

undefined

core.labelsEnabled

Disable labels from being sent to Split backend. Labels may contain sensitive information.

true

storage.type

Storage type to be used by the SDK. Possible values are MEMORY and LOCALSTORAGE.

MEMORY

storage.prefix

An optional prefix for your data, to avoid collisions.

SPLITIO

debug

Boolean flag for activating SDK logs.

false

To set each of the parameters defined above, use the following syntax.

Localhost mode

Features start their life on one developer's machine. A developer should be able to put code behind splits on their development machine without the SDK requiring network connectivity. To achieve this, the Split SDK can be started in localhost mode (aka off-the-grid mode). In this mode, the SDK neither polls nor updates Split servers. Instead, it uses an in-memory data structure to determine what treatments to show to the logged in customer for each of the features.

When instantiating the SDK in localhost mode, your authorizationKey is localhost. Define the features you want to use Split on in the features object. All getTreatment calls for a Split now only return the one treatment (and configs, if defined) you have defined in the map. You can then change the treatment as necessary for your testing. If you wish to update a treatment or a config, or just add or remove splits from the mock cache, update the features object you've provided. The SDK will simulate polling for changes and update from it.

Any feature that is not provided in the features map returns the control treatment if the SDK was asked to evaluate them.

You can use the additional configuration parameters below when instantiating the SDK in localhost mode.

Configuration

Description

Default value

scheduler.offlineRefreshRate

The refresh interval for the mocked features treatments.

15

features

A fixed mapping of which treatment to show for our mocked features.

{} By default we have no mocked features.

Below is example of how you can start the SDK in localhost mode. Note that you can define the object between split name and treatment directly or use a map to define both a treatment and a dynamic configuration

If you define just a string as the value for a split name, anyd config returned by our SDKs will always be null. If you use a map, we return the specified treatment and the specified config (which can also be null).

Listener

Split SDKs send impression data back to Split servers periodically and as a result of evaluating splits. To additionally send this information to a location of your choice, define and attach an impression listener. For that purpose, the SDK's configurations have a parameter called impressionListener where an implementation of ImpressionListener could be added. This implementation must define the logImpression method and it receives data in the following schema.

Name

Type

Description

impression

Object

attributes

Object

A map of attributes passed to getTreatment/getTreatments (if any).

sdkLanguageVersion

String

The version of the SDK. In this case the language is javascript plus the version currently running.

Note

There are two additional keys on this object, ip and hostname. They are not used on the browser.

Note

Advanced: Instantiate multiple SDK clients

Each JavaScript SDK client is tied to one specific customer and traffic type at a time (for example, user, account, organization). This enhances performance and reduces data cached within the SDK.

Split supports the ability to release based on multiple traffic types. With traffic types, you can release to users in one split and accounts in another. If you are unfamiliar with using multiple traffic types, you can learn more here.

If you need to roll out splits by different traffic types, instantiate multiple SDK clients, one for each traffic type. For example, you may want to roll out the feature user-poll by users and the feature account-permissioning by accounts.

You can do this with the example below.

var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_AUTH_KEY',
key: 'CUSTOMER_ACCOUNT_ID',
// Istantiate the sdk once and provide the ID for one of the
// traffic types that you plan to release to. It doesn't
// matter which you pick to start off with.
trafficType: 'A_TRAFFIC_TYPE'
// You can also provide a traffic type you want to use for
// events tracking. This setting is optional, if not provided
// you can pass the traffic type directly to client.track()
},
});
// now when you call factory.client(), the sdk will create a client
// using the Account ID and traffic type name (if any)
// you passed in during the factory creation.
var account_client = factory.client();
// to create another client for a User instead, just pass in a User ID
// and an optional Traffic Type to the factory.client() method.
// This is only valid after at least one client has been initialized.
var user_client = factory.client('CUSTOMER_USER_ID', 'ANOTHER_TRAFFIC_TYPE');
// check treatment for user-poll and CUSTOMER_USER_ID
var user_poll_treatment = user_client.getTreatment('user-poll');
// check treatment for account-permissioning and CUSTOMER_ACCOUNT_ID
var account_permissioning_treatment = account_client.getTreatment('account-permissioning');
// track events for accounts
user_client.track('PAGELOAD', 7.86);
// or track events for users
account_client.track('ACCOUNT_CREATED');

const sdk: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_AUTH_KEY',
key: 'CUSTOMER_ACCOUNT_ID'
// instantiate the sdk once and provide the ID for one of the
// traffic types that you plan to release to. It doesn't
// matter which you pick to start off with.
},
});
// now when you call sdk.client(), the sdk will create a client
// using the Account ID you passed in during the factory creation.
const account_client: SplitIO.IClient = factory.client();
// to create another client for a User instead, just pass in a
// User ID to the sdk.client() method. This is only valid after
// at least one client has been initialized.
const user_client: SplitIO.IClient =
factory.client('CUSTOMER_USER_ID');
// check treatment for user-poll and CUSTOMER_USER_ID
const user_poll_treatment: SplitIO.Treatment =
user_client.getTreatment('user-poll');
// check treatment for account-permissioning and CUSTOMER_ACCOUNT_ID
const account_permissioning_treatment: SplitIO.Treatment =
account_client.getTreatment('account-permissioning');

Number of SDK instances

While the SDK does not put any limitations on the number of instances that can be created, we strongly recommend keeping the number of SDKs down to one or two.

Advanced: Subscribe to events and changes

You can listen for three different types from the SDK:

SDK_READY - Use this before performing any getTreatment calls.

SDK_READY_TIMED_OUT - This event fires when the time set for readyTimeout in the configuration has elapsed and the SDK has not fully loaded. (Learn more changing the configuration of your SDK above.)

SDK_UPDATE - This event fires whenever a split or segment is changed. Use this if you want to reload your app every time you make a change in the Split Web console.

The syntax to listen for each event is shown below.

function whenReady() {
var treatment = client.getTreatment('YOUR_SPLIT');
if (treatment === 'on') {
// insert on code
} else if (treatment === 'off') {
// insert off code
} else {
// insert control code (usually the same as default treatment)
}
}
// the client is ready for start making evaluations with your data
client.on(client.Event.SDK_READY, whenReady);
client.on(client.Event.SDK_READY_TIMED_OUT, function () {
// this callback will be called after 1.5 seconds if and only if the client
// is not ready for that time. You can still call getTreatment()
// but it could return CONTROL.
});
client.on(client.Event.SDK_UPDATE, function () {
// fired each time the client state change.
// For example, when a Split or a Segment changes.
console.log('The SDK has been updated!');
});

function whenReady() {
const treatment: SplitIO.Treatment = client.getTreatment('YOUR_SPLIT');
if (treatment === 'on') {
// insert on code
} else if (treatment === 'off') {
// insert off code
} else {
// insert control code (usually the same as default treatment)
}
}
// the client is ready for start making evaluations with your data
client.on(client.Event.SDK_READY, whenReady);
client.on(client.Event.SDK_READY_TIMED_OUT, () => {
// this callback will be called after 1.5 seconds if and only if the client
// is not ready for that time. You can still call getTreatment()
// but it could return CONTROL.
});
client.on(client.Event.SDK_UPDATE, () => {
// fired each time the client state change.
// For example, when a Split or a Segment changes.
console.log('The SDK has been updated!');
});

Example apps

Here are example applications detailing how to configure and instantiate the Split JavaScript SDK on commonly used platforms.