JavaScript, Node, Deno V2.3.X
Introduction
SDK overview
Welcome to the Flagship JavaScript / TypeScript / NodeJS & Deno SDK documentation!
The following article will guide you through the steps to get Flagship up and running on your JavaScript environment (client-side or server-side) using our library with preconfigured methods to implement the Decision API or Bucketing Mode.
SDK features
That SDK version helps you :
- Set a visitor ID
- Update user context
- Assign campaigns via the Decision API or via Bucketing Mode
- Get flag
- Manage visitor consent
- Use experience continuity
- Activate campaigns
- Send hits to our Universal Collect
- Manage visitor cache
Prerequisites
NodeJS | Deno |
---|---|
- Your server/device must have an access to the internet. - Node.js: version 6.0.0 or later - NPM: version 3.0.0 or later | - Your server/device must have an access to the internet. - Deno: 1.10.3 or later |
Good to know
NodeJS | Deno |
---|---|
- Github repository: https://github.com/flagship-io/flagship-ts-sdk - Gzipped size: ~13.9 kB - SDK runs on both Client and Server-side - Typescript code supported | - Github repository: https://github.com/flagship-io/flagship-ts-sdk - Deno land: https://deno.land/x/flagship_io_js_sdk |
Getting Started
Installation
NodeJS
The SDK can be added as dependency via NPM or YARN
npm install @flagship.io/js-sdk
yarn add @flagship.io/js-sdk@beta
Deno
Deno supports 2 methods:
- URLs for dependency management, so you just need to add the deno.land URL
import { Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
- and import maps
{
"imports": {
"@flagship.io/js-sdk": "https://deno.land/x/flagship_io_js_sdk/mod.ts"
}
}
JavaScript & NodeJS | Deno |
---|---|
To initialize and start the SDK, import the Flagship class from @flagship.io/js-sdk package then simply call the static function start . It should be better to call this function just once in the most appropriate location for your application. | To initialize and start the SDK, import the Flagship class from flagship deno land repos then simply call the static function start . It should be better to call this function just once in the most appropriate location for your application. |
Initialization
The first step to use the SDK is to create an instance of Flagship that defines your Flagship account and targeted environment.
Here's the simplest way to initialize Flagship, including the import :
import { Flagship } from "@flagship.io/js-sdk";
Flagship.start("<ENV_ID>", "<API_KEY>");
// or
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
import { Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
Flagship.start("<ENV_ID>", "<API_KEY>");
// or
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
start
function
start
functionStart the flagship SDK and return the Flagship instance or null if the start has failed.
static start (envId: string, apiKey: string, config?: IFlagshipConfig): Flagship | null
Arguments | Type | Required | Description |
---|---|---|---|
envId | String | Required | Environment id provided by Flagship. |
apiKey | String | Required | Api authentication key provided by Flagship. |
config | Object | Optional | Custom flagship configuration. see configuration attribute |
Advanced Configuration
Here are all available settings you can set on the SDK.
Those settings can be setup only at the start function.
Here's the full pure example of usage :
import { Flagship, DecisionMode, LogLevel } from "@flagship.io/js-sdk";
Flagship.start("<ENV_ID>", "<API_KEY>", {
decisionMode: DecisionMode.BUCKETING,
fetchNow: false,
timeout: 10,
enableClientCache: true,
logLevel: LogLevel.CRITICAL,
logManager: sentryMiddleware,
decisionApiUrl: 'https://example.com',
pollingInterval: 100,
activateDeduplicationTime: 0,
hitDeduplicationTime: 0,
initialBucketing: {},
statusChangedCallback: function(status){
console.log(status)
},
onBucketingSuccess: function(status, payload){
console.log(status, payload)
},
onBucketingFail: function(error){
console.log(error)
},
onBucketingUpdated: function(lastUpdate){
console.log(lastUpdate)
}
});
import { Flagship, DecisionMode, LogLevel } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
Flagship.start("<ENV_ID>", "<API_KEY>", {
decisionMode: DecisionMode.BUCKETING,
fetchNow: false,
timeout: 10,
enableClientCache: true,
logLevel: LogLevel.CRITICAL,
logManager: sentryMiddleware,
decisionApiUrl: 'https://example.com',
pollingInterval: 100,
activateDeduplicationTime: 0,
hitDeduplicationTime: 0,
initialBucketing: {},
statusChangedCallback: function(status){
console.log(status)
},
onBucketingSuccess: function(status, payload){
console.log(status, payload)
},
onBucketingFail: function(error){
console.log(error)
},
onBucketingUpdated: function(lastUpdate){
console.log(lastUpdate)
}
});
Below the details of every attribute you can set inside the SDK config object :
Attribute | Type | Default | Description |
---|---|---|---|
decisionMode | API |BUCKETING | API | Specify the SDK running mode. see Decision Mode |
fetchNow | boolean | true | If it's set to true, it will call automatically synchronizeModifications when creating a new Visitor |
timeout | number | 2 | Specify timeout in seconds for api request. Note: timeout can't be lower than 0 second. |
enableClientCache | boolean | false | Indicates whether enables or disables the client cache manager. By enabling the client cache, it will allow you to keep cross sessions visitor experience. Note: The client cache is useful only when you do not specify a visitor id when creating a visitor. From there, you only need to be focus on handling the visitor context and whether he is authenticated or not. That's it. Note2: Not available on server side, this setting will be ignored |
logLevel | number | 9 | Set the maximum log level to display see LogLevel |
logManager | object | Defined | Specify a custom implementation of LogManager in order to receive logs from the SDK. Note: The object must fill Interface IFlagshipLogManager |
decisionApiUrl | string | https://decision.flagship.io/v2 | This setting can be useful if you need to simulate the API for tests such as end-to-end or if you want to move to an earlier version of the Flagship API. |
pollingInterval | number | 1 | Specify delay in seconds between two bucketing polling when SDK is running on Bucketing mode. Note: If 0 is given, it should poll only once at start time. |
activateDeduplicationTime | number | 2.5 | Specify delay in seconds of activate deduplication. After an activate is sent, all future sending of this activate will be blocked until the expiration of the delay. Note: if 0 is given, no deduplication process will be used |
hitDeduplicationTime | number | 2.5 | Specify delay in seconds of hit deduplication. After a hit is sent, all future sending of this hit will be blocked until the expiration of the delay. Note: if 0 is given, no deduplication process will be used |
initialBucketing | object | undefined | Optional This is an object of the data received when fetching bucketing endpoint. Providing this prop will make bucketing ready to use and the first polling will immediatly check for an update. |
visitorCacheImplementation | object | Defined on client side and undefined on server side | Optional Define an object that implement the interface visitorCacheImplementation , to handle the visitor cache. see cache-manager |
hitCacheImplementation | object | Defined on client side and undefined on server side | Optional Define an object that implement the interface IHitCacheImplementation , to handle the visitor cache. see cache-manager |
disableCache | boolean | false | if it's set to true, hit cache and visitor cache will be disabled otherwise will be enabled. see cache-manager |
statusChangedCallback | function(number):void | undefined | Optional Define a callable in order to get callback when the SDK status has changed. see arguments. |
onBucketingSuccess | function(object):void | undefined | Optional Define a callable in order to get callback when the first bucketing polling succeed. see arguments |
onBucketingFail | function(error):void | undefined | Optional Define a callable to get callback when the first bucketing polling failed. see arguments |
onBucketingUpdated | function(object):void | undefined | Optional Define a callable to get callback each time bucketing data from Flagship has updated. see arguments |
Decision Mode
API
Mode (by default)
When the SDK is running in API
mode, the campaign assignments and targeting validation will be run through our Decision API. In this mode, each time a new Decision is required, it will create an HTTPS request to the API.
This mode is used by default for all our SDK.
Bucketing
Mode
When the SDK is running in Bucketing
mode, the SDK downloads all the campaigns configurations at once in a single bucketing file so that variation assignment can be computed client-side by the SDK. This bucketing file is stored in cache and will only be downloaded again when campaign configurations are modified in the Flagship interface. Learn more
DecisionMode
is an enum defined decision type
import { DecisionMode } from "@flagship.io/js-sdk";
//const mode = DecisionMode.DECISION_API;
const mode = DecisionMode.BUCKETING;
Flagship.start("<ENV_ID>", "<API_KEY>", {
decisionMode:mode
});
import { DecisionMode } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
//const mode = DecisionMode.DECISION_API;
const mode = DecisionMode.BUCKETING;
Flagship.start("<ENV_ID>", "<API_KEY>", {
decisionMode:mode
});
Key | Value | Type | Description |
---|---|---|---|
DECISION_API | API | string | Flagship SDK mode Decision API |
BUCKETING | BUCKETING | string | Flagship SDK mode bucketing |
LogLevel
LogLevel is an enum defined the level of log to receive
import { LogLevel } from "@flagship.io/js-sdk";
const level = LogLevel.ERROR;
Flagship.start("<ENV_ID>", "<API_KEY>", {
logLevel:level
});
import { LogLevel } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const level = LogLevel.ERROR;
Flagship.start("<ENV_ID>", "<API_KEY>", {
logLevel:level
});
Key | Value | Type | Description |
---|---|---|---|
NONE | 0 | int | Logging will be disabled. |
EMERGENCY | 1 | int | Only emergencies will be logged |
ALERT | 2 | int | Only alerts and above will be logged. |
CRITICAL | 3 | int | Only critical and above will be logged. |
ERROR | 4 | int | Only errors and above will be logged. |
WARNING | 5 | int | Only warnings and above will be logged. |
NOTICE | 6 | int | Only notices and above will be logged. |
INFO | 7 | int | Only info logs and above will be logged. |
DEBUG | 8 | int | Only debug logs and above will be logged. |
ALL | 9 | int | Everything will be logged. |
IFlagshipLogManager
The aims of this Interface is to define methods that an object must have in order to receive Flagship SDK logs
interface IFlagshipLogManager {
emergency(message: string, tag: string): void;
alert(message: string, tag: string): void;
critical(message: string, tag: string): void;
error(message: string, tag: string): void;
warning(message: string, tag: string): void;
notice(message: string, tag: string): void;
info(message: string, tag: string): void;
debug(message: string, tag: string): void;
log(level: LogLevel, message: string, tag: string): void;
}
Argument | Type | Description |
---|---|---|
message | string | Get a description of the log |
tag | string | Get the function that triggered the log |
level | number | Get the log level. Note: only for log method see LogLevel |
Usage :
import { LogLevel, Flagship } from "@flagship.io/js-sdk";
const customLog = {
emergency(message, tag) {
this.log(LogLevel.EMERGENCY, message, tag);
},
alert(message, tag) {
this.log(LogLevel.ALERT, message, tag);
},
critical(message, tag) {
this.log(LogLevel.CRITICAL, message, tag);
},
error(message, tag) {
this.log(LogLevel.ERROR, message, tag);
},
warning(message, tag) {
this.log(LogLevel.WARNING, message, tag);
},
notice(message, tag) {
this.log(LogLevel.NOTICE, message, tag);
},
info(message, tag) {
this.log(LogLevel.INFO, message, tag);
},
debug(message, tag) {
this.log(LogLevel.DEBUG, message, tag);
},
log(level, message, tag) {
console.log(`[${LogLevel[level]}] [${tag}] : ${message}`);
},
};
Flagship.start("<ENV_ID>", "<API_KEY>", {
logManager: customLog,
logLevel: LogLevel.ALL
});
import { LogLevel, Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const customLog = {
emergency(message, tag) {
this.log(LogLevel.EMERGENCY, message, tag);
},
alert(message, tag) {
this.log(LogLevel.ALERT, message, tag);
},
critical(message, tag) {
this.log(LogLevel.CRITICAL, message, tag);
},
error(message, tag) {
this.log(LogLevel.ERROR, message, tag);
},
warning(message, tag) {
this.log(LogLevel.WARNING, message, tag);
},
notice(message, tag) {
this.log(LogLevel.NOTICE, message, tag);
},
info(message, tag) {
this.log(LogLevel.INFO, message, tag);
},
debug(message, tag) {
this.log(LogLevel.DEBUG, message, tag);
},
log(level, message, tag) {
console.log(`[${LogLevel[level]}] [${tag}] : ${message}`);
},
};
Flagship.start("your_env_id", "your_api_key", {
logManager: customLog,
logLevel: LogLevel.ALL,
fetchNow: false,
timeout: 2,
});
FlagshipStatus
FlagshipStatus
is an enum defining the different status of Flagship SDK
import { FlagshipStatus } from "@flagship.io/js-sdk";
const status = FlagshipStatus.READY;
import { FlagshipStatus } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const status = FlagshipStatus.READY;
Key | Value | Type | Description |
---|---|---|---|
NOT_INITIALIZED | 0 | int | It is the default initial status. This status remains until the sdk has been initialized successfully. |
STARTING | 1 | int | Flagship SDK is starting. |
POLLING | 2 | int | Flagship SDK has been started successfully but is still polling campaigns. |
READY_PANIC_ON | 3 | int | Flagship SDK is ready but is running in Panic mode: All features are disabled except the one which refresh this status. |
READY | 4 | int | Flagship SDK is ready to use. |
statusChangedCallback
The statusChangedCallback function has one argument
Argument | Type | Description |
---|---|---|
status | number | Status of the SDK. seeFlagshipStatus |
onBucketingSuccess
The onBucketingSuccess function has one argument with the following shape:
Key/Property | Type | Description |
---|---|---|
status | number | String. Returns either 200 (fresh update) or 304 (no change). |
payload | object | The latest bucketing data received. |
onBucketingFail
The onBucketingFail function has one argument
Argument | Type | Description |
---|---|---|
error | object | Returns the error occurred |
onBucketingUpdated
The onBucketingUpdated function has one argument
Argument | Type | Description |
---|---|---|
lastUpdate | Date | Get the date of the latest update |
Other Flagship methods
getStatus
function
getStatus
functionReturn current status of Flagship SDK. seeFlagshipStatus
getStatus (): FlagshipStatus
static getStatus (): FlagshipStatus
getConfig
function
getConfig
functionReturn the current config used by the SDK. see configuration attribute
getConfig (): IFlagshipConfig
static getConfig (): IFlagshipConfig
getVisitor
function
getVisitor
functionReturn the last visitor created and saved or return undefined if no visitor has been saved. see newVisitor.
getVisitor ():Visitor|undefined
static getVisitor ():Visitor|undefined
import { Flagship } from "@flagship.io/js-sdk";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const status = fsInstance.getStatus();
//or
const status = Flagship.getStatus();
import { Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const status = fsInstance.getStatus();
//or
const status = Flagship.getStatus();
Create a visitor
The Visitor
instance is an object that contains everything related to your visitor, its data but also the Decision of Flagship.
By creating a new visitor, you be able to set all the data relevant for Flagship to take a Decision and know your visitor, this includes :
- Visitor ID
- Visitor Context
- GDPR Consent
- Authenticated or not (See Experience Continuity Feature)
The visitor context is a dataset (object) that defines your current visitor.
This dataset is sent to Flagship for targeting purposes (use-case assignment) but also to enrich your reporting with Context Filters.
You may have to sync with your team to know what data is useful for them to have into Flagship reporting.
By default, depending on IFlagshipConfig
, this will automatically trigger a Decision of Flagship and will be available through the Getting modifications method
import { Flagship } from "@flagship.io/js-sdk";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const fsVisitor = fsInstance.newVisitor({
visitorId: "<VISITOR_ID>",
context: {
// <CONTEXT_KEY>: <CONTEXT_KEY>,
}
});
// or
const fsVisitor = Flagship.newVisitor({
visitorId: "<VISITOR_ID>",
context: {
// <CONTEXT_KEY>: <CONTEXT_KEY>,
}
});
import { Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const fsVisitor = fsInstance.newVisitor({
visitorId: "<VISITOR_ID>",
context: {
// <CONTEXT_KEY>: <CONTEXT_KEY>,
}
});
// or
const fsVisitor = Flagship.newVisitor({
visitorId: "<VISITOR_ID>",
context: {
// <CONTEXT_KEY>: <CONTEXT_KEY>,
}
});
Let's take an example:
if you want to enable a specific feature to all your VIPs
user,
you'll need to add this data as an attribute into the visitor context (key-value pair) in the visitor context: isVIP: true
.
Based on your targeting criteria defined in your use-case (isVIP === true
), Flagship will take the Decision and show your feature to visitors that at least contains isVIP
in their context and for which isVIP
is equal to true
.
import { Flagship } from "@flagship.io/js-sdk";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const fsVisitor = fsInstance.newVisitor({
visitorId: "<VISITOR_ID>",
isAuthenticated: true,
hasConsented: true,
context: {
isVIP: true,
country: "NL",
loginProvider: "Google"
}
});
import { Flagship } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const fsInstance = Flagship.start("<ENV_ID>", "<API_KEY>");
const fsVisitor = fsInstance.newVisitor({
visitorId: "<VISITOR_ID>",
isAuthenticated: true,
hasConsented: true,
context: {
isVIP: true,
country: "NL",
loginProvider: "Google"
}
});
newVisitor
function
newVisitor
functionCreates and returns a new Visitor
or null
if the SDK hasn't started successfully.
This method should always be called after the Flagship SDK has started.
-
static newVisitor (params: INewVisitor): Visitor | null
-
newVisitor (params: INewVisitor): Visitor | null
This method has only one argument with the following shape:
Key/Property | Type | Default | Description |
---|---|---|---|
visitorId | string | undefined | Optional - Unique visitor identifier. Note: It will be generated if not set |
isAuthenticated | boolean | false | Specify if the visitor is authenticated or anonymous for experience continuity. |
hasConsented | boolean | false | Specify if visitor has consented for protected data usage. |
context | object { [key: string]: string | number | boolean } | {} | Initial visitor context. |
isNewInstance | boolean | true on server-sidefalse on client-side | If true The newly created visitor instance won't be saved and will simply be returned otherwise the newly created visitor instance will be returned and saved into the Flagship instance. Note: will be default true on server-side and false on client-side |
initialCampaigns | object | undefined | Optional - This is an object of the data received when fetching the Flagship decision API (decisionMode="API"). Providing this property avoid the SDK to have an empty cache during first initialization. |
initialModifications | array | undefined | Optional - This is a set of modification provided to avoid the SDK to have an empty cache during the first initialization. |
- When both initialCampaigns and initialModifications are provided, only initialModifications will be used.
- User context keys must have a type of
string
- User context values must have a type of
string
,boolean
,number
- User context keys and values are case sensitive
Updating the visitor context
The user context is a property dataset that defines the current user of your app. This dataset is sent and used as targeting criteria for campaign assignment.
The following method from the Visitor
instance allows you to set new context values matching the given keys.
//... import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { age: 31, isVip: true },
});
visitor.updateContext({ lastPurchaseDate: 1615384464 });
updateContext
function
updateContext
functionUpdate the visitor context values, matching the given keys, used for targeting.
A new context value associated with this key will be created if there is no previous matching value.
public updateContext(context: Record<string, string | number | boolean>): void
It has one argument :
Argument | Type | Description |
---|---|---|
context | object | A Set of keys, values. |
context
property
context
propertyThis property returns all the visitor's current context as an object
get context () : Record<string, string | number | boolean>
clearContext
function
clearContext
functionClear the actual visitor context
clearContext(): void
- User context keys must have a type of
string
- User context values must have a type of
string
,bool
,numeric
- User context keys and values are case sensitive
update context with predefined keys of context
import { Flagship, DEVICE_LOCALE, OS_NAME } from "@flagship.io/js-sdk";
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { age: 31, isVip: true },
});
visitor.updateContext({
[DEVICE_LOCALE]: "fr",
[OS_NAME]: "Ubuntu",
});
import { Flagship, DEVICE_LOCALE, OS_NAME } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { age: 31, isVip: true },
});
visitor.updateContext({
[DEVICE_LOCALE]: "fr",
[OS_NAME]: "Ubuntu",
});
Learn more about predefined keys of context
Managing visitor campaigns
Synchronizing campaigns
The synchronizeModifications()
method of the Visitor
instance, according to Decision Mode, will either automatically call the Flagship Decision API to run campaign assignments according to the current user context and retrieve applicable modifications,
or check bucketing file
, validate campaigns targeting the visitor, assign a variation and retrieve applicable modifications
These modifications are then stored in the SDK and updated asynchronously when synchronizeModifications()
is called.
//... import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { key: "value" },
});
visitor.synchronizeModifications().then(() => {
//ready to use all features from the SDK
});
synchronizeModifications
function
synchronizeModifications
functionIn DecisionApi Mode this function calls the Flagship Decision API to run
campaign assignments according to the current user context
and retrieve applicable modifications.
In bucketing Mode, it checks bucketing file,
validates campaigns targeting the visitor,
assigns a variation and retrieve applicable modifications
synchronizeModifications(): Promise<void>
Event listeners
The Visitor
instance includes event listeners to help you handle the SDK.
//... import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { key: "value" },
});
visitor.on("ready", (error) => {
if (error) {
//do some stuff
return;
}
//ready to use all features from the SDK
//do some stuff
});
visitor.synchronizeModifications();
Event listener | Description |
---|---|
ready | This is a mandatory listener to listen. Once it's called, you are ready to use all features from the SDK. Note: It'll be called each time synchronizeModifications has updated stored modifications |
Before using any function from
Visitor
, it is important that you have listened theready
event to ensure everything is working properly and your visitor is up to date with campaigns assignment.
Getting modifications
Once the campaign has been assigned and synchronized, all the modifications are stored in the SDK. You can retrieve these modifications using the following functions from the Visitor
instance:
//...import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { isVip: true },
});
visitor.on("ready", async (error) => {
if (error) {
//do some stuff
return;
}
//Get flag displayVipFeature
const modification = await visitor.getModification({
key: "displayVipFeature",
defaultValue: false,
activate: false,
});
//do some stuff
});
visitor.synchronizeModifications();
getModification
function
getModification
functionRetrieve a modification value by its key. If no modification match the given key or if the stored value type and default value type do not match, default value will be returned.
getModification<T> (params: modificationsRequested<T>): Promise<T>
getModificationSync
function
getModificationSync
functionSee getModification
. But running synchronously
getModificationSync<T> (params: modificationsRequested<T>): T
These 2 functions have one argument with the following structure:
modificationsRequested
modificationsRequested
Key/Property | Type | Default | Description |
---|---|---|---|
key | string | required | key associated to the modification. |
defaultValue | string, number, boolean, object, array | required | default value to return. |
activate | boolean | false | set this parameter to true to automatically report on our server that the current visitor has seen this modification. It is possible to call activateModification() later. |
- Default value must be one of the following type :
string
,number
,boolean
,object
,array
.
getModifications
function
getModifications
functionReturn an object where each key corresponds to flag name and the value corresponds to the matching modification's value. If no modification match a given key or if the stored value type and default value type do not match, default value will be returned.
getModifications<T> (params: modificationsRequested<T>[], activateAll?: boolean): Promise<Record<string, T>>
getModificationsSync
function
getModificationsSync
functionSee getModifications
. But running synchronously
getModificationsSync<T> (params: modificationsRequested<T>[], activateAll?: boolean): Record<string, T>
//... other code
const { flag1, flag2 } = await visitor.getModifications([
{
key: "flag1",
defaultValue: "defaultValue",
activate: false,
},
{
key: "flag2",
defaultValue: false,
activate: false,
},
]);
These 2 functions have 2 arguments:
Argument | Type | Default | Description |
---|---|---|---|
params | Array<object> | required | List of all modifications you're looking for. see modificationsRequested |
activateAll | boolean | false | If set to true, all modifications will be activated. If set to false, none will be activated. NOTE: Setting this argument will override the activate attribute set in each element of the modificationsRequested array. see Activating modifications |
modifications
property
modifications
propertyReturn all flags for all the campaigns associated with the current visitor.
get modifications (): Map<string, Modification>
A Modification
has the following structure
Key\Property | Type | Description |
---|---|---|
key | string | Name of flag |
campaignId | string | ID of the campaign |
variationGroupId | string | |
variationId | string | The variation ID assigned to the user |
isReference | boolean | Specify if its the reference variation |
value | any | Value of flag |
Getting campaign information
You may need to send campaign IDs to a third-party for reporting and/or analytics purposes. It is possible to retrieve campaigns IDs for a specific modification key.
// import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { isVip: true },
});
visitor.on("ready", async (error) => {
if (error) {
//do some stuff
return;
}
//Get flag information
const modificationInfo = await visitor.getModificationInfo(
"displayVipFeature"
);
//do some stuff
});
visitor.synchronizeModifications();
getModificationInfo
function
getModificationInfo
functionGet the campaign Modification
information value matching the given key or null if the modification is not found.
getModificationInfo(key: string): Promise<Modification | null>
getModificationInfoSync
function
getModificationInfoSync
functionSee getModificationInfo
. But it's running synchronously
getModificationInfoSync(key: string): Modification | null
Argument | Type | Default | Description |
---|---|---|---|
key | string | required | key which identify the modification. |
Activating modifications
Once a modification is displayed on the screen for a user, you must send an activate event to tell Flagship that the user has seen it.
There are 3 options for activating a modification:
- Pass an
activate=true
parameter to thegetModification()
function - Pass an
activateAll=true
parameter to thegetModifications
function - Use the following activateModification() method from the visitor instance.
//... import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
context: { isVip: true },
});
visitor.on("ready", async (error) => {
if (error) {
//do some stuff
return;
}
const modification = await visitor.getModification({
key: "displayVipFeature",
defaultValue: false,
activate: true, //Pass an `activate=true` parameter
});
const modifications = await visitor.getModifications(
[
{
key: "flag1",
defaultValue: false,
activate: false,
},
{
key: "flag2",
defaultValue: false,
activate: false,
},
],
true //Pass an `activateAll=true` parameter
);
//or send via activateModification method
visitor.activateModification("displayVipFeature");
//do some stuff
});
visitor.synchronizeModifications();
activateModification
function
activateModification
functionReport this user has seen this modification.
activateModification(key: string): Promise<void>
Argument | Type | Default | Description |
---|---|---|---|
key | string | required | key which identify the modification to activate. |
activateModifications
function
activateModifications
functionReport this user has seen theses modifications.
activateModifications(keys: Array<string>): Promise<void>
Argument | Type | Default | Description |
---|---|---|---|
keys | Array<string> | required | an array of keys which identify the modifications to activate. |
Managing visitor consent
The Visitor
class provides a method to let you manage visitor consent for data privacy usage. When False, campaign activation and hits will be disabled.
There are 2 ways to set visitor consent :
- Set
hasConsented
key to true when creating a new visitor - Use
setConsent
method of visitor instance
//... import code
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
hasConsented: true, // set hasConsented to true
context: { isVip: true },
});
// or use setConsent method
visitor.setConsent(true);
setConsent
function
setConsent
functionSet if visitor has consented for protected data usage.
setConsent(hasConsented: boolean): void
Argument | Type | Default | Description |
---|---|---|---|
hasConsented | boolean | required | Set visitor consent for private data usage. When false some features will be deactivated. |
hasConsented
property
hasConsented
propertyReturn True if the visitor has consented for private data usage, otherwise return False.
hasConsented: boolean
Experience Continuity
In some situations, you may want experience consistency between an anonymous visitor and an authenticated visitor. Flagship provides the following two methods in order to help you to specify when a visitor is authenticated or not.
Authenticate
There are 2 ways to authenticate a visitor:
- Set key isAuthenticated to true when creating a new visitor
- Use authenticate of method of
Visitor
instance
Authenticate anonymous visitor
authenticate(visitorId: string): void
Argument | Type | Default | Description |
---|---|---|---|
visitorId | string | required | id of the new authenticated visitor. |
Unauthenticate
This function change authenticated Visitor to anonymous visitor
unauthenticate(): void
Code example
Let's assume basic scenario to understand how things work:
- Your visitor arrives on your app for the first time.
We need to initialize the visitor but as we don't known anything about this visitor, we'll create a random visitor id or let the SDK do it for us. You can also specify some visitor context if necessary.
const visitor = Flagship.newVisitor({
context: { key: "value" },
});
We don't set visitorId property so the SDK has auto-created an id for our visitor.
Whatever how it has been set, the actual visitor id will be what we call its anonymous id.
- Your visitor is signing in.
To tell the SDK about this change, you'll have to call authenticate function which takes a visitor id as argument.
The visitor id set in argument is required and should be an existing visitor id (that has previously seen specific campaign's modifications) in order to make the experience continuity effective.
visitor.authenticate("VISITOR_ID_ALREADY_KNOWN_BY_FLAGSHIP");
This new visitor id is what we call its authenticated id.
The visitor is updated as authenticated, keeping the previous variations from campaigns that are still matched and thus gives you same modifications as before being logged in.
Keep in mind that if the visitor also has its context changed, you might still have changes on modifications as your visitor might target new campaigns.
- Your visitor decide to sign out.
If you want to keep the same visitor experience, then you should do:
visitor.unauthenticate();
Hit Tracking
This section helps you track your users in your application and learn how to build hits in order to feed your reports. For more information about our measurement protocol, read our Universal Collect documentation.
There are five different types of Hits available:
- Page
- Screen
- Transaction
- Item
- Event
HitType
import { HitType } from "@flagship.io/js-sdk";
const page = HitType.PAGE;
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
const page = HitType.PAGE;
Key | type | Value | Description |
---|---|---|---|
PAGE | string | PAGEVIEW | User has seen a URL. |
SCREEN | string | SCREENVIEW | User has seen a screen. |
TRANSACTION | string | TRANSACTION | User has made a transaction. |
ITEM | string | ITEM | Item bought in a transaction. |
EVENT | string | EVENT | User has made a specific action. |
They must all be built and sent with the following function from the Visitor
instance:
import { Flagship, HitType } from "@flagship.io/js-sdk";
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
hasConsented: true, // set hasConsented to true
context: { isVip: true },
});
visitor.sendHit({
type: HitType.PAGE,
documentLocation: "https://localhost",
});
//or
visitor.sendHits([
{
type: HitType.PAGE,
documentLocation: "https://localhost",
},
{
type: HitType.SCREEN,
documentLocation: "home",
},
]);
import { Flagship, HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
Flagship.start("your_env_id", "your_api_key");
const visitor = Flagship.newVisitor({
visitorId: "your_visitor_id",
hasConsented: true, // set hasConsented to true
context: { isVip: true },
});
visitor.sendHit({
type: HitType.PAGE,
documentLocation: "https://localhost",
});
//or
visitor.sendHits([
{
type: HitType.PAGE,
documentLocation: "https://localhost",
},
{
type: HitType.SCREEN,
documentLocation: "home",
},
]);
sendHit
function
sendHit
functionSend Hit to Flagship servers for reporting.
sendHit (hit: IHit): Promise<void>
Parameter | Type | Default | Description |
---|---|---|---|
hit | object | required | Hit to send. see Hit |
sendHits
function
sendHits
functionSend Hits to Flagship servers for reporting.
sendHits (hits: IHit[]): Promise<void>
Parameter | Type | Default | Description |
---|---|---|---|
hit | Array<object> | required | A set of Hit to send. see Hit |
Hit common optional parameters
import { HitType } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.PAGE,
documentLocation: "https://localhost",
userIp: "127.0.0.1",
screenResolution: "800X600",
locale: "fr",
sessionNumber: "1234",
});
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.PAGE,
documentLocation: "https://localhost",
userIp: "127.0.0.1",
screenResolution: "800X600",
locale: "fr",
sessionNumber: "1234",
});
Parameter | Type | Description |
---|---|---|
userIp | String | (Optional) User IP |
screenResolution | string | (Optional) Screen resolution. |
locale | String | (Optional) User language |
sessionNumber | string | (Optional) Session number |
Page
This hit should be sent each time a visitor arrives on a new page.
import { HitType } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.PAGE, //or "PAGEVIEW"
documentLocation: "https://www.my_domain_com/my_page",
});
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.PAGE, //or "PAGEVIEW"
documentLocation: "https://www.my_domain_com/my_page",
});
- A hit of type
Page
has this following structure:
Key/Property | Type | Default | Description |
---|---|---|---|
type | string (PAGEVIEW ) | required | type of hit. see HitType |
documentLocation | String | required | Valid url. |
Screen
This hit should be sent each time a visitor arrives on an interface on client side.
import { HitType } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.SCREEN, //or "SCREENVIEW"
documentLocation: "home_screen",
});
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.SCREEN, //or "SCREENVIEW"
documentLocation: "home_screen",
});
- A hit of type
Screen
has this following structure:
Key/Property | Type | Default | Description |
---|---|---|---|
type | string (SCREENVIEW ) | required | Type of hit. see HitType |
documentLocation | String | required | Name of screen. |
Transaction
This hit should be sent when a user complete a Transaction.
import { HitType } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.TRANSACTION, //or "TRANSACTION"
transactionId: "#12345",
affiliation: "affiliation",
taxes: 19.99,
currency: "USD",
couponCode: "code",
itemCount: 1,
shippingMethod: "road",
shippingCosts: 5,
paymentMethod: "credit_card",
totalRevenue: "199.99",
});
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.TRANSACTION, //or "TRANSACTION"
transactionId: "#12345",
affiliation: "affiliation",
taxes: 19.99,
currency: "USD",
couponCode: "code",
itemCount: 1,
shippingMethod: "road",
shippingCosts: 5,
paymentMethod: "credit_card",
totalRevenue: "199.99",
});
A hit of type TRANSACTION
has this following structure:
Key/Property | Type | Default | Description |
---|---|---|---|
type | string (TRANSACTION ) | required | Type of hit. see HitType |
transactionId | String | required | Unique identifier for your transaction. |
affiliation | String | required | The name of the KPI that you will have inside your reporting. Learn more |
totalRevenue | float | optional | Specifies the total revenue associated with the transaction. This value should include any shipping and/or tax amounts. |
shippingCosts | float | optional | The total shipping cost of your transaction. |
shippingMethod | String | optional | The shipping method for your transaction. |
taxes | float | optional | Specifies the total amount of taxes in your transaction. |
currency | String | optional | Specifies the currency of your transaction. NOTE: This value should be a valid ISO 4217 currency code. |
paymentMethod | String | optional | Specifies the payment method used for your transaction. |
itemCount | int | optional | Specifies the number of items in your transaction. |
couponCode | String | optional | Specifies the coupon code used by the customer in your transaction. |
Item
This hit is used to link an item with a transaction. It must be sent after the corresponding transaction hit.
import { HitType } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.ITEM, //or "ITEM"
transactionId: "#12345",
productName: "product",
productSku: "sku123",
itemPrice: 199.99,
itemQuantity: 1,
itemCategory: "test",
});
import { HitType } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.ITEM, //or "ITEM"
transactionId: "#12345",
productName: "product",
productSku: "sku123",
itemPrice: 199.99,
itemQuantity: 1,
itemCategory: "test",
});
A hit of type ITEM
has this following structure:
Key/Property | Type | Default | Description |
---|---|---|---|
type | string (ITEM ) | required | Type of hit. see HitType |
transactionId | String | required | Unique identifier for your transaction. |
productName | String | required | Name of your item. |
productSku | String | required | Specifies the SKU or item code. |
itemCategory | String | optional | Specifies the category that the item belongs to. |
itemPrice | float | optional | Specifies the price for a single item/unit. |
itemQuantity | int | optional | Specifies the number of items purchased. |
The
Item
hit isn't available yet in the Flagship reporting view.
Event
This hit can be used for any event (e.g. Add To Cart click, newsletter subscription).
import { HitType, EventCategory } from "@flagship.io/js-sdk";
visitor.sendHit({
type: HitType.EVENT, //or "EVENT"
category: EventCategory.USER_ENGAGEMENT, // or EventCategory.ACTION_TRACKING
eventLabel: "label",
eventValue: 100,
});
import { HitType, EventCategory } from "https://deno.land/x/flagship_io_js_sdk/mod.ts";
visitor.sendHit({
type: HitType.EVENT, //or "EVENT"
category: EventCategory.USER_ENGAGEMENT, // or EventCategory.ACTION_TRACKING
eventLabel: "label",
eventValue: 100,
});
A hit of type EVENT
has this following structure:
Key/Property | Type | Default | Description |
---|---|---|---|
type | string (EVENT ) | required | Type of hit. see HitType |
category | string | required | Specifies the category of your event. NOTE: This value must be either USER_ENGAGEMENT or ACTION_TRACKING . |
action | string | required | Event name that will also serve as the KPI that you will have inside your reporting. Learn more |
setEventLabel | string | optional | Additional description of your event. |
setEventValue | Number | optional | Specifies the monetary value associated with an event (e.g. you earn 10 to 100 euros depending on the quality of lead generated). NOTE: this value must be non-negative. |
Managing visitor cache
The aims of the cache management is the response to the following problematic:
- Re-allocation in bucketing mode :
In bucketing mode, the SDK will always keep visitor in variation where he was allocated first, in case of the customer or the dynamic allocation has changed the traffic allocation. Indeed in bucketing mode the assignation is made on local device so changing campaign allocation in the platform would make visitors to see different campaigns.
- Handle offline mode on client side :
With the cache enabled, the SDK will try to retrieve the latest visitor data (campaign assignations) from the cache, also will save all the failed hits and activateModification in order to resend them later.
By default the Flagship JS SDK provide a default cache manager implementation. It is possible to use your own cache manager by implementing the intefaces IVisitorCacheImplementation
and IHitCacheImplementation
.
Visitor Cache
The visitor cache is used to store the visitor data in a database through the IVisitorCacheImplementation
interface which defines the methods that an object must implement in order to handle it.
interface IVisitorCacheImplementation {
cacheVisitor: (visitorId: string, Data: VisitorSaveCacheDTO) => void;
lookupVisitor(visitorId: string): VisitorLookupCacheDTO;
flushVisitor(visitorId: string): void;
}
cacheVisitor
function
cacheVisitor
functionThis method is called when the SDK needs to cache visitor information in your database.
public cacheVisitor(visitorId: string, Data: object):void
It has 2 arguments :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
Data | object | visitor data. The object follows the shape of type VisitorSaveCacheDTO . |
lookupVisitor
function
lookupVisitor
functionThis method is called when the SDK needs to get the visitor information corresponding to visitor ID from your database.
It has to return an object of type VisitorLookupCacheDTO
which follows this shape see.
public lookupVisitor(visitorId: string): object
It has one argument :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
flushVisitor
function
flushVisitor
functionThis method is called when the SDK needs to erase the visitor information corresponding to visitor ID in your database.
It will be called every time setConsent
get false.
public flushVisitor(visitorId: string): void
It has one argument :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
flushVisitor
method will be called every timesetConsent
get false.
VisitorSaveCacheDTO
type VisitorSaveCacheDTO = {
version: number;
data: {
visitorId: string;
anonymousId: string | null;
consent: boolean;
context: Record<string, primitive>;
campaigns: Array<{
campaignId: string;
variationGroupId: string;
variationId: string;
isReference?: boolean;
type: string;
activated: boolean;
flags: Record<string, unknown>;
}>;
};
};
VisitorLookupCacheDTO
type VisitorLookupCacheDTO = {
version: number;
data: {
visitorId: string;
anonymousId: string | null;
consent?: boolean;
context?: Record<string, primitive>;
campaigns?: Array<{
campaignId: string;
variationGroupId: string;
variationId: string;
isReference?: boolean;
type: string;
activated?: boolean;
flags?: Record<string, unknown>;
}>;
};
};
Hit Cache
The hit cache is used to store the failed hits and activateModification in your database through the IHitCacheImplementation
interface which defines the methods that an object must implement in order to handle it.
interface IHitCacheImplementation {
cacheHit(visitorId: string, data: HitCacheSaveDTO): void;
lookupHits(visitorId: string): HitCacheLookupDTO;
flushHits(visitorId: string): void;
}
cacheHit
function
cacheHit
functionThis method will be called to cache visitor hits when a hit has failed to be sent if there is no internet, there has been a timeout or if the request responded with something > 2XX.
public cacheHit(visitorId: string, data: object):void
It has 2 arguments :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
data | object | hit data. This object follows the shape of type HitCacheSaveDTO . |
lookupHits
function
lookupHits
functionThis method will be called to load hits corresponding to visitor ID from your database and trying to send them again in the background.
It has to return an object of type HitCacheLookupDTO
which follows this shape see.
public lookupHits(visitorId: string):object
It has one argument :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
flushHits
function
flushHits
functionThis method will be called to erase the visitor hits cache corresponding to visitor ID from your database.
NOTE: It will be called every time setConsent
get false.
public flushHits(visitorId: string):void
It has one argument :
Argument | Type | Description |
---|---|---|
visitorId | string | visitor ID |
HitCacheSaveDTO
type HitCacheSaveDTO = {
version: number;
data: {
visitorId: string;
anonymousId: string | null;
type: HitType | "ACTIVATE";
time: number;
content: Record<string, unknown>;
};
};
HitCacheLookupDTO
type HitCacheLookupDTO = {
version: number;
data: {
visitorId: string;
anonymousId: string | null;
type: HitType | "ACTIVATE";
time: number;
content?: Record<string, unknown>;
};
};
flushHits
method will be called every timesetConsent
get false.- After
lookupHits
has returned the visitor hits information corresponding to visitor ID, this data must be deleted from persistent storage.Hits
older than 4H will be ignored during the resending process.
API reference
Flagship
class
Flagship
classVisitor
class
Visitor
class- updateContext
- context
- clearContext
- synchronizeModifications
- Event listeners
- modifications
- getModification
- getModificationSync
- getModifications
- getModificationsSync
- getModificationInfo
- getModificationInfoSync
- activateModification
- activateModifications
- setConsent
- hasConsented
- Authenticate
- Unauthenticate
- sendHit
- sendHits
Release notes
2.3.1-beta.10
- Managing visitor cache
2.3.1-alpha.0
Fixed
- webpack minify issue
2.3.0-alpha.0
Added
- SDK Status / Status changed callback.
- Visitor consent.
- Predefined context.
- Visitor.clearContext
- Visitor.getModification
- Visitor.getModificationSync and getModificationsSync in order to run synchronously
- Visitor.getModificationInfoSync
- Custom log manager
Changed
- Flagship.newVisitor signature.
- Visitor.sendHit and Visitor.sendHits signature
- Visitor.activateModifications signature
Removed
- Flagship.startBucketingPolling method
- Flagship.stopBucketingPolling method
Appendix
Predefined user context keys :
The Flagship SDK contains predefined user context keys.
The keys marked as Yes in the Auto-set by SDK column will be automatically set, while the ones marked as No need to be set by customer.
You can overwrite these keys at any time. The keys-value pairs will be sent to the server in the user context and can be edited in the Persona section of the Flagship platform.
SDK constant Name | Description | Context variable name | Type | Auto-set by SDK | Example |
---|---|---|---|---|---|
DEVICE_LOCALE | Language of the device | sdk_deviceLanguage | String | No | fra |
DEVICE_TYPE | Type of the device | sdk_deviceType | DeviceType | No | Mobile |
DEVICE_MODEL | Model of the device | sdk_deviceModel | String | No | samsung E1200 |
LOCATION_CITY | City geolocation | sdk_city | String | No | toulouse |
LOCATION_REGION | Region geolocation | sdk_region | String | No | occitanie |
LOCATION_COUNTRY | Country geolocation | sdk_country | String | No | France |
LOCATION_LAT | Current Latitude | sdk_lat | Double | No | 43.623647 |
LOCATION_LONG | Current Longitude | sdk_long | Double | No | 1.445397 |
IP | IP of the device | sdk_ip | String | No | 127.0.0.1 |
OS_NAME | Name of the OS | sdk_osName | String | YES | ubuntu / centos |
OS_VERSION_NAME | Version name of the OS | sdk_osVersionName | String | No | 9.0.0 |
OS_VERSION_CODE | Version code of the OS | sdk_osVersionCode | Number | No | 24 |
CARRIER_NAME | Name of the carrier or mobile virtual network operator | sdk_carrierName | String | No | free |
INTERNET_CONNECTION | What is the internet connection | sdk_internetConnection | String | No | 5g |
APP_VERSION_NAME | Version name of the app | sdk_versionName | String | No | 1.1.2-beta |
APP_VERSION_CODE | Version code of the app | sdk_versionCode | Number | No | 40 |
INTERFACE_NAME | Name of the interface | sdk_interfaceName | String | No | ProductPage |
FLAGSHIP_CLIENT | Flagship SDK client (Reserved) | fs_client | String | Yes | TS |
FLAGSHIP_VERSION | Version of the Flagship SDK (Reserved) | fs_version | String | Yes | 2.0.0 |
FLAGSHIP_VISITOR | Current visitor id (Reserved) | fs_users | String | Yes | visitor_id |
To overwrite the keys, use the
updateContext
method
Updated 5 months ago