
Official documentation for Amplitude Experiment's Client-side JavaScript SDK implementation.

## Install

Install the Experiment JavaScript Client SDK with one of the three following methods:

{% callout type="info" heading="Unified SDK" %}
Install the [Browser Unified SDK](/docs/sdks/analytics/browser/browser-unified-sdk) to access the Experiment SDK along with other Amplitude products (Analytics, Session Replay). The Unified SDK provides a single entry point for all Amplitude features and simplifies the integration process by handling the initialization and configuration of all components.

{% /callout %}

{% code-group %}
```bash npm
# Install Experiment SDK only
npm install --save @amplitude/experiment-js-client

# Or install Unified SDK to get access to all Amplitude products
npm install @amplitude/unified
```

```bash yarn
# Install Experiment SDK only
yarn add @amplitude/experiment-js-client

# Or install Unified SDK to get access to all Amplitude products
yarn add @amplitude/unified
```

```html script
<script src="https://unpkg.com/@amplitude/experiment-js-client@1.15.5/dist/experiment.umd.js"></script>
<script>
    // TODO: Replace DEPLOYMENT_KEY with your own deployment key.
    // If you're using a 3rd party for analytics, configure an exposure
    // tracking provider.
    window.experiment = Experiment.initializeWithAmplitudeAnalytics('DEPLOYMENT_KEY');
</script>
```
{% /code-group %}

{% callout type="tip" heading="Quick start" %}
The right way to initialize the Experiment SDK depends on whether you use an Amplitude SDK for analytics or a third party (for example, Segment).

{% tabs tabs="Amplitude, Unified SDK, Third party" %}
{% tab name="Amplitude" %}

1. [Initialize the experiment client](#initialize)
2. [Fetch variants](#fetch)
3. [Access a flag's variant](#variant)

```typescript
import { Experiment } from '@amplitude/experiment-js-client';

// (1) Initialize the experiment client with Amplitude Analytics.
const experiment = Experiment.initializeWithAmplitudeAnalytics(
    'DEPLOYMENT_KEY'
);

// (2) Fetch variants and await the promise result.
await experiment.fetch();

// (3) Lookup a flag's variant.
const variant = experiment.variant('FLAG_KEY');
if (variant.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}
```

{% /tab %}
{% tab name="Unified SDK" %}

1. [Initialize the Unified SDK](#initialize)
2. [Fetch variants](#fetch)
3. [Access a flag's variant](#variant)

```typescript
import { initAll, experiment } from '@amplitude/unified';

// (1) Initialize the Unified SDK with your API key
// Note: if deploymentKey is not provided, it will fall back to the api key
initAll('YOUR_API_KEY', {
    experiment: {
        deploymentKey: 'DEPLOYMENT_KEY'
    }
});

// (2) Fetch variants and await the promise result.
await experiment()?.fetch();

// (3) Lookup a flag's variant.
const variant = experiment()?.variant('FLAG_KEY');
if (variant.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}
```

{% /tab %}
{% tab name="Third party" %}

1. [Initialize the experiment client](#initialize)
2. [Fetch variants for a user](#fetch)
3. [Access a flag's variant](#variant)

```typescript
import { Experiment } from '@amplitude/experiment-js-client';

// (1) Initialize the experiment client and implement a
//     custom exposure tracking provider.
const experiment = Experiment.initialize(
    'DEPLOYMENT_KEY',
    {
        exposureTrackingProvider: {
            track: (exposure) => {
                // TODO: Implement exposure tracking
                // analytics.track('$exposure', exposure)
            }
        }
    }
);

// (2) Fetch variants with the user and await the promise result.
const user = {
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        premium: true,
    },
}
await experiment.fetch(user);

// (3) Lookup a flag's variant.
const variant = experiment.variant('FLAG_KEY');
if (variant.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}
```

{% /tab %}
{% /tabs %}
{% /callout %}

## Initialize

Initialize the SDK in your application on startup. The [deployment key](/docs/feature-experiment/data-model#deployments) argument you pass into the `apiKey` parameter must live in the same Amplitude project to which you send events.

{% code-group %}
```typescript Amplitude
initializeWithAmplitudeAnalytics(apiKey: string, config?: ExperimentConfig): ExperimentClient
```

```typescript Unified SDK
initAll(apiKey: string, config?: UnifiedConfig): void
```

```typescript Third-party
initialize(apiKey: string, config?: ExperimentConfig): ExperimentClient
```
{% /code-group %}

| Parameter | Description                                                                                                        |
| --------- | ------------------------------------------------------------------------------------------------------------------ |
| `apikey`  | _Required_. The deployment key which authorizes fetch requests and determines which flags to evaluate for the user |
| `config`  | The client configuration to customize SDK client behavior.                                                         |

The initializer returns a singleton instance, so subsequent initializations for the same instance name always return the initial instance. To create multiple instances, use the `instanceName` configuration.

{% code-group %}
```typescript Amplitude
import { Experiment } from '@amplitude/experiment-js-client';

const experiment = initializeWithAmplitudeAnalytics('DEPLOYMENT_KEY');
```

```typescript Unified SDK
import { initAll, experiment } from '@amplitude/unified';

// Note: if deploymentKey is not provided, it will fall back to the api key
initAll('YOUR_API_KEY', {
    experiment: {
        deploymentKey: 'DEPLOYMENT_KEY'
    }
});
```

```typescript Third-party
import { Experiment } from '@amplitude/experiment-js-client';

const experiment = Experiment.initialize(
    'DEPLOYMENT_KEY',
    {
        exposureTrackingProvider: {
            track: (exposure) => {
                // TODO: Implement exposure tracking
                // analytics.track('$exposure', exposure)
            }
        }
    }
);
```
{% /code-group %}

### Configuration

Configure the SDK client during initialization.

{% accordion title="Configuration" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `debug` | **Deprecated.** When `true`, sets `logLevel` to `Debug`. Use `logLevel` instead. | `false` |
| `logLevel` | The minimum log level to output. The SDK ignores messages below this level. Options: `LogLevel.Disable`, `LogLevel.Error`, `LogLevel.Warn`, `LogLevel.Info`, `LogLevel.Debug`, `LogLevel.Verbose`. Go to [Custom logging](#custom-logging) for details. | `LogLevel.Error` |
| `loggerProvider` | Custom logger implementation. Must implement the `Logger` interface. Go to [Custom logging](#custom-logging). | `null` (uses default ConsoleLogger) |
| `fallbackVariant` | The default variant to fall back if a variant for the provided key doesn't exist. | `{}` |
| `initialVariants` | An initial set of variants to access. This field helps bootstrap the client SDK with values rendered by the server using server-side rendering (SSR). | `{}` |
| `source` | The primary source of variants. Set the value to `Source.InitialVariants` and configured `initialVariants` to bootstrap the SDK for SSR or testing purposes. | `Source.LocalStorage` |
| `serverZone` | Select the Amplitude data center to get flags and variants from, `us` or `eu`. | `us` |
| `serverUrl` | The host to fetch remote evaluation variants from. For hitting the EU data center, use `serverZone`. | `https://api.lab.amplitude.com` |
| `flagsServerUrl` | The host to fetch local evaluation flags from. For hitting the EU data center, use `serverZone`. | `https://flag.lab.amplitude.com` |
| `fetchTimeoutMillis` | The timeout for fetching variants in milliseconds. | `10000` |
| `retryFetchOnFailure` | Whether to retry variant fetches in the background if the request doesn't succeed. | `true` |
| `automaticExposureTracking` | If true, calling [`variant()`](#variant) tracks an exposure event through the configured `exposureTrackingProvider`. If no exposure tracking provider is set, this configuration option does nothing. | `true` |
| `fetchOnStart` | If true or undefined, always [fetch](#fetch) remote evaluation variants on [start](#start). If false, never fetch on start. | `true` |
| `pollOnStart` | Poll for local evaluation flag configuration updates every minute on [start](#start). | `true` |
| `automaticFetchOnAmplitudeIdentityChange` | Only matters if you use the `initializeWithAmplitudeAnalytics` initialization function to integrate with the Amplitude Analytics SDK. If `true` any change to the user ID, device ID or user properties from analytics triggers the experiment SDK to fetch variants and update its cache. | `false` |
| `userProvider` | An interface used to provide the user object to `fetch()` when called. | `null` |
| `exposureTrackingProvider` | Implement and configure this interface to track exposure events through the experiment SDK, either automatically or explicitly. | `null` |
| `instanceName` | Custom instance name for experiment SDK instance. **The value of this field is case-sensitive.** | `null` |
| `initialFlags` | A JSON string representing an initial array of flag configurations to use for local evaluation. | `undefined` |
| `httpClient` | (Advanced) Use your own HTTP client implementation to handle network requests made by the SDK. | Default HTTP client |

{% /accordion %}

### Integrations

If you use either Amplitude or Segment Analytics SDKs to track events into Amplitude, set up an integration on initialization. Integrations automatically implement [provider](#providers) interfaces to enable a more streamlined developer experience by making it easier to **manage user identity** and **track exposures events**.

{% accordion title="Amplitude integration" %}
The Amplitude Experiment SDK is set up to integrate with the Amplitude Analytics SDK.

```typescript
import * as amplitude from '@amplitude/analytics-browser';
import { Experiment } from '@amplitude/experiment-js-client';

amplitude.init('API_KEY');
const experiment = Experiment.initializeWithAmplitudeAnalytics('DEPLOYMENT_KEY');
```

Using the integration initializer configures implementations of the [user provider](#user-provider) and [exposure tracking provider](#exposure-tracking-provider) interfaces to pull user data from the Amplitude Analytics SDK and track exposure events.

**Supported Versions**

All versions of the next-generation [Amplitude analytics Browser](/docs/sdks/analytics/browser/browser-sdk-2) SDK support this integration.

| Legacy Analytics SDK Version | Experiment SDK Version |
| ---------------------------- | ---------------------- |
| `8.18.1+`                    | `1.4.1+`               |

{% /accordion %}

{% accordion title="Segment integration" %}
Experiment's integration with Segment Analytics requires manual configuration. Then, configure the Experiment SDK on initialization with an instance of the exposure tracking provider. Make sure this happens _after_ the analytics SDK loads an initializes.

```typescript
analytics.ready(() => {
    const experiment =  Experiment.initialize('DEPLOYMENT_KEY', {
        exposureTrackingProvider: {
            track: (exposure) => {
                analytics.track('$exposure', exposure)
            }
        }
    });
});
```

When [fetching variants](#fetch), pass the segment anonymous ID and user ID for the device ID and user ID, respectively.

```typescript
await experiment.fetch({
    user_id: analytics.user().id(),
    device_id: analytics.user().analyticsId(),
});
```

{% /accordion %}

{% accordion title="mParticle integration" %}
Experiment's integration with mParticle requires manual integration. The values you use for `user_id` and `device_id` depend on your specific configuration.

In accordance with your event forwarding settings to Amplitude, the event type `Other` may not be the right classification. Make sure that destination settings forward the event type you use to Amplitude.

```typescript
const identityRequest = {
    userIdentities: {
        email: "joe_slow@gmail.com",
        customerid: "abcdxyz"
    }
};
mParticle.Identity.login(identityRequest, () => {
    console.log("Identity callback");
});

const experiment = Experiment.initialize("DEPLOYMENT_KEY", {
    exposureTrackingProvider: {
        track: (exposure) => {
            window.mParticle.logEvent('$exposure', window.mParticle.EventType.Other, exposure);
        }
    },
    userProvider: {
        getUser: () => {
            const user_id = window.mParticle.Identity.getCurrentUser().getUserIdentities().userIdentities.customerid;
            const device_id = window.mParticle.getDeviceId();
            if (user_id != null) {
                return {
                    user_id: user_id,
                    device_id: device_id
                };
                else
                    return {
                        device_id: device_id
                    };
            }
        }
    }
});
```

{% /accordion %}

## Manage user consent

The Experiment SDK doesn't expose a consent API. There's no `consentOptions` configuration, `ConsentStatus` type, or `setConsentStatus()` method.

To support GDPR-style consent flows, gate Amplitude initialization and variant fetches on the signal from your consent management platform (CMP). Don't initialize the analytics SDK or call [`fetch()`](#fetch) or [`start()`](#start) until the user grants consent.

```typescript
import * as amplitude from '@amplitude/analytics-browser';
import { Experiment } from '@amplitude/experiment-js-client';

// Call this only after your CMP reports that the user granted consent.
async function onConsentGranted() {
    amplitude.init('API_KEY');
    const experiment = Experiment.initializeWithAmplitudeAnalytics('DEPLOYMENT_KEY');
    await experiment.fetch();
}
```

If a user withdraws consent, stop calling `fetch()` and clear any stored variants with [`clear()`](#clear).

## Fetch

Fetches variants for a [user](/docs/feature-experiment/data-model#users) and stores the results in the client for fast access. The function [remote evaluates](/docs/feature-experiment/remote-evaluation) the user for flags associated with the deployment used to initialize the SDK client.

{% callout type="tip" heading="Fetch on user identity change" %}
If you want the most up-to-date variants for the user, it's recommended that you call `fetch()` whenever the user state changes in a meaningful way. For example, if the user logs in and receives a user ID, or has a user property set which may affect flag or experiment targeting rules.

Pass new **user properties** explicitly to `fetch()` instead of relying on user enrichment before [remote evaluation](/docs/feature-experiment/remote-evaluation). Remote user-property sync through a separate system has no timing guarantees for `fetch()`, which can create a race condition.
{% /callout %}

```typescript
fetch(user?: ExperimentUser, options?: FetchOptions): Promise<Client>
```

| Parameter | Requirement | Description                                                                                                                                                                                                                                                                                                                                     |
| --------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user`    | optional    | Explicit [user](/docs/feature-experiment/data-model#users) information to pass with the request to evaluate. The SDK merges this user information with user information provided from [integrations](#integrations) through the [user provider](#user-provider), preferring properties passed explicitly to `fetch()` over provided properties. |
| `options` | optional    | Explicit flag keys to fetch.                                                                                                                                                                                                                                                                                                                    |

{% accordion title="Account-level bucketing and analysis (v1.5.6+)" %}
If your organization has purchased the [Accounts add-on](/docs/analytics/account-level-reporting) you may perform bucketing and analysis on groups rather than users. Reach out to your representative to gain access to this beta feature.

Include groups in the user sent with the fetch request (recommended), or identify groups with the user through a group identify call from the [Group Identify API](/docs/apis/analytics/group-identify) or through [`setGroup()` from an analytics SDK](/docs/sdks/analytics/browser/browser-sdk-2#user-groups).

```typescript
await fetch({
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        'premium': true,
    },
    groups: {'org name': ['Amplitude']}
});
```

To pass freeform group properties, refer to this example:

```typescript
await fetch({
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        'premium': true,
    },
    group_properties: {'org name': ['Amplitude']}
});
```

{% /accordion %}

```typescript
const user = {
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        'premium': true,
    },
};
await experiment.fetch(user);
```

If you're using an [integration](#integrations) or a custom [user provider](#user-provider) then you can fetch without inputting the user.

```typescript
await experiment.fetch();
```

If `fetch()` times out (default 10 seconds) or fails for any reason, the SDK client returns and retries in the background with back-off. You may configure the timeout or disable retries in the [configuration options](#configuration) during SDK client initialization.

## Start

{% callout type="info" heading="Fetch vs start" %}
Use `start` if you're using client-side [local evaluation](/docs/feature-experiment/local-evaluation). If you're only using [remote evaluation](/docs/feature-experiment/remote-evaluation), call [fetch](#fetch) instead of `start`.
{% /callout %}

Start the SDK by getting flag configurations from the server and fetching remote evaluation variants for the user. The SDK is ready when the returned promise resolves.

```typescript
start(user?: ExperimentUser): Promise<void>
```

| Parameter | Requirement | Description                                                                                                                                                                                                                                                                                                                                                                                    |
| --------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `user`    | optional    | Explicit [user](/docs/feature-experiment/data-model#users) information to pass with the request to fetch variants. The SDK merges this user information with user information provided from [integrations](#integrations) through the [user provider](#user-provider), preferring properties passed explicitly to `fetch()` over provided properties. Also sets the user in the SDK for reuse. |

Call `start()` when your application is initializing, after user information is available to evaluate or [fetch](#fetch) variants. The promise resolves after loading local evaluation flag configurations and fetching remote evaluation variants.

Configure the behavior of `start()` by setting `fetchOnStart` in the SDK configuration on initialization to improve performance based on the needs of your application.

- If your application never relies on remote evaluation, set `fetchOnStart` to `false` to avoid increased startup latency caused by remote evaluation.
- If your application relies on remote evaluation, but not right at startup, you may set `fetchOnStart` to `false` and call `fetch()` and await the promise separately.

{% code-group %}
```typescript Amplitude
await experiment.start();
```

```typescript Third party
const user = {
    user_id: 'user@company.com',
    device_id: 'abcdefg',
    user_properties: {
        premium: true
    }
};
await experiment.start(user);
```
{% /code-group %}

## Variant

Access a [variant](/docs/feature-experiment/data-model#variants) for a [flag or experiment](/docs/feature-experiment/data-model#flags-and-experiments) from the SDK client's local store.

{% callout type="info" heading="Automatic exposure tracking" %}
When you use an [integration](#integrations) or set a custom [exposure tracking provider](#exposure-tracking-provider), `variant()` automatically tracks an exposure event through the tracking provider. To disable this functionality, [configure](#configuration) `automaticExposureTracking` to be `false`, and track exposures manually using [`exposure()`](#exposure).
{% /callout %}

```typescript
variant(key: string, fallback?: string | Variant): Variant
```

| Parameter  | Requirement | Description                                                                                                                                 |
| ---------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `key`      | required    | The **flag key** to identify the [flag or experiment](/docs/feature-experiment/data-model#flags-and-experiments) to access the variant for. |
| `fallback` | optional    | The value to return if no variant was found for the given `flagKey`.                                                                        |

When determining which variant a user has been bucketed into, you'll want to compare the variant `value` to a well-known string.

```typescript
const variant = experiment.variant('<FLAG_KEY>');
if (variant.value === 'on') {
    // Flag is on
} else {
    // Flag is off
}
```

{% callout type="info" heading="Access a variant's payload" %}
A variant may also be configured with a dynamic [payload](/docs/feature-experiment/data-model#variants) of arbitrary data. Access the `payload` field from the variant object after checking the variant's `value`.

```typescript
const variant = experiment.variant('<FLAG_KEY>');
if (variant.value === 'on') {
    const payload = variant.payload;
}
```

{% /callout %}

A `null` variant `value` means that the user hasn't been bucketed into a variant. You may use the built in **fallback** parameter to provide a variant to return if the store doesn't contain a variant for the given flag key.

```typescript
const variant = experiment.variant('<FLAG_KEY>', { value: 'control' });
if (variant.value === 'control') {
    // Control
} else if (variant.value === 'treatment') {
    // Treatment
}
```

## All

Access all [variants](/docs/feature-experiment/data-model#variants) stored by the SDK client.

```typescript
all(): Variants
```

## Clear

Clear all [variants](/docs/feature-experiment/data-model#variants) in the cache and storage.

```typescript
clear(): void
```

You can call `clear` after user logout to clear the variants in cache and storage.

```typescript
experiment.clear();
```

## Exposure

Manually track an [exposure event](/docs/feature-experiment/under-the-hood/event-tracking#exposure-events) for the current variant of the given flag key through configured [integration](#integrations) or custom [exposure tracking provider](#exposure-tracking-provider). Generally used in conjunction with setting the `automaticExposureTracking` [configuration](#configuration) optional to `false`.

```typescript
exposure(key: string): void
```

| Parameter | Requirement | Description                                                                                                                                                                                                                        |
| --------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key`     | required    | The **flag key** to identify the [flag or experiment](/docs/feature-experiment/data-model#flags-and-experiments) variant to track an [exposure event](/docs/feature-experiment/under-the-hood/event-tracking#exposure-events) for. |

```typescript
const variant = experiment.variant('<FLAG_KEY>');

// Do other things...

experiment.exposure('<FLAG_KEY>');
if (variant.value === 'control') {
    // Control
} else if (variant.value === 'treatment') {
    // Treatment
}
```

## Providers

{% callout type="tip" heading="Integrations" %}
If you use Amplitude or Segment analytics SDKs along side the Experiment Client SDK, Amplitude recommends you use an [integration](#integrations) instead of implementing custom providers.
{% /callout %}

Provider implementations enable a more streamlined developer experience by making it easier to manage user identity and track exposures events.

### User provider

The SDK client uses the user provider to access the most up-to-date user information only when needed (for example, when [`fetch()`](#fetch) is called). The user provider is optional, but helps if you have a user information store already set up in your application. With a user provider, you don't need to manage two separate user info stores in parallel. Separate stores can create divergent user state if the application user store is updated and experiment isn't (or vice versa).

```typescript title="ExperimentUserProvider"
interface ExperimentUserProvider {
  getUser(): ExperimentUser;
}
```

To use your custom user provider, set the `userProvider` [configuration](#configuration) option with an instance of your custom implementation on SDK initialization.

```typescript
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
    userProvider: new CustomUserProvider(),
});
```

### Exposure tracking provider

Amplitude highly recommends implementing an exposure tracking provider. [Exposure tracking](/docs/feature-experiment/under-the-hood/event-tracking#exposure-events) increases the accuracy and reliability of experiment results and improves visibility into which flags and experiments a user is exposed to.

```typescript title="ExposureTrackingProvider"
export interface ExposureTrackingProvider {
  track(exposure: Exposure): void;
}
```

The implementation of `track()` should track an event of type `$exposure` (a.k.a name) with two event properties, `flag_key` and `variant`, corresponding to the two fields on the `Exposure` object argument. Finally, the event tracked must eventually end up in Amplitude Analytics for the same project that the [deployment] used to [initialize](#initialize) the SDK client lives within, and for the same user that variants were [fetched](#fetch) for.

To use your custom user provider, set the `exposureTrackingProvider` [configuration](#configuration) option with an instance of your custom implementation on SDK initialization.

```typescript
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
    exposureTrackingProvider: new CustomExposureTrackingProvider(),
});
```

## Bootstrapping

You may want to bootstrap the experiment client with an initial set of flags or variants when variants come from an external source (for example, not from calling `fetch()` on the SDK client). Use cases include [local evaluation](/docs/feature-experiment/local-evaluation), [server-side rendering](/docs/feature-experiment/advanced-techniques/server-side-rendering), or integration testing on specific variants.

### Bootstrapping variants

To bootstrap the client with a predefined set of variants, set the flags and variants in the `initialVariants` [configuration](#configuration) object, then set the `source` to `Source.InitialVariants` so that the SDK client prefers the bootstrapped variants over any previously fetched & stored variants for the same flags.

```typescript
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
    // Map flag keys to variant objects. The variant object may either be
    // pre-evaluation (SSR) or input manually in for testing.
    initialVariants: {
        "<FLAG_KEY>": {
            "value": "<VARIANT>"
         }
    },
    source: Source.InitialVariants,
});
```

### Bootstrapping flag configurations

You may choose to bootstrap the SDK with an initial set of local evaluation flag configurations using the `initialFlags` configuration. The SDK evaluates these flag configurations when [variant](#variant) is called, unless an updated flag config or variant is loaded with [start](#start) or [fetch](#fetch).

To download initial flags, use the [evaluation flags API](/docs/apis/experiment/experiment-evaluation-api#flags-api)

```typescript
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
    initialFlags: "<FLAGS_JSON>",
});
```

## HTTP client

You can provide a custom HTTP client implementation to handle network requests made by the SDK. This is useful for environments with specific networking requirements or when you need to customize request handling.

```typescript title="HttpClient"
export interface SimpleResponse {
  status: number;
  body: string;
}

export interface HttpClient {
  request(
    requestUrl: string,
    method: string,
    headers: Record<string, string>,
    data: string,
    timeoutMillis?: number,
  ): Promise<SimpleResponse>;
}
```

To use your custom HTTP client, set the `httpClient` [configuration](#configuration) option with an instance of your implementation on SDK initialization.

```typescript
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
    httpClient: new CustomHttpClient(),
});
```

## Custom logging

Control log verbosity with the `logLevel` configuration, or implement the `Logger` interface to integrate your own logging solution.

### Log levels

- `LogLevel.Disable` - No logging
- `LogLevel.Error` - Errors only (default)
- `LogLevel.Warn` - Errors and warnings
- `LogLevel.Info` - Errors, warnings, and informational messages
- `LogLevel.Debug` - Errors, warnings, info, and debug messages
- `LogLevel.Verbose` - All messages including verbose details

```typescript
import { Experiment, LogLevel } from '@amplitude/experiment-js-client';

// Only log errors
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  logLevel: LogLevel.Error
});

// Log errors and warnings
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  logLevel: LogLevel.Warn
});

// Log everything (verbose)
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  logLevel: LogLevel.Verbose
});
```

### Custom logger

Implement the `Logger` interface to use your own logging solution:

```typescript
import { Experiment, Logger, LogLevel } from '@amplitude/experiment-js-client';

// Implement the Logger interface
class CustomLogger implements Logger {
  error(message?: any, ...optionalParams: any[]): void {
    // Send errors to your logging service
    myLoggingService.error(message, ...optionalParams);
  }

  warn(message?: any, ...optionalParams: any[]): void {
    myLoggingService.warn(message, ...optionalParams);
  }

  info(message?: any, ...optionalParams: any[]): void {
    myLoggingService.info(message, ...optionalParams);
  }

  debug(message?: any, ...optionalParams: any[]): void {
    myLoggingService.debug(message, ...optionalParams);
  }

  verbose(message?: any, ...optionalParams: any[]): void {
    myLoggingService.verbose(message, ...optionalParams);
  }
}

// Initialize with custom logger
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  loggerProvider: new CustomLogger(),
  logLevel: LogLevel.Warn
});
```

### Debug flag (deprecated)

The `debug` configuration flag is deprecated. Use `logLevel` instead.

```typescript
// Deprecated: Sets logLevel to Debug
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  debug: true
});

// Preferred: Use logLevel instead
const experiment = Experiment.initialize('<DEPLOYMENT_KEY>', {
  logLevel: LogLevel.Debug
});
```
