# Migrate from Javascript SDK to Browser SDK 2.0

> For AI agents: a documentation index is available at [/docs/llms.txt](/docs/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

Amplitude Browser SDK 2.0 (`@amplitude/analytics-browser@2+`) offers these features:

- Plugin architecture.
- Built-in type definition.
- Broader support for front-end frameworks.
- Autocapture.
- Improved marketing attribution tracking.
- Identical interfaces across platforms with other Amplitude SDKs.

Browser SDK 2.0 isn't backwards compatible with `amplitude-js`.

To migrate to `@amplitude/analytics-browser@2+`, update your dependencies and instrumentation.

> **Warning:** Breaking changes
>
> When you migrate to `@amplitude/analytics-browser@2+`, your implementation may experience disruption to web attribution. Before you upgrade, choose whether attribution occurs during a session. After you upgrade, attribution can happen during the session, and you can't configure it.
>
> In both versions, attribution can occur during initialization.

> **Warning:** Cookie migration
>
> Browser SDK 2.0 automatically migrates cookies from the JavaScript SDK, version 6.0.0 or above:
>
> - Old cookie name `AMP_{first 6 digit of api key}` from JavaScript SDK 6.0.0 and above.
> - New cookie name `AMP_{first 10 digit of api key}` from Browser SDK 2.
>
> Migrating from a JavaScript SDK version before 6.0.0 requires manual cookie migration.
>
> To manually migrate cookies:
>
> 1. Read the values from the old cookie.
> 2. Pass those values to `amplitude.init()` in the SDK configuration.
>
> ```ts
> this.init("API_KEY", {
>   deviceId: "device_id",
>   userId: "user_id",
> });
> ```

## Terminology

- `amplitude-js`: Maintenance Browser SDK.
- `@amplitude/analytics-browser@2+`: Browser SDK 2.0.

## Dependency

For snippet installation, update your project's [snippet loader](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2#install-the-sdk).

For Node projects, update your dependency list in `package.json`.

#### amplitude-js

```json
{
  "dependencies": {
    "amplitude-js": "^8"
  }
}
```

#### @amplitude/analytics-browser@2+

```json
{
  "dependencies": {
    "@amplitude/analytics-browser": "^2.11.8"
  }
}
```

## Instrumentation

Browser SDK 2.0 offers an API to instrument events. To migrate to Browser SDK 2.0, update a few calls. The following sections detail which calls changed.

## Initialization

Browser SDK 2.0 removes `getInstance()`. To initialize the SDK, call `init()` with the same parameters. The `config` object uses a different shape. Refer to [Configuration](#configuration).

#### amplitude-js

```javascript
import amplitude from "amplitude-js";

amplitude.getInstance().init(API_KEY, OPTIONAL_USER_ID, config);
```

#### @amplitude/analytics-browser@2+

```typescript
import * as amplitude from "@amplitude/analytics-browser";

amplitude.init(API_KEY, OPTIONAL_USER_ID, config);
```

## Configuration

#### Configuration options

| amplitude-js | @amplitude/analytics-browser@2+ |
| --- | --- |
| `config.apiEndpoint` | `config.serverUrl` |
| `config.batchEvents` | `config.flushQueueSize` |
| `config.cookieExpiration` | `config.cookieOptions.expiration` |
| `config.secureCookie` | `config.cookieOptions.secure` |
| `config.sameSiteCookie` | `config.cookieOptions.sameSite` |
| `config.cookieName` | NOT SUPPORTED |
| `config.cookieForceUpgrade` | NOT SUPPORTED |
| `config.deferInitialization` | NOT SUPPORTED. Refer to [Defer initialization](#defer-initialization). |
| `config.disableCookies` | `config.identityStorage`. Set it to `'localStorage'` to disable cookies. |
| `config.deviceId` | `config.deviceId` |
| `config.deviceIdFromUrlParam` | Browser SDK 2.0 pulls the device ID from the URL parameter by default. Refer to [Browser SDK 2.0 Cross-domain tracking](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2#cross-domain-tracking). |
| `config.domain` | NOT SUPPORTED |
| `config.eventUploadPeriodMillis` | `config.flushIntervalMillis` |
| `config.eventUploadThreshold` | `config.flushQueueSize` |
| `config.forceHTTPs` | NOT SUPPORTED |
| `config.includeFbclid` | NOT SUPPORTED. Refer to [Web attribution](#web-attribution). |
| `config.includeGclid` | NOT SUPPORTED. Refer to [Web attribution](#web-attribution). |
| `config.includeReferrer` | NOT SUPPORTED. Refer to [Web attribution](#web-attribution). |
| `config.includeUtm` | NOT SUPPORTED. Refer to [Web attribution](#web-attribution). |
| `config.language` | NOT SUPPORTED. Refer to [Plugins](#plugins). |
| `config.library` | NOT SUPPORTED. Refer to [Plugins](#plugins). |
| `config.logLevel` | `config.logLevel` |
| `config.logAttributionCapturedEvent` | NOT SUPPORTED |
| `config.optOut` | `config.optOut` |
| `config.onError` | NOT SUPPORTED |
| `config.onExitPage` | NOT SUPPORTED. Refer to [Flush](#flush-or-onexitpage). |
| `config.platform` | NOT SUPPORTED at the configuration level, but `platform` still exists in the event object. To overwrite it, assign a platform when you track an event, or enrich `event.platform` using the enrichment plugin. Refer to [Plugins](#plugins). |
| `config.savedMaxCount` | NOT SUPPORTED |
| `config.saveEvents` | NOT SUPPORTED |
| `config.saveParamsReferrerOncePerSession` | NOT SUPPORTED. |
| `config.sessionTimeout` | `config.sessionTimeout` |
| `config.storage` | `config.identityStorage` |
| `config.trackingOptions` | `config.trackingOptions` |
| `config.transport` | `config.transportProvider` |
| `config.unsetParamsReferrerOnNewSession` | NOT SUPPORTED. Default behavior. |
| `config.unsentKey` | NOT SUPPORTED |
| `config.unsentIdentifyKey` | NOT SUPPORTED |
| `config.uploadBatchSize` | `config.flushQueueSize` |
| `config.headers` | NOT SUPPORTED |
| `config.serverZone` | `config.serverZone` |
| `config.useDynamicConfig` | NOT SUPPORTED |
| `config.serverZoneBasedApi` | NOT SUPPORTED |
| `config.sessionId` | `config.sessionId` |
| `config.partnerId` | `config.partnerId` |

## Tracking events

The maintenance Browser SDK offered several `logEvent` APIs, such as `logEventWithTimestamp` and `logEventWithGroups`, to override specific properties in the event payload. In `@amplitude/analytics-browser@2+`, use the unified `track` API instead.

### logEvent()

The `logEvent()` API maps to `track()`.

#### amplitude-js

```javascript
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
amplitude.getInstance().logEvent(eventType, eventProperties);
```

#### @amplitude/analytics-browser@2+

```typescript
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
amplitude.track(eventType, eventProperties);
```

### logEventWithTimestamp()

The `logEventWithTimestamp()` API maps to `track()`.

#### amplitude-js

```javascript
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
const timestamp = Date.now();
amplitude
  .getInstance()
  .logEventWithTimestamp(eventType, eventProperties, timestamp);
```

#### @amplitude/analytics-browser@2+

```typescript
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
const eventOptions = {
  time: Date.now(),
};
amplitude.track(eventType, eventProperties, eventOptions);
```

### logEventWithGroups()

The `logEventWithGroups()` API maps to `track()`.

#### amplitude-js

```javascript
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
const groups = {
  orgId: "12345",
};
amplitude.getInstance().logEventWithGroups(eventType, eventProperties, groups);
```

#### @amplitude/analytics-browser@2+

```typescript
const event_type = "Button Clicked";
const event_properties = {
  type: "primary",
};
const groups = {
  orgId: "12345",
};
const event = {
  event_type,
  event_properties,
  groups,
};
amplitude.track(event);
```

### `sendEvents()`

The `sendEvents()` API maps to `flush()`.

#### amplitude-js

```javascript
amplitude.getInstance().sendEvents();
```

#### @amplitude/analytics-browser@2+

```typescript
amplitude.flush();
```

## Set user properties

The APIs for setting user properties are the same, except that `getInstance()` is no longer required. The following code snippets show how to migrate APIs for user properties.

### setUserId()

> **Warning:** Minimum identifier length
>
> The maintenance SDK uses an old SDK endpoint (`api2.amplitude.com`) which enforces no length limit for `deviceId` and `userId`. The latest SDK uses Amplitude's HTTP V2 API (`api2.amplitude.com/2/httpapi`) and requires identifiers to be at least five characters by default. When you migrate to the latest SDK, set `config.minIdLength` to a smaller value if you allowed identifiers with fewer than five characters.

Set a `userId` when you invoke `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const userId = "1";
amplitude.getInstance().setUserId(userId);
```

#### @amplitude/analytics-browser@2+

```typescript
const userId = "1";
amplitude.setUserId(userId);
```

### setDeviceId()

> **Warning:** Minimum identifier length
>
> The maintenance SDK uses an old SDK endpoint (`api2.amplitude.com`) which enforces no length limit for `deviceId` and `userId`. The latest SDK uses Amplitude's HTTP V2 API (`api2.amplitude.com/2/httpapi`) and requires identifiers to be at least five characters by default. When you migrate to the latest SDK, set `config.minIdLength` to a smaller value if you allowed identifiers with fewer than five characters.

Set a `deviceId` when you invoke `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const deviceId = "1";
amplitude.getInstance().setDeviceId(deviceId);
```

#### @amplitude/analytics-browser@2+

```typescript
const deviceId = "1";
amplitude.setDeviceId(deviceId);
```

### setSessionId()

Set a `sessionId` when you invoke `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const sessionId = Date.now();
amplitude.getInstance().setSessionId(sessionId);
```

#### @amplitude/analytics-browser@2+

```typescript
const sessionId = Date.now();
amplitude.setSessionId(sessionId);
```

### clearUserProperties()

Browser SDK 2.0 removes the `clearUserProperties` API. Use the unified `identify` API to remove user properties.

#### amplitude-js

```javascript
amplitude.getInstance().clearUserProperties();
```

#### @amplitude/analytics-browser@2+

```typescript
amplitude.identify(new amplitude.Identify().identify.clearAll());
```

### setUserProperties()

Browser SDK 2.0 removes the `setUserProperties` API. Use the unified `identify` API to add user properties.

#### amplitude-js

```javascript
amplitude.getInstance().setUserProperties({
  membership, "paid",
  payment, "bank",
})
```

#### @amplitude/analytics-browser@2+

```typescript
const identify = new amplitude.Identify();
identify.set("membership", "paid").set("payment", "bank");
amplitude.identify(identify);
```

### identify()

Make an identify call on `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.getInstance().identify(identify);
```

#### @amplitude/analytics-browser@2+

```typescript
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.identify(identify);
```

## Set group properties

### groupIdentify()

Make an identify call on `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.getInstance().groupIdentify(identify);
```

#### @amplitude/analytics-browser@2+

```typescript
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.groupIdentify(identify);
```

## Track revenue

### logRevenueV2()

Track revenue using `revenue()` API on `amplitude` without calling `getInstance()`.

#### amplitude-js

```javascript
const revenue = new amplitude.Revenue();
revenue.setProductId("productId").setPrice(10);
amplitude.getInstance().logRevenueV2(revenue);
```

#### @amplitude/analytics-browser@2+

```typescript
const revenue = new amplitude.Revenue();
revenue.setProductId("productId").setPrice(10);
amplitude.revenue(revenue);
```

## Patterns

### Plugins

In `amplitude-js`, the configs `config.language`, `config.library`, and `config.platform` let you modify event payloads for these specific fields. Although `@amplitude/analytics-browser@2+` doesn't support these configurations, you can add plugins to the new Browser SDK to enrich event payloads.

```ts
import {
  BrowserConfig,
  EnrichmentPlugin,
  Event,
  PluginType,
} from "@amplitude/analytics-types";

export class LibraryModifierPlugin implements EnrichmentPlugin {
  name = "library-modifier";
  type = PluginType.ENRICHMENT as const;

  /**
   * setup() is called on plugin installation
   * example: client.add(new LibraryModifierPlugin());
   */
  setup(config: BrowserConfig): Promise<undefined> {
    this.config = config;
  }

  /**
   * execute() is called on each event instrumented
   * example: client.track('New Event');
   */
  execute(event: Event): Promise<Event> {
    event.library = "my-library-name/1.0.0";
    return Promise.resolve(event);
  }
}
```

To install your custom plugin, use `add()` with your custom plugin as a parameter.

```typescript
import * as amplitude from "@amplitude/analytics-browser";

amplitude.add(new LibraryModifierPlugin());
amplitude.init(API_KEY, OPTIONAL_USER_ID);
```

### Defer initialization

To defer initialization in `amplitude-js`, call `init` with `config.deferInitialization` set to `true`, then call `enableTracking()` to formalize initialization and send all enqueued events.

#### amplitude-js

```javascript
amplitude.getInstance().init(API_KEY, OPTIONAL_USER_ID, {
  deferInitialization: true,
});

amplitude.getInstance().logEvent("Event 1");
amplitude.getInstance().logEvent("Event 2");
amplitude.getInstance().logEvent("Event 3");

amplitude.getInstance().enableTracking();
```

#### @amplitude/analytics-browser@2+

Call `init()` later than `track()`. The SDK processes all `track()` calls after initialization completes.

```typescript
amplitude.track("Event 1");
amplitude.track("Event 2");
amplitude.track("Event 3");

amplitude.init(API_KEY, OPTIONAL_USER_ID);
```

### Web attribution

In `amplitude-js`, enable web attribution through the following configurations:

- `config.includeGclid`.
- `config.includeFbclid`.
- `config.includeReferrer`.
- `config.includeUtm`.

In `@amplitude/analytics-browser@2+`, the single configuration `config.autocapture.attribution` controls web attribution. The default setting is `true`, and it captures all campaign parameters. These are the same campaign parameters that `amplitude-js` supports.

### Flush or onExitPage

Sometimes you need to send events immediately, such as when a user navigates away from a page. Immediate sending is common when you track button clicks that direct the user to another page while sending event payloads in batches.

In `amplitude-js`, use the `onExitPage()` callback.

#### amplitude-js

```javascript
amplitude.getInstance().init(API_KEY, OPTIONAL_USER_ID, {
  onExitPage: () => {
    amplitude.sendEvents();
  },
});
```

#### @amplitude/analytics-browser@2+

Add your own event listener for the `pagehide` event.

```javascript
window.addEventListener("pagehide", () => {
  // Set https transport to use sendBeacon API
  amplitude.setTransport("beacon");
  // Send all pending events to server
  amplitude.flush();
});
```

### Callback

`amplitude-js` accepts one `init` callback function to run after initialization, plus two separate callback functions for success and error network requests. Because `@amplitude/analytics-browser@2+` supports promises and async/await, asynchronous methods like `init()`, `track()`, `identify()`, and `groupIdentify()` return a custom promise interface.

```javascript
const initResult = await amplitude.init("YOUR_API_KEY").promise;
if (initResult.code === 200) {
  // success logic
} else {
  // error logic
}

const result = await amplitude.track("Button Clicked").promise;
if (result.code === 200) {
  // success logic
} else {
  // error logic
}
```
