This guide provides detailed information about our JavaScript Browser SDK, built on top of our JS SDK core modules but optimized for Web Browsers. This SDK also has a pluggable API you can use to include more functionality optionally and keep your bundle leaner.
All of our SDKs are open source. Go to our JavaScript Browser SDK GitHub repository to see the source code.
Language Support
The JavaScript Browser SDK supports all major browsers. While the library was built to support ES5 syntax, there are two APIs you'll need to polyfill if not available in your target browsers, Promise and Fetch.
If you're looking for possible polyfill options, for Promise check es6-promise and for Fetch we recommend the lightweight unfetch or whatwg-fetch
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 two methods below, NPM or our bundled option which we host through our CDN.
You can take full advantage of the pluggable API when using NPM as you decide what to import.
But on the already bundled option the code included is static, so we decided to expose two different combinations for now, regular and full. The regular version includes all the key functionality of the SDK, with the full one including every available pluggable module, for example the logger or the integrations.
<!-- Choose the preferred script tag, you don't need both -->
<!-- Regular build, smaller footprint -->
<script src="//cdn.split.io/sdk/split-browser-0.1.0.min.js"></script>
<!-- Full build, bigger footprint but all modules are exposed and usable -->
<script src="//cdn.split.io/sdk/split-browser-0.1.0.full.min.js"></script>
npm install --save @splitsoftware/splitio-browserjs@0.1.0
2. Instantiate the SDK and create a new Split client
// Instantiate the SDK. CDN will expose a splitio object globally with a reference to
// the SplitFactory (as well as any extra modules)
var factory = splitio.SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
// key represents your internal user id, or the account id that
// the user belongs to.
// This coudld also be a cookie you generate for anonymous users
key: 'key'
}
});
// And get the client instance you'll use
var client = factory.client();
var SplitFactory = require('@splitsoftware/splitio-browserjs').SplitFactory;
// Instantiate the SDK
var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
// key represents your internal user id, or the account id that
// the user belongs to.
// This coudld also be a cookie you generate for anonymous users
key: 'key'
}
});
// And get the client instance you'll use
var client = factory.client();
import { SplitFactory } from '@splitsoftware/splitio-browserjs';
// Instantiate the SDK
const factory: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
// key represents your internal user id, or the account id that
// the user belongs to.
// This coudld also be a cookie you generate for anonymous users
key: 'key'
}
});
// And get the client instance you'll use
const client: SplitIO.IClient = factory.client();
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 "Client-side" 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 key
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.
client.on(client.Event.SDK_READY, function() {
var treatment = client.getTreatment("SPLIT_NAME");
if (treatment == "on") {
// insert code here to show on treatment
} else if (treatment == "off") {
// insert code here to show off treatment
} else {
// insert your control treatment code here
}
});
client.on(client.Event.SDK_READY, function() {
const treatment: SplitIO.Treatment = client.getTreatment("SPLIT_NAME");
if (treatment == "on") {
// insert code here to show on treatment
} else if (treatment == "off") {
// insert code here to show off treatment
} else {
// insert your control treatment code here
}
});
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.
var splitNames = ['SPLIT_NAME_1', 'SPLIT_NAME_2'];
var treatments = client.getTreatments(splitNames);
// treatments will have the following form:
// {
// SPLIT_NAME_1: 'on',
// SPLIT_NAME_2: 'visa'
// }
const splitNames = ['SPLIT_NAME_1', 'SPLIT_NAME_2'];
const treatments: SplitIO.Treatments = client.getTreatments(splitNames);
// treatments will have the following form:
// {
// SPLIT_NAME_1: 'on',
// SPLIT_NAME_2: 'visa'
// }
Attribute syntax
To target based on custom attributes, the SDK's getTreatment
method needs to be passed an attribute map at runtime.
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
}
const attributes: SplitIO.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 array will be compared against a set called `permissions`
permissions: ['read', 'write']
};
const treatment: SplitIO.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
}
You can pass your attributes in exactly this way to the client.getTreatments
method.
Get Treatments with Configurations
To leverage dynamic configurations with your treatments, you should use the getTreatmentWithConfig
method.
This method will return an object with the structure below:
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:
var TreatmentResult = client.getTreatmentWithConfig('SPLIT_NAME', attributes);
var configs = JSON.parse(TreatmentResult.config);
var treatment = TreatmentResult.treatment;
if (treatment === 'on') {
// insert on code here and use configs here as necessary
} else if (treatment === 'off') {
// insert off code here and use configs here as necessary
} else {
// insert control code here
}
const TreatmentResult: SplitIO.TreatmentWithConfig = client.getTreatmentWithConfig('SPLIT_NAME', attributes);
const configs = JSON.parse(TreatmentResult.config);
const treatment = TreatmentResult.treatment;
if (treatment === 'on') {
// insert on code here and use configs here as necessary
} else if (treatment === 'off') {
// insert off code here and use configs here as necessary
} else {
// insert control code here
}
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.
var splitNames = ['SPLIT_NAME_1', 'SPLIT_NAME_2'];
var TreatmentResults = client.getTreatmentsWithConfig(splitNames);
// TreatmentResults will have the following form:
// {
// SPLIT_NAME_1: {treatment: 'on',
// config: "{ 'color' : 'red'}}",
// SPLIT_NAME_2: {treatment: 'v2',
// config: "{ 'copy' : 'better copy'}}",
// }
const splitNames = ['SPLIT_NAME_1', 'SPLIT_NAME_2'];
const TreatmentResults: SplitIO.TreatmentsWithConfig = client.getTreatmentsWithConfig(splitNames);
// TreatmentResults will have the following form:
// {
// SPLIT_NAME_1: {treatment: 'on',
// config: "{ 'color' : 'red'}}",
// SPLIT_NAME_2: {treatment: 'v2',
// config: "{ 'copy' : 'better copy'}}",
// }
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.
Learn more about using track events in splits.
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 key 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
// The expected parameters are:
var queued = client.track('TRAFFIC_TYPE', 'EVENT_TYPE', eventValue, { properties });
// Example with both a value and properties
var properties = {package : "premium", admin : true, discount : 50};
var queued = client.track('user', 'page_load_time', 83.334, properties);
// Example with only properties
var properties = {package : "premium", admin : true, discount : 50};
var queued = client.track('user', 'page_load_time', null, properties);
// The expected parameters are:
const queued: boolean = client.track('TRAFFIC_TYPE', 'EVENT_TYPE', eventValue, , { properties });
// Example with both a value and properties
const properties = {package : "premium", admin : true, discount : 50};
const queued = client.track('user', 'page_load_time', 83.334, properties);
// Example with only properties
const properties = {package : "premium", admin : true, discount : 50};
const queued = client.track('user', 'page_load_time', null, properties);
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 |
---|---|---|
core.labelsEnabled | Enable impression labels from being sent to Split backend. Labels may contain sensitive information. | true |
startup.readyTimeout | Maximum amount of time in seconds to wait before firing the SDK_READY_TIMED_OUT event |
10 |
startup.requestTimeoutBeforeReady | The SDK has two main endpoints it uses /splitChanges and /mySegments that it hits to get ready. This config sets how long (in seconds) the SDK will wait for each request it makes as part of getting ready. | 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 (expressed in seconds) 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.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 |
sync.splitFilters | Filter specific splits to be synced and evaluated by the SDK. This is formed by a type string property and a list of string values for the given criteria. Using the type 'byName' pass an array of split names as a string. If empty, all splits will be downloaded by the SDK. | [] |
sync.impressionsMode | This configuration defines how impressions are queued on the SDK. Supported modes are OPTIMIZED and DEBUG. In OPTIMIZED mode, only unique impressions are queued and posted to Split. In DEBUG mode, ALL impressions are queued and sent to Split. Use DEBUG mode when you want every impression to be logged in Split's webconsole when trying to debug your SDK setup. This setting does not impact the impression listener which will receive all generated impressions. | OPTIMIZED |
streamingEnabled | Boolean flag to enable the streaming service as default synchronization mechanism. In the event of an issue with streaming, the SDK will fallback to the polling mechanism. If false, the SDK will poll for changes as usual without attempting to use streaming. | true |
storage | Pluggable storage instance to be used by the SDK as a complement to in memory storage. Only supported option today is InLocalStorage . Read more here. |
In memory storage |
debug | Either a boolean flag, string log level or logger instance for activating SDK logs. See logging for details. | false |
To set each of the parameters defined above, use the following syntax.
var sdk = SplitFactory({
startup: {
readyTimeout: 10, // 10 sec
eventsFirstPushWindow: 10 // 10 sec
},
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'YOUR_KEY'
},
scheduler: {
impressionsRefreshRate: 60, // 60 sec
eventsPushRate: 60, // 60 sec
eventsQueueSize: 500 // 500 items
},
sync: {
splitFilters: [{
type: 'byName',
values: ['split_name_1', 'split_name_2']
}],
impressionsMode: 'OPTIMIZED'
},
streamingEnabled: true,
debug: false
});
const sdk: SplitIO.ISDK = SplitFactory({
startup: {
readyTimeout: 10, // 10 sec
eventsFirstPushWindow: 10 // 10 sec
},
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'YOUR_KEY'
},
scheduler: {
impressionsRefreshRate: 60, // 60 sec
eventsPushRate: 60, // 60 sec
eventsQueueSize: 500 // 500 items
},
sync: {
splitFilters: [{
type: 'byName',
values: ['split_name_1', 'split_name_2']
}],
impressionsMode: 'OPTIMIZED'
},
streamingEnabled: true,
debug: false
});
Configuring LocalStorage cache for the SDK
To use the pluggable InLocalStorage
option of the SDK and be able to cache flags for subsequent loads in the same browser, you need to pass it to the SDK config on it's storage
option.
This InLocalStorage
function accepts an optional object with options described below:
Configuration | Description | Default value |
---|---|---|
prefix | An optional prefix for your data, to avoid collisions. | SPLITIO |
These pluggable caches are always available on NPM, but if using the CDN you need the full bundle. See more here.
var factory = window.splitio.SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
// Same as SplitFactory, InLocalStorage is exposed on the global splitio object
storage: window.splitio.InLocalStorage({
prefix: 'MY_PREFIX'
})
});
// Now use the SDK as usual
var client = factory.client();
import { SplitFactory, InLocalStorage } from '@splitsoftware/splitio-browserjs';
const factory: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
storage: InLocalStorage({
prefix: 'MY_PREFIX'
})
});
// Now use the SDK as usual
const client = factory.client();
Manager
Use the Split Manager to get a list of features available to the Split client.
To instantiate a Manager in your code base, use the same factory that you used for your client.
var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
// the key can be the logged in
// user id, or the account id that
// the logged in user belongs to.
// The type of customer (user, account, custom)
// is chosen during Split's sign-up process.
key: 'key'
}
});
var manager = factory.manager();
manager.once(manager.Event.SDK_READY, function() {
// Once it's ready, use the manager
});
const factory: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
// the key can be the logged in
// user id, or the account id that
// the logged in user belongs to.
// The type of customer (user, account, custom)
// is chosen during Split's sign-up process.
key: 'key'
}
});
const manager: SplitIO.IManager = factory.manager();
manager.once(manager.Event.SDK_READY, function() {
// Once it's ready, use the manager
});
The Manager then has the following methods available.
/**
* Returns the Split registered with the SDK of this name.
*
* @return SplitView or null.
*/
var splitView = manager.split('name-of-split');
/**
* Retrieves the Splits that are currently registered with the
* SDK.
*
* returns a List of SplitViews.
*/
var splitViewsList = manager.splits();
/**
* Returns the names of features (or Splits) registered with the SDK.
*
* @return a List of Strings of the features' names.
*/
var splitNamesList = manager.names();
/**
* Returns the Split registered with the SDK of this name.
*
* @return SplitView or null.
*/
const splitView: SplitIO.SplitView = manager.split('name-of-split');
/**
* Retrieves the Splits that are currently registered with the
* SDK.
*
* returns a List of SplitViews.
*/
const splitViewsList: SplitIO.SplitViews = manager.splits();
/**
* Returns the names of features (or Splits) registered with the SDK.
*
* @return a List of Strings of the features' names.
*/
const splitNamesList: SplitIO.SplitNames = manager.names();
The SplitView
class referenced above has the following structure.
class SplitView {
name: string,
trafficType: string,
killed: boolean,
treatments: Array<string>,
changeNumber: number,
configs: {
[treatmentName: string]: string
}
}
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 | Impression object that has the feature, key, treatment, label, etc. |
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 browserjs plus the version currently running. |
Note
There are two additional keys on this object, ip
and hostname
. They are not captured on the client side but kept for consistency.
Implement custom impression listener
Here is an example of how implement a custom impression listener.
function logImpression(impressionData) {
// do something with the impression data.
}
var factory = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
impressionListener: {
logImpression: logImpression
}
});
class MyImprListener implements SplitIO.IImpressionListener {
logImpression(impressionData: SplitIO.ImpressionData) {
// do something with impressionData
}
}
const factory: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
impressionListener: {
logImpression: new MyImprListener()
}
});
An impression listener is called asynchronously from the corresponding evaluation, but is almost immediate.
Even though the SDK does not fail if there is an exception in the listener, do not block the call stack.
Logging
To trim as many bits as possible from the user application builds, we divided the logger in implementations that contain the log messages for each log level: ErrorLogger
, WarnLogger
, InfoLogger
and DebugLogger
. Higher log level options contain the messages for the lower ones, with DebugLogger containing them all.
Thus, to enable descriptive SDK logging you need to plug in a logger instance as shown below:
import { SplitFactory, DebugLogger } from '@splitsoftware/splitio-browserjs';
const sdk: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
debug: DebugLogger() // other options are `InfoLogger`, `WarnLogger` and `ErrorLogger`
});
var splitio = require('@splitsoftware/splitio-browserjs');
var sdk = splitio.SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
debug: splitio.DebugLogger() // other options are `InfoLogger`, `WarnLogger` and `ErrorLogger`
});
var sdk = splitio.SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
debug: splitio.DebugLogger() // Only the full UMD bundle includes `DebugLogger`, `InfoLogger`, `WarnLogger` and `ErrorLogger` modules in the `splitio` namespace.
});
You can also enable the SDK logging via a boolean or log level value as debug
settings, and change it dinamically by calling the SDK Logger API.
However, in any case where the proper logger instance is not plugged in, instead of a human readable message you'll get a code and optionally some params for the log itself.
While these logs would be enough for the Split support team, if you find yourself in a scenario where you need to parse this information, you can check the constant files in our javascript-commons repository (where you have tags per version if needed) under the logger folder.
import { SplitFactory } from '@splitsoftware/splitio-browserjs';
const sdk: SplitIO.ISDK = SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
debug: true // other options are 'ERROR', 'WARN', 'INFO' and 'DEBUG
});
// Or you can use the Logger API methods which have an immediate effect.
sdk.Logger.setLogLevel('WARN'); // Acceptable values are: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'
sdk.Logger.enable(); // equivalent to `setLogLevel('DEBUG')`
sdk.Logger.disable(); // equivalent to `setLogLevel('NONE')`
var splitio = require('@splitsoftware/splitio-browserjs');
var sdk = splitio.SplitFactory({
core: {
authorizationKey: 'YOUR_API_KEY',
key: 'key'
},
debug: true // other options are 'ERROR', 'WARN', 'INFO' and 'DEBUG
});
// Or you can use the Logger API methods which have an immediate effect.
sdk.Logger.setLogLevel('WARN'); // Acceptable values are: 'DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'
sdk.Logger.enable(); // equivalent to `setLogLevel('DEBUG')`
sdk.Logger.disable(); // equivalent to `setLogLevel('NONE')`
Finally, SDK logging can also be globally enabled via a localStorage value, by opening your DevTools console and typing the following.
// Acceptable values are 'on', 'enable' and 'enabled'
localStorage.splitio_debug = 'on' <enter>
Advanced: Instantiate multiple SDK clients
Each JavaScript Browser SDK client is tied to one specific customer and traffic type at a time (for example, user
, account
, organization
).
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.
},
});
// 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
// This is only valid after at least one client has been initialized.
var user_client = factory.client('CUSTOMER_USER_ID');
// 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('account', 'PAGELOAD', 7.86);
// or track events for users
account_client.track('user', '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');
// track events for accounts
user_client.track('account', 'PAGELOAD', 7.86);
// or track events for users
account_client.track('user', 'ACCOUNT_CREATED');
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 to four different events from the SDK:
SDK_READY_FROM_CACHE
- The SDK is ready to evaluate using LocalStorage cached data (which might be stale). If conditions are met, this event will be emitted almost immediately since access to the cache is synchronous. Otherwise it won't fire.SDK_READY
- The SDK is ready to be used and has the most up-to-date snapshot of your splits.SDK_READY_TIMED_OUT
- This event fires when the time set forreadyTimeout
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.once(client.Event.SDK_READY, whenReady);
client.once(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!');
});
// This event will fire only using the LocalStorage option and if there's Split data stored in the browser.
client.once(client.Event.SDK_READY_FROM_CACHE, function () {
// Fired after the SDK could confirm the presence of the Split data.
// This event fires really quickly, since there's no actual fetching of information.
// Keep in mind that data might be stale, this is NOT a replacement of SDK_READY.
});
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.once(client.Event.SDK_READY, whenReady);
client.once(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!');
});
// This event will fire only using the LocalStorage option and if there's Split data stored in the browser.
client.once(client.Event.SDK_READY_FROM_CACHE, function () {
// Fired after the SDK could confirm the presence of the Split data.
// This event fires really quickly, since there's no actual fetching of information.
// Keep in mind that data might be stale, this is NOT a replacement of SDK_READY.
});
Example apps
Here are example applications detailing how to configure and instantiate the Split JavaScript Browser SDK on commonly used platforms.
Comments
0 comments
Please sign in to leave a comment.