Project: Flagsmith (Observability and Analysis / Feature Flagging)
File: javascript.md

title: Flagsmith JavaScript SDK sidebar_label: JavaScript description: Manage your Feature Flags and Remote Config in your JavaScript applications. slug: /clients/javascript This library can be used with pure JavaScript, React (and all other popular frameworks/libraries) and React Native projects. The source code for the client is available on . Example applications for a variety of JavaScript frameworks such as React, Vue and Angular, as well as React Native, can be found here: :::tip We also have flagsmith-es if you'd prefer to use modules. ::: ```bash npm i flagsmith --save ``` :::tip The React Native SDK shares the exact same implementation of Flagsmith, however it requires an implementation of AsyncStorage to be provided (e.g. @react-native-community/async-storage) in order to utilise analytics and caching. See . ::: ```bash npm i react-native-flagsmith --save ``` ```html <script src="https://cdn.jsdelivr.net/npm/flagsmith/index.js"></script> ``` The SDK is initialised against a single environment within a project on , for example the Development or Production environment. You can find your Client-side Environment Key in the Environment settings page. ```javascript import flagsmith from 'flagsmith or react-native-flagsmith'; //Add this line if you're using flagsmith via npm flagsmith.init({ environmentID: '<YOURCLIENTSIDEENVIRONMENTKEY>', // api:"http://localhost:8000/api/v1/" set this if you are self hosting, and point it to your API cacheFlags: true, // stores flags in localStorage cache enableAnalytics: true, // See https://docs.flagsmith.com/flag-analytics/ for more info. onChange: (oldFlags, params) => { //Occurs whenever flags are changed const { isFromServer } = params; //determines if the update came from the server or local cached storage //Check for a feature if (flagsmith.hasFeature('mycoolfeature')) { myCoolFeature(); } //Or, use the value of a feature const bannerSize = flagsmith.getValue('banner_size'); //Check whether value has changed const bannerSizeOld = oldFlags['bannersize'] && oldFlags['bannersize'].value; if (bannerSize !== bannerSizeOld) { // Do something! } }, }); ``` :::info As of flagsmith 4.0.0, `flagsmith.init` will return a promise resolving with either cache or the latest features or defaults. The promise will reject if there is no cache and an invalid or no API response was received. ::: You can define default flag values when initialising the SDK. This ensures that your application works as intended in the event that it . ```javascript import flagsmith from 'flagsmith or react-native-flagsmith'; //Add this line if you're using flagsmith via npm flagsmith.init({ environmentID: '<YOURCLIENTSIDEENVIRONMENTKEY>', defaultFlags: { feature_a: { enabled: false}, font_size: { enabled: true, value: 12 }, } onChange: (oldFlags, params) => { ... }, }); ``` You can automatically set default flags for your frontend application in CI/CD by using our in your build pipelines. The main steps to achieving this are as follows: Install the CLI `npm i flagsmith-cli --save-dev` Call the CLI as part of npm postinstall to create a `flagsmith.json` each time you run `npm install`. This can be done by either: Using an environment variable `export FLAGSMITHENVIRONMENT=<YOURCLIENTSIDEENVIRONMENT_KEY> flagsmith get` Manually specifying your environment key `flagsmith get <YOURCLIENTSIDEENVIRONMENTKEY>`. In your application, initialise Flagsmith with the resulting JSON, this will set default flags before attempting to use local storage or call the API. `flagsmith.init({environmentID: json.environmentID, state:json})` A working example of this can be found . A list of cli commands can be found . Identifying users allows you to target specific users from the Flagsmith dashboard and configure features and traits. You can call this before or after you initialise the project, calling it after will re-fetch features from the API. You can identify the users as part of initialising the client or after with the function `flagsmith.identify`. User features can be managed by navigating to users on for your desired

When you initialise the client without an identity, it will fetch the flags for a given environment (unless you provide `preventFetch:true`). ```javascript import flagsmith from 'flagsmith'; flagsmith.init({ environmentID: '<YOURCLIENTSIDEENVIRONMENTKEY>', onChange: (oldFlags, params) => { //Occurs whenever flags are changed const { isFromServer } = params; //determines if the update came from the server or local cached storage //Set a trait against the Identity flagsmith.setTrait('favourite_colour', 'blue'); //This save the trait against the user, it can be queried with flagsmith.getTrait //Check for a feature if (flagsmith.hasFeature('mypoweruser_feature')) { myPowerUserFeature(); } //Check for a trait if (!flagsmith.getTrait('acceptedcookiepolicy')) { showCookiePolicy(); } //Or, use the value of a feature const myPowerUserFeature = flagsmith.getValue('mypoweruser_feature'); //Check whether value has changed const myPowerUserFeatureOld = oldFlags['mypoweruserfeature'] && oldFlags['mypoweruserfeature'].value; if (myPowerUserFeature !== myPowerUserFeatureOld) { // Do something! } }, }); /* Can be called either after you're done initialising the project or in flagsmith.init with its identity and trait properties to prevent flags being fetched twice. */ flagsmith.identify('flagsmithsampleuser'); //This will create a user in the dashboard if they don't already exist ``` Initialising the client with an identity property will retrieve the user's flags instead of the environment defaults. You can also specify traits at this point which could determine the flags that come back based on segment overrides. ```javascript import flagsmith from 'flagsmith'; flagsmith.init({ environmentID: '<YOURCLIENTSIDEENVIRONMENTKEY>', identity: 'flagsmithsampleuser', traits: { age: 21, country: 'England' }, // these will add to the user's existing traits onChange: (oldFlags, params) => { //Occurs whenever flags are changed const { isFromServer } = params; //determines if the update came from the server or local cached storage //Set a trait against the Identity flagsmith.setTrait('favourite_colour', 'blue'); //This save the trait against the user, it can be queried with flagsmith.getTrait //Check for a feature if (flagsmith.hasFeature('mypoweruser_feature')) { myPowerUserFeature(); } //Check for a trait if (!flagsmith.getTrait('acceptedcookiepolicy')) { showCookiePolicy(); } //Or, use the value of a feature const myPowerUserFeature = flagsmith.getValue('mypoweruser_feature'); //Check whether value has changed const myPowerUserFeatureOld = oldFlags['mypoweruserfeature'] && oldFlags['mypoweruserfeature'].value; if (myPowerUserFeature !== myPowerUserFeatureOld) { } }, }); ``` All function and property types can be seen . | Property | Description | Required | Default Value | | - | :--: | -: | -: | | `environmentID: string` | Defines which project environment you wish to get flags for. example ACME Project - Staging. | YES | null | | `onChange?: (previousFlags:IFlags, params:IRetrieveInfo, loadingState:LoadingState)=> void` | Your callback function for when the flags are retrieved `(previousFlags,{isFromServer:true/false,flagsChanged: true/false, traitsChanged:true/false})=>{...}` | YES | null | | `onError?: (res:{message:string}) => void` | Callback function on failure to retrieve flags. `(error)=>{...}` | | null | | `realtime?:boolean` | Whether to listen for | | false | | `AsyncStorage?:any` | Needed in certain frameworks cacheFlags and enableAnalytics options, used to tell the library what implementation of AsyncStorage your app uses, e.g. @react-native-community/async-storage, for web this defaults to an internal implementation. | | built in implementation for web, otherwise undefined. | | `cacheFlags?: boolean` | Any time flags are retrieved they will be cached, flags and identities will then be retrieved from local storage before hitting the API (see cache options). Requires AsyncStorage to be accessible. | | null | | `cacheOptions?: \{ttl?:number, skipAPI?:boolean\}` | A ttl in ms (default to 0 which is infinite) and option to skip hitting the API in flagsmith.init if there's cache available. | | \{ttl:0, skipAPI:false\} | | `enableAnalytics?: boolean` | for getValue and hasFeature

| | false | | `enableLogs?: boolean` | Enables logging for key Flagsmith events | | null | | `defaultFlags?: {flag_name: {enabled: boolean, value: string,number,boolean}}` | Allows you define default features, these will all be overridden on first retrieval of features. | | null | | `preventFetch?: boolean` | If you want to disable fetching flags and call getFlags later. | | false | | `state?: IState` | Set a predefined state, useful for SSR / isomorphic applications. | | false | | `api?: string` | Use this property to define where you're getting feature flags from, e.g. if you're self hosting. | | https://edge.api.flagsmith.com/api/v1/ | | `eventSourceUrl?: string` | Use this property to define where you're getting real-time flag update events (server sent events) from, e.g. if you're self hosting. | | https://edge.api.flagsmith.com/api/v1/ | | `identity?: string` | Specifying an identity will fetch flags for that identity in the initial API call. | YES | null | | `traits?:Record<string, string or number or boolean>` | Specifying traits will send the traits for that identity in the initial API call. | YES | null | | Property | Description | | | :--: | | <code>init(initialisationOptions)=> Promise&lt;void&gt;</code> | Initialise the sdk against a particular environment | | <code>hasFeature(key:string)=> boolean</code> | Get the value of a particular feature e.g. `flagsmith.hasFeature("powerUserFeature") // true` | | <code>getValue\<T=string&#124;number&#124;boolean&#124;null\>(key:string,\{ json?:boolean, fallback?:T \})=> string&#124;number&#124;boolean</code> | Get the value of a particular feature e.g. `flagsmith.getValue("font_size", { fallback: 12 }) // 10`, specifying json:true will automatically parse the value as JSON. | | <code>getTrait(key:string)=> string&#124;number&#124;boolean</code> | Once used with an identified user you can get the value of any trait that is set for them e.g. `flagsmith.getTrait("acceptedcookiepolicy")` | | <code>getAllTraits()=> Record&lt;string,string&#124;number&#124;boolean&gt;</code> | Once used with an identified user you can get a key value pair of all traits that are set for them e.g. `flagsmith.getTraits()` | | <code>getState()=>IState</code> | Retrieves the current state of flagsmith, useful in NextJS / isomorphic applications. `flagsmith.getState()` | | <code>setState(state: IState)=>void</code> | Set the current state of flagsmith, e.g. `flagsmith.setState({identity: 'mary@mycompany.com'})`. | | <code>setTrait(key:string, value:string&#124;number&#124;boolean)=> Promise&lt;IFlags&gt;</code> | Once used with an identified user you can set the value of any trait relevant to them e.g. `flagsmith.setTrait("acceptedcookiepolicy", true)` | | <code>setTraits(values:Record\<string, string&#124;number&#124;boolean>)=\> Promise&lt;IFlags&gt;</code> | Set multiple traits e.g. `flagsmith.setTraits({foo:"bar",numericProp:1,boolProp:true})`. Setting a value of null for a trait will remove that trait. | | <code>incrementTrait(key:string, value:number)=> Promise&lt;IFlags&gt;</code> | You can also increment/decrement a particular trait them e.g. `flagsmith.incrementTrait("click_count", 1)` | | <code>startListening(ticks=1000:number)=>void</code> | Poll the api for changes every x milliseconds | | <code>stopListening()=>void</code> | Stop polling the api | | <code>getFlags()=> Promise&lt;IFlags&gt;</code> | Trigger a manual fetch of the environment features, if a user is identified it will fetch their features. Resolves a promise when the flags are updated. | | <code>getAllFlags()=> &lt;IFlags&gt;</code> | Returns the current flags. | | <code>identify(userId:string, traits?:Record\<string, string or number or boolean\>)=> Promise&lt;IFlags&gt;</code> | Identify as a user, optionally with traits e.g. `{foo:"bar",numericProp:1,boolProp:true}`. This will create a user for your environment in the dashboard if they don't exist, it will also trigger a call to `getFlags()`, resolves a promise when the flags are updated. | | <code>logout()=>Promise&lt;IFlags&gt;</code> | Stop identifying as a user, this will trigger a call to `getFlags()` | allows you to create multiple instances of the Flagsmith SDK. This may be used when you wish to identify multiple users simultaneously within your app and retain access to getValue, hasFeature etc for each

Type: ```javascript export function createFlagsmithInstance (): IFlagsmith ``` Usage: ```javascript import { createFlagsmithInstance } from 'flagsmith'; const flagsmith = createFlagsmithInstance(); const flagsmithB = createFlagsmithInstance(); // now you can use flagsmith as before but in its own instance ``` allows you to determine the current loading state of the SDK and whether its current data is from default flags, cache or the API. Flagsmith loading state can be accessed via the onChange event and the hook in the React SDK. The expected type of Flagsmith loading state is as follows: ```typescript export declare enum FlagSource { 'NONE' = 'NONE', 'DEFAULTFLAGS' = 'DEFAULTFLAGS', 'CACHE' = 'CACHE', 'SERVER' = 'SERVER', } export declare type LoadingState = { error: Error | null; // Current error, resets on next attempt to fetch flags isFetching: bool; // Whether there is a current request to fetch server flags isLoading: bool; // Whether any flag data exists source: FlagSource; //Indicates freshness of flags }; ``` The Flagsmith JavaScript client supports JSON remote config / feature values. When calling `flagsmith.getValue`, specifying `json:true` will attempt to parse the feature value as JSON, it will fallback to `fallback` failing to parse it. ```javascript const json = flagsmith.getValue('json_value', { json: true, fallback: { foo: null, bar: null }, }); ``` Flagsmith has full TypeScript support for its JavaScript clients, you can find our main type definition file . You can also enforce type safety of feature and trait names using generics: Given that we type our flags and traits: ```typescript type FlagOptions = 'font_size' | 'hero'; type TraitOptions = 'example_trait'; ``` We can now enforce these types: ```typescript // enforces you passing the correct key to flagsmith.getValue(flag:FlagOptions), flagsmith.getTrait(trait:TraitOptions) import flagsmith from 'flagsmith'; const typedFlagsmith = flagsmith as IFlagsmith<FlagOptions, TraitOptions>; // Similarly for the useFlagsmith hook is typed with useFlagsmith(flags:FlagOptions[],traits:TraitOptions[]) const flagsmith = useFlagsmith<FlagOptions, TraitOptions>(); // enforces flagsmith.getValue() // for useFlags this will ensure you only can pass correct keys also const flags = useFlags<FlagOptions, TraitOptions>(['fontsize'], ['exampletrait']); // for getting JSON values this will type the return const json = flagsmith.getValue<{ foo: string | null; bar: string | null }>('json_value', { json: true, fallback: { foo: null, bar: null }, }); console.log(json.foo); // typed as {foo: string|null, bar: string|null} // If a type is not specified for getValue it will asume it from the type of fallback. In this case, a number. const fontsize = flagsmith.getValue('fontsize', { fallback: 12 }); ``` :::caution This feature is still in beta with Datadog. Contact your Datadog representative before enabling the integration below. ::: The Flagsmith JavaScript SDK can be configured so that feature enabled state and remote config can be stored as and user traits can be stored as . The integration requires an initialised Datadog `datadogRum` client. To start collecting feature flag data, initialize the Datadog RUM SDK and configure the enableExperimentalFeatures initialization parameter with ["feature_flags"]. ```typescript import { datadogRum } from '@datadog/browser-rum'; // Initialize Datadog Browser SDK datadogRum.init({ enableExperimentalFeatures: ["feature_flags"], ... }); ``` Initialise the Flagsmith SDK with the datadogRum option. Optionally, you can configure the client so that Flagsmith traits are sent to Datadog via ``datadogRum.setUser()````. ```typescript import { datadogRum } from '@datadog/browser-rum'; ... // Initialize the Flagsmith SDK flagsmith.init({ datadogRum: { client: datadogRum, trackTraits: true, }, ... }) ``` Whenever flag values are evaluated in your code, they will be sent to Datadog as user events. If the option to send Traits is enabled, the Trait key/value pairs will be sent to Datadog when the SDK receives its Flags. This will track remote config and feature enabled states as feature flags in the following format ```bash flagsmithvalue<FEATURE_NAME> // remote config flagsmithenabled<FEATURE_NAME> // enabled state ``` Additionally, the integration will also store Flagsmith traits against the Datadog user in the following format: ```bash flagsmithtrait<FEATURE_NAME> // remote config ``` You can find an example of this integration

The Flagsmith JavaScript SDK can be configured so that feature enabled state, remote config and user traits can be stored as Dynatrace session properties. The integration requires a configured Dynatrace `dtrum` object that is already set up. In order to configure the JavaScript SDK, you need to pass in an instance of . ```javascript // Initialize the Flagsmith SDK flagsmith.init({ //...Initialisation properties, enableDynatrace: true, }); ``` When setting `enableDynatrace` to true `flagsmith.init`, Flagsmith will send session properties corresponding to flag enabled state, flag values and user traits via flag enabled state sends as a shortString as `true` or `false` with the prefix `flagsmithenabled` example: `flagsmithenabledhero: "true"` Remote config values sends as value with the prefix flagsmith value, this value will be a javaDouble for numeric values and a shortString for any other. example: `flagsmithvaluefontsize: 21`, `flagsmithvalueherocolour: "blue"` Remote config values sends as value with the prefix flagsmith value, this value will be a javaDouble for numeric values and a shortString for any other. example: `flagsmithtraitage: 21`, `flagsmithtraitfavourite_colour: "blue"` , you need to also define session properties within the RUM application settings. You can also add these properties via the . Defining Dynatrace Properties: Defining a Flagsmith and Dynatrace Property: Filtering on a Flagsmith Flag: How do I call `identify`, `setTraits` etc alongside `init`? `init` should be called once in your application, we recommend you call `init` before any other flagsmith call. `init` retrieves flags by default, you can turn this off with the `preventFetch` option to `init`. This is useful for when you know you're identifying a user straight after. When does onChange callback? `onChange` calls when flags are fetched this can be a result of: init setTrait incrementTrait getFlags identify flags evaluated by local storage Using onChange is best used in combination with your application's state management e.g. onChange triggering an action to re-evaluate flags with `hasFeature` and `getValue`. However, if this does not fit in with your development pattern, all the above flagsmith functions return a promise that resolves when fresh flags have been retrieved. For example by doing the following: ```javascript await flagsmith.setTrait('age', 21); const hasFeature = flagsmith.hasFeature('my_feature'); ``` On change calls back with information telling you what has changed, you can use this to prevent any unnecessary re-renders. ```javascript onChange(oldFlags, { isFromServer: true, // flags have come from the server or local storage flagsChanged: string[] | null, traitsChanged: string[] | null, }, loadingState) ``` :::info Prior to `flagsmith 4.0.0`, flagsChanged and traitsChanged returned a boolean. ::: How does caching flags work? If the `cacheFlags` is set to true on `init`, the SDK will cache flag evaluations in local async storage. Upon reloading the browser, an onChange event will be fired immediately with the local storage flags. The flow for this is as follows `init` is called if `cacheFlags` is enabled, local storage checks for any stored flags and traits. if flags have been found in local storage, `onChange` is triggered with the stored flags. at the same time, fresh flags will be retrieved which will result in another `onChange` callback. whenever flags have been retrieved local storage will be updated. By default, these flags will be persisted indefinitely, you can clear this by removing `"BULLETTRAINDB"` from `localStorage`. Why am I seeing `ReferenceError: XMLHttpRequest is not defined`? The Flagsmith JavaScript client uses the API to handle REST calls. Some frameworks such as Manifest and Nuxt do not support this out of the box. In order to resolve this issue, you can provide a custom fetch implementation to the Flagsmith SDK. An example of this can be found .