JavaScript, Node, Deno V3.0.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 :

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

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/[email protected]

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";
{
   "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 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 fetchFlags 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
seeLogLevel

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;
KeyValueTypeDescription
NOT_INITIALIZED0intIt is the default initial status. This status remains until the sdk has been initialized successfully.
STARTING1intFlagship SDK is starting.
POLLING2intFlagship SDK has been started successfully but is still polling campaigns.
READY_PANIC_ON3intFlagship SDK is ready but is running in Panic mode: All features are disabled except the one which refresh this status.
READY4intFlagship SDK is ready to use.

statusChangedCallback

The statusChangedCallback function has one argument

ArgumentTypeDescription
statusnumberStatus of the SDK. seeFlagshipStatus

onBucketingSuccess

The onBucketingSuccess function has one argument with the following shape:

Key/PropertyTypeDescription
statusnumberString. Returns either 200 (fresh update) or 304 (no change).
payloadobjectThe latest bucketing data received.

onBucketingFail

The onBucketingFail function has one argument

ArgumentTypeDescription
errorobjectReturns the error occurred

onBucketingUpdated

The onBucketingUpdated function has one argument

ArgumentTypeDescription
lastUpdateDateGet the date of the latest update


Other Flagship methods

getStatus function

Return current status of Flagship SDK. seeFlagshipStatus

  • getStatus (): FlagshipStatus
  • static getStatus (): FlagshipStatus

getConfig function

Return the current config used by the SDK. see configuration attribute

  • getConfig (): IFlagshipConfig
  • static getConfig (): IFlagshipConfig

getVisitor function

Return 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 :

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 getFlag 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

Creates 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

NOTE 2: In client side if you do not specify a value, the id will be either automatically generated or will be the visitor id from previous session (if enableClientCache equals true.

isAuthenticated

boolean

false

Specify if the visitor is authenticated or anonymous for experience continuity.

hasConsented

boolean

true

Specify if visitor has consented for protected data usage.

context

object { [key: string]: string | number | boolean }

{}

Initial visitor context.

isNewInstance

boolean

true on server-side
false 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.

initialFlagsData

array

undefined

Optional - This is a set of flag data provided to avoid the SDK to have an empty cache during the first initialization.


Flag data shape:

Key\PropertyTypeDescription
keystringName of flag
campaignIdstringID of the campaign
slugstringcampaign slug
campaignTypestringcampaign type
variationGroupIdstring
variationIdstringThe variation ID assigned to the user
isReferencebooleanSpecify if its the reference variation
valueanyValue of flag

🚧

  • When both initialCampaigns and initialFlags are provided, only initialFlags 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

Update 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 :

ArgumentTypeDescription
contextobjectA Set of keys, values.

context property

This property returns all the visitor's current context as an object

  • get context () : Record<string, string | number | boolean>

clearContext function

Clear 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


Fetching Flags

The fetchFlags() 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 flags,
or check bucketing file, validate campaigns targeting the visitor, assign a variation and retrieve applicable flags

These flags are then stored in the SDK and updated asynchronously when fetchFlags() is called.


//... import code

Flagship.start("your_env_id", "your_api_key");

const visitor = Flagship.newVisitor({
  visitorId: "your_visitor_id",
  context: { key: "value" },
});

visitor.fetchFlags().then(() => {
  //ready to use all features from the SDK
});

fetchFlags function

In DecisionApi Mode this function calls the Flagship Decision API to run campaign assignments according to the current user context and retrieve applicable flags.

In bucketing Mode, it checks bucketing file, validates campaigns targeting the visitor, assigns a variation and retrieve applicable flags

  • fetchFlags(): Promise<void>

Event listeners

The Visitor instance includes event listeners to help you handle the SDK.

Event listenerDescription
readyThis 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 fetchFlags has updated stored flags

❗️

Before using any function from Visitor, it is important that you have listened the ready event to ensure everything is working properly and your visitor is up to date with campaigns assignment.


Getting flags

Once the campaign has been assigned and fetched, all the flags are stored in the SDK. You can retrieve them 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",  (error) => {
  if (error) {
    //do some stuff
    return;
  }

  //Get flag displayVipFeature
  const flag = visitor.getFlag("displayVipFeature", false);

  //do some stuff
});

visitor.fetchFlags();

getFlag function

Return a Flag object by its key. If no flag match the given key an empty flag will be returned. Call exists() to check if the flag has been found.

  • getFlag<T>(key:string, defaultValue: T):IFlag<T>

ArgumentTypeDescription
keyStringkey associated to the flag.
defaultValueTflag default value.

🚧

  • Default value must be one of the following type : string, number, boolean, object, array or null.
  • When the defaultValue is null, no type checking will be performed

Getting flags current values

getValue function

To retrieve flag current value, simply call getValue() method of the Flag object.

//...import code

Flagship.start("your_env_id", "your_api_key");

const visitor = Flagship.newVisitor({
  visitorId: "your_visitor_id",
  context: { isVip: true },
});

visitor.on("ready", (error) => {
  if (error) {
    //do some stuff
    return;
  }

  //Get flag displayVipFeature
  const flagValue = visitor.getFlag("displayVipFeature", false).getValue();

  //do some stuff
});

visitor.fetchFlags();
  • getValue(userExposed : boolean) : T function

Returns the value from the assigned campaign variation or the Flag default value if the Flag does not exist, or if types are different.

Parameter

Type

Default Value

Description

userExposed

Boolean

true

Tells Flagship the user have been exposed and have seen this flag. This will increment the visits for the current variation on your campaign reporting.
If needed it is possible to set this param to false and call userExposed() afterward when the user sees it.


Getting flags campaigns metadata

metadata property

You may need to send campaign IDs or variation IDs to a third party for reporting and/or analytics purposes. It is possible to retrieve campaigns metadata for a specific Flag.


//...import code

Flagship.start("your_env_id", "your_api_key");

const visitor = Flagship.newVisitor({
  visitorId: "your_visitor_id",
  context: { isVip: true },
});

visitor.on("ready", (error) => {
  if (error) {
    //do some stuff
    return;
  }

  //Get flag displayVipFeature
  const campaignMetada = visitor.getFlag("displayVipFeature", false).metadata;

  //do some stuff
});

visitor.fetchFlags();
  • metadata:IFlagMetadata

Return the campaign information metadata or an empty object if the Flag doesn't exist or if the default value type does not correspond to the Flag type in Flagship.

interface IFlagMetadata{
    campaignId:string
    variationGroupId:string
    variationId: string
    isReference: boolean
    campaignType: string
    slug?:string|null
}
Key\PropertyTypeDescription
campaignIdstringID of the campaign
variationGroupIdstring
variationIdstringThe variation ID assigned to the user
isReferencebooleanSpecify if its the reference variation
campaignTypestringcampaign type
slugstringcampaign slug

Report a Flag exposition

userExposed function

By default when the method getValue() is called, The SDK considers that the user have seen the effets of your Flag, unless you pass false to getValue(). In this case you will have to call userExposed().

There are two ways for exposing a user to a flag:

  1. Pass an userExposed=true parameter to the getValue() method.
  2. Use the following userExposed() method from the Flag 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", (error) => {
  if (error) {
    //do some stuff
    return;
  }

  //Get flag displayVipFeature
  const flag = visitor.getFlag("displayVipFeature", false);
  const value = flag.getValue(false);
  
  //Report a flag exposition
  flag.userExposed();

  //do some stuff
});

visitor.fetchFlags();

  • userExposed(): Promise<void>

Tells Flagship the user have been exposed and have seen this flag. This will increment the visits for the current variation on your campaign reporting. No user exposition will be sent if the Flag doesn't exist or if the default value type do not correspond to the Flag type in Flagship.


Check if a Flag exists

exists function

This method will return true if a Flag exists in Flagship

  • exists(): boolean
//...import code

Flagship.start("your_env_id", "your_api_key");

const visitor = Flagship.newVisitor({
  visitorId: "your_visitor_id",
  context: { isVip: true },
});

visitor.on("ready", (error) => {
  if (error) {
    //do some stuff
    return;
  }

  const isDisplayVipFeature = visitor.getFlag("displayVipFeature", false).exists();

  //do some stuff
});

visitor.fetchFlags();


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 :

  1. Set hasConsented key to true when creating a new visitor
  2. 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

Set if visitor has consented for protected data usage.

  • setConsent(hasConsented: boolean): void
ArgumentTypeDefaultDescription
hasConsentedbooleanrequiredSet visitor consent for private data usage. When false some features will be deactivated.

hasConsented property

Return 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:

  1. Set key isAuthenticated to true when creating a new visitor
  2. Use authenticate of method of Visitor instance

Authenticate anonymous visitor

  • authenticate(visitorId: string): void
ArgumentTypeDefaultDescription
visitorIdstringrequiredid 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:

  1. 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.

  1. 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 flags) 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 flags as before being logged in.

📘

Keep in mind that if the visitor also has its context changed, you might still have changes on flags as your visitor might target new campaigns.

  1. Your visitor decide to sign out.

If you want to keep the same visitor experience, then you should do:

visitor.unauthenticate();

Other visitor instance membre

getFlagsDataArray function

Return an array of all flags data fetched for the current visitor.

  • getFlagsDataArray():FlagDTO[]

getAllFlagsData function

The getAllFlagsData method returns a Promise<object> containing all the data for all the campaigns associated with the current visitor.

The object resolved by the promise has the same shape as the Decision API response (normal mode).

  • getAllFlagsData(activate : boolean) : Promise<{ visitorId: string; campaigns: CampaignDTO[];}>

The function takes the following arguments:

AttributeTypeDefaultDescription
activatebooleanfalseEnables modifications while getting them. NOTE: If modifications have already been retrieved, the activation will be sent in another request.

getFlagsDataForCampaign function

Useful to request the data for a specific campaign.

  • getModificationsForCampaign(campaignId: string, activate: boolean): Promise<{visitorId: string; campaigns: CampaignDTO[];}>;

The function takes the following arguments:

AttributeTypeDefaultDescription
campaignIdstringRequiredIdentifies the campaign whose modifications you want to retrieve. **See description
activatebooleanfalseEnables modifications while getting them. NOTE: If modifications have already been retrieved, the activation will be sent in another request.


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;
KeytypeValueDescription
PAGEstringPAGEVIEWUser has seen a URL.
SCREENstringSCREENVIEWUser has seen a screen.
TRANSACTIONstringTRANSACTIONUser has made a transaction.
ITEMstringITEMItem bought in a transaction.
EVENTstringEVENTUser 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

Send Hit to Flagship servers for reporting.

  • sendHit (hit: IHit): Promise<void>
ParameterTypeDefaultDescription
hitobjectrequiredHit to send. see Hit

sendHits function

Send Hits to Flagship servers for reporting.

  • sendHits (hits: IHit[]): Promise<void>
ParameterTypeDefaultDescription
hitArray<object>requiredA 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",
});

ParameterTypeDescription
userIpString(Optional) User IP
screenResolutionstring(Optional) Screen resolution.
localeString(Optional) User language
sessionNumberstring(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/PropertyTypeDefaultDescription
typestring (PAGEVIEW)requiredtype of hit. see HitType
documentLocationStringrequiredValid 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/PropertyTypeDefaultDescription
typestring (SCREENVIEW)requiredType of hit. see HitType
documentLocationStringrequiredName 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/PropertyTypeDefaultDescription
typestring (TRANSACTION)requiredType of hit. see HitType
transactionIdStringrequiredUnique identifier for your transaction.
affiliationStringrequiredThe name of the KPI that you will have inside your reporting. Learn more
totalRevenuefloatoptionalSpecifies the total revenue associated with the transaction. This value should include any shipping and/or tax amounts.
shippingCostsfloatoptionalThe total shipping cost of your transaction.
shippingMethodStringoptionalThe shipping method for your transaction.
taxesfloatoptionalSpecifies the total amount of taxes in your transaction.
currencyStringoptionalSpecifies the currency of your transaction. NOTE: This value should be a valid ISO 4217 currency code.
paymentMethodStringoptionalSpecifies the payment method used for your transaction.
itemCountintoptionalSpecifies the number of items in your transaction.
couponCodeStringoptionalSpecifies 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/PropertyTypeDefaultDescription
typestring (ITEM)requiredType of hit. see HitType
transactionIdStringrequiredUnique identifier for your transaction.
productNameStringrequiredName of your item.
productSkuStringrequiredSpecifies the SKU or item code.
itemCategoryStringoptionalSpecifies the category that the item belongs to.
itemPricefloatoptionalSpecifies the price for a single item/unit.
itemQuantityintoptionalSpecifies 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
  action: "click",
  label: "label",
  value: 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
  label: "label",
  value: 100,
});

A hit of type EVENT has this following structure:

Key/PropertyTypeDefaultDescription
typestring (EVENT)requiredType of hit. see HitType
categorystringrequiredSpecifies the category of your event. NOTE: This value must be either User Engagement or Action Tracking.
actionstringrequiredEvent name that will also serve as the KPI that you will have inside your reporting. Learn more
labelstringoptionalAdditional description of your event.
valueintegeroptionalSpecifies 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 the visitors 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 userExposed in order to resend them later.


By default the Flagship JS SDK provide a default cache manager implementation on client side. It is possible to use your own cache manager by implementing the intefaces IVisitorCacheImplementation and IHitCacheImplementation through visitorCacheImplementation and hitCacheImplementation properties of configuration.

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: VisitorCacheDTO) => void;
  lookupVisitor(visitorId: string): VisitorCacheDTO;
  flushVisitor(visitorId: string): void;
}

cacheVisitor function

This 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 :

ArgumentTypeDescription
visitorIdstringvisitor ID
Dataobjectvisitor data. The object follows the shape of type VisitorCacheDTO.

lookupVisitor function

This 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 VisitorCacheDTO which follows this shape see.

  • public lookupVisitor(visitorId: string): object

It has one argument :

ArgumentTypeDescription
visitorIdstringvisitor ID

flushVisitor function

This 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 :

ArgumentTypeDescription
visitorIdstringvisitor ID

📘

  • flushVisitor method will be called every time setConsent get false.

VisitorCacheDTO
type VisitorCacheDTO = {
  version: number;
  data: {
    visitorId: string;
    anonymousId: string | null;
    consent?: boolean;
    context?: Record<string, boolean|number|string>;
    assignmentsHistory?: Record<string, string>;
    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 userExposed 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: HitCacheDTO): void;
  lookupHits(visitorId: string): HitCacheDTO;
  flushHits(visitorId: string): void;
}

cacheHit function

This 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 :

ArgumentTypeDescription
visitorIdstringvisitor ID
dataobjecthit data. This object follows the shape of type HitCacheDTO.

lookupHits function

This 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 array of type HitCacheDTO which follows this shape see.

  • public lookupHits(visitorId: string):object

It has one argument :

ArgumentTypeDescription
visitorIdstringvisitor ID

flushHits function

This 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 :

ArgumentTypeDescription
visitorIdstringvisitor ID

HitCacheDTO
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 time setConsent 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

Visitor class

Flag class


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 NameDescriptionContext variable nameTypeAuto-set by SDKExample
DEVICE_LOCALELanguage of the devicesdk_deviceLanguageStringNofra
DEVICE_TYPEType of the devicesdk_deviceTypeDeviceTypeNoMobile
DEVICE_MODELModel of the devicesdk_deviceModelStringNosamsung E1200
LOCATION_CITYCity geolocationsdk_cityStringNotoulouse
LOCATION_REGIONRegion geolocationsdk_regionStringNooccitanie
LOCATION_COUNTRYCountry geolocationsdk_countryStringNoFrance
LOCATION_LATCurrent Latitudesdk_latDoubleNo43.623647
LOCATION_LONGCurrent Longitudesdk_longDoubleNo1.445397
IPIP of the devicesdk_ipStringNo127.0.0.1
OS_NAMEName of the OSsdk_osNameStringYESubuntu / centos
OS_VERSION_NAMEVersion name of the OSsdk_osVersionNameStringNo9.0.0
OS_VERSION_CODEVersion code of the OSsdk_osVersionCodeNumberNo24
CARRIER_NAMEName of the carrier or mobile virtual network operatorsdk_carrierNameStringNofree
INTERNET_CONNECTIONWhat is the internet connectionsdk_internetConnectionStringNo5g
APP_VERSION_NAMEVersion name of the appsdk_versionNameStringNo1.1.2-beta
APP_VERSION_CODEVersion code of the appsdk_versionCodeNumberNo40
INTERFACE_NAMEName of the interfacesdk_interfaceNameStringNoProductPage
FLAGSHIP_CLIENTFlagship SDK client (Reserved)fs_clientStringYesTS
FLAGSHIP_VERSIONVersion of the Flagship SDK (Reserved)fs_versionStringYes2.0.0
FLAGSHIP_VISITORCurrent visitor id (Reserved)fs_usersStringYesvisitor_id

📘

To overwrite the keys, use the updateContext method


Did this page help you?