# Migrating to @statsig/js-client

{% callout type="warning" %}
### Deprecated

Migrate soon! Official support for statsig-js ended Jan 31, 2025.
{% /callout %}

The updated SDK retains the architecture and most APIs. However,
some modifications address common pitfalls, resolve existing issues, and streamline the SDK logic, resulting in some breaking changes.

## Breaking changes

* The SDK now offers both a synchronous and asynchronous [initialization](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#initialization) and [updateUser](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#updating-the-user) methods.
* The "getConfig" method has [changed to "getDynamicConfig"](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#getconfig-is-now-getdynamicconfig)
* When Bootstrapping, you now [pass the hash parameter as 'djb2'](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#bootstrapping)
* The top-level static instance has moved to a static method, [StatsigClient.instance()](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#static-instance)
* Overrides have moved into their own package: [js-local-overrides](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#overrides)
* Parameters for GDPR compliance have [changed and been centralized](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#gdpr)
* The method to retrieve a stableID [has changed](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#stableid-and-getstableid)
* The structure of [cached values has changed](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#cached-values), with implications on first-run experience
* Several StatsigOptions [have changed](https://docs.statsig.com/client/migration-guides/MigrationFromOldJsClient#legacy-statsigoptions)
* Statsig has deprecated the manual exposure logging methods (`getExperimentWithExposureLoggingDisabled`, `checkGateWithExposureLoggingDisabled`). The checkGate and getExperiment methods now support a second argument that [disables exposure logging](https://docs.statsig.com/client/javascript-sdk/#manual-exposures).

### Initialization

Previously, the SDK used a single method for initialization. Because waiting for a method call during app startup can be impractical, the new SDK provides two distinct initialization approaches: one synchronous and one asynchronous.

Synchronous initialization uses cache (if available) and returns immediately. The SDK then fetches data for subsequent sessions in the background.

Asynchronous initialization is awaitable and ensures the SDK fetches and uses the most current data.

{% codetabs %}
```typescript statsig-js (Legacy)
import Statsig from "statsig-js";

// initialize returns a promise which always resolves
await Statsig.initialize(
  "client-sdk-key",
  { userID: "some_user_id" },
  { environment: { tier: "staging" } } // optional, pass options here if needed
);
```

```typescript New - Async
import { StatsigClient } from '@statsig/js-client';

const client = new StatsigClient(
  'client-sdk-key',
  { userID: 'some_user_id' },
  { environment: { tier: 'staging' } }
);

// Async - waits for latest values
await client.initializeAsync();
```

```typescript New - Sync
import { StatsigClient } from '@statsig/js-client';

const client = new StatsigClient(
  'client-sdk-key',
  { userID: 'some_user_id' },
  { environment: { tier: 'staging' } }
);

// Sync - uses cache, fetches in background
client.initializeSync();
```
{% /codetabs %}

{% callout type="tip" %}
View a full example on [GitHub](https://github.com/statsig-io/js-client-monorepo/blob/main/samples/react/src/samples/precomputed-client/sample-precomp-initialize.tsx) or read more about StatsigClient initialization [here](https://docs.statsig.com/client/javascript-sdk#initialize-the-sdk).
{% /callout %}

### getConfig is now getDynamicConfig

Update your `getConfig` call sites to call the new method, `getDynamicConfig`. In addition, `DynamicConfig` and `Layer` are no longer classes but JavaScript objects. Convenience `get` methods remain unchanged.

```js
// old
statsig.getConfig('config_name');

// new
statsigClient.getDynamicConfig('config_name');
```

### Bootstrapping

When bootstrapping from a server SDK, update how the server SDK generates values. The new `js-client` SDK uses a `djb2` hash instead of `sha256` for hashing gate/experiment names. By default, all server SDKs generate `sha256` hashes in the `getClientInitializeResponse` method. Set the hash algorithm parameter to `"djb2"` to bootstrap the new client SDK. This change also reduces the overall payload size, benefiting package size and speed. This doesn't change any bucketing logic, only the obfuscation method used for the payload.

For example, if you're bootstrapping from a nodejs app, you need to:

```js
statsig.getClientInitializeResponse(
  user,
  '[client-key]',
  {
    hash: 'djb2',
  },
);
```

### Updating the user

Similar to initialization, the `updateUser` method now supports both synchronous and asynchronous approaches, working the same way as the corresponding initialization approach.

{% codetabs %}
```typescript statsig-js (Legacy)
import Statsig from "statsig-js";

const user = { userID: "a-user" };

await Statsig.updateUser(user);
```

```typescript New - Async
import { StatsigClient } from '@statsig/js-client';

const client = new StatsigClient('client-sdk-key', { userID: 'initial-user' });
await client.initializeAsync();

// Update to new user - async
const newUser = { userID: 'a-user' };
await client.updateUserAsync(newUser);
```

```typescript New - Sync
import { StatsigClient } from '@statsig/js-client';

const client = new StatsigClient('client-sdk-key', { userID: 'initial-user' });
client.initializeSync();

// Update to new user - sync
const newUser = { userID: 'a-user' };
client.updateUserSync(newUser);
```
{% /codetabs %}

{% callout type="tip" %}
View a full example on [GitHub](https://github.com/statsig-io/js-client-monorepo/blob/main/samples/react/src/samples/precomputed-client/sample-precomp-update-user.tsx)
{% /callout %}

## Static instance

In the previous SDK version, there was a top-level static interface for using Statsig. To improve support for multiple instances, a static method that retrieves an instance now replaces it.

{% codetabs %}
```typescript statsig-js (Legacy)
import Statsig from "statsig-js";

await Statsig.initialize(YOUR_CLIENT_KEY, { userID: 'a-user' });

// then later, at some other location in your code base
if (Statsig.checkGate('a_gate')) { 
  // do something...
}
```

```typescript New
import { StatsigClient } from '@statsig/js-client';

// Initialize once in your app
const client = new StatsigClient(YOUR_CLIENT_KEY, { userID: 'a-user' });
await client.initializeAsync();

// then later, at some other location in your code base
const instance = StatsigClient.instance(YOUR_CLIENT_KEY);
if (instance.checkGate('a_gate')) { 
  // do something...
}
```
{% /codetabs %}

{% callout type="tip" %}
View a full example on [GitHub](https://github.com/statsig-io/js-client-monorepo/blob/main/samples/react/src/samples/precomputed-client/sample-precomp-static-instance.tsx) or read more about StatsigClient multi-instance support [here](https://docs.statsig.com/client/javascript-sdk#multiple-client-instances).
{% /callout %}

## Overrides

Previously, the client had top-level methods for managing overrides for gates/configs/experiments/layers. Statsig removed this functionality from the main SDK and moved it to its own package. You can implement your own overrides, or use `@statsig/js-local-overrides` and set it as the local override adapter in `StatsigOptions`.

```
import { StatsigClient } from '@statsig/js-client';
import { LocalOverrideAdapter } from '@statsig/js-local-overrides';

const overrideAdapter = new LocalOverrideAdapter();
overrideAdapter.overrideGate('gate_a', false);
overrideAdapter.overrideGate('gate_b', true);

const client = new StatsigClient(
  DEMO_CLIENT_KEY,
  { userID: 'a-user' },
  {
    overrideAdapter,
  },
);
```

Full example here:

https://github.com/statsig-io/js-client-monorepo/blob/0e7201635f71e77633de04c4c19c1006030a3a81/samples/next-js/src/app/override-adapter-example/OverrideAdapterExample.tsx#L14

## GDPR

In consent management use cases, you must suspend cache and network usage until the user grants specific permissions. Previously, the approach was fragmented. The new SDK consolidates these settings for consistency and ease of implementation.

{% codetabs %}
```typescript statsig-js (Legacy)
// start the SDK without storage or logging
Statsig.initialize(
  'client-key',
  { userID: 'a_user' },
  { disableAllLogging: true, disableLocalStorage: true },
);

// then, once permission was granted
Statsig.shutdown();
Statsig.initialize(
  'client-key',
  { userID: 'a_user' },
  { disableAllLogging: false, disableLocalStorage: false },
);

// or, by manually flipping the related flags
Statsig.reenableAllLogging();
StatsigLocalStorage.disabled = false;
```

```typescript New
import { StatsigClient } from '@statsig/js-client';

// start the SDK without storage or logging
const client = new StatsigClient(
  'client-key',
  { userID: 'a_user' },
  {
    disableLogging: true,
    disableStorage: true,
    networkConfig: { preventAllNetworkTraffic: true },
  }
);

await client.initializeAsync();

// then, once permission was granted
client.updateRuntimeOptions({
  disableLogging: false,
  disableStorage: false,
  networkConfig: { preventAllNetworkTraffic: false },
});
```
{% /codetabs %}

{% callout type="tip" %}
View a full example on [GitHub](https://github.com/statsig-io/js-client-monorepo/blob/main/samples/react/src/samples/precomputed-client/sample-precomp-gdpr.tsx)
{% /callout %}

## stableID and getStableID

`statsig.getStableID()` no longer exists. You can get the stableID like this: `myStatsigClient.getContext().stableID`

The key for the stableID in local storage has changed. The new key is a function of the SDK key used to initialize the SDK, which allows multiple SDK instances to coexist on a single page without overlapping cached data. To keep the existing stableID, access it in local storage from the old key `STATSIG_LOCAL_STORAGE_STABLE_ID` and set it in `customIDs` to override the stableID.

## Cached values

The structure of cached values has changed significantly, and there is no supported migration path from the old format to the new format. To pre-populate cached values, run the new SDK without issuing checks against it for some time before switching to use it for all checks.

## Legacy StatsigOptions

The options for parameterizing SDK initialization have changed. In some cases, Statsig removed or moved the underlying features, and you can enable or disable them in a different way. In other cases, there is a new API for managing them. The following maps old options to their equivalents in the new SDK.

#### disableErrorLogging

> This feature doesn't exist in the new Javascript SDK, so there is no option to disable it.

#### disableAutoMetricsLogging

> Moved to optional package [`@statsig/web-analytics`](https://www.npmjs.com/package/@statsig/web-analytics)

#### disableAllLogging

> This is now `StatsigOptions.disableLogging`

#### disableCurrentPageLogging

> This is now `StatsigOptions.includeCurrentPageUrlWithEvents`

#### disableLocalStorage

> This is now `StatsigOptions.disableStorage`

#### localMode

> This is now `StatsigOptions.networkConfig.preventAllNetworkTraffic`

#### loggingIntervalMillis

> This is now `StatsigOptions.loggingIntervalMs`

#### loggingBufferMaxSize

> Unchanged

#### environment

> Unchanged

#### disableNetworkKeepalive

> Statsig completely removed this. Control network requests with `StatsigOptions.networkConfig.networkOverrideFunc`.

#### api

> This is now `StatsigOptions.networkConfig.api`

#### overrideStableID

> stableID is now just part of `StatsigUser.customIDs`. This brings it inline with Statsig server
> SDKs and helps avoid mis-configuration between client and server

#### initTimeoutMs

> Timeouts now live as part of the `async` call.
>
> eg:
> `myStatsigClient.initializeAsync(1000); // 1 sec timeout`

#### initializeValues

> Replaced by the usage of [StatsigEvaluationsDataAdapter](https://docs.statsig.com/client/javascript-mono/UsingEvaluationsDataAdapter)

#### eventLoggingApi

> Replaced by `StatsigOptions.networkConfig.logEventUrl`

#### prefetchUsers

> Replaced by the usage of [StatsigEvaluationsDataAdapter](https://docs.statsig.com/client/javascript-mono/UsingEvaluationsDataAdapter)

#### initCompletionCallback

> Replaced by the usage of [StatsigClientEventEmitter](https://docs.statsig.com/client/javascript-sdk#client-event-emitter)

```js
statsigClient.on('values_updated', function(evt) {
  if(evt.status && evt.status === 'Ready') { /* client has initialized */ } 
});    
```

#### updateUserCompletionCallback

> Replaced by the usage of [StatsigClientEventEmitter](https://docs.statsig.com/client/javascript-sdk#client-event-emitter)

#### fetchMode

> Replaced by the usage of [StatsigEvaluationsDataAdapter](https://docs.statsig.com/client/javascript-mono/UsingEvaluationsDataAdapter)

#### disableDiagnosticsLogging

> There currently is no diagnostics logging in the new SDK

#### initRequestRetries

> Statsig completely removed this. Control network requests with `StatsigOptions.networkConfig.networkOverrideFunc`.

#### ignoreWindowUndefined

> No longer applicable

#### disableHashing

> This is now StatsigOptions.networkConfig.initializeHashAlgorithm

#### logLevel

> Statsig hasn't changed this, but the enum values are no longer `UPPERCASED`.

#### logger

> Not yet supported

#### evaluationCallback

> Replaced by the usage of [StatsigClientEventEmitter](https://docs.statsig.com/client/javascript-sdk#client-event-emitter)
