# Flutter SDK 4

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

- **Package:** `amplitude_flutter` ([pubdev](https://pub.dev/packages/amplitude_flutter))
- **Latest version:** 4.7.1

This is the official documentation for the Amplitude Analytics Flutter SDK. The Flutter SDK lets you send events from your Flutter application to Amplitude.

## Compatibility

Amplitude Flutter v4 bumps the Kotlin version to v1.9.22 to support the latest Gradle.

The following matrix lists the minimum support for the Amplitude Flutter SDK version.

| Amplitude Flutter | Dart | Flutter | Gradle | Android Gradle Plugin | Kotlin Gradle Plugin |
| --- | --- | --- | --- | --- | --- |
| >= 4.0.0 | >=3.3 | >=3.7 | 8.2 | 8.2.2 | 1.9.22 |

## Install the SDK

Run the following command to get the latest version of `amplitude_flutter`, add it to your `pubspec.yaml`, then retrieve dependencies:

```bash
flutter pub add amplitude_flutter
```

### iOS installation

Add `platform :ios, '13.0'` to your Podfile. Run `pod install` in the ios directory of your Flutter project to update the CocoaPods dependencies.

To enable Bitcode, follow Flutter's [documentation](https://github.com/flutter/flutter/wiki/Creating-an-iOS-Bitcode-enabled-app).

### macOS installation

Add `platform :osx, '10.15'` to your Podfile. Run `pod install` in the macos directory of your Flutter project to update the CocoaPods dependencies. Ensure your app has the `com.apple.security.network.client` entitlement to be able to send requests. Manually edit the `macos/Runner/Release.entitlements` and `macos/Runner/DebugProfile.entitlements` files to include:

```xml
	<key>com.apple.security.network.client</key>
	<true/>
```

Refer to [Flutter's documentation](https://docs.flutter.dev/platform-integration/macos/building#setting-up-entitlements) for more information.

### Web installation (optional)

The Flutter SDK uses Dart's JavaScript interoperability to enable [Browser SDK 2](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2) for Flutter Web. This requires that you make the SDK available within the global JavaScript scope. Add the following Browser SDK 2 snippet to `web/index.html` in your Flutter project:

```html
<script type="text/javascript">
  !(function () {
    "use strict";
    !(function (e, t) {
      var r = e.amplitude || { _q: [], _iq: {} };
      if (r.invoked)
        e.console &&
          console.error &&
          console.error("Amplitude snippet has been loaded.");
      else {
        var n = function (e, t) {
            e.prototype[t] = function () {
              return (
                this._q.push({
                  name: t,
                  args: Array.prototype.slice.call(arguments, 0),
                }),
                this
              );
            };
          },
          s = function (e, t, r) {
            return function (n) {
              e._q.push({
                name: t,
                args: Array.prototype.slice.call(r, 0),
                resolve: n,
              });
            };
          },
          o = function (e, t, r) {
            e[t] = function () {
              if (r)
                return {
                  promise: new Promise(
                    s(e, t, Array.prototype.slice.call(arguments)),
                  ),
                };
              !(function (e, t, r) {
                e._q.push({ name: t, args: Array.prototype.slice.call(r, 0) });
              })(e, t, Array.prototype.slice.call(arguments));
            };
          },
          i = function (e) {
            for (var t = 0; t < v.length; t++) o(e, v[t], !1);
            for (var r = 0; r < y.length; r++) o(e, y[r], !0);
          };
        r.invoked = !0;
        var c = t.createElement("script");
        ((c.type = "text/javascript"),
          (c.integrity =
            "sha384-lUDMpxCLYsnroVQqNbtcMW8an6gKOeYD+lp8pILILRV5HggRTJEm0A1BokY4ErgJ"),
          (c.crossOrigin = "anonymous"),
          (c.async = !0),
          (c.src =
            "https://cdn.amplitude.com/libs/analytics-browser-2.45.5-min.js.gz"),
          (c.onload = function () {
            e.amplitude.runQueuedFunctions ||
              console.log("[Amplitude] Error: could not load SDK");
          }));
        var a = t.getElementsByTagName("script")[0];
        a.parentNode.insertBefore(c, a);
        for (
          var p = function () {
              return ((this._q = []), this);
            },
            u = [
              "add",
              "append",
              "clearAll",
              "prepend",
              "set",
              "setOnce",
              "unset",
              "preInsert",
              "postInsert",
              "remove",
              "getUserProperties",
            ],
            l = 0;
          l < u.length;
          l++
        )
          n(p, u[l]);
        r.Identify = p;
        for (
          var d = function () {
              return ((this._q = []), this);
            },
            f = [
              "getEventProperties",
              "setProductId",
              "setQuantity",
              "setPrice",
              "setRevenue",
              "setRevenueType",
              "setReceipt",
              "setReceiptSig",
              "setCurrency",
              "setEventProperties",
            ],
            g = 0;
          g < f.length;
          g++
        )
          n(d, f[g]);
        r.Revenue = d;
        var v = [
            "getDeviceId",
            "setDeviceId",
            "getSessionId",
            "setSessionId",
            "getUserId",
            "setUserId",
            "setOptOut",
            "setTransport",
            "reset",
            "extendSession",
          ],
          y = [
            "init",
            "add",
            "remove",
            "track",
            "logEvent",
            "identify",
            "groupIdentify",
            "setGroup",
            "revenue",
            "flush",
          ];
        (i(r),
          (r.createInstance = function (e) {
            return ((r._iq[e] = { _q: [] }), i(r._iq[e]), r._iq[e]);
          }),
          (e.amplitude = r));
      }
    })(window, document);
  })();
</script>
```

> **Note:**
>
> Element interactions require Browser SDK 2.10.0 or later. Page URL enrichment requires Browser SDK 2.29.0 or later. The snippet above loads Browser SDK 2.45.5, which supports every autocapture option the Flutter SDK exposes. If you change the snippet version, update the `integrity` (SRI) hash to match that file.

## Initialize the SDK

> **Note:** Sending events
>
> This SDK uses the [HTTP V2](https://amplitude.com/docs/apis/analytics/http-v2) API and follows the same constraints for events. Make sure all events logged in the SDK contain at least one of `deviceId` (included by default) or `userId`, and follow the HTTP API's constraints on each of those fields.
>
> To prevent instrumentation issues, device IDs and user IDs must be strings with a length of 5 characters or more. If an event contains a device ID or user ID that's too short, Amplitude removes the ID value from the event. If the event doesn't have a `userId` or `deviceId` value, Amplitude may reject the upload with a 400 status. Override the default minimum length of 5 characters by setting the `minIdLength` config option.

Before you instrument your application, initialize the SDK with your Amplitude project's API key.

```dart
import 'package:amplitude_flutter/amplitude.dart';
import 'package:amplitude_flutter/configuration.dart';
import 'package:amplitude_flutter/events/base_event.dart';

class YourClass {
  Future<void> exampleForAmplitude() async {
    // Create and initialize the instance
    final Amplitude amplitude = Amplitude(Configuration(
        apiKey: 'YOUR-API-KEY',
    ));

    // Wait until the SDK is initialized
    await amplitude.isBuilt;

    // Track an event
    amplitude.track(BaseEvent(
        eventType: 'BUTTON_CLICKED',
        eventProperties: {'Hover Time': '100ms'},
    ));

    // Send events to the server
    amplitude.flush()
  }
}
```

## Configure the SDK

| Name | Description | Default Value |
| --- | --- | --- |
| `apiKey` | `String`. The apiKey of your project. | `null` |
| `flushQueueSize` | `int`. The SDK attempts to upload when the unsent event count exceeds the event upload threshold or reaches the `flushIntervalMillis` interval. | `30` |
| `flushIntervalMillis` | `int`. The amount of time the SDK waits before it attempts to upload unsent events to the server or before it reaches the `flushQueueSize` threshold. The value is in milliseconds. | `30000` |
| `instanceName` | `String`. The name of the instance. Instances with the same name share storage and identity. For isolated storage and identity, use a unique `instanceName` for each instance. | `$default_instance` |
| `optOut` | `bool`. Opt the user out of tracking. | `false` |
| `logLevel` | `LogLevel` The log level. `LogLevel.off`, `LogLevel.error`, `LogLevel.warn`, `LogLevel.log`, `LogLevel.debug` | `LogLevel.warn` |
| `minIdLength` | `int`. The minimum length for user id or device id. | `5` |
| `partnerId` | `int`. The partner id for partner integration. | `null` |
| `flushMaxRetries` | `int`. Maximum retry times. | `5` |
| `useBatch` | `bool`. Whether to use batch API. | `false` |
| `serverZone` | `ServerZone`. `ServerZone.us` or `ServerZone.eu`. The server zone Amplitude sends data to. Amplitude adjusts the server URL based on this config. | `ServerZone.us` |
| `serverUrl` | `String`. The server URL the SDK uploads events to. | `https://api2.amplitude.com/2/httpapi` |
| `minTimeBetweenSessionsMillis` | `int`. The amount of time for session timeout. The value is in milliseconds. Defaults to 300,000 (5 minutes) for iOS/Android and 1,800,000 (30 minutes) for Web. Overriding this value changes the session timeout for all platforms. This maps to `minTimeBetweenSessionsMillis` for iOS/Android and `sessionTimeout` for Web. | `300000` |
| `trackingOptions` | `TrackingOptions`. Options to control the values tracked in SDK. | `enable` |
| `autocapture` | `Autocapture`. Configures autocapture for sessions, app lifecycles, deep links, screen views, page views, element interactions, form interactions, file downloads, page URL enrichment, and marketing attribution. Use `AutocaptureDisabled()`, `AutocaptureEnabled()`, or `AutocaptureOptions()` for granular control. Refer to [Autocapture](#autocapture). | Derived from `defaultTracking` when not set explicitly |

### Configuration for Android and iOS

| Name | Description | Default Value |
| --- | --- | --- |
| ~`defaultTracking`~ (Deprecated. Use [`autocapture`](#autocapture) instead.) | `DefaultTrackingOptions`. Options to control default event tracking. When you don't set `autocapture` explicitly, the SDK derives it from `defaultTracking`. | `DefaultTrackingOptions(sessions: true)` |
| `enableCoppaControl` | `bool`. Whether to enable COPPA control for tracking options. | `false` |
| `flushEventsOnClose` | `bool`. Flush unsent events on app close. | `true` |
| `identifyBatchIntervalMillis` | `int`. The amount of time the SDK waits before it batches intercepted identify events. The value is in milliseconds. | `30000` |
| `migrateLegacyData` | `bool`. Whether to migrate maintenance Android SDK and maintenance iOS SDK data (events, user/device ID). Learn more at the configuration section of the underlying [Kotlin SDK](https://amplitude.com/docs/sdks/analytics/android/android-kotlin-sdk/#configuration) and [Swift SDK](https://amplitude.com/docs/sdks/analytics/ios/ios-swift-sdk/#configure-the-sdk). | `true` |

### Configuration for web and Android

| Name | Description | Default Value |
| --- | --- | --- |
| `deviceId` | `String`. The device ID to use for this device. If you don't provide a `deviceId`, Amplitude generates one. | `null` |

### Configuration for Android

| Name | Description | Default Value |
| --- | --- | --- |
| `locationListening` | `bool`. Whether to enable Android location service. Learn more [here](https://amplitude.com/docs/sdks/analytics/android/android-kotlin-sdk/#location-tracking). | `true` |
| `useAdvertisingIdForDeviceId` | `bool`. Whether to use advertising id as device id. Check [here](https://amplitude.com/docs/sdks/analytics/android/android-kotlin-sdk/#advertiser-id) for required module and permission. | `false` |
| `useAppSetIdForDeviceId` | `bool`. Whether to use app set id as device id. Check [here](https://amplitude.com/docs/sdks/analytics/android/android-kotlin-sdk/#app-set-id) for required module and permission. | `false` |

### Configuration for web

- **`appVersion`**

  - **Description**: `String`. Sets an app version for events tracked. This can be the version of your application. For example: "1.0.0".
  - **Default Value**: `null`
- **`cookieOptions.domain`**

  - **Description**: `String`. Sets the domain property of cookies created.
  - **Default Value**: `null`
- **`cookieOptions.expiration`**

  - **Description**: `int`. Sets expiration of cookies created in days.
  - **Default Value**: 365 days
- **`cookieOptions.sameSite`**

  - **Description**: `String`. Sets `SameSite` property of cookies created.
  - **Default Value**: `null`
- **`cookieOptions.secure`**

  - **Description**: `bool`. Sets `Secure` property of cookies created.
  - **Default Value**: `null`
- **`cookieOptions.upgrade`**

  - **Description**: `bool`. Sets upgrading from cookies created by [maintenance Browser SDK](https://amplitude.com/docs/sdks/analytics/browser/javascript-sdk). If `true`, new Browser SDK deletes cookies created by maintenance Browser SDK. If `false`, Browser SDK keeps cookies created by maintenance Browser SDK.
  - **Default Value**: `null`
- **`identityStorage`**

  - **Description**: `String`. Sets storage API for user identity. Options include cookie for `document.cookie`, `localStorage` for `localStorage`, or none to opt-out of persisting user identity.
  - **Default Value**: `cookie`
- **`userId`**

  - **Description**: `String`. Sets an identifier for the tracked user. Must have a minimum length of 5 characters unless overridden with the minIdLength option.
  - **Default Value**: `null`
- **`transport`**

  - **Description**: `String`. Sets request API to use by name. Options include `fetch` for `fetch`, `xhr` for `XMLHTTPRequest`, or `beacon` for `navigator.sendBeacon`.
  - **Default Value**: `fetch`
- **`fetchRemoteConfig`**

  - **Description**: `bool`. Whether the SDK fetches remote configuration. Review [Browser SDK 2](https://amplitude.com/docs/sdks/analytics/browser/browser-sdk-2#remote-configuration) for more information. The default depends on the Browser SDK version used. For Browser SDK 2.16.1+, the default is `true`.
  - **Default Value**: `false` (for Browser SDK = 2.16.1)

### Configure batching behavior

To support high-performance environments, the SDK sends events in batches. The `track` method queues every event in memory, and the SDK flushes events in batches in the background. Customize batch behavior with `flushQueueSize` and `flushIntervalMillis`. By default, the `serverUrl` is `https://api2.amplitude.com/2/httpapi`.

If you need to send large batches of data at once, set `useBatch` to `true`. This sets `setServerUrl` to the batch event upload API `https://api2.amplitude.com/batch`. Both the regular mode and the batch mode use the same events upload threshold and flush time intervals.

```dart
final Amplitude analytics = Amplitude(Configuration(
    apiKey: 'YOUR-API-KEY',
    flushIntervalMillis: 50000,
    flushQueueSize: 20,
));
```

### EU data residency

Configure the server zone when you initialize the client to send data to Amplitude's EU servers. The SDK sends data based on the server zone if you set it.

> **Note:**
>
> For EU data residency, the project must be set up inside Amplitude EU. You must initialize the SDK with the API key from Amplitude EU.

```dart
final Amplitude analytics = Amplitude(Configuration(
    apiKey: 'YOUR-API-KEY',
    serverZone: ServerZone.eu,
));
```

## Track

Events represent how users interact with your application. For example, "Song Played" can be an action you want to track.

```dart
amplitude.track(BaseEvent('Song Played'));
```

You can also optionally include event properties.

```dart
amplitude.track(BaseEvent('Song Played', eventProperties: {'title': 'Happy Birthday'}));
```

Refer to the [BaseEvent](https://github.com/amplitude/Amplitude-Flutter/blob/beta/lib/events/base_event.dart) interface for all available fields.

## Identify

Use Identify to set the user properties of a particular user without sending any event. The SDK supports the `set`, `setOnce`, `unset`, `add`, `append`, `prepend`, `preInsert`, `postInsert`, `remove`, and `clearAll` operations on individual user properties. Declare the operations with the provided Identify interface. You can chain multiple operations in a single Identify object, then pass the Identify object to the Amplitude client to send to the server.

> **Note:**
>
> If you send the Identify call after the event, the results of operations appear immediately in the dashboard user's profile area, but they don't appear in chart results until the SDK sends another event after the Identify call. As a result, the Identify call only affects future events. For more information, refer to [User Properties and Events](https://amplitude.com/docs/data/user-properties-and-events).

You can handle a user's identity using the identify methods. Proper use of these methods connects events to the correct user as the user moves across devices, browsers, and other platforms. Send an identify call containing those user property operations to the Amplitude server to tie a user's events to specific user properties.

```dart
final Identify identify = Identify()
    ..set('color', 'green')
amplitude.identify(identify)
```

### Clear all user properties

Use `clearAll` to remove all user properties from a user. Use `clearAll` with care because the operation is irreversible.

```dart
final Identify identify = Identify()
    ..clearAll();
amplitude.identify(identify);
```

## Autocapture

The SDK tracks sessions, app lifecycle events, deep links, screen views, page views, element interactions, form interactions, file downloads, page URL enrichment, and marketing attribution automatically without manual instrumentation. Configure this behavior with the `autocapture` parameter using `AutocaptureDisabled()`, `AutocaptureEnabled()`, or `AutocaptureOptions()`.

> **Deprecated:**
>
> `defaultTracking` and `DefaultTrackingOptions` are deprecated. Use `autocapture` instead. Existing code that passes `defaultTracking` continues to work: when you don't set `autocapture` explicitly, the SDK derives it from `defaultTracking`. If you pass both, `autocapture` takes precedence.

When you omit both `autocapture` and `defaultTracking`, the SDK enables session tracking by default. On Web, it also enables marketing attribution. Web options for page views, form interactions, file downloads, element interactions, and page URL enrichment default to off and require an explicit opt-in.

The SDK supports the following autocapture options:

| Option | Platforms | Default | Description |
| --- | --- | --- | --- |
| `sessions` | All | `true` | Session start and end events. Refer to [Track sessions](#track-sessions). |
| `appLifecycles` | iOS, Android | `false` | Application installed, updated, opened, and backgrounded events. Refer to [Track application lifecycles](#track-application-lifecycles). |
| `deepLinks` | Android | `false` | Deep link opened events. iOS doesn't map this flag. Refer to [Track deep links](#track-deep-links). |
| `screenViews` | All | `false` | Screen viewed events from Flutter route navigation. Requires `AmplitudeNavigatorObserver`. Refer to [Track screen views](#track-screen-views). |
| `pageViews` | Web | `PageViewsDisabled()` | Page view events when the browser URL changes. Opt-in. Refer to [Page views](#page-views). |
| `attribution` | Web | `AttributionOptions()` | Marketing attribution parameters from URL query strings. Refer to [Attribution](#attribution). |
| `formInteractions` | Web | `false` | Form started and form submitted events. Requires Flutter web semantics. Refer to [Track form interactions](#track-form-interactions). |
| `fileDownloads` | Web | `false` | File downloaded events. Requires Flutter web semantics. Refer to [Track file downloads](#track-file-downloads). |
| `elementInteractions` | Web | `ElementInteractionsDisabled()` | Element clicked and element changed events. Requires Flutter web semantics. Refer to [Track element interactions](#track-element-interactions). |
| `pageUrlEnrichment` | Web | `false` | Attaches page URL properties to events. Requires Browser SDK 2.29.0 or later. Refer to [Page URL enrichment](#page-url-enrichment). |

> **Note:** Web Browser SDK version
>
> Load the Amplitude Browser SDK snippet in your Flutter web app's `web/index.html`. Element interactions require Browser SDK 2.10.0 or later. Page URL enrichment requires Browser SDK 2.29.0 or later; older versions ignore the option.

### Enable autocapture

To enable all autocapture features on every platform, use `AutocaptureEnabled()`:

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureEnabled(),
  )
);
```

On iOS and Android, `AutocaptureEnabled()` enables sessions, app lifecycles, deep links, and screen views. On Web, it also enables page views, attribution, form interactions, file downloads, element interactions, and page URL enrichment. Screen views still require you to attach `AmplitudeNavigatorObserver`. DOM-based web options also require the Flutter web semantics tree. Refer to [Track screen views](#track-screen-views) and [Flutter web DOM capture](#flutter-web-dom-capture).

### Disable autocapture

To disable all autocapture features, use `AutocaptureDisabled()`:

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureDisabled(),
  )
);
```

### Configure autocapture

Use `AutocaptureOptions` for granular control:

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureOptions(
      sessions: true,
      appLifecycles: true,
      deepLinks: true,
      screenViews: true,
      pageViews: PageViewsOptions(
        trackHistoryChanges: 'pathOnly',
        eventType: '[Amplitude] Page Viewed',
      ),
      attribution: AttributionOptions(
        excludeReferrers: ['example.com'],
        initialEmptyValue: 'NONE',
        resetSessionOnNewCampaign: true,
      ),
      formInteractions: true,
      fileDownloads: true,
      elementInteractions: ElementInteractionsOptions(),
      pageUrlEnrichment: true,
    ),
  )
);
```

> **Warning:**
>
> Amplitude may add more autocapture events in a future version, and `AutocaptureEnabled()` enables tracking for those events.

### Track sessions

When you set `sessions` to `true`, Amplitude tracks session start and session end events. When you set `sessions` to `false`, Amplitude tracks `sessionId` only.

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureOptions(
      sessions: true,
    )
  )
);
```

### Track application lifecycles

When you set `appLifecycles` to `true`, Amplitude tracks application lifecycle events on iOS and Android.

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureOptions(
      appLifecycles: true,
    )
  )
);
```

After you enable this setting, Amplitude tracks the following events:

- `[Amplitude] Application Installed`: fires when a user opens the application for the first time right after installation.
- `[Amplitude] Application Updated`: fires when a user opens the application after updating it.
- `[Amplitude] Application Opened`: fires when a user launches or foregrounds the application after the first open.
- `[Amplitude] Application Backgrounded`: fires when a user backgrounds the application.

Tracked event properties include: `[Amplitude] Version`, `[Amplitude] Build`, `[Amplitude] Previous Version`, `[Amplitude] Previous Build`, `[Amplitude] From Background`.

### Track deep links

> **Note:**
>
> Deep link tracking is available on Android only. The iOS native SDK doesn't expose deep links as an autocapture option, so the Flutter SDK ignores the `deepLinks` flag on iOS.

When you set `deepLinks` to `true`, Amplitude tracks events related to deep links in your Android application.

```dart
Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureOptions(
      deepLinks: true,
    )
  )
);
```

After you enable this setting, Amplitude tracks the `[Amplitude] Deep Link Opened` event with the URL and referrer information. Tracked event properties include: `[Amplitude] Link URL`, `[Amplitude] Link Referrer`.

### Track screen views

A Flutter app runs inside a single native surface, so the native SDKs' screen view autocapture can't observe Flutter route navigation. Enable `screenViews` and attach an `AmplitudeNavigatorObserver` to your app's `navigatorObservers`:

```dart
import 'package:amplitude_flutter/observers/amplitude_navigator_observer.dart';

final Amplitude analytics = Amplitude(
  Configuration(
    apiKey: 'YOUR-API-KEY',
    autocapture: AutocaptureOptions(
      screenViews: true,
    ),
  ),
);

MaterialApp(
  navigatorObservers: [AmplitudeNavigatorObserver(analytics)],
  // ...
);
```

You must both enable `screenViews` and attach the observer. The observer emits `[Amplitude] Screen Viewed` with `[Amplitude] Screen Name` from the route name on push, replace, and pop, on every platform including Web.

Screen names come from `RouteSettings.name`. Give your routes names with named routes, `RouteSettings(name: ...)`, or a router such as go\_router. The observer skips routes with no name, and debug builds log why. Pass a custom `nameExtractor` to derive names differently, or a custom `routeFilter` to include or exclude routes.

On Web, `pageViews` and screen views are independent. A Flutter route change doesn't necessarily change the browser URL, so the observer captures navigations that URL-based `pageViews` miss. If you enable both, a URL-changing navigation records both `[Amplitude] Page Viewed` and `[Amplitude] Screen Viewed`. `pageViews` defaults off, so screen views are the single navigation event unless you opt back into `pageViews`.

### Page views

Configure page view tracking on Web with `PageViewsOptions`. Page views default to off so Flutter navigation doesn't double-count as both a screen view and a page view.

| Option | Type | Description | Default |
| --- | --- | --- | --- |
| `trackHistoryChanges` | `String` | Track page views on navigation changes. Options: `'all'` (track all URL changes including fragments) or `'pathOnly'` (track only path changes). | `'all'` |
| `eventType` | `String` | Custom event type for page view events. If not set or set to `''` (empty string), defaults to `'[Amplitude] Page Viewed'`. | `''` |

```dart
autocapture: AutocaptureOptions(
  pageViews: PageViewsOptions(
    trackHistoryChanges: 'pathOnly',
    eventType: 'Page View',
  ),
)
```

To disable page view tracking, use `PageViewsDisabled()`:

```dart
autocapture: AutocaptureOptions(
  pageViews: PageViewsDisabled(),
)
```

### Attribution

Configure marketing attribution tracking on Web with `AttributionOptions`:

| Option | Type | Description | Default |
| --- | --- | --- | --- |
| `excludeReferrers` | `List<String>` | List of referrer domains to exclude from attribution tracking. | `null` |
| `initialEmptyValue` | `String` | Value to represent undefined initial campaign parameters for first-touch attribution. | `'EMPTY'` |
| `resetSessionOnNewCampaign` | `bool` | Start a new session when campaign parameters change. | `false` |

```dart
autocapture: AutocaptureOptions(
  attribution: AttributionOptions(
    excludeReferrers: ['example.com', 'internal.com'],
    initialEmptyValue: 'NONE',
    resetSessionOnNewCampaign: true,
  ),
)
```

To disable attribution tracking, use `AttributionDisabled()`:

```dart
autocapture: AutocaptureOptions(
  attribution: AttributionDisabled(),
)
```

### Flutter web DOM capture

`elementInteractions`, `formInteractions`, and `fileDownloads` rely on the Browser SDK, which only sees real DOM elements. With the default CanvasKit renderer, Flutter paints UI to a `<canvas>`, so the Browser SDK observes Flutter's accessibility semantics tree.

> **Warning:** Semantics has a real cost on Flutter web
>
> DOM-based Autocapture only works when you enable Flutter's accessibility semantics tree app-wide (for example with `SemanticsBinding.instance.ensureSemantics()`). That change adds runtime and memory overhead, and Flutter documents known side effects for apps that don't already rely on semantics. Don't enable it only for Amplitude clicks, forms, or file downloads unless you accept that tradeoff. Screen views through `AmplitudeNavigatorObserver` don't need semantics.

To capture these events after you accept the tradeoff:

1. Enable the semantics tree globally early in `main()`, for example with `SemanticsBinding.instance.ensureSemantics()`.
2. Rely on the Flutter-aware default `cssSelectorAllowlist` for element interactions, or supply your own selectors.

### Track form interactions

When you set `formInteractions` to `true` on Web, Amplitude tracks `[Amplitude] Form Started` and `[Amplitude] Form Submitted`. This option requires the Flutter web semantics tree. Refer to [Flutter web DOM capture](#flutter-web-dom-capture).

```dart
autocapture: AutocaptureOptions(
  formInteractions: true,
)
```

### Track file downloads

When you set `fileDownloads` to `true` on Web, Amplitude tracks `[Amplitude] File Downloaded`. This option requires the Flutter web semantics tree and real `<a download>` anchors, which Flutter web apps rarely render. Refer to [Flutter web DOM capture](#flutter-web-dom-capture).

```dart
autocapture: AutocaptureOptions(
  fileDownloads: true,
)
```

### Track element interactions

When you enable `elementInteractions` on Web, Amplitude tracks `[Amplitude] Element Clicked` and `[Amplitude] Element Changed`. This option requires Browser SDK 2.10.0 or later and the Flutter web semantics tree. Refer to [Flutter web DOM capture](#flutter-web-dom-capture).

Flutter emits ARIA roles such as `role="button"` rather than native HTML tags, so the Browser SDK's tag-based default allowlist doesn't match Flutter widgets. `ElementInteractionsOptions()` defaults `cssSelectorAllowlist` to a Flutter-aware set that includes those roles. Pass `cssSelectorAllowlist: null` to fall back to the Browser SDK default, or supply your own list.

| Option | Type | Description | Default |
| --- | --- | --- | --- |
| `cssSelectorAllowlist` | `List<String>` | CSS selectors that gate which elements generate click events. Pass `null` to use the Browser SDK default. | Flutter-aware default (`a`, `button`, `[role="button"]`, and related selectors) |
| `actionClickAllowlist` | `List<String>` | CSS selectors whose clicks also attribute to a matching ancestor. | `null` |
| `dataAttributePrefix` | `String` | Prefix for `data-*` attributes captured as event properties. | `null` |
| `pageUrlAllowlist` | `List<String>` | Page URLs where Amplitude tracks element interactions. String entries only. | `null` |

```dart
autocapture: AutocaptureOptions(
  elementInteractions: ElementInteractionsOptions(
    cssSelectorAllowlist: [
      'a',
      'button',
      '[role="button"]',
      '[role="link"]',
    ],
    actionClickAllowlist: ['div'],
    dataAttributePrefix: 'data-amp-track-',
  ),
)
```

To enable clicks with the Flutter-aware defaults, use `ElementInteractionsEnabled()`. To disable, use `ElementInteractionsDisabled()`.

### Page URL enrichment

When you set `pageUrlEnrichment` to `true` on Web, Amplitude attaches page URL properties to events. This option requires Browser SDK 2.29.0 or later; older versions ignore it. Enable it alongside `screenViews` or `pageViews` to enrich navigation events.

```dart
autocapture: AutocaptureOptions(
  pageUrlEnrichment: true,
  screenViews: true,
)
```

## User groups

Amplitude supports assigning users to groups and running queries, such as Count by Distinct, on those groups. If at least one member of the group has performed the specific event, the count includes the group.

For example, group your users by the organization they belong to using an 'orgId'. Joe is in 'orgId' '10', and Sue is in 'orgId' '15'. Sue and Joe both perform a certain event. You can query their organizations in the Event Segmentation Chart.

When setting groups, define a `groupType` and `groupName`. In the previous example, 'orgId' is the `groupType` and '10' and '15' are the values for `groupName`. Another example of a `groupType` could be 'sport' with `groupName` values like 'tennis' and 'baseball'.

Setting a group also sets the `groupType:groupName` as a user property and overwrites any existing `groupName` value for that user's `groupType` and the corresponding user property value. `groupType` is a string, and `groupName` can be either a string or an array of strings, where the array indicates that a user is in multiple groups.

> **Example:**
>
> If Joe is in 'orgId' '15', the `groupName` is '15'.
>
> ```dart
> // set group with a single group name
> amplitude.setGroup('orgId', '15');
> ```
>
> If Joe is in 'sport' 'tennis' and 'soccer', the `groupName` is '\["tennis", "soccer"\]'.
>
> ```dart
> // set group with multiple group names
> amplitude.setGroup('sport', ['tennis', 'soccer']);
> ```

You can also set event-level groups by passing an `Event` Object with `groups` to `track`. With event-level groups, the group designation applies only to the specific logged event and doesn't persist on the user unless you set the group explicitly with `setGroup`.

```dart
amplitude.track(BaseEvent('event type',
    eventProperties: {'event property': 'event property value'},
    groups: {'ordId': '15'}));
```

## Group identify

Use the Group Identify API to set or update the properties of particular groups. Keep these considerations in mind:

- Updates affect only future events, and don't update historical events.
- You can track up to 5 unique group types and 10 total groups.

The `groupIdentify` method accepts a group type string parameter, a group name object parameter, and an Identify object that Amplitude applies to the group.

```dart
final groupType = 'plan';
final groupName = 'enterprise';

final identify = Identify().set('key', 'value');
amplitude.groupIdentify(groupType, groupName, identify);
```

## Track revenue

Amplitude can track revenue generated by a user. Amplitude tracks revenue through distinct revenue objects, which have special fields that Amplitude's Event Segmentation and Revenue LTV charts use. Amplitude then displays revenue data in the platform automatically. Revenue objects support the following special properties, and also support user-defined properties through the `eventProperties` field.

```dart
final revenue = Revenue()
  ..productId = 'com.company.productId'
  ..price = 3.99
  ..quantity = 3;
amplitude.revenue(revenue);
```

| Name | Description |
| --- | --- |
| `productId` | Optional. String. An identifier for the product. Amplitude recommends something like the Google Play Store product ID. Defaults to `null`. |
| `quantity ` | Required. Integer. The quantity of products purchased. Note: revenue = quantity \* price. Defaults to 1. |
| `price ` | Required. Double. The price of the products purchased, and this can be negative. Note: revenue = quantity \* price. Defaults to `null`. |
| `revenueType` | Optional, but required for revenue verification. String. The revenue type (for example, tax, refund, income). Defaults to `null`. |
| `receipt` | Optional. String. The receipt identifier of the revenue. For example, "123456". Defaults to `null`. |
| `receiptSignature` | Optional, but required for revenue verification. String. Defaults to `null`. |

## Custom user ID

If your app has a login system you want to track users with, call `setUserId` at any time.

> **Note:** Sending events
>
> This SDK uses the [HTTP V2](https://amplitude.com/docs/apis/analytics/http-v2) API and follows the same constraints for events. Make sure all events logged in the SDK contain at least one of `deviceId` (included by default) or `userId`, and follow the HTTP API's constraints on each of those fields.
>
> To prevent instrumentation issues, device IDs and user IDs must be strings with a length of 5 characters or more. If an event contains a device ID or user ID that's too short, Amplitude removes the ID value from the event. If the event doesn't have a `userId` or `deviceId` value, Amplitude may reject the upload with a 400 status. Override the default minimum length of 5 characters by setting the `minIdLength` config option.

```dart
amplitude.setUserId('user@amplitude.com');
```

## Custom device ID

Assign a new device ID using `deviceId`. When you set a custom device ID, make sure the value is sufficiently unique. Amplitude recommends using a UUID.

> **Note:** Sending events
>
> This SDK uses the [HTTP V2](https://amplitude.com/docs/apis/analytics/http-v2) API and follows the same constraints for events. Make sure all events logged in the SDK contain at least one of `deviceId` (included by default) or `userId`, and follow the HTTP API's constraints on each of those fields.
>
> To prevent instrumentation issues, device IDs and user IDs must be strings with a length of 5 characters or more. If an event contains a device ID or user ID that's too short, Amplitude removes the ID value from the event. If the event doesn't have a `userId` or `deviceId` value, Amplitude may reject the upload with a 400 status. Override the default minimum length of 5 characters by setting the `minIdLength` config option.

```dart
amplitude.setDeviceId('your-unique-device-id');
```

## Reset when a user logs out

`reset` is a shortcut to anonymize users after they log out. It does the following:

- Sets `userId` to `null`.
- Sets `deviceId` to a new value based on the current configuration.

With an empty `userId` and a new `deviceId`, the current user appears as a new user in the dashboard.

```dart
amplitude.reset();
```
