React V2.1.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:

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

Changelog

Getting started

Initialization

There are four steps to follow to get started with the React Flagship SDK.

  1. Install the node module
npm install @flagship.io/react-sdk
  1. 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>
  </>
);
  1. Initialize the provider

You must at least include the required props like envId, apiKey, visitorData.

NOTE: apiKey is not required for now but will be in next major release!

import React from "react";
import { FlagshipProvider } 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,
      }}
      enableConsoleLogs={true}
    >
      {/* [...] */}
    </FlagshipProvider>
  </>
);
  1. Use a Flagship hook in a component

In most case, you will get the desired modifications.

import React from "react";
import { useFsModifications } from "@flagship.io/react-sdk";

export const MyReactComponent = () => {
  const fsModifications = useFsModifications([
    {
      key: "backgroundColor",
      defaultValue: "green",
      activate: true,
    },
  ]);
  return (
    <div
      style={{
        height: "200px",
        width: "200px",
        backgroundColor: fsModifications.backgroundColor,
      }}
    >
      {"I'm a square with color=" + fsModifications.backgroundColor}
    </div>
  );
};

API Reference

FlagshipProvider

Here is the full list of props available to use inside the FlagshipProvider React component:

PropsTypeDefaultDescription
envIdstringRequiredYour Flagship environment id.
visitorDataobjectRequiredThis is the data to identify the current visitor using your app. See arguments
onInitStartfunction():voidnullCallback function called when the SDK starts initialization.
onInitDonefunction():voidnullCallback function called when the SDK ends initialization.
onUpdatefunction(object):voidnullCallback function called when the SDK is updated. For example, after a synchronize is triggered or visitor context has changed. See arguments
onBucketingSuccessfunction(object):voidnullCallback function called when the bucketing polling succeed.

See arguments
onBucketingFailfunction(object):voidnullCallback function called when the bucketing polling failed.

See arguments
initialModificationsArray(object)undefinedThis is an array of modifications where each element must be same shape as the element inside the "campaigns" attribute. Providing this prop prevents the SDK from having an empty cache when it first initializes. If the shape of an element is not correct, an error log will give the reason why.
initialBucketingArray(object)undefinedThis 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.

If the shape of an element is not correct, an error log will give the reason why.
loadingComponentReact.ReactNodeundefinedThis 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 modifications value for a very short moment.
fetchNowbooleantrueDecide to fetch automatically modifications when SDK is initialized.

NOTE: When fetchNow=false the property loadingComponent will be ignored.
fetchNow=false
activateNowbooleanfalseDecide to trigger automatically the data when SDK is initialized. NOTE: when set to true, it will implicitly set fetchNow=true as well.
enableConsoleLogsbooleanfalseEnable it to display logs on the console when SDK is running. This will only display logs such as Warnings, Errors, Fatal errors and Info.
enableSafeModebooleanfalseEnable it to run the SDK into a safe mode when an error might occurs through the SDK. When safe mode is triggered, default modifications will be returned and other function will just be executed without doing anything.

NOTE: This feature is still experimental as it is currently
catching errors globally (SDK + your app) which can gives side effects
to your app. We're working on improvement.
enableCachebooleantrueIndicates wether enable or disable the client cache manager (local storage).

By enabling the cache, this will allow keep cross sessions visitor experience.

Note: The 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 it is authenticated or not. That's it.
enableErrorLayoutbooleanfalseThis is a small layout visible at the bottom of the screen. It is displayed only when an unexpected error occurred in the SDK. By default, it's set to false and if set to true , it will be only visible in a node environment other than production . Here a screenshot to have a look.
nodeEnvstring'production'If value is other than production , it will also display Debug logs.
flagshipApistring'https://decision-api.flagship.io/v1/'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.
Decision API V1 is set by default but deprecated, starting next version, only Decision API V2 will be implemnented.
apiKeystringnullIf you want to use the Decision API V2 , you must contact the support team so they'll provide you an API Key to authenticate the calls.

You can find the api key of your environment on the Flagship dashboard, in Parameters > Environment & Security.

NOTE: apiKey will be required in the next major release.
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.

Note: When Bucketing mode is set, you mustspecify pollingInterval attribute as well, so that bucketing can check for updates.

Note2: When Bucketing mode is set, and the polling detects an update, it won't apply new changes until you manually trigger a campaign synchronization.

Note3: Bucketing mode only works when you allow to start it during
SDK initialization (fetchNow=true). We will add the ability
to trigger it manually in the next minor release.
pollingIntervalnumbernullIndicates the polling interval period in seconds when SDK is running Bucketing mode (decisionMode="Bucketing").

For example, if pollingInterval=5, a bucketing call will be
trigger in background every 5 seconds.

Note1: pollingInterval can't be lower than 1 second.

Note2: if bucketing is enabled and pollingInterval
value is null, the polling will be done once and an error log will be trigger.
timeoutnumber2Indicates the delay in seconds before it triggers a timeout when requesting campaigns via the Flagship decision api.

Note: timeout can't be lower than 0 second.

📘

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
  • visitorData
  • initialModifications
  • initialBucketing
  • fetchNow
  • activateNow
  • enableConsoleLogs
  • nodeEnv
  • flagshipApi
  • apiKey
  • pollingInterval

visitorData

The visitorData object takes the following arguments:

ArgumentTypeDescription
idstringOptional. 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.

NOTE2: If you do not specify a value, the id will be either
automatically generated or will be the visitor id from previous session
(if enableCache equals true).
contextobjectOptional. JSON object of key-value pairs describing the user and device context. Learn more
isAuthenticatedbooleanOptional. 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

onUpdate

The onUpdate object has one argument with the following shape:

Key/PropertyDescription
fsModificationsArray 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.
configObject. The current configuration running on the SDK.
statusObject. Contains informations about the actual SDK status. (Details below 👇)

status object shape:

Key/PropertyDescription
isLoadingBoolean. When true, the SDK is still not ready to render your App otherwise it'll use default modifications.
isSdkReadyBoolean. true after it has fully finished initialization tasks, false otherwise.
isVisitorDefinedBoolean. When true the flagship visitor instance is truthy, false otherwise.
hasErrorBoolean. true when an error occured inside the SDK, false otherwise.
lastRefreshString or null. The last update date occured on the flagship visitor instance.
firstInitSuccessString or null. When null no initialization succeed yet. When string contains stringified date of last successful initialization.

onBucketingSuccess

The onBucketingSuccess object has one argument with the following shape:

Key/PropertyDescription
statusString. Returns either 200 (fresh update) or 304 (no change).
payloadObject. The latest bucketing data received.

onBucketingFail

The onBucketingFail object has one argument with the following shape:

Key/PropertyDescription
errorObject. Returns the error occurred and leads to bucketing polling failure.

useFlagship

Demo:

This is the most used hook from the Flagship React SDK. It gives further functionalities such as getting current modifications of your actual visitor, send hit tracking, SDK status...

Returns an object. (Typescript: UseFlagshipOutput)

useFlagship input

ArgumentTypeDescription
optionsobjectSee description

useFlagship input options

Key/PropertyTypeDescription
modificationsobjectNode param to specify Flagship modifications. See description

useFlagship input options modifications

ArgumentDescription
requestedRequired. An array of objects for each modifications. See description
activateAllOptional. The value is false by default

useFlagship input options modifications requested

ArgumentDescription
keyRequired. The name of the modification.
defaultValueRequired. The default value if no value for this modification is found.
activateOptional.

useFlagship output

Key/PropertyTypeDescription
modificationsobjectAn object where each key is a modification with corresponding value
getModificationInfofunctionReturns a promise with an object containing informations about modification matching the key specified in argument. See description
synchronizeModificationsfunctionUpdates campaigns targeting that match the current visitor context. See description
hitobjectGives you functions to send one or further hits. See description
statusobjectGives you information about SDK current state. See description
startBucketingPollingfunction()Call this function to start the bucketing manually. See description
stopBucketingPollingfunction()Call this function to stop the bucketing manually. See description

useFlagship output getModificationInfo

Full details here

Returns Promise<object | null>. (Typescript: GetModificationInfoOutput)

ArgumentTypeDescription
keystringThe modification key.

useFlagship output synchronizeModifications

Returns Promise<number>.

Full details here

ArgumentTypeDefaultDescription
activateAllModificationsbooleanfalseIf set to true, all modifications will be activated. If set to false (default behavior), none will be activated.

useFlagship output hits

Key/PropertyDescription
sendTakes an object as parameter. The object must follow a hit shape.
sendMultipleTakes an array of object as parameter. Each object must follow a hit shape. You can mix different hit shapes within the array.

useFlagship output status

Key/PropertyDescription
isLoadingIf true, the SDK isn't ready.
lastRefreshDate cast string with ISO format. This is the date corresponding to the most recent moment where modifications were saved in cache.

useFlagship output startBucketingPolling

Key/PropertyDescription
successBoolean. If true means it succeed, false otherwise.
reasonString. A message telling the reason in case of failure.

useFlagship output stopBucketingPolling

Key/PropertyDescription
successBoolean. If true means it succeed, false otherwise.
reasonString. A message telling the reason in case of failure.

useFsModifications

Demo:

The useFsModifications hook gives you the modifications saved in the SDK cache.

📘

If the SDK cache is empty, it will always return modification's default values.

Returns Flagship modifications. (Typescript: UseFsModificationsOutput)

useFsModifications input

ArgumentTypeDefaultDescription
modificationsRequestedArray(object)RequiredList of all modifications you're looking for. See description
activateAllModificationsbooleanfalseIf set to true, all modifications will be activated. If set to false, none will be activated. NOTE: Setting this argument will override the activate attribute set in each element of the modificationsRequested array.

useFsModifications input modificationsRequested

ArgumentDescription
keyRequired. The name of the modification.
defaultValueRequired. The default value if no value for this modification is found.
activateOptional. Determines whether or not the modification is activated (if activateAllModifications is not set).

useFsActivate

Demo:

Returns void.

useFsActivate input

ArgumentTypeDefaultDescription
modificationKeysArray(string)RequiredAn array of modification keys. For each key, a HTTP request will be sent to activate the corresponding modification.
applyEffectScopeArray(string)[]This argument behaves the same way as the second argument in the React.useEffect hook. It will listen for the array values and synchronize if it detects any changes. By default, it is triggered when the component where it's used is first rendered.

Getting modifications

with useFlagship hook (1/3)

Demo:

import { useFlagship } from "@flagship.io/react-sdk";

const fsParams = {
  modifications: {
    requested: [
      {
        key: "btnColor",
        defaultValue: "green",
        activate: true,
      },
    ],
  },
};

const {
  modifications: fsModifications,
  status: fsStatus,
  hit: fsHit,
} = useFlagship(fsParams);

with useFsModifications hook

Demo:

import { useFsModifications } from "@flagship.io/react-sdk";

const fsModifications = useFsModifications([
  {
    key: "btnColor",
    defaultValue: "green",
    activate: true,
  },
]);

Campaign synchronization

with useFlagship hook (2/3)

Demo:

import { useFlagship } from "@flagship.io/react-sdk";

const { synchronizeModifications } = useFlagship();

return (
  <>
    <Button
      onClick={() => {
        synchronizeModifications(activateAllModifications)
          .then((statusCode) => {
            if (statusCode < 300) {
              // Notify success...
            } else {
              // Notify failure...
            }
          })
          .catch((error) => {
            // Notify error...
          });
      }}
    >
      Trigger a synchronize
    </Button>
  </>
);

Campaign activation

with useFsActivate hook

Demo:

import { useFsActivate } from "@flagship.io/react-sdk";

const [toggle, setToggle] = React.useState(false);

useFsActivate(["btnColor", "otherKey1", "otherKey2"], [toggle]); // trigger an activate when "toggle" value change.

// insider render function:

<Button variant="secondary" onClick={() => setToggle(!toggle)}>
  Trigger activate
</Button>;

Experience continuity

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.

As this visitor will be considered as anonymous, we'll not specify a visitor id so that the SDK will a generate automatically one 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 enableCache 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.

  1. Your visitor is signing in.

We need to set the value of visitorData.isAuthenticated to true.

Moreover, the visitor id set should be an existing visitor id (that has previously seen specific campaign's modifications) 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>
  </>
);

This new visitor id is what we call its authenticated id.

The visitor is updated as authenticated, keeping the previous variations from campaigns that are still matched and thus gives you same modifications as before being logged in.

📘

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

  1. 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 enableCache, you'll have to:

  • enableCache=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>
  </>
);
  • enableCache=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 campaign goals. For more information about our measurement protocol, read our Universal Collect documentation.

There are four different types of hits available:

with useFlagship hook (3/3)

Demo:

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

// insider render function:

<Button
  onClick={() => {
    const mockHit = {
      type: "Transaction",
      data: {
        transactionId: "12451342423",
        affiliation: "myAffiliation",
        totalRevenue: 999,
        shippingCost: 888,
        shippingMethod: "DHL",
        currency: "USD",
        taxes: 1234444,
        paymentMethod: "creditCard",
        itemCount: 2,
        couponCode: "myCOUPON",
        documentLocation:
          "http%3A%2F%2Fabtastylab.com%2F60511af14f5e48764b83d36ddb8ece5a%2F",
        pageTitle: "myScreen",
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a transaction hit
</Button>;

Hit types

Screen

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

<Button
  onClick={() => {
    const mockHit = {
      type: "Screen",
      data: {
        documentLocation: "screenName"
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a screen hit
</Button>;
AttributeTypeDescription
documentLocationstringRequired. Specifies the current name of the screen when the hit is sent.

Page

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

<Button
  onClick={() => {
    const mockHit = {
      type: "Page",
      data: {
        documentLocation:
          "http%3A%2F%2Fabtastylab.com%2F60511af14f5e48764b83d36ddb8ece5a%2F",
        pageTitle: "HomePage"
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a screen hit
</Button>;
AttributeTypeDescription
documentLocationstringRequired. Specifies the current URL of the page when the hit is sent.
pageTitlestringOptional. Specifies the current name of the page when the hit is sent.

Transaction

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

<Button
  onClick={() => {
    const mockHit = {
      type: "Transaction",
      data: {
        transactionId: "12451342423",
        affiliation: "myAffiliation",
        totalRevenue: 999,
        shippingCost: 888,
        shippingMethod: "DHL",
        currency: "USD",
        taxes: 1234444,
        paymentMethod: "creditCard",
        itemCount: 2,
        couponCode: "myCOUPON",
        documentLocation:
          "http%3A%2F%2Fabtastylab.com%2F60511af14f5e48764b83d36ddb8ece5a%2F",
        pageTitle: "myScreen",
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a transaction hit
</Button>;
AttributeTypeDescription
transactionIdstringRequired. The ID of your transaction.
affiliationstringRequired. The name of the KPI that you will have inside your reporting. Learn more
totalRevenuenumberOptional. Specifies the total revenue associated with the transaction. This value should include any shipping and/or tax amounts.
shippingCostnumberOptional. The total shipping cost of your transaction.
shippingMethodstringOptional. The shipping method for your transaction.
taxesnumberOptional. Specifies the total amount of taxes in your transaction.
currencystringOptional. Specifies the currency of your transaction. NOTE: This value should be a valid ISO 4217 currency code.
paymentMethodstringOptional. Specifies the payment method used for your transaction.
itemCountnumberOptional. Specifies the number of items of your transaction.
couponCodestringOptional. The coupon code associated with the transaction.
documentLocationstringOptional. Specifies the current URL of the page when the hit is sent.
pageTitlestringOptional. Specifies the current name of the page when the hit is sent.

Item

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

<Button
  onClick={() => {
    const mockHit = {
      type: "Item",
      data: {
        transactionId: "0987654321",
        name: "testItem",
        price: 999,
        code: "testCode",
        category: "testCategory",
        quantity: 123,
        documentLocation:
          "http%3A%2F%2Fabtastylab.com%2F60511af14f5e48764b83d36ddb8ece5a%2F",
        pageTitle: "testItem",
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a item hit
</Button>;
AttributeTypeDescription
transactionIdstringRequired. The ID of your transaction.
namestringRequired. The name of your item.
pricenumberOptional. Specifies the price for a single item/unit.
codestringOptional. Specifies the SKU or item code.
categorystringOptional. Specifies the category that the item belongs to.
quantitynumberOptional. Specifies the number of items purchased.
documentLocationstringOptional. Specifies the current URL of the page when the hit is sent.
pageTitlestringOptional. Specifies the current name of the page when the hit is sent.

📘

The Item hit isn't available yet in the Flagship reporting view.

Event

import { useFlagship } from "@flagship.io/react-sdk";

const { hit: fsHit } = useFlagship();

<Button
  onClick={() => {
    const mockHit = {
      type: "Event",
      data: {
        category: "User Engagement",
        action: "signOff",
        label: "Hello world",
        value: 123,
        documentLocation:
          "http%3A%2F%2Fabtastylab.com%2F60511af14f5e48764b83d36ddb8ece5a%2F",
        pageTitle: "testEvent",
      },
    };
    fsHit.send(mockHit);
  }}
>
  Send a event hit
</Button>;
AttributeTypeDescription
categorystringRequired. Specifies the category of your event. NOTE: This value must be either 'Action Tracking' or 'User Engagement'.
actionstringRequired. The name of the KPI you will have inside the reporting.
labelstringOptional. Specifies additional description of your event.
valuenumberOptional. Specifies the monetary value associated with an event (e.g. you earn 10 to 100 euros depending on the quality of lead generated). NOTE: this value must be non-negative.
documentLocationstringOptional. Specifies the current URL of the page when the hit is sent.
pageTitlestringOptional. Specifies the current name of the page when the hit is sent.

Demos

Following demos illustrate how the SDK is used in practice ☕

Developer Demo

react-dev-demo

Code sandbox Demo

react-sandbox-demo

Ecommerce store Demo

react-ecommerce-demo

Readme 📖

Live Demo 🕹

Appendix

Release note

Take a look to the Release note.

Contributing

Take a look at the Contributors Guide if you're interested in contributing to the SDK.

License

This Flagship SDK is distributed under the Apache version 2.0 license.