For AI agents: A markdown version of this page is available at https://docs.datadoghq.com/feature_flags/client/javascript.md.
A documentation index is available at /llms.txt.
This product is not supported for your selected Datadog site. ().
Overview
This page describes how to instrument your browser JavaScript application with the Datadog Feature Flags SDK. Datadog feature flags provide a unified way to remotely control feature availability in your app, experiment safely, and deliver new experiences with confidence.
The Datadog Feature Flags SDK for JavaScript is built on OpenFeature, an open standard for feature flag management. This guide explains how to install the SDK, configure the Datadog provider, and evaluate flags in your application.
Installation
Install the Datadog OpenFeature provider and the OpenFeature Web SDK using your preferred package manager:
Create a DatadogProvider instance with your Datadog credentials. For live Browser Feature Flags configuration, applicationId, clientToken, site, and env are required. To create a client token, see Client tokens.
Browser Feature Flags are not supported for the selected Datadog site ().
Define who or what the flag evaluation applies to using an evaluation context. The evaluation context includes user or session information used to determine which flag variations should be returned. Reference these attributes in your targeting rules to control who sees each variant.
Datadog Feature Flags requires evaluation context attributes to be flat primitive values: strings, numbers, and Booleans. Do not pass nested objects or arrays; they are not supported and can cause exposure data to be dropped.
The targetingKey is used as the randomization subject for percentage-based targeting. When a flag targets a percentage of subjects (for example, 50%), the targetingKey determines which "bucket" a user falls into. Users with the same targetingKey always receive the same variant for a given flag.
Evaluate flags
After the provider is initialized, you can evaluate flags anywhere in your application. Flag evaluation is local and instantaneous—the SDK uses locally cached data, so no network requests occur when evaluating flags.
Get a client
Retrieve the OpenFeature client to evaluate flags:
constclient=OpenFeature.getClient();
Boolean flags
Use getBooleanValue(key, defaultValue) for flags that represent on/off or true/false conditions:
When you need more than just the flag value, use the detail methods. These return both the evaluated value and metadata explaining the evaluation:
constdetails=client.getBooleanDetails('checkout_new',false);console.log(details.value);// Evaluated value (true or false)
console.log(details.variant);// Variant name, if applicable
console.log(details.reason);// Why this value was chosen
console.log(details.errorCode);// Error code, if evaluation failed
Complete example
Here’s a complete example showing how to set up and use Datadog Feature Flags in a JavaScript application:
import{DatadogProvider}from'@datadog/openfeature-browser';import{OpenFeature}from'@openfeature/web-sdk';// Initialize the Datadog provider
constprovider=newDatadogProvider({applicationId:'<APPLICATION_ID>',clientToken:'<CLIENT_TOKEN>',site:'',env:'<ENV_NAME>',});// Set the evaluation context
constevaluationContext={targetingKey:'user-123',user_id:'123',user_role:'admin',};awaitOpenFeature.setProviderAndWait(provider,evaluationContext);// Get the client and evaluate flags
constclient=OpenFeature.getClient();constshowNewFeature=client.getBooleanValue('new_feature',false);if(showNewFeature){console.log('New feature is enabled!');}
Update the evaluation context
To update the evaluation context after initialization (for example, when a user logs in), use OpenFeature.setContext():
The web provider also supports these optional settings:
Option
Default
Use
enableExposureLogging
true
Send exposure events to the exposures intake.
enableFlagEvaluationTracking
true
Send aggregated evaluation telemetry.
enableRumFeatureFlagTracking
true
Add flag evaluations to RUM events when Browser RUM is available. Enabling this option can increase RUM-billed event counts.
flagEvaluationTrackingInterval
10000 ms
Flush interval for evaluation telemetry.
initialFlagsConfiguration
{}
Bootstrap with precomputed flags.
flaggingProxy
unset
Fetch flags through a proxy instead of site.
customHeaders
unset
Add headers to flag-fetch requests.
overwriteRequestHeaders
false
Replace default request headers with customHeaders.
Testing
You can test against a dedicated Datadog test environment with the real DatadogProvider, or swap it for OpenFeature’s InMemoryProvider to control flag values directly in test code. This section shows the in-memory approach, which keeps tests hermetic and offline. InMemoryProvider is exported directly from @openfeature/web-sdk, so no additional dependency is required.
Unlike the server-side SDK, the Web SDK evaluates flags synchronously after initialization. Still awaitsetProviderAndWait once in beforeEach to ensure the provider is ready.
import{beforeEach,afterAll,expect,test}from'vitest';import{OpenFeature,TypedInMemoryProvider}from'@openfeature/web-sdk';constflags={new_checkout_button:{variants:{on:true,off:false},defaultVariant:'on',disabled:false,},ui_theme:{variants:{dark:'dark',light:'light'},defaultVariant:'light',disabled:false,},};beforeEach(async()=>{awaitOpenFeature.setProviderAndWait(newTypedInMemoryProvider(flags));});afterAll(async()=>{awaitOpenFeature.close();});test('new checkout button is enabled by default',()=>{constclient=OpenFeature.getClient();expect(client.getBooleanValue('new_checkout_button',false)).toBe(true);});test('missing flag returns default',()=>{constclient=OpenFeature.getClient();expect(client.getBooleanValue('does-not-exist',false)).toBe(false);});
The Web SDK flag shape requires variants, defaultVariant, and disabled. Omitting any of these fails TypeScript compilation; at runtime, evaluating an unknown flag key returns the supplied default. Prefer TypedInMemoryProvider over the deprecated InMemoryProvider for type-checked flag configurations. The same test pattern works with Jest + jsdom; swap the vitest imports for @jest/globals and add jest-environment-jsdom to your project.
Further reading
Additional helpful documentation, links, and articles: