
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.

{% callout type="warning" heading="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.
{% /callout %}

{% callout type="warning" heading="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",
});
```

{% /callout %}

## Terminology

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

## Dependency

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

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

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

```json @amplitude/analytics-browser@2+
{
  "dependencies": {
    "@amplitude/analytics-browser": "^2.11.8"
  }
}
```
{% /code-group %}

## 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).

{% code-group %}
```javascript amplitude-js
import amplitude from "amplitude-js";

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

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

amplitude.init(API_KEY, OPTIONAL_USER_ID, config);
```
{% /code-group %}

## Configuration

{% accordion title="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](/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`|

{% /accordion %}

## 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()`.

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

```typescript @amplitude/analytics-browser@2+
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
amplitude.track(eventType, eventProperties);
```
{% /code-group %}

### logEventWithTimestamp()

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

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

```typescript @amplitude/analytics-browser@2+
const eventType = "Button Clicked";
const eventProperties = {
  type: "primary",
};
const eventOptions = {
  time: Date.now(),
};
amplitude.track(eventType, eventProperties, eventOptions);
```
{% /code-group %}

### logEventWithGroups()

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

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

```typescript @amplitude/analytics-browser@2+
const event_type = "Button Clicked";
const event_properties = {
  type: "primary",
};
const groups = {
  orgId: "12345",
};
const event = {
  event_type,
  event_properties,
  groups,
};
amplitude.track(event);
```
{% /code-group %}

### `sendEvents()`

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

{% code-group %}
```javascript amplitude-js
amplitude.getInstance().sendEvents();
```

```typescript @amplitude/analytics-browser@2+
amplitude.flush();
```
{% /code-group %}

## 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()

{% callout type="warning" heading="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.
{% /callout %}

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

{% code-group %}
```javascript amplitude-js
const userId = "1";
amplitude.getInstance().setUserId(userId);
```

```typescript @amplitude/analytics-browser@2+
const userId = "1";
amplitude.setUserId(userId);
```
{% /code-group %}

### setDeviceId()

{% callout type="warning" heading="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.
{% /callout %}

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

{% code-group %}
```javascript amplitude-js
const deviceId = "1";
amplitude.getInstance().setDeviceId(deviceId);
```

```typescript @amplitude/analytics-browser@2+
const deviceId = "1";
amplitude.setDeviceId(deviceId);
```
{% /code-group %}

### setSessionId()

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

{% code-group %}
```javascript amplitude-js
const sessionId = Date.now();
amplitude.getInstance().setSessionId(sessionId);
```

```typescript @amplitude/analytics-browser@2+
const sessionId = Date.now();
amplitude.setSessionId(sessionId);
```
{% /code-group %}

### clearUserProperties()

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

{% code-group %}
```javascript amplitude-js
amplitude.getInstance().clearUserProperties();
```

```typescript @amplitude/analytics-browser@2+
amplitude.identify(new amplitude.Identify().identify.clearAll());
```
{% /code-group %}

### setUserProperties()

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

{% code-group %}
```javascript amplitude-js
amplitude.getInstance().setUserProperties({
  membership, "paid",
  payment, "bank",
})
```

```typescript @amplitude/analytics-browser@2+
const identify = new amplitude.Identify();
identify.set("membership", "paid").set("payment", "bank");
amplitude.identify(identify);
```
{% /code-group %}

### identify()

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

{% code-group %}
```javascript amplitude-js
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.getInstance().identify(identify);
```

```typescript @amplitude/analytics-browser@2+
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.identify(identify);
```
{% /code-group %}

## Set group properties

### groupIdentify()

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

{% code-group %}
```javascript amplitude-js
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.getInstance().groupIdentify(identify);
```

```typescript @amplitude/analytics-browser@2+
const identify = new amplitude.Identify();
identify.set("membership", "paid");
amplitude.groupIdentify(identify);
```
{% /code-group %}

## Track revenue

### logRevenueV2()

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

{% code-group %}
```javascript amplitude-js
const revenue = new amplitude.Revenue();
revenue.setProductId("productId").setPrice(10);
amplitude.getInstance().logRevenueV2(revenue);
```

```typescript @amplitude/analytics-browser@2+
const revenue = new amplitude.Revenue();
revenue.setProductId("productId").setPrice(10);
amplitude.revenue(revenue);
```
{% /code-group %}

## 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.

{% tabs tabs="amplitude-js, @amplitude/analytics-browser@2+" %}
{% tab name="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();
```

{% /tab %}
{% tab name="@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);
```

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

### 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.

{% tabs tabs="amplitude-js, @amplitude/analytics-browser@2+" %}
{% tab name="amplitude-js" %}

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

{% /tab %}
{% tab name="@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();
});
```

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

### 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
}
```
