このページでは

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

Browser SDK 2 usage guide

このページはまだあなたの言語に翻訳されていません。 現在取り組んでいますので、後でもう一度確認してください。

This guide covers the everyday work with Browser SDK 2 after Get started: tracking your own events, managing identity and sessions, choosing Autocapture features, and controlling how events reach Amplitude. For exact signatures and every option, go to the Reference. To find the release that added or changed a feature, go to Browser SDK 2 release notes.

Track events

Browser SDK 2 sends five kinds of data: custom events, user properties, group membership, group properties, and revenue. Each has its own method, and each method returns { promise }, which resolves after the upload attempt. Use these methods for events your tracking plan defines. For page views, clicks, form interactions, and other events the SDK can collect without code, go to Autocapture.

Track a custom event

Pass an event name and, optionally, an object of event properties.

ts
amplitude.track("Song Played", {
  title: "Here Comes the Sun",
  duration_seconds: 185,
  genres: ["rock", "pop"],
});

Use strings, numbers, booleans, arrays, or nested objects as property values. The event name must be a non-empty string. The SDK drops events with an empty name and logs Event skipped due to empty event type.

logEvent() is an alias of track() with the same arguments.

Pass the event as an object

To set more fields than the name and properties, pass a BaseEvent object. This form accepts every field the HTTP V2 API accepts, such as groups, time, app_version, and insert_id.

ts
amplitude.track({
  event_type: "Song Played",
  event_properties: { title: "Here Comes the Sun" },
  time: Date.now() - 60_000,
  insert_id: "song-played-8f2c",
});

Set insert_id when the same event might send twice, for example after a retry from your own code. Amplitude ignores a second event with the same insert_id and device_id within seven days.

Override identity for one event

Pass user_id or device_id in the third argument, the event options. The override applies to this event only. Later events still use the identity from setUserId() and setDeviceId().

ts
amplitude.track(
  "Invite Sent",
  { channel: "email" },
  {
    user_id: "user-12345",
  },
);

identify() behaves differently. Passing user_id or device_id to identify() also calls setUserId() or setDeviceId(), which changes the identity for every later event.

Wait for an event before navigating

The SDK uploads events in batches about once a second. If your code leaves the page right after track(), wait for the promise first:

ts
await amplitude.track("Checkout Started").promise;
window.location.assign("/checkout");

The default fetch transport already sends with keepalive, so most events survive navigation without waiting. Wait when the event must arrive before the next page loads. For more on unload behavior, go to Data delivery.

Set user properties

User properties describe the user and stay attached to every later event until they change. Build an Identify object, add one or more operations, and pass it to identify().

ts
const identifyEvent = new amplitude.Identify()
  .set("plan", "pro")
  .setOnce("first_seen_at", "2026-10-26")
  .add("login_count", 1)
  .append("visited_sections", "billing");

amplitude.identify(identifyEvent);

The SDK sends an $identify event. It doesn't appear as an event in charts, but it updates the user's properties.

Each property can appear in only one operation per Identify object. The SDK silently ignores a second operation on the same key, so split conflicting operations across two identify() calls.

To set user properties as part of initialization, so they apply before the first autocaptured event, pass the Identify object to init():

ts
amplitude.init("YOUR_API_KEY", "user-12345", {
  identify: new amplitude.Identify().set("plan", "pro"),
});

The SDK sends this identify each time a new session starts, before the session's start event. The identify option requires Browser SDK 2.25.0 or later.

Assign a user to a group

Groups let you analyze behavior at the account or organization level. Group analytics requires the Accounts add-on.

setGroup() assigns the current user to one or more groups of a type. The assignment persists on the user like a user property.

ts
amplitude.setGroup("company", "Acme Inc");
amplitude.setGroup("team", ["engineering", "design"]);

To associate only one event with a group, without changing the user's groups, set groups on the event:

ts
amplitude.track({
  event_type: "Report Exported",
  groups: { company: "Acme Inc" },
});

Set group properties

Group properties describe the group, not the user. Use groupIdentify() with an Identify object. All Identify operations work the same way as they do for user properties. Updates apply only to events from that point onward.

ts
const groupProperties = new amplitude.Identify()
  .set("plan", "enterprise")
  .set("seats", 250);

amplitude.groupIdentify("company", "Acme Inc", groupProperties);

Track revenue

Build a Revenue object and pass it to revenue(). The SDK sends a revenue_amount event that Amplitude uses for revenue analysis.

ts
const purchase = new amplitude.Revenue()
  .setProductId("com.example.pro-annual")
  .setPrice(99.99)
  .setQuantity(2)
  .setRevenueType("subscription")
  .setCurrency("USD")
  .setEventProperties({ coupon: "FALL26" });

amplitude.revenue(purchase);

Amplitude computes revenue as price * quantity unless you call setRevenue(), which sets the total directly. quantity defaults to 1, and setQuantity() ignores values of 0 or less. setPrice() accepts negative values, for example for a refund. Revenue verification requires setRevenueType() and setReceiptSig(). For every setter, go to Revenue in the API reference.

Amplitude converts revenue to your project's currency only when you set currency. For more on currency conversion and revenue event setup, go to Track revenue.

To get the most from revenue data, also track products with the product array method.

Track video playback

trackVideo() sends Video Content Started and Video Content Stopped events from an HTML <video> element or a player.js-compatible embedded player. This API is experimental and can change without notice. Requires Browser SDK 2.39.0 or later.

ts
const video = document.querySelector("video");

if (video) {
  const stopTracking = amplitude.trackVideo(amplitude, video, {
    extraEventProperties: { placement: "homepage" },
  });

  // Later, when you no longer need video events:
  if (typeof stopTracking === "function") {
    stopTracking();
  }
}

Every event from one trackVideo() call carries the same view_session_id, a UUID the SDK generates, plus your extraEventProperties. trackVideo() returns an Error instead of a function if it can't attach to the player.

Send events to more than one project

Each Amplitude project has its own API key. To send to two projects, create a second instance with createInstance() and give it a distinct instanceName.

ts
amplitude.init("PRODUCTION_API_KEY");

const marketing = amplitude.createInstance();
marketing.init("MARKETING_API_KEY", {
  instanceName: "marketing",
});

amplitude.track("Signup Completed");
marketing.track("Signup Completed");

Each instance keeps its own user ID, device ID, session, queue, and plugins. Instances that share an API key share their identity cookie, so give each project its own key.

Identity and sessions

Browser SDK 2 attaches three identifiers to every event: a device ID, an optional user ID, and a session ID. Amplitude uses them to merge events into users and sessions. The SDK stores all three, plus the opt-out flag, in a first-party cookie named AMP_ followed by the first 10 characters of your API key, so they persist across page loads and subdomains.

How the SDK chooses identifiers on load

During init(), the SDK takes each identifier from the first source that has a value.

Device ID

  1. The deviceId option.
  2. The ampDeviceId URL parameter, then the legacy deviceId URL parameter.
  3. The AMP_ cookie.
  4. A cookie from the maintenance JavaScript SDK (amp_ prefix).
  5. A new UUID.

User ID

  1. The userId argument or option.
  2. The AMP_ cookie.
  3. A cookie from the maintenance JavaScript SDK.

Session ID

  1. The sessionId option.
  2. The ampSessionId URL parameter.
  3. A session deferred by opt-out.
  4. The AMP_ cookie, if the last event was within sessionTimeout.
  5. Date.now().

The SDK ignores the URL parameters when an ampTimestamp parameter is present and earlier than the current time. Go to Track users across domains.

Set the user ID

Call setUserId() when a user signs in. Use a stable, unique identifier from your system, such as a database ID. Avoid email addresses if they can change.

ts
amplitude.setUserId("user-12345");

The new user ID applies to every later event and persists in the cookie. User IDs and device IDs must be at least five characters, or Amplitude rejects the event. To allow shorter IDs, set minIdLength in init().

If you know the user ID at page load, pass it to init() instead, so the first autocaptured events carry it:

ts
amplitude.init("YOUR_API_KEY", "user-12345");

Reset identity when a user signs out

Call reset() when a user signs out. It sets the user ID to undefined and generates a new device ID, so later activity on this browser doesn't merge into the signed-out user.

ts
amplitude.reset();

reset() doesn't start a new session, clear user properties on Amplitude's servers, or change opt-out. Plugins can react to it through their onReset() hook.

Set the device ID

The SDK generates a random UUID as the device ID. Set your own only when you already have a stable anonymous identifier, for example one shared with your server or a mobile app.

ts
amplitude.setDeviceId("2f9d6a1e-4b7c-4f0e-9a51-0c3e8b7d5a12");

Use a value that's unique per device and at least five characters long. Two browsers with the same device ID merge into one user in Amplitude.

Read and update identity together

getIdentity() returns the current device ID, user ID, and the user properties the SDK tracked in this page load. Requires Browser SDK 2.18.0 or later.

ts
const { deviceId, userId, userProperties } = amplitude.getIdentity();

setIdentity() updates any combination of the three. When you include userProperties, the SDK sends an $identify event that sets each key with $set. setIdentity() requires Browser SDK 2.35.0 or later.

ts
amplitude.setIdentity({
  userId: "user-12345",
  userProperties: { plan: "pro" },
});

setIdentity() doesn't unset properties you leave out of userProperties. To remove a user property, send new amplitude.Identify().unset("key").

userProperties reflects only the $set, $unset, and $clearAll operations sent from this page load. It doesn't read user properties from Amplitude's servers.

How sessions work

A session groups the events a user triggers in one visit. Its ID is the Unix timestamp, in milliseconds, of the session's first event.

  • The SDK starts a new session when an event arrives more than sessionTimeout after the previous event. The default timeout is 30 minutes.
  • Sessions continue across page loads and tabs on the same domain, because the last event time lives in the cookie.
  • With session autocapture on (the default), the SDK sends session_start at the start of each session and session_end at the end of the previous one. Amplitude shows them as [Amplitude] Start Session and [Amplitude] End Session. The SDK sends session_end when the next session starts, not when the user leaves.
  • With autocapture.attribution.resetSessionOnNewCampaign set to true, a new campaign also starts a new session.

To change the timeout, set sessionTimeout in milliseconds:

ts
amplitude.init("YOUR_API_KEY", {
  sessionTimeout: 60 * 60 * 1000, // 1 hour
});

For how Amplitude counts session length and session metrics, go to Track sessions.

Keep a session alive without an event

extendSession() updates the last activity time without sending an event. Use it for activity the SDK can't observe, such as a user watching a long video.

ts
amplitude.extendSession();

Start a session with a specific ID

setSessionId() ends the current session and starts one with the ID you pass. Pass a Unix timestamp in milliseconds.

ts
amplitude.setSessionId(Date.now());

With session autocapture on, the SDK treats the ID as the session's last activity time. If you pass an ID that isn't a recent timestamp, the next event looks more than sessionTimeout late, and the SDK replaces your ID with a new session. setSessionId() does nothing if the ID equals the current session ID.

Track users across domains

The AMP_ cookie covers one registrable domain and its subdomains, such as www.example.com and app.example.com. To keep one anonymous user and session across two different domains, such as example.com and example-shop.com, pass the identifiers in the link URL. The ampDeviceId and ampSessionId parameters require Browser SDK 2.8.0 or later.

  1. On the source domain, read the current IDs and add them to the link:

    ts
    const url = new URL("https://www.example-shop.com/cart");
    url.searchParams.set("ampDeviceId", amplitude.getDeviceId() ?? "");
    url.searchParams.set("ampSessionId", String(amplitude.getSessionId()));
    url.searchParams.set("ampTimestamp", String(Date.now() + 60_000));
    window.location.assign(url.toString());
    
  2. On the destination domain, initialize the SDK without deviceId or sessionId options. The SDK reads the parameters automatically.

    ts
    amplitude.init("YOUR_API_KEY");
    

ampTimestamp limits how long the link works. The SDK uses ampDeviceId and ampSessionId only while ampTimestamp is later than the current time. Without ampTimestamp, the parameters never expire, so a shared or bookmarked link can merge unrelated visitors into one device. ampTimestamp requires Browser SDK 2.21.1 or later.

Opt users out of tracking

setOptOut(true) stops the SDK from tracking or uploading events for this browser. The setting persists in the AMP_ cookie.

ts
amplitude.setOptOut(true);

// Later, after the user consents:
amplitude.setOptOut(false);

While opt-out is on:

  • Every tracking call resolves immediately with code 0 and Event skipped due to optOut config.
  • The SDK doesn't start sessions. If init() runs while opted out, the SDK defers the session and starts it when you call setOptOut(false).
  • Page view and attribution tracking start when opt-out turns off.

To start opted out until a user consents, pass optOut: true to init(). For consent banners, deferred initialization, and cookie-free storage, go to Cookies and consent management.

Choose where the SDK stores identity

identityStorage controls where the SDK keeps the device ID, user ID, session ID, and opt-out flag.

ts
amplitude.init("YOUR_API_KEY", {
  identityStorage: "localStorage",
});

By default, the SDK writes the cookie on the highest domain it can, such as .example.com, so subdomains share identity. It finds that domain by writing and deleting an AMP_TLDTEST cookie at each level. To pin the domain or change other cookie attributes, set cookieOptions. Go to Cookie options.

Autocapture

Autocapture is the set of plugins Browser SDK 2 installs during init() to track common browser events without code. You control them with the autocapture option, and your Amplitude project's remote configuration can override your settings per feature. For a general introduction, go to Autocapture.

Choose a starting point

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    elementInteractions: true,
    fileDownloads: false,
    pageViews: { trackHistoryChanges: "pathOnly" },
  },
});

In a Chrome extension, the SDK turns off the default set. Set each feature you want to true. This default changed in 2.42.1.

autocapture replaces the deprecated defaultTracking option. If you set both, autocapture wins.

Features and events

For every sub-option and default, go to Autocapture options in the configuration reference.

Remote configuration overrides local settings

By default, init() fetches your project's remote configuration from Amplitude before it installs plugins. You edit remote configuration in Data > Settings > Autocapture. For each feature that remote configuration sets, its value replaces yours. Features it doesn't set keep your local value. Remote configuration requires Browser SDK 2.10.0 or later, and its default changed to on in 2.16.1.

ts
// Local configuration
amplitude.init("YOUR_API_KEY", {
  autocapture: { pageViews: true, elementInteractions: true },
});

// Remote configuration: elementInteractions off, frustrationInteractions on
// Result: pageViews on, elementInteractions off, frustrationInteractions on

Remote configuration can turn on a feature even when you set autocapture: false. To make local settings final, turn off the fetch:

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: false,
  remoteConfig: { fetchRemoteConfig: false },
});

The fetch goes to https://sr-client-cfg.amplitude.com/config (or sr-client-cfg.eu.amplitude.com for EU). The SDK caches the response in the browser and applies whichever arrives first, the cache or the network. If an ad blocker or a Content Security Policy blocks the request, the SDK uses the cached copy, or your local settings when no cache exists. To route it through your own server, set remoteConfig.serverUrl (Browser SDK 2.28.0 or later).

Marketing attribution

Attribution reads UTM parameters, click IDs, and the referrer when the page loads. It records them in two independent ways, controlled by attribution.trackingMethod. Both run by default. The eventProperty method requires Browser SDK 2.40.0 or later, and the default changed to both methods in 2.45.0.

The SDK reads these parameters: utm_source, utm_medium, utm_campaign, utm_term, utm_content, utm_id, referrer, referring_domain, dclid, fbclid, gbraid, gclid, ko_click_id, li_fat_id, msclkid, rdt_cid, ttclid, twclid, and wbraid.

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    attribution: {
      trackingMethod: "userProperty",
      excludeReferrers: [/example\.com$/, "checkout.partner.com"],
      resetSessionOnNewCampaign: true,
    },
  },
});

These options apply only to userProperty tracking:

  • excludeReferrers ignores campaigns from matching referring domains. By default it excludes your own domain and its subdomains. Setting it replaces the default, so include your own domain.
  • excludeInternalReferrers ignores referrers on the same domain as the page. Set true (or { condition: "always" }) to always ignore them, or { condition: "ifEmptyCampaign" } to ignore them only when the URL has no UTM parameters or click IDs. Requires Browser SDK 2.36.0 or later.
  • initialEmptyValue is the value for initial_* properties that have no campaign value. The default is "EMPTY".
  • resetSessionOnNewCampaign starts a new session when the campaign changes.

fallbackAttributionEvent applies only to eventProperty tracking. Set it to true to send an [Amplitude] Attribution event on every page view, so campaign data arrives even if the user triggers no other event.

Single-page apps lose campaign context

In a single-page app, document.referrer doesn't change after the first load, and routers often strip the query string. Two consequences:

  • userProperty tracking reads the campaign only during init(). A campaign that appears later through pushState doesn't update user properties.
  • eventProperty tracking replaces the campaign on each navigation. After a user moves from /?utm_source=newsletter to /pricing, later events have no utm_source, but they keep the original referrer.

Initialize the SDK before your router rewrites the URL, and keep campaign parameters on server-side redirects. To drop the referrer after the landing page, add an enrichment plugin:

ts
const landingUrl = location.href;

amplitude.add({
  name: "drop-referrer-after-landing",
  execute: async (event) => {
    if (location.href !== landingUrl && event.event_properties) {
      delete event.event_properties.referrer;
      delete event.event_properties.referring_domain;
    }
    return event;
  },
});

Page views

The SDK sends [Amplitude] Page Viewed when it initializes, and again when the URL changes through history.pushState() or the popstate event (back, forward, and hash changes). history.replaceState() doesn't trigger a page view.

Multi-step forms

A multi-step form that updates in place without changing the URL produces one page view. To track each step, add a hash to the URL for each step, for example with Google Tag Manager.

Each page view includes:

Options:

  • trackOn controls when to send page views. Omit it to send on every load and URL change. Set "attribution" to send a page view only when attribution sends a campaign. Set a function that returns true to send.
  • trackHistoryChanges controls which URL changes count. The default sends a page view on any change to the URL, including the query string and hash. Set "pathOnly" to ignore changes that keep the same origin and path.
  • eventType renames the event.
ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    pageViews: {
      trackOn: () => location.pathname.startsWith("/app"),
      trackHistoryChanges: "pathOnly",
    },
  },
});

To add your own properties to page view events, use an enrichment plugin. For a working example, go to page-view-tracking-enrichment on GitHub.

Page titles in single-page apps

The SDK reads document.title right after pushState() returns. Routers in Angular, SvelteKit, React Router, and others often set the title after the URL changes, so the page view records the previous page's title. To fix this, turn off page views and track them from your router after it sets the title:

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: { pageViews: false },
});

// Call from your router's navigation-end hook, after the title updates.
function trackPageView() {
  amplitude.track("[Amplitude] Page Viewed", {
    "[Amplitude] Page Domain": location.hostname,
    "[Amplitude] Page Location": location.href,
    "[Amplitude] Page Path": location.pathname,
    "[Amplitude] Page Title": document.title,
    "[Amplitude] Page URL": location.href.split("?")[0],
  });
}

Page views you track yourself don't include [Amplitude] Page Counter or [Amplitude] Page View ID.

Sessions

The SDK sends session_start when a session begins and session_end for the previous session when the next one begins. Amplitude displays them as [Amplitude] Start Session and [Amplitude] End Session. With sessions: false, the SDK still assigns session IDs to events. For session rules, go to Identity and sessions.

Form interactions

The SDK tracks <form> elements:

  • [Amplitude] Form Started on the first change to any field in the form.
  • [Amplitude] Form Submitted on submit. If the user submits without changing a field, the SDK sends Form Started first.

Both events include [Amplitude] Form ID, [Amplitude] Form Name, and [Amplitude] Form Destination (the form's action URL).

Forms with the novalidate attribute fire submit even when the input is invalid. To decide which submits count, pass shouldTrackSubmit (Browser SDK 2.34.0 or later):

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    formInteractions: {
      shouldTrackSubmit: (event) =>
        (event.target as HTMLFormElement).checkValidity(),
    },
  },
});

File downloads

The SDK sends [Amplitude] File Downloaded when a user clicks an <a> element whose URL path ends in one of these extensions: pdf, xls, xlsx, doc, docx, txt, rtf, csv, exe, key, pps, ppt, pptx, 7z, pkg, rar, gz, zip, avi, mov, mp4, mpg, mpeg, wmv, mid, midi, mp3, wav, or wma. It watches links added after load too.

Properties: [Amplitude] File Extension, [Amplitude] File Name (the URL path), [Amplitude] Link ID, [Amplitude] Link Text, and [Amplitude] Link URL.

Page URL enrichment

Page URL enrichment adds page context to every event, including custom ones: [Amplitude] Page Domain, [Amplitude] Page Location, [Amplitude] Page Path, [Amplitude] Page Title, [Amplitude] Page URL, [Amplitude] Previous Page Location, and [Amplitude] Previous Page Type. It doesn't overwrite a property the event already has. For details, go to Page URL enrichment plugin. Requires Browser SDK 2.22.0 or later, and the default changed to on in 2.29.0.

If you turn off Autocapture, you can still add the plugin yourself:

ts
import { pageUrlEnrichmentPlugin } from "@amplitude/plugin-page-url-enrichment-browser";

amplitude.add(pageUrlEnrichmentPlugin());
amplitude.init("YOUR_API_KEY", { autocapture: false });

Element interactions

Element interactions send [Amplitude] Element Clicked and [Amplitude] Element Changed for interactive elements. Visual labeling and Zoning Insights depend on these events. For the data collected and how text masking works, go to Autocapture privacy and security.

By default the SDK tracks clicks and changes on a, button, input, select, textarea, label, video, audio, [contenteditable="true"], [data-amp-default-track], and .amp-default-track. It also tracks clicks on div, span, and h1 through h6 when the click changes the DOM or navigates.

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

amplitude.init("YOUR_API_KEY", {
  autocapture: {
    elementInteractions: {
      cssSelectorAllowlist: [
        ...amplitude.Types.DEFAULT_CSS_SELECTOR_ALLOWLIST,
        ".track-me",
      ],
      pageUrlExcludelist: [/\/admin\//],
      dataAttributePrefix: "data-analytics-",
    },
  },
});
  • cssSelectorAllowlist replaces the default list. Spread DEFAULT_CSS_SELECTOR_ALLOWLIST to extend it. Import it as amplitude.Types.DEFAULT_CSS_SELECTOR_ALLOWLIST from @amplitude/analytics-browser; @amplitude/plugin-autocapture-browser doesn't export it.
  • actionClickAllowlist replaces the div, span, and heading list for clicks that change the page. Set [] when you narrow cssSelectorAllowlist, so only your selectors count.
  • pageUrlAllowlist and pageUrlExcludelist limit tracking by page URL. The exclude list wins.
  • shouldTrackEventResolver decides per element. When you set it, the SDK ignores the allowlists.
  • dataAttributePrefix captures matching data- attributes as properties. The default is data-amp-track-, so data-amp-track-plan="pro" becomes the plan property.
  • maskTextRegex masks text that matches your patterns, in addition to the SDK's built-in masking.
  • shadowDomEnabled (experimental) captures interactions inside open shadow roots, up to maxShadowDomDepth boundaries (default 1, maximum 10). After it turns on, it stays on until the next full page load.

Event properties include [Amplitude] Element ID, [Amplitude] Element Class, [Amplitude] Element Tag, [Amplitude] Element Text (clicks only), [Amplitude] Element Href (clicks only), [Amplitude] Element Position Left, [Amplitude] Element Position Top, [Amplitude] Element Hierarchy, [Amplitude] Element Path (a CSS selector for the element), [Amplitude] Element Attributes, [Amplitude] Element Aria Label, [Amplitude] Element Parent Label, [Amplitude] Viewport Height, [Amplitude] Viewport Width, [Amplitude] Page URL, and [Amplitude] Page Title.

Frustration interactions

frustrationInteractions: true turns on rage clicks and dead clicks. Error clicks and thrashed cursor are off until you turn them on individually. Frustration interactions require Browser SDK 2.24.0 or later.

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    frustrationInteractions: {
      rageClicks: true,
      deadClicks: { cssSelectorAllowlist: ["button", "a"] },
      errorClicks: true,
      thrashedCursor: { directionChanges: 12, threshold: 1500 },
    },
  },
});

Dead clicks and error clicks use the interactive-element lists DEFAULT_DEAD_CLICK_ALLOWLIST and DEFAULT_ERROR_CLICK_ALLOWLIST unless you set cssSelectorAllowlist. For the selectors, go to frustration-interactions.ts on GitHub.

Each signal also accepts pageUrlAllowlist, pageUrlExcludelist, shouldTrackEventResolver, dataAttributePrefix, and maskTextRegex at the frustrationInteractions level.

Network tracking

Network tracking sends [Amplitude] Network Request for fetch and XMLHttpRequest calls. By default it captures only responses with status 500 through 599, and it ignores requests to Amplitude. Requires Browser SDK 2.17.0 or later.

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    networkTracking: {
      ignoreHosts: ["*.example-cdn.com"],
      captureRules: [
        { statusCodeRange: "400-599" },
        {
          urls: [/https:\/\/api\.example\.com\/orders/],
          methods: ["POST"],
          statusCodeRange: "0,200-599",
          responseHeaders: true,
          responseBody: { allowlist: ["order/id", "order/status"] },
        },
      ],
    },
  },
});

The SDK checks captureRules from last to first and applies the first rule that matches the URL, so put specific rules after general ones. Each rule accepts:

  • urls (string or RegExp, supports *) or the older hosts. Omit both to match every URL.
  • methods, for example ["POST", "PUT"]. Default: all.
  • statusCodeRange, a comma-separated list of codes and ranges. Default: "500-599". 0 matches requests that failed without a response.
  • requestHeaders and responseHeaders: true captures a fixed set of non-sensitive headers, such as content-type and cache-control. An array captures exactly the names you list.
  • requestBody and responseBody: JSON bodies only. allowlist lists JSON pointers to keep (* matches one key, ** any depth). excludelist removes keys the allowlist matched. The SDK captures no body content unless you set an allowlist.

For example, with this body:

json
{ "a": "A", "b": { "c": "C", "d": { "e": "E", "f": "F" } }, "g": "G" }

Event properties: [Amplitude] URL (with sensitive parts masked), [Amplitude] URL Query, [Amplitude] URL Fragment, [Amplitude] Request Method, [Amplitude] Status Code, [Amplitude] Error Code, [Amplitude] Error Message, [Amplitude] Start Time, [Amplitude] Completion Time, [Amplitude] Duration, [Amplitude] Request Body Size, [Amplitude] Response Body Size, and, when configured, [Amplitude] Request Body, [Amplitude] Response Body, [Amplitude] Request Headers, and [Amplitude] Response Headers.

Web vitals

Web vitals sends one [Amplitude] Web Vitals event per page load, when the tab first becomes hidden. It includes [Amplitude] LCP, [Amplitude] FCP, [Amplitude] INP, [Amplitude] CLS, and [Amplitude] TTFB when the browser reports them, plus the page domain, location, path, title, and URL. For metric definitions, go to web.dev: LCP, FCP, INP, CLS, and TTFB. Requires Browser SDK 2.20.0 or later.

In single-page apps, set webVitals: { reportSoftNav: true } (experimental) to also send one event per soft navigation. This requires the Soft Navigations API (Chromium 151 and later). Other browsers report only the initial load.

Performance tracking

Performance tracking sends [Amplitude] Main Thread Block when the main thread stays busy for at least 100 ms. It uses the Long Animation Frames API where available and falls back to Long Tasks. autocapture: true doesn't turn it on. Requires Browser SDK 2.41.0 or later.

ts
amplitude.init("YOUR_API_KEY", {
  autocapture: {
    performanceTracking: {
      mainThreadBlock: { durationThreshold: 200 },
    },
  },
});

Data delivery

Browser SDK 2 doesn't send each event as it's tracked. It saves events to a queue in localStorage, uploads them in batches, and retries failed uploads. This section covers each setting that changes that behavior. The defaults suit most sites. Change them when events go missing on navigation, when a network blocks Amplitude's domain, or when you need a specific data region.

How the SDK uploads events

  1. track() adds the event to an in-memory queue and writes the queue to localStorage under AMP_unsent_ plus the first 10 characters of your API key.
  2. flushIntervalMillis (default 1000) after the first event enters the queue, the SDK sends the whole queue, split into requests of up to flushQueueSize (default 30) events. Requests go out one at a time to keep events in order. A full queue doesn't trigger an early upload.
  3. On a 200 response, the SDK removes the events from the queue and storage.
  4. On a failure, the SDK retries. After network errors and 5xx responses, the wait grows by 1 second with each attempt. Throttled events (429) wait 30 seconds. A 413 halves flushQueueSize. After flushMaxRetries (default 5) attempts, the SDK drops the event.
  5. On the next page load, the SDK sends any events still in localStorage.

localStorage holds at most 1,000 unsent events. If the queue grows past that, for example during a long offline period, the SDK logs Failed to save N events because the queue length exceeded 1000 and doesn't persist the extra events. If localStorage isn't available, the SDK keeps the queue in memory only and logs a warning.

ts
amplitude.init("YOUR_API_KEY", {
  flushIntervalMillis: 5000,
  flushQueueSize: 50,
  flushMaxRetries: 3,
});

To send the queue now, call flush(). It sends every queued event once, without retries.

ts
await amplitude.flush().promise;

Tune upload performance

track() doesn't wait for the network. The SDK queues the event and uploads in the background, so most tuning is a tradeoff between request count and delay:

  • Fewer requests: raise flushIntervalMillis. Events wait longer before they upload. If the page closes first, they stay in localStorage until the user's next visit.
  • Faster delivery: lower flushIntervalMillis. The SDK sends more, smaller requests.
  • Larger requests: raise flushQueueSize when a single flush often holds more than 30 events. Each request carries more events, so a busy queue needs fewer requests. If a request is too large, Amplitude returns 413 and the SDK halves flushQueueSize.
  • High-volume sources: set useBatch: true to send to the Batch Event Upload API, which has higher rate limits. It doesn't reduce the number of requests.

For current bundle size, check the npm package page or BundlePhobia.

Choose a data region

Set serverZone to the data center of your Amplitude organization. The default is US.

ts
amplitude.init("YOUR_API_KEY", {
  serverZone: "EU",
});

useBatch: true switches to the Batch Event Upload API (/batch), which has higher rate limits for high-volume sources. It doesn't change how the SDK batches events in the browser.

Allow Amplitude in a Content Security Policy

If your site sends a Content-Security-Policy header, allow Amplitude's domains:

text
script-src  https://*.amplitude.com;
connect-src https://*.amplitude.com;

You need script-src only when you load the SDK from Amplitude's CDN with the script loader. connect-src covers event uploads, remote configuration, and SDK diagnostics. If you proxy all traffic through your own domain, allow that domain instead.

Send events when the page unloads

Browsers cancel in-flight requests when a page unloads, so you can lose events tracked right before a navigation, such as a login that redirects.

The default fetch transport sets keepalive on requests with bodies of 16 KB or less, so the browser finishes them after the page unloads. Keepalive keeps compression, custom headers, responses, and retries. Browsers share a 64 KB keepalive budget across all in-flight requests on a page, which is why the SDK sends larger bodies without it. The SDK measures the body after compression. If the browser rejects a keepalive request because the budget is full, the SDK retries on the next flush. Browsers that don't support keepalive ignore the flag and send a normal request.

For bodies larger than 16 KB, switch to the beacon transport when the page hides:

ts
window.addEventListener("pagehide", () => {
  amplitude.setTransport("beacon");
  amplitude.flush();
});

sendBeacon hands the request to the browser and returns immediately. It has these limits:

  • No response, so the SDK can't retry failures. It treats a request the browser accepts as successful.
  • No custom headers, so no compression.
  • No ordering guarantee between requests.

To turn off keepalive, for example to debug a keepalive-specific failure, set enableKeepalive: false:

ts
amplitude.init("YOUR_API_KEY", {
  transport: { type: "fetch", enableKeepalive: false },
});

Choose a transport

Pass a string, or an object to set options:

ts
amplitude.init("YOUR_API_KEY", {
  transport: {
    type: "fetch",
    headers: { "X-Request-Source": "web" },
    referrerPolicy: "strict-origin-when-cross-origin",
  },
});
  • headers adds HTTP headers to each upload (fetch and xhr). The SDK always sets Content-Type and Accept, and your headers can't replace them. Custom headers make the request non-simple, so the server must answer a CORS preflight. Amplitude's endpoints do. Check your proxy. Requires Browser SDK 2.33.0 or later.
  • referrerPolicy sets the fetch referrer policy for uploads. Requires Browser SDK 2.44.0 or later.
  • enableKeepalive turns fetch keepalive on or off. It's on by default, a default that changed in 2.43.0.

To change the transport after init(), call setTransport().

Compress request bodies

When the browser supports CompressionStream, the SDK gzip-compresses request bodies of 2 KB or more and sets Content-Encoding: gzip. This is always on for Amplitude's endpoints. For a custom serverUrl, it's off unless you set enableRequestBodyCompression: true, because your server must accept gzip bodies. Compression requires Browser SDK 2.36.0 or later, and the default changed to on for Amplitude's endpoints in 2.42.0.

ts
amplitude.init("YOUR_API_KEY", {
  serverUrl: "https://collect.example.com/amplitude",
  enableRequestBodyCompression: true,
});

Chrome and Edge 80, Firefox 113, Safari 16.4, and later versions support CompressionStream. Older browsers send uncompressed bodies. The beacon transport never compresses.

Send events through a proxy

Ad blockers and some corporate networks block *.amplitude.com. A proxy on your own domain avoids that. Point serverUrl at the proxy, and forward each request body unchanged to the Amplitude endpoint for your region.

ts
amplitude.init("YOUR_API_KEY", {
  serverUrl: "https://collect.example.com/amplitude",
  remoteConfig: {
    serverUrl: "https://collect.example.com/amplitude-config",
  },
});

serverUrl overrides serverZone and useBatch for event uploads. remoteConfig.serverUrl routes the remote configuration fetch separately.

Your proxy must:

  • Answer OPTIONS preflight requests and return Access-Control-Allow-Origin for your site. Without it, the browser blocks the request and the console shows has been blocked by CORS policy.
  • Forward the request body and Content-Encoding header unchanged, or decompress before forwarding.
  • Forward the client's IP address, for example in X-Forwarded-For, if you want Amplitude to derive location from it. Otherwise Amplitude records the proxy's IP.
  • Return Amplitude's status code and JSON body unchanged. The SDK reads them to decide whether to retry.

For setup examples, go to Proxy requests.

Work offline

The SDK listens for the browser's online and offline events. While navigator.onLine is false, it keeps events in the queue and doesn't attempt uploads. When the browser comes back online, it uploads the queue after flushIntervalMillis. Requires Browser SDK 2.4.0 or later.

Keep flushIntervalMillis well above a few milliseconds. With a value such as 1, the upload starts almost the moment the online event fires, often before the connection settles, and Chrome can fail it with ERR_NETWORK_CHANGED. The SDK retries the failed upload.

To control connectivity yourself, for example in a webview that reports onLine incorrectly, turn off the built-in check:

ts
amplitude.init("YOUR_API_KEY", {
  offline: amplitude.Types.OfflineDisabled,
});

With OfflineDisabled, the SDK always attempts uploads and relies on retries.

Store unsent events somewhere else

storageProvider replaces localStorage for the unsent-event queue. Pass any object that implements the Storage interface (isEnabled, get, getRaw, set, remove, reset), or an in-memory store to keep events out of persistent storage:

ts
const memoryQueue = new Map<string, amplitude.Types.Event[]>();

amplitude.init("YOUR_API_KEY", {
  storageProvider: {
    isEnabled: async () => true,
    get: async (key) => memoryQueue.get(key),
    getRaw: async (key) => JSON.stringify(memoryQueue.get(key)),
    set: async (key, value) => void memoryQueue.set(key, value),
    remove: async (key) => void memoryQueue.delete(key),
    reset: async () => memoryQueue.clear(),
  },
});

With memory-only storage, events still queued when the page unloads are lost. Identity storage is separate. Go to Choose where the SDK stores identity.

これは役に立ちましたか?