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.
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.
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().
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:
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().
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.
| Method | Effect on the user property |
|---|---|
set(key, value) | Sets the value, replacing any existing value. |
setOnce(key, value) | Sets the value only if the property has no value yet. Use it for first-touch facts, such as a signup date. |
add(key, number) | Adds the number to the current numeric value. Pass a negative number to subtract. A missing property starts at 0. |
append(key, value) | Adds the value, or each item of an array, to the end of a list property. Creates the list if it doesn't exist. |
prepend(key, value) | Adds the value, or each item of an array, to the start of a list property. |
postInsert(key, value) | Like append(), but skips values the list already contains. |
preInsert(key, value) | Like prepend(), but skips values the list already contains. |
remove(key, value) | Removes the value, or each item of an array, from a list property. |
unset(key) | Removes the property from the user. |
clearAll() | Removes every user property. You can't undo it. Ignores every other operation in the same Identify object. |
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():
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.
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:
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.
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.
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.
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.
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
- The
deviceIdoption. - The
ampDeviceIdURL parameter, then the legacydeviceIdURL parameter. - The
AMP_cookie. - A cookie from the maintenance JavaScript SDK (
amp_prefix). - A new UUID.
User ID
- The
userIdargument or option. - The
AMP_cookie. - A cookie from the maintenance JavaScript SDK.
Session ID
- The
sessionIdoption. - The
ampSessionIdURL parameter. - A session deferred by opt-out.
- The
AMP_cookie, if the last event was withinsessionTimeout. 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.
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:
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.
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.
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.
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.
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
sessionTimeoutafter 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_startat the start of each session andsession_endat the end of the previous one. Amplitude shows them as[Amplitude] Start Sessionand[Amplitude] End Session. The SDK sendssession_endwhen the next session starts, not when the user leaves. - With
autocapture.attribution.resetSessionOnNewCampaignset totrue, a new campaign also starts a new session.
To change the timeout, set sessionTimeout in milliseconds:
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.
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.
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.
On the source domain, read the current IDs and add them to the link:
tsconst 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());On the destination domain, initialize the SDK without
deviceIdorsessionIdoptions. The SDK reads the parameters automatically.tsamplitude.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.
amplitude.setOptOut(true);
// Later, after the user consents:
amplitude.setOptOut(false);
While opt-out is on:
- Every tracking call resolves immediately with code
0andEvent 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 callsetOptOut(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.
| Value | Storage | Shared across subdomains | Persists after the tab closes |
|---|---|---|---|
"cookie" (default) | First-party cookie | Yes | Yes, until cookieOptions.expiration (365 days) |
"localStorage" | localStorage | No | Yes |
"sessionStorage" | sessionStorage | No | No |
"none" | Memory only | No | No, and a reload creates a new device and session |
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
autocapture value | Features on |
|---|---|
| Omitted | The default set: attribution, page views, sessions, form interactions, file downloads, and page URL enrichment. |
true | The default set, plus element interactions, frustration interactions, network tracking, and web vitals. Performance tracking stays off. |
false | None. |
| An object | The default set, with your changes. Set a feature to false to turn it off, or to true or an options object to turn it on. |
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
| Feature | Option | Default | Events |
|---|---|---|---|
| Marketing attribution | attribution | On | $identify with campaign user properties, campaign event properties, optional [Amplitude] Attribution |
| Page views | pageViews | On | [Amplitude] Page Viewed |
| Sessions | sessions | On | session_start, session_end |
| Form interactions | formInteractions | On | [Amplitude] Form Started, [Amplitude] Form Submitted |
| File downloads | fileDownloads | On | [Amplitude] File Downloaded |
| Page URL enrichment | pageUrlEnrichment | On | No event. Adds page properties to every event. |
| Element interactions | elementInteractions | Off | [Amplitude] Element Clicked, [Amplitude] Element Changed |
| Frustration interactions | frustrationInteractions | Off | [Amplitude] Rage Click, [Amplitude] Dead Click, [Amplitude] Error Click, [Amplitude] Thrashed Cursor |
| Network tracking | networkTracking | Off | [Amplitude] Network Request |
| Web vitals | webVitals | Off | [Amplitude] Web Vitals |
| Performance tracking | performanceTracking | Off | [Amplitude] Main Thread Block |
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.
// 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:
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.
| Method | What it does | Use it for |
|---|---|---|
userProperty | Sends an $identify event that sets the campaign as user properties, and sets first-touch initial_* properties once. It sends the identify at the start of a session, or mid-session when the campaign changes. It stores the last campaign in an AMP_MKTG_ cookie. The identify also unsets campaign fields that the new campaign doesn't have, such as UTM parameters, click IDs, and referrer fields. | First-touch and last-touch attribution on the user |
eventProperty | Adds the current page's campaign parameters to the event properties of every event. It updates on page load and on SPA navigation. | Multi-touch attribution with persisted properties |
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.
amplitude.init("YOUR_API_KEY", {
autocapture: {
attribution: {
trackingMethod: "userProperty",
excludeReferrers: [/example\.com$/, "checkout.partner.com"],
resetSessionOnNewCampaign: true,
},
},
});
These options apply only to userProperty tracking:
excludeReferrersignores 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.excludeInternalReferrersignores referrers on the same domain as the page. Settrue(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.initialEmptyValueis the value forinitial_*properties that have no campaign value. The default is"EMPTY".resetSessionOnNewCampaignstarts 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:
userPropertytracking reads the campaign only duringinit(). A campaign that appears later throughpushStatedoesn't update user properties.eventPropertytracking replaces the campaign on each navigation. After a user moves from/?utm_source=newsletterto/pricing, later events have noutm_source, but they keep the originalreferrer.
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:
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:
| Property | Value |
|---|---|
[Amplitude] Page Domain | location.hostname |
[Amplitude] Page Location | location.href, decoded |
[Amplitude] Page Path | location.pathname, decoded |
[Amplitude] Page Title | document.title, or ***** when the <title> element has a data-amp-mask attribute |
[Amplitude] Page URL | location.href without the query string |
[Amplitude] Page View ID | A UUID for this page view, shared with element interaction events on the page |
[Amplitude] Page Counter | The number of page views so far in this session |
| Campaign parameters | UTM parameters, click IDs, and referrer fields, when present |
Options:
trackOncontrols 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 returnstrueto send.trackHistoryChangescontrols 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.eventTyperenames the event.
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:
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 Startedon the first change to any field in the form.[Amplitude] Form Submittedon submit. If the user submits without changing a field, the SDK sendsForm Startedfirst.
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):
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:
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.
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-",
},
},
});
cssSelectorAllowlistreplaces the default list. SpreadDEFAULT_CSS_SELECTOR_ALLOWLISTto extend it. Import it asamplitude.Types.DEFAULT_CSS_SELECTOR_ALLOWLISTfrom@amplitude/analytics-browser;@amplitude/plugin-autocapture-browserdoesn't export it.actionClickAllowlistreplaces thediv,span, and heading list for clicks that change the page. Set[]when you narrowcssSelectorAllowlist, so only your selectors count.pageUrlAllowlistandpageUrlExcludelistlimit tracking by page URL. The exclude list wins.shouldTrackEventResolverdecides per element. When you set it, the SDK ignores the allowlists.dataAttributePrefixcaptures matchingdata-attributes as properties. The default isdata-amp-track-, sodata-amp-track-plan="pro"becomes theplanproperty.maskTextRegexmasks text that matches your patterns, in addition to the SDK's built-in masking.shadowDomEnabled(experimental) captures interactions inside open shadow roots, up tomaxShadowDomDepthboundaries (default1, maximum10). 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.
| Signal | Event | Definition |
|---|---|---|
| Rage click | [Amplitude] Rage Click | Four or more clicks on the same element, within 50 pixels, in one second. Tracked on any element. |
| Dead click | [Amplitude] Dead Click | A click on an interactive element that changes neither the DOM nor the URL within three seconds. |
| Error click | [Amplitude] Error Click | A click on an interactive element followed within two seconds by a JavaScript error, console error, or unhandled promise rejection. Properties include [Amplitude] Kind, [Amplitude] Message, [Amplitude] Stack, [Amplitude] Filename, [Amplitude] Line Number, [Amplitude] Column Number, and the clicked element's properties, such as [Amplitude] Element Text. |
| Thrashed cursor | [Amplitude] Thrashed Cursor | Rapid back-and-forth pointer movement: 20 direction changes (minimum 5) within 2,000 ms (maximum 4,000). The SDK counts X-axis and Y-axis direction changes separately. |
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.
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 olderhosts. 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".0matches requests that failed without a response.requestHeadersandresponseHeaders:truecaptures a fixed set of non-sensitive headers, such ascontent-typeandcache-control. An array captures exactly the names you list.requestBodyandresponseBody: JSON bodies only.allowlistlists JSON pointers to keep (*matches one key,**any depth).excludelistremoves keys the allowlist matched. The SDK captures no body content unless you set an allowlist.
For example, with this body:
{ "a": "A", "b": { "c": "C", "d": { "e": "E", "f": "F" } }, "g": "G" }
allowlist | excludelist | Captured |
|---|---|---|
["a"] | None | { "a": "A" } |
["*"] | None | { "a": "A", "g": "G" } |
["b/c"] | None | { "b": { "c": "C" } } |
["b/d/*"] | None | { "b": { "d": { "e": "E", "f": "F" } } } |
["b/**"] | None | { "b": { "c": "C", "d": { "e": "E", "f": "F" } } } |
["**/e"] | None | { "b": { "d": { "e": "E" } } } |
["b/**"] | ["b/d/f"] | { "b": { "c": "C", "d": { "e": "E" } } } |
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.
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
track()adds the event to an in-memory queue and writes the queue tolocalStorageunderAMP_unsent_plus the first 10 characters of your API key.flushIntervalMillis(default1000) after the first event enters the queue, the SDK sends the whole queue, split into requests of up toflushQueueSize(default30) events. Requests go out one at a time to keep events in order. A full queue doesn't trigger an early upload.- On a
200response, the SDK removes the events from the queue and storage. - On a failure, the SDK retries. After network errors and
5xxresponses, the wait grows by 1 second with each attempt. Throttled events (429) wait 30 seconds. A413halvesflushQueueSize. AfterflushMaxRetries(default5) attempts, the SDK drops the event. - 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.
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.
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 inlocalStorageuntil the user's next visit. - Faster delivery: lower
flushIntervalMillis. The SDK sends more, smaller requests. - Larger requests: raise
flushQueueSizewhen 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 returns413and the SDK halvesflushQueueSize. - High-volume sources: set
useBatch: trueto 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.
amplitude.init("YOUR_API_KEY", {
serverZone: "EU",
});
serverZone | Event endpoint | Remote configuration |
|---|---|---|
US | https://api2.amplitude.com/2/httpapi | https://sr-client-cfg.amplitude.com/config |
EU | https://api.eu.amplitude.com/2/httpapi | https://sr-client-cfg.eu.amplitude.com/config |
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:
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:
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:
amplitude.init("YOUR_API_KEY", {
transport: { type: "fetch", enableKeepalive: false },
});
Choose a transport
transport | API | Keepalive | Compression | Custom headers | Retries |
|---|---|---|---|---|---|
"fetch" (default) | fetch() | Yes, bodies of 16 KB or less | Yes | Yes | Yes |
"xhr" | XMLHttpRequest | No | Yes | Yes | Yes |
"beacon" | navigator.sendBeacon() | Not applicable | No | No | No |
Pass a string, or an object to set options:
amplitude.init("YOUR_API_KEY", {
transport: {
type: "fetch",
headers: { "X-Request-Source": "web" },
referrerPolicy: "strict-origin-when-cross-origin",
},
});
headersadds HTTP headers to each upload (fetchandxhr). The SDK always setsContent-TypeandAccept, 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.referrerPolicysets thefetchreferrer policy for uploads. Requires Browser SDK 2.44.0 or later.enableKeepaliveturnsfetchkeepalive 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.
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.
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
OPTIONSpreflight requests and returnAccess-Control-Allow-Originfor your site. Without it, the browser blocks the request and the console showshas been blocked by CORS policy. - Forward the request body and
Content-Encodingheader 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:
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:
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.
これは役に立ちましたか?