React V3.0.X
Introduction
SDK overview
Welcome to the Flagship ReactJS SDK documentation!
The following documentation helps you to run Flagship on your ReactJS environment (client-side or server-side).
Flagship ReactJS SDK provides a <FlagshipProvider />
, which makes Flagship features available to the rest of your app.
Flagship features are accessible using Flagship hooks, have a look at the documentation for details.
Feel free to contact us if you have any questions regarding this documentation.
SDK features
This SDK version helps you:
- Set a visitor ID
- Update visitor context
- Assign campaigns via the Decision API or via the Bucketing
- Get Flags
- Manage visitor consent
- Activate campaigns
- Send hits to our Universal Collect
- Manage visitor cache
Prerequisites
- Node.js: version 6.0.0 or later
- Npm: version 5.2.0 or later
- React: version 16.8.0 or later (the SDK only supports hooks for now)
Good to know
- Github repository
- Gzipped size: ~24.1 kB
- Typescript code supported
Getting started
Initialization
There are four steps to follow to get started with the React Flagship SDK.
- Install the node module
npm install @flagship.io/react-sdk
- Import the Flagship React provider
In most cases, do this in your App.js
file to wrap your entire app with the provider.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider>{/* [...] */}</FlagshipProvider>
</>
);
- Initialize the provider
You must at least include the required props like envId
, apiKey
, visitorData
.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: "YOUR_VISITOR_ID",
context: {
// some context
},
isAuthenticated: false,
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
- Use a Flagship hook in a component
In most case, you will get the desired flags.
import React from "react";
import { useFsFlag } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const flagBackgroundColor = useFsFlag("backgroundColor","green")
return (
<div
style={{
height: "200px",
width: "200px",
backgroundColor: flagBackgroundColor.getValue(),
}}
>
{"I'm a square with color=" + flagBackgroundColor.getValue()}
</div>
);
};
API Reference
FlagshipProvider
FlagshipProvider
Here is the full list of props available to use inside the FlagshipProvider
React component:
Props | Type | Default | Description |
---|---|---|---|
envId | string | Required | Environment id provided by Flagship. |
apiKey | string | Required | Api authentication key provided by Flagship. |
visitorData | object | null | This is the data to identify the current visitor using your app. See arguments |
onInitStart | function():void | null | Callback function called when the SDK starts initialization. |
onInitDone | function():void | null | Callback function called when the SDK ends initialization. |
onUpdate | function(object): void | null | Callback function called when the SDK is updated. For example, after a synchronize is triggered or visitor context has changed. See arguments |
onBucketingSuccess | function(object): void | null | Define a callable in order to get callback when the first bucketing polling succeed. see arguments |
onBucketingFail | function(object): void | null | Define a callable to get callback when the first bucketing polling failed. see arguments |
onBucketingUpdated | function(Date): void | null | Define a callable to get callback each time bucketing data from Flagship has updated. see arguments |
initialFlagsData | Array(object) | undefined | This is a set of flag data provided to avoid the SDK to have an empty cache during the first initialization. |
initialCampaigns | object | undefined | 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. |
initialBucketing | object | undefined | 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. |
loadingComponent | React.ReactNode | undefined | This component will be rendered when Flagship is loading at first initialization only. By default, the value is undefined. It means it will display your app and it might display default flags value for a very short moment. |
fetchNow | boolean | true | Decide to fetch automatically flags when SDK is initialized. NOTE: When fetchNow=false the property loadingComponent will be ignored. |
enableClientCache | boolean | true | 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. Note 2: Not available on server side, this setting will be ignored |
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. |
decisionMode | API | Bucketing | API | Indicates the behavior of the SDK. In API mode, it will get the modifications using the Flagship decision API.With Bucketing , it will load all campaigns once and compute the variation assignment of the visitor locally.learn more |
pollingInterval | number | 1 | Indicates the polling interval period in seconds when SDK is running Bucketing mode (decisionMode="Bucketing" ).For example, if pollingInterval=5 , a bucketing call will betrigger in background every 5 seconds. Note 1: pollingInterval can't be lower than 1 second. Note 2: if bucketing is enabled and pollingInterval value is 0, the polling will be done once. |
timeout | number | 2 | Specify timeout in seconds for api request. Note: timeout can't be lower than 0 second. |
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 |
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 |
visitorCacheImplementation | object | Defined | Define an object that implement the interface visitorCacheImplementation , to handle the visitor cache. see cache-manager |
hitCacheImplementation | object | Defined | 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 | Define a callable in order to get callback when the SDK status has changed. see arguments. |
onUserExposure | function(object):void | undefined | Optional Define a callable to get callback each time a Flag have been user exposed (activation hit has been sent) by SDK see arguments |
onLog | function(level: LogLevel, tag: string, message: string):void | undefined | Optional Define a callable to get a callback whenever the SDK needs to report a log see arguments |
When bucketing is running (
decisionMode="BUCKETING"
), the polling will restart its interval period based on the moment when one of the following props changes after first rendering :
- envId
- apiKey
- decisionMode
Any change of props
visitorData
will fetch flags automatically.On SDK initialization, if the props
visitorData
is null, no visitor will be initialized until set
visitorData
The visitorData
object takes the following arguments:
Argument | Type | Default | Description |
---|---|---|---|
id | string | undefined | Optional Unique identifier for the current user. This can be an ID from your database or a session ID. Learn more NOTE: The visitor id must be a string and can't be a number .NOTE 2: 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 ). |
context | object | {} | Optional JSON object of key-value pairs describing the user and device context. Learn more |
isAuthenticated | boolean | false | Optional Indicates if the visitor is authenticated (true) or not (false, by default). NOTE: The SDK will listen the change of this value (switching from true to false or from false to true ).This attribute is used for the experience continuity. Learn more |
hasConsented | boolean | true | Specify if visitor has consented for protected data usage. |
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
Key | Value | Type | Description |
---|---|---|---|
DECISION_API | API | string | Flagship SDK mode Decision API |
BUCKETING | BUCKETING | string | Flagship SDK mode bucketing |
onUpdate
The onUpdate
object has one argument with the following shape:
Key/Property | Description |
---|---|
fsModifications | Array or null. It contains the last modifications saved in cache. When null , it means the SDK still not ready. You can check the SDK status with other attributes. |
config | Object. The current configuration running on the SDK. |
status | Object. Contains informations about the actual SDK status. (Details below 👇) |
status
object shape:
Key/Property | Description |
---|---|
isLoading | Boolean. When true , the SDK is still not ready to render your App otherwise it'll use default modifications. |
isSdkReady | Boolean. true after it has fully finished initialization tasks, false otherwise. |
isVisitorDefined | Boolean. When true the flagship visitor instance is truthy, false otherwise. |
hasError | Boolean. true when an error occured inside the SDK, false otherwise. |
lastRefresh | String or null. The last update date occured on the flagship visitor instance. |
firstInitSuccess | String or null. When null no initialization succeed yet. When string contains stringified date of last successful initialization. |
onBucketingSuccess
The onBucketingSuccess
function has one argument with the following shape:
Key/Property | Description |
---|---|
status | 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 |
statusChangedCallback
The statusChangedCallback function has one argument
Argument | Type | Description |
---|---|---|
status | number | Status of the SDK. seeFlagshipStatus |
onUserExposure
The onUserExposure
function has one argument with the following shape:
Argument | Type | Description |
---|---|---|
param | UserExposureInfo | Get data from exposed flag |
UserExposureType shape
type UserExposureInfo = {
flagData: {
key: string
value: unknown
metadata: IFlagMetadata
},
visitorData: {
visitorId: string
anonymousId: string|null
context: Record<string, string|number|boolean>
}
}
Key/Property | Type | Description |
---|---|---|
flagData | object | key: flag key value: flag value metadata: Campaign information metadata see |
visitorData | object | visitorId: visitor id anonomousId: anonymous id context: visitor context |
Use case example
Learn more about getting flags
onLog
The onLog
function has 3 arguments
Argument | Type | Description |
---|---|---|
level | number | Get the log level. see LogLevel |
tag | string | Get the function that triggered the log |
message | string | Get a description of the log |
Usage :
import React from "react";
import { FlagshipProvider, LogLevel } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY" // <= Required in next major release
visitorData={{
id: "YOUR_VISITOR_ID",
context: {
// some context
},
isAuthenticated: false,
}}
onLog={(level, tag, message) => {
console.log(`[${LogLevel[level]}] [${tag}] : ${message}`);
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
FlagshipStatus
FlagshipStatus
is an enum defining the different status of Flagship SDK
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. |
Flag data shape:
type FlagDTO= {
key: string;
campaignId: string;
variationGroupId: string;
variationId: string;
isReference?: boolean;
campaignType?: string;
slug?:string|null;
value: any;
}
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 |
slug | slug | campaign slug |
value | any | Value of flag |
LogLevel
LogLevel is an enum defined the level of log to receive
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 React from "react";
import { FlagshipProvider } from "@flagship.io/react-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}`);
},
};
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY" // <= Required in next major release
visitorData={{
id: "YOUR_VISITOR_ID",
context: {
// some context
},
isAuthenticated: false,
}}
logManager={customLog},
>
{/* [...] */}
</FlagshipProvider>
</>
);
useFlagship
useFlagship
Demo:
This is the most used hook from the Flagship React SDK. It gives further functionalities such as getting current flags of your actual visitor, send hit tracking, SDK status...
Returns an object. (Typescript: UseFlagshipOutput)
useFlagship output
useFlagship output
Key/Property | Type | Description |
---|---|---|
visitorId | string | A unique identifier for the current user |
anonymousId | string | |
context | object | A dataset (object) that defines the current visitor. |
setConsent | function(hasConsented: boolean): void | Set if visitor has consented for protected data usage. |
hasConsented | boolean | Return True if the visitor has consented for private data usage, otherwise return False. |
updateContext | function(context: Record<string, boolean|string|number>): void | 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. Context keys must be String, and values types must be one of the following : Number, Boolean, String. See description. |
clearContext | function(): void | Clear the actual visitor context. See description. |
getFlag | function(key: string, defaultValue: T): object | Retrieve a Flag object by its key. If no flag match the given key an empty flag will be returned. See description |
fetchFlags | function(): Promise | 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. See description |
authenticate | function(visitorId: string): void | Authenticate anonymous visitor See description |
unauthenticate | function(): void | This function change authenticated Visitor to anonymous visitor. See description |
status | object | Gives you information about SDK current state. See description |
flagsData | array | An array of flag data |
hit | object | Gives you functions to send one or further hits. See description |
useFlagship output setConsent
useFlagship output setConsent
Set if visitor has consented for protected data usage.
setConsent(hasConsented: boolean): void;
It has one argument :
Argument | Type | Description |
---|---|---|
hasConsented | boolean | True if the visitor has consented false otherwise. |
useFlagship output updateContext
useFlagship output updateContext
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.
updateContext(context: Record<string, string | number | boolean>): void
It has one argument :
Argument | Type | Description |
---|---|---|
context | object | A Set of keys, values. |
useFlagship output clearContext
useFlagship output clearContext
Clear the actual visitor context
clearContext(): void
useFlagship output fetchFlags
useFlagship output fetchFlags
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>
useFlagship output getFlag
useFlagship output getFlag
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>
Argument | Type | Description |
---|---|---|
key | String | key associated to the flag. |
defaultValue | T | flag default value. |
- Default value must be one of the following type :
string
,number
,boolean
,object
,array
.
useFlagship output authenticate
useFlagship output authenticate
Authenticate anonymous visitor
authenticate(visitorId: string): void
Argument | Type | Default | Description |
---|---|---|---|
visitorId | string | required | id of the new authenticated visitor. |
useFlagship output unauthenticate
useFlagship output unauthenticate
This function change authenticated Visitor to anonymous visitor
unauthenticate(): void
useFlagship output hit
useFlagship output hit
useFlagship output status
useFlagship output status
Key/Property | Description |
---|---|
isLoading | If true , the SDK isn't ready. |
lastRefresh | Date cast string with ISO format. This is the date corresponding to the most recent moment where modifications were saved in cache. |
All useFlagship hook methods will be deactivated when visitor is not initialized except getFlag
useFsFlag
useFsFlag
This hook returns a Flag object by its key. If no flag match the given key an empty flag will be returned.
useFsFlag<T>(key: string, defaultValue: T) : IFlag<T>
Argument | Type | Description |
---|---|---|
key | String | key associated to the flag. |
defaultValue | T | flag default value. |
Flag class api
getValue
function
getValue
functionTo retrieve flag current value, simply call value() method of the Flag object.
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. |
Will return default value when visitor is not yet initialized
metadata
property
metadata
propertyYou 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.
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
}
Key\Property | Type | Description |
---|---|---|
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 |
userExposed
function
userExposed
functionBy 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:
- Pass an
userExposed=true
parameter to the getValue() method. - Use the following userExposed() method from the Flag instance.
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.
exists
function
exists
functionThis method will return true if a Flag exists in Flagship
exists(): boolean
Getting flags
with useFsFlag hook
Demo:
import React from "react";
import { useFsFlag } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const flag = useFsFlag("backgroundColor","green")
const flagExists = flag.exists()
const flagMetadata = flag.metadata
return (
<button
onClick={()=>{
// Activate campaign
flag.userExposed().then(()=>{
// Notify success
}).catch(()=>{
// Notify error
})
}}
style={{
height: "200px",
width: "200px",
backgroundColor: flag.getValue(),
}}
>
{"I'm a square with color=" + flag.getValue()}
</button>
);
};
with useFlagship hook
Demo:
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { getFlag } = useFlagship()
const flag = getFlag("backgroundColor","green")
const flagExists = flag.exists()
const flagMetadata = flag.metadata
return (
<button
style={{
height: "200px",
width: "200px",
backgroundColor: flag.getValue(),
}}
>
{"I'm a square with color=" + flag.getValue()}
</button>
);
};
Report a Flag exposition
import React from "react";
import { useFsFlag } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const flag = useFsFlag("backgroundColor","green")
const flagExists = flag.exists()
const flagMetadata = flag.metadata
return (
<button
onClick={()=>{
// Report the flag exposition
flag.userExposed().then(()=>{
// Notify success
}).catch(()=>{
// Notify error
})
}}
style={{
height: "200px",
width: "200px",
backgroundColor: flag.getValue(),
}}
>
{"I'm a square with color=" + flag.getValue()}
</button>
);
};
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { getFlag } = useFlagship()
const flag = getFlag("backgroundColor","green")
const flagExists = flag.exists()
const flagMetadata = flag.metadata
return (
<button
onClick={()=>{
// Report the flag exposition
flag.userExposed().then(()=>{
// Notify success
}).catch(()=>{
// Notify error
})
}}
style={{
height: "200px",
width: "200px",
backgroundColor: flag.value(),
}}
>
{"I'm a square with color=" + flag.value()}
</button>
);
};
Fetching Flags
with useFlagship hook
Demo:
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { fetchFlags } = useFlagship()
return (
<button
onClick={()=>{
fetchFlags().then(()=>{
// Notify success...
}).catch(()=>{
// Notify error...
})
}}>
Trigger a fetch flag
</button>
);
};
Managing visitor consent
With Flagship React SDK
, you can 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 or false in props VisitordData of FlagshipProvider - Use
setConsent
method ofuseFlagship
hook
Demo:
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: null, // or remove this line
context: {
// some context
},
hasConsented: true, // set hasConsented to true or false
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { setConsent } = useFlagship()
return (
<button
onClick={()=>{
setConsent(true)
}}>
Accept consent
</button>
);
};
Update context with predefined keys of context
Demo:
import React from "react";
import { FlagshipProvider, DEVICE_LOCALE } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: null, // or remove this line
context: {
[DEVICE_LOCALE]: "fr",
},
hasConsented: true, // set hasConsented to true or false
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { updateContext } = useFlagship()
return (
<button
onClick={()=>{
updateContext({
[DEVICE_LOCALE]: "fr"
})
}}>
Trigger update context
</button>
);
};
Learn more about predefined keys of context
Experience continuity
Make sure that the experience continuity option is enabled on the flagship platform before using those methods.
It might happen that a visitor from your app is not yet recognized and is being authenticated (and recognized) later on...
From there, we provide the ability to ensure that during such transition, your visitor will keep same experience (meaning targetting still the same campaign's variations and thus same modifications).
In order to do a successful experience continuity, we will have to distinguish when the visitor is anonymous or authenticated.
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 know 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.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: null, // or remove this line
context: {
// some context
},
isAuthenticated: false, //
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
Whatever how it has been set, the actual visitor id will be what we call its anonymous id.
Be aware that when you do not specify a visitor id, as
enableClientCache
is enable by default, the SDK will try to find a previous visitor experience. If so, the new visitor will have the same visitor id as it was during the previous visitor session. From there, no id will be automatically generated.
- Your visitor is signing in.
We need to set the value of visitorData.isAuthenticated
to true
or call the method authenticate
of useFlagship
hook.
Moreover, the visitor id set should be an existing visitor id (that has previously seen specific campaign's flags) in order to make the experience continuity effective.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: "AUTHENTICATED_ID",
context: {
// some context
},
isAuthenticated: true,
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { authenticate } = useFlagship()
return (
<button
onClick={()=>{
// ... sign in code
authenticate("AUTHENTICATED_ID")
})
}}>
Trigger sign in
</button>
);
};
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 flags as your visitor might target new campaigns.
- Your visitor decide to sign out.
We need to set the value of visitorData.isAuthenticated
back to false
.
If you want to keep the same visitor (anonymous) experience as before, depending on the value of prop enableClientCache
, you'll have to:
enableClientCache=true
: the sdk will put back the previous anonymous id
automatically based on data from cache.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: null,
context: {
// some context
},
isAuthenticated: false, // <--- back to false
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
import React from "react";
import { useFlagship } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { unauthenticate } = useFlagship()
return (
<button
onClick={()=>{
// ... sign out code
unauthenticate()
})
}}>
Trigger sign out
</button>
);
};
enableClientCache=false
: you should specify in
prop, the same value as you set in step 1.
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: "YOUR_VISITOR_ID", // <--- same value as step 1
context: {
// some context
},
isAuthenticated: false, // <--- back to false
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
If you need a completly brand new visitor experience, you should put a new visitor id in visitorData.id
prop instead:
import React from "react";
import { FlagshipProvider } from "@flagship.io/react-sdk";
const App = () => (
<>
<FlagshipProvider
envId="YOUR_ENV_ID"
apiKey="YOUR_API_KEY"
visitorData={{
id: "YOUR_BRAND_NEW_VISITOR_ID", // <--- new value
context: {
// some context
},
isAuthenticated: false, // <--- back to false
}}
>
{/* [...] */}
</FlagshipProvider>
</>
);
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 React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
const pageHit = {
type: HitType.PAGE,
documentLocation: "https://localhost",
}
fsHit.send(pageHit).then(()=>{
// Notify success
}).catch(()=>{
// Notify error
})
}}
>
Send a hit
</button>
);
};
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 functions from the `useFlagship hook
import React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
fsHit.send({
type: HitType.PAGE,
documentLocation: "https://localhost"
})
// or send multiple
fsHit.sendMultiple(
{
type: HitType.PAGE,
documentLocation: "https://localhost"
},
{
type: HitType.SCREEN,
documentLocation: "home"
}
)
}}
>
Send a hit
</button>
);
};
useFlagship output hit.send
function
useFlagship output hit.send
functionSend Hit to Flagship servers for reporting.
send (hit: IHit): Promise<void>
Parameter | Type | Default | Description |
---|---|---|---|
hit | object | required | Hit to send. see Hit |
useFlagship output hit.sendMultiple
function
useFlagship output hit.sendMultiple
functionSend Hits to Flagship servers for reporting.
sendMultiple(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 React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
fsHit.send({
type: HitType.PAGE,
documentLocation: "https://localhost",
userIp: "127.0.0.1",
screenResolution: "800X600",
locale: "fr",
sessionNumber: "1234"
})
}}
>
Send a hit
</button>
);
};
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 React, { useEffect } from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship();
useEffect(() => {
fsHit.send({
type: HitType.PAGE, // or "PAGEVIEW",
documentLocation: '<PAGE_URL>' // https://example.com/my/page/url
});
}, []);
return <>{/* [...] */}</>;
};
- 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 React, { useEffect } from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship();
useEffect(() => {
fsHit.send({
type: HitType.SCREEN, // or "SCREENVIEW",
documentLocation: '<SCREEN_NAME>'
});
}, []);
return <>{/* [...] */}</>;
};
- 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 React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
fsHit.send({
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"
})
}}
>
Send a hit
</button>
);
};
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 React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
fsHit.send({
type: HitType.ITEM, //or "ITEM"
transactionId: "#12345",
productName: "product",
productSku: "sku123",
itemPrice: 199.99,
itemQuantity: 1,
itemCategory: "test"
})
}}
>
Send a hit
</button>
);
};
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 React from "react";
import { useFlagship, HitType } from "@flagship.io/react-sdk";
export const MyReactComponent = () => {
const { hit: fsHit } = useFlagship()
return (
<button
onClick={()=>{
fsHit.send({
type: HitType.EVENT, //or "EVENT"
category: EventCategory.USER_ENGAGEMENT, // or EventCategory.ACTION_TRACKING
action: "click",
label: "label",
value: 100,
})
}}
>
Send a hit
</button>
);
};
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 |
label | string | optional | Additional description of your event. |
value | integer | optional | (optional) Can be used to evaluate user interactions with individual site objects or content items. NOTE: this value must be non-negative / non-float |
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 userExposed in order to resend them later.
By default the Flagship ReactJS SDK provide a default cache manager implementation. It is possible to use your own cache manager by implementing the intefaces IVisitorCacheImplementation
and IHitCacheImplementation
through visitorCacheImplementation and hitCacheImplementation props of FlagshipProvider.
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
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 VisitorCacheDTO . |
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 VisitorCacheDTO
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.
VisitorCacheDTO
type VisitorCacheDTO = {
version: number;
data: {
visitorId: string;
anonymousId: string | null;
consent?: boolean;
context?: Record<string, boolean|number|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
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 HitCacheDTO . |
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 HitCacheDTO
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 |
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 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.
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
License
This Flagship SDK is distributed under the Apache version 2.0 license.
Updated 6 months ago