> ## Documentation Index
> Fetch the complete documentation index at: https://launchdarkly.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Experimentation

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

This topic explains how to set up select client-side LaunchDarkly SDKs to use the [Experimentation feature](/docs/home/experimentation).

The configuration requirements for individual SDKs are included below.

## Client-side SDKs

Code samples for this feature are available for the following client-side SDKs:

* [Android](#android)
* [iOS](#ios)
* [JavaScript](#javascript)
* [React Native](#react-native)
* [React Web](#react-web)

### Android

> **Expand Android code sample**
>
> To use Experimentation with the Android SDK, you must configure the following SDK features:
>
> * [Track](/docs/sdk/features/evaluating.md#android): Track methods send custom events to LaunchDarkly using an event key when a user or other context takes an action in your app. You use the event key with LaunchDarkly metrics to measure signals during an experiment.
>
>   This example shows how to initialize the SDK with the track call included:
>
>   ```kotlin title="Android SDK initialization for Experimentation" expandable lines wrap theme={null}
>   import com.launchdarkly.sdk.*
>   import com.launchdarkly.sdk.android.*
>   import com.launchdarkly.sdk.android.LDConfig.Builder.AutoEnvAttributes
>
>   // This is your mobile key.
>   val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
>       .mobileKey("YOUR_MOBILE_KEY")
>       .build()
>
>   // A "context" is a data object representing users, devices, organizations, and other entities.
>   val context = LDContext.builder("EXAMPLE_CONTEXT_KEY")
>       .set("email", "EXAMPLE_EMAIL")
>       .build()
>
>   // If you don't want to block execution while the SDK tries to get
>   // latest flags, move this code into an async IO task and await on its completion.
>   val client: LDClient = LDClient.init(this@BaseApplication, ldConfig, context, 5)
>
>   // Call trackMetric when a metric action occurs in your app —
>   // a tap, a form submit, a screen view, a custom event, whatever your metric measures.
>   fun trackMetric(metricKey: String, data: LDValue = LDValue.ofNull()) {
>       LDClient.get().trackData(metricKey, data)
>   }
>   ```
>
> * [Variation](/docs/sdk/features/evaluating.md#android): Variation methods evaluate a flag for a specific context and return the variation value. Variation methods also record an exposure event so LaunchDarkly knows this context was part of the experiment. Use typed variation methods such as `stringVariation()` or `boolVariation()` that match your flag's value type. Call a variation method after `identify()` has completed, and call it where the experience is rendered rather than in `onCreate()` or application startup.
>
> * [Identify](/docs/sdk/features/identify.md#android): Identify methods update the context the SDK uses for flag evaluation. All flags re-evaluate against the new context when it completes. You need `identify()` when a user or other context logs in, switches accounts, or their attributes change mid-session in a way that affects targeting, for example, an in-app purchase or plan upgrade. Always call `identify()` off of the main thread. It is a network operation and will block the UI if called on the main thread. Wrap it in a coroutine: `CoroutineScope(Dispatchers.IO).launch { client.identify(ctx).get() }`.
>
> * [Flush](/docs/sdk/features/flush.md): Flush methods force the SDK to send all queued events, including exposures and conversions, to LaunchDarkly immediately instead of waiting for the automatic send interval.

### iOS

> **Expand iOS code sample**
>
> To use Experimentation with the iOS SDK, you must configure the following SDK features:
>
> * [Track](/docs/sdk/features/events.md): Track methods send custom events to LaunchDarkly using an event key when a user or other context takes an action in your app.
>
>   This example shows how to initialize the SDK with the track call included:
>
>   ```swift title="iOS SDK initialization for Experimentation" expandable lines wrap theme={null}
>   import LaunchDarkly
>
>   // Call this once from your app startup (e.g. application(_:didFinishLaunchingWithOptions:)).
>   // You can't invoke LDClient.start() at the top level in Swift — wrap it in a function.
>   func startLaunchDarkly() {
>       // This is your mobile key.
>       let config = LDConfig(mobileKey: "YOUR_MOBILE_KEY", autoEnvAttributes: .enabled)
>
>       // A "context" is a data object representing users, devices, organizations, and other entities.
>       var contextBuilder = LDContextBuilder(key: "EXAMPLE_CONTEXT_KEY")
>       contextBuilder.trySetValue("email", .string("EXAMPLE_EMAIL"))
>       guard case .success(let context) = contextBuilder.build() else { return }
>
>       LDClient.start(config: config, context: context, startWaitSeconds: 5) { timedOut in
>           if timedOut {
>               print("SDK didn't initialize in 5 seconds. SDK is still running and trying to get latest flags.")
>           } else {
>               print("SDK successfully initialized with the latest flags")
>           }
>       }
>   }
>
>   // Call trackMetric when a metric action occurs in your app —
>   // a tap, a form submit, a screen view, a custom event, whatever your metric measures.
>   func trackMetric(metricKey: String, data: LDValue = .null) {
>       let client = LDClient.get()!
>       client.track(key: metricKey, data: data)
>   }
>   ```
>
> * [Variation](/docs/sdk/features/evaluating.md#ios): Variation methods evaluate a flag for a specific context and return the variation value. Variation methods also record an exposure event so LaunchDarkly knows this user or other context was part of the experiment.
>
> * [Identify](/docs/sdk/features/identify.md#ios): Identify methods update the context the SDK uses for flag evaluation. All flags re-evaluate against the new context when it completes.
>
> * [Flush](/docs/sdk/features/flush.md#ios): Flush methods force the SDK to send all queued events, including exposures and conversions, to LaunchDarkly immediately instead of waiting for the automatic send interval.

### JavaScript

> **Expand JavaScript code sample**
>
> To use Experimentation with the JavaScript SDK, you must configure the following SDK features:
>
> * [Track](/docs/sdk/features/events.md#javascript): Track methods send custom events to LaunchDarkly using an event key when a user or other context takes an action in your app.
>
>   This example shows how to initialize the SDK with the track call included:
>
>   ```js title="JavaScript SDK initialization for Experimentation" expandable lines wrap theme={null}
>   import { createClient } from '@launchdarkly/js-client-sdk';
>
>   // A "context" is a data object representing users, devices, organizations, and
>   // other entities. You'll need this later, but you can ignore it for now.
>   const context = {
>     kind: 'user',
>     key: 'EXAMPLE_CONTEXT_KEY',
>     email: 'EXAMPLE_EMAIL',
>   };
>
>   // This is your client-side ID.
>   const ldClient = createClient('YOUR_CLIENT_SIDE_ID', context);
>
>   // await start — you only need waitForInitialization() if you wait somewhere
>   // other than where you start the client.
>   await ldClient.start();
>   console.log('SDK successfully initialized!');
>
>   // Call trackMetric when a metric action occurs in your app —
>   // a click, a form submit, a page view, a custom event, whatever your metric measures.
>   function trackMetric(metricKey, data) {
>     ldClient.track(metricKey, data);
>   }
>   ```
>
> * [Variation](/docs/sdk/features/evaluating.md#javascript): Variation methods evaluate a flag for a specific context and return the variation value. Variation methods also record an exposure event so LaunchDarkly knows this user or other context was part of the experiment. Call `ldClient.variation()` at the exact moment the context encounters the experience, not at initialization, and not cached ahead of time.
>
> * [Identify](/docs/sdk/features/identify.md#javascript): Identify methods update the context the SDK uses for flag evaluation. All flags re-evaluate against the new context when it completes. You need `identify()` when the context's identity changes after the SDK has already initialized, for example, when a user on a public page logs in, when identity loads asynchronously after SDK startup, or when a user completes a cookie consent flow. You do not need it if the user is already logged in when the page loads. Pass their context in the initial configuration instead.
>
> * [Flush](/docs/sdk/features/flush.md#javascript): Flush methods force the SDK to send all queued events, including exposures and conversions, to LaunchDarkly immediately instead of waiting for the automatic send interval. Call `flush()` after `track()` on any event that causes navigation, such as a button click that redirects, a form submission, or a link, because the page may unload before the automatic flush fires. Also call it on single-page application (SPA) route changes where the user leaves the current view.

### React Native

> **Expand React Native code sample**
>
> To use Experimentation with the React Native SDK, you must configure the following SDK features:
>
> * [Track](/docs/sdk/features/events.md): Track methods send custom events to LaunchDarkly using an event key when a user or other context takes an action in your app.
>
>   This example shows how to initialize the SDK with the track call included:
>
>   ```ts title="React Native SDK initialization for Experimentation" expandable lines wrap theme={null}
>   import React, { useEffect, useState, useCallback } from 'react';
>   import {
>     AutoEnvAttributes,
>     LDProvider,
>     ReactNativeLDClient,
>   } from '@launchdarkly/react-native-client-sdk';
>
>   // This is your mobile key.
>   const ldClient = new ReactNativeLDClient('YOUR_MOBILE_KEY', AutoEnvAttributes.Enabled, {
>     debug: true,
>     applicationInfo: {
>       id: 'ld-rn-test-app',
>       version: '0.0.1',
>     },
>   });
>
>   // A "context" is a data object representing users, devices, organizations, and other entities.
>   const context = { kind: 'user', key: 'EXAMPLE_CONTEXT_KEY', email: 'EXAMPLE_EMAIL' };
>
>   export default function App() {
>     const [ready, setReady] = useState<boolean>(false);
>     // Wait for identify to complete before rendering, so no flag evaluates
>     // against defaults during startup.
>     useEffect(() => {
>       (async () => {
>         await ldClient.identify(context);
>         setReady(true);
>       })();
>     }, []);
>     // Call trackMetric when a metric action occurs in your app —
>     // a tap, a form submit, a screen view, a custom event, whatever your metric measures.
>     const trackMetric = useCallback(
>       (metricKey: string, data?: unknown) => {
>         ldClient.track(metricKey, data);
>       },
>       [],
>     );
>     if (!ready) return null;
>     return (
>       <LDProvider client={ldClient}>
>         <YourComponent />
>       </LDProvider>
>     );
>   }
>   ```
>
> * [Variation](/docs/sdk/features/evaluating.md#react-native): Variation methods evaluate a flag for a specific context and return the variation value. Variation methods also record an exposure event so LaunchDarkly knows this context was part of the experiment. Use the typed hooks such as `useBoolVariation()`, `useStringVariation()`, and `useNumberVariation()`. These hooks are reactive and return a typed value with a per-call-site default, so you get the right type and a fallback without having to check the result afterward.
>
> * [Identify](/docs/sdk/features/identify.md#react-native): Identify methods update the context the SDK uses for flag evaluation. All flags re-evaluate against the new context when it completes. You need `identify()` in the same scenarios as the JavaScript SDK, as well as when a user switches accounts on a shared device or completes onboarding and becomes a known entity mid-session. Always await the result before evaluating experiment flags, but await with a timeout. `identify()` is not guaranteed to complete on a slow or offline network, so waiting indefinitely can make your app unavailable during a network outage.
>
> * [Flush](/docs/sdk/features/flush.md#react-native): Flush methods force the SDK to send all queued events, including exposures and conversions, to LaunchDarkly immediately instead of waiting for the automatic send interval. Call `flush()` in an `AppState` change listener when state leaves `active`, so queued events are sent before the app moves to the background.

### React Web

> **Expand React Web code sample**
>
> To use Experimentation with the React Web SDK, you must configure the track, variation, identify, and flush methods.
>
> This example shows how to initialize the SDK with the track call included:
>
> ```ts title="React Web SDK initialization for Experimentation" expandable lines wrap theme={null}
> // Add the code below to the root of your React app.
> import { StrictMode, useCallback } from 'react';
> import { createRoot } from 'react-dom/client';
> import { createLDReactProvider, useLDClient } from '@launchdarkly/react-sdk';
>
> function App() {
>   const ldClient = useLDClient();
>   // Call trackMetric when a metric action occurs in your app —
>   // a click, a form submit, a page view, a custom event, whatever your metric measures.
>   const trackMetric = useCallback(
>     (metricKey: string, data?: unknown) => {
>       ldClient?.track(metricKey, data);
>     },
>     [ldClient],
>   );
>   return <div>Let your feature flags fly!</div>;
> }
>
> // A "context" is a data object representing users, devices, organizations, and other entities.
> const context = {
>   kind: 'user',
>   key: 'EXAMPLE_CONTEXT_KEY',
>   email: 'EXAMPLE_EMAIL',
> };
>
> // Initialize the SDK so flag values are ready before your app renders.
> // This is your client-side ID.
> const LDProvider = createLDReactProvider('YOUR_CLIENT_SIDE_ID', context);
>
> createRoot(document.getElementById('root') as HTMLElement).render(
>   <StrictMode>
>     <LDProvider>
>       <App />
>     </LDProvider>
>   </StrictMode>,
> );
> ```
>
> The React Web SDK relies on the [JavaScript SDK](#javascript) for the [variation](/docs/sdk/features/evaluating.md#javascript), [identify](/docs/sdk/features/identify.md#javascript), and [flush](/docs/sdk/features/flush.md#javascript) methods. The same guidance applies.
