
This is the official documentation for the Amplitude Analytics iOS SDK.

{% callout type="info" heading="Unified SDK" %}
Install the [Unified SDK for Swift](/docs/sdks/analytics/ios/unified-sdk) to access the Experiment SDK along with other Amplitude products (Analytics, Session Replay). The Unified SDK provides a single entry point for all Amplitude features and handles the initialization and configuration of all components.
{% /callout %}

## Install the SDK

{% tabs tabs="Swift Package Manager, CocoaPods, Carthage" %}
{% tab name="Swift Package Manager" %}

1.  Navigate to _File > Swift Package Manager > Add Package Dependency_.
2.  Enter the URL `https://github.com/amplitude/Amplitude-Swift` in the search bar.
3.  Select a specific version or let Xcode resolve to the latest version automatically.
4.  Select **Next** to confirm the addition of the package as a dependency.
5.  Build your project to confirm the package integrates correctly.
{% /tab %}
{% tab name="CocoaPods" %}

1. Add the dependency to your `Podfile`:

   ```bash
   pod 'AmplitudeSwift', '~> 1.0'
   ```

2. Run `pod install` in the project directory.

{% /tab %}
{% tab name="Carthage" %}

Add the following line to your `Cartfile`.

```bash
github "amplitude/Amplitude-Swift" ~> 1.0
```

Go to the [Carthage docs](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for more information.
{% /tab %}
{% /tabs %}

## Initialize the SDK

Initialize the SDK before you instrument events. You need the API key for your Amplitude project.

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: AMPLITUDE_API_KEY,
    autocapture: .all
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.autocapture = AMPAutocaptureOptions.all;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

## Configure the SDK

{% accordion title="Configuration options" %}
| Name | Description | Default Value |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `apiKey` | The apiKey of your project. | `nil` |
| `instanceName` | 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" |
| `storageProvider` | Implements a custom `storageProvider` class from `Storage`. Not supported in Objective-C. | `PersistentStorage` |
| `logLevel` | The log level enums: `LogLevelEnum.OFF`, `LogLevelEnum.ERROR`, `LogLevelEnum.WARN`, `LogLevelEnum.LOG`, `LogLevelEnum.DEBUG` | `LogLevelEnum.WARN` |
| `loggerProvider` | Implements a custom `loggerProvider` class from the Logger, and passes it in the configuration during initialization to help collect error messages from the SDK in a production environment. | `ConsoleLogger` |
| `flushIntervalMillis` | The amount of time the SDK waits before it uploads unsent events to the server, or before it reaches the `flushQueueSize` threshold. | `30000` |
| `flushQueueSize` | The SDK uploads events when the unsent event count exceeds this threshold, or when it reaches the `flushIntervalMillis` interval. | `30` |
| `flushMaxRetries` | Maximum retry times. | `6` |
| `minIdLength` | The minimum length for user id or device id. | `5` |
| `partnerId` | The partner id for partner integration. | `nil` |
| `identifyBatchIntervalMillis` | The amount of time the SDK batches intercepted identify events. | `30000` |
| `flushEventsOnClose` | Flushes unsent events on app close. | `true` |
| `callback` | Callback function after event sent. | `nil` |
| `optOut` | Opt the user out of tracking. | `false` |
| ~`defaultTracking`~ (Deprecated. Use [`autocapture`](#autocapture) instead.) | Enable tracking of default events for sessions, app lifecycles, screen views, and deep links. | `DefaultTrackingOptions(sessions: true)` |
| `autocapture` | Enable tracking of [Autocapture events](#autocapture) for sessions, app lifecycles, screen views, deep links, network requests, and element interactions. | `AutocaptureOptions.sessions` |
| `enableAutoCaptureRemoteConfig` | Enable remote configuration for autocapture settings. When enabled, Amplitude updates Autocapture settings remotely after initialization. | `true` |
| `minTimeBetweenSessionsMillis` | The amount of time for session timeout. | `300000` |
| `serverUrl` | The server url events upload to. | `https://api2.amplitude.com/2/httpapi` |
| `serverZone` | The server zone to send to. Amplitude adjusts the server url based on this config. | `US` |
| `useBatch` | Whether to use batch api. | `false` |
| `trackingOptions` | Options to control the values tracked in SDK. | `enable` |
| `enableCoppaControl` | Whether to enable COPPA control for tracking options. | `false` |
| `migrateLegacyData` | Available in `0.4.7+`. Whether to migrate [maintenance SDK](/docs/sdks/analytics/ios/ios-sdk) data (events, user/device ID). | `true` |
| `offline` | Available in `1.2.0+`. Whether the SDK connects to a network. Learn more in [Offline mode](#offline-mode). | `false` |
| `maxQueuedEventCount` | Available in `1.9.1+`. Maximum number of events to retain in storage. When set to a positive number, the SDK removes oldest events at startup to maintain this limit. When set to -1, no cleanup occurs. | `-1` |
| `networkTrackingOptions` | Available in `1.12.0+`. Options to control the network tracking. | `NetworkTrackingOptions.default` |
| `interactionsOptions` | Available in `1.15.0+`. Options to control the interaction tracking. | `InteractionsOptions.default` |

{% /accordion %}

## Track events

Events represent how users interact with your application. For example, "Button Clicked" may be an action you want to track.

{% code-group %}
```swift Swift
let event = BaseEvent(
    eventType: "Button Clicked",
    eventProperties: ["my event prop key": "my event prop value"]
)
amplitude.track(event: event)
```

```objc Obj-C
AMPBaseEvent *event = [AMPBaseEvent initWithEventType:@"Button Clicked"
    eventProperties:@{@"my event prop key": @"my event prop value"}];

[amplitude track:event];
```
{% /code-group %}

Another way to instrument a basic tracking event:

{% code-group %}
```swift Swift
amplitude.track(
    eventType: "Button Clicked",
    eventProperties: ["my event prop key": "my event prop value"]
)
```

```objc Obj-C
[amplitude track:@"Button Clicked" eventProperties:@{
    @"my event prop key": @"my event prop value"
}];
```
{% /code-group %}

## Identify

{% callout type="note" heading="" %}
Starting from release v0.4.0, the SDK batches identify events that contain only set operations and sends them with fewer events. This change doesn't affect how the set operations run. The config `identifyBatchIntervalMillis` manages the interval to flush the batched identify intercepts.
{% /callout %}

Identify sets the user properties of a particular user without sending any event. The SDK supports the operations `set`, `setOnce`, `unset`, `add`, `append`, `prepend`, `preInsert`, `postInsert`, `remove`, and `clearAll` on individual user properties. Declare the operations through a 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.

{% callout type="note" heading="" %}
If you send the Identify call after the event, the operation results appear immediately in the dashboard user's profile area, but don't appear in chart results until you send another event after the Identify call. The Identify call only affects events going forward. For more details, refer to [User properties and events](/docs/data/user-properties-and-events).
{% /callout %}

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

{% code-group %}
```swift Swift
let identify = Identify()
identify.set(property: "color", value: "green")
amplitude.identify(identify: identify)
```

```objc Obj-C
AMPIdentify *identify = [AMPIdentify new];
[identify set:@"color" value:@"green"];
[amplitude identify:identify];
```
{% /code-group %}

### Clear all user properties

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

{% code-group %}
```swift Swift
let identify = Identify()
identify.clearAll()
amplitude.identify(identify: identify)
```

```objc Obj-C
AMPIdentify *identify = [AMPIdentify new];
[identify clearAll];
[amplitude identify:identify];
```
{% /code-group %}

## Autocapture

Starting from release v1.8.0, the SDK can track more events without manual instrumentation. Configure the SDK to track the following events automatically:

- Sessions
- App lifecycles
- Screen views
- Element interactions
- Frustration interactions
  - Rage clicks
  - Dead clicks
- Network requests

{% accordion title="Autocapture options" %}
| Name | Type | Enabled by default | Description |
| --- | --- | --- | --- |
| `sessions` | `AutocaptureOptions` | Yes | Enables session tracking. When set, Amplitude tracks session start and session end events. Otherwise, Amplitude doesn't track session events. When this setting isn't set, Amplitude tracks `sessionId` only. Refer to [Track sessions](#track-sessions) for more information. |
| `appLifecycles` | `AutocaptureOptions` | No | Enables application lifecycle event tracking. When set, Amplitude tracks application installed, application updated, application opened, and application backgrounded events. Event properties tracked include: `[Amplitude] Version`, `[Amplitude] Build`, `[Amplitude] Previous Version`, `[Amplitude] Previous Build`, `[Amplitude] From Background`. Refer to [Track application lifecycles](#track-application-lifecycles) for more information. |
| `screenViews` | `AutocaptureOptions` | No | Enables screen view tracking. When set, Amplitude tracks screen viewed events. Event properties tracked include: `[Amplitude] Screen Name`. Refer to [Track screen views](#track-screen-views) for more information. |
| `elementInteractions` | `AutocaptureOptions` | No | Enables element interaction tracking. When set, Amplitude tracks user interactions with `UIControl` elements and `UIGestureRecognizer`. Event properties tracked include: `[Amplitude] Action`, `[Amplitude] Target View Class`, `[Amplitude] Target Text`, `[Amplitude] Action Method`, `[Amplitude] Gesture Recognizer`, `[Amplitude] Hierarchy`, `[Amplitude] Accessibility Identifier`, `[Amplitude] Accessibility Label`, `[Amplitude] Screen Name`. Refer to [Track element interactions](#track-element-interactions) for more information. |
| `networkTracking` | `AutocaptureOptions` | No | Enables network tracking. When set, Amplitude tracks network requests. Event properties tracked include: `[Amplitude] URL`, `[Amplitude] URL Query`, `[Amplitude] URL Fragment`, `[Amplitude] Request Method`, `[Amplitude] Status Code`, `[Amplitude] Error Code`, `[Amplitude] Error Message`, `[Amplitude] Start Time`, `[Amplitude] End Time`, `[Amplitude] Duration`, `[Amplitude] Request Body Size`, `[Amplitude] Response Body Size`. Refer to [Track network requests](#track-network-requests) for more information. |
| `frustrationInteractions` | `AutocaptureOptions` | No | Available in `1.15.0+`. Enables frustration interaction tracking. When set, Amplitude tracks frustration interactions (Rage Clicks and Dead Clicks) with `UIControl` elements and `UIGestureRecognizer`. Rage Clicks generate the `[Amplitude] Rage Click` event and Dead Clicks generate the `[Amplitude] Dead Click` event. Go to [Track frustration interactions](#track-frustration-interactions) for more information. |

{% /accordion %}

You can configure Amplitude to start tracking Autocapture events. Otherwise, you can omit the configuration to keep only session tracking enabled.

{% tabs tabs="Swift, Obj-C" %}
{% tab name="Swift" %}
The `autocapture` configuration accepts an [`OptionSet`](https://developer.apple.com/documentation/swift/optionset){:target="\_blank"} with `AutocaptureOptions` values.

```swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: [.sessions, .appLifecycles, .screenViews, .networkTracking]
))
```

By default, if you don't explicitly set the `autocapture` configuration during `Configuration` initialization, `configuration.autocapture` automatically includes `AutocaptureOptions.sessions`.

To prevent automatic session event capture, set `autocapture` without the `AutocaptureOptions.sessions` option.

```swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .appLifecycles 	// or use `[]` to disable Autocapture.
))
```

{% /tab %}
{% tab name="Obj-C" %}
The `autocapture` configuration accepts an `Array` of `AutocaptureOptions` values.

```objc
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[
    AMPAutocaptureOptions.sessions,
    AMPAutocaptureOptions.appLifecycles,
    AMPAutocaptureOptions.screenViews,
    AMPAutocaptureOptions.networkTracking
]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```

By default, if you don't explicitly set the `autocapture` configuration during `Configuration` initialization, `configuration.autocapture` automatically includes `AutocaptureOptions.sessions`.

To prevent automatic session event capture, set `autocapture` without the `AutocaptureOptions.sessions` option.

```objc
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.appLifecycles]];   // or use an empty array to disable Autocapture.
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```

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

### Remote configuration for autocapture

Starting from release v1.10.0, the SDK supports remote configuration for autocapture settings. This feature lets you update autocapture settings after initialization without requiring an app update.

By default, Amplitude enables remote configuration for autocapture. To disable it, set `enableAutoCaptureRemoteConfig` to `false` in the configuration:

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: [.sessions, .appLifecycles, .screenViews],
    enableAutoCaptureRemoteConfig: false
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[
    AMPAutocaptureOptions.sessions,
    AMPAutocaptureOptions.appLifecycles,
    AMPAutocaptureOptions.screenViews
]];
configuration.enableAutoCaptureRemoteConfig = NO;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

When you enable remote configuration, the SDK checks for updates to Autocapture settings in your project. If the SDK finds updates, it applies them automatically. This lets you:

- Enable or disable specific autocapture features remotely.
- Change autocapture settings without requiring users to update the app.

Changes made through remote configuration affect future events and don't apply to events that Amplitude already tracked.

### Track sessions

Amplitude enables session tracking by default. Include `AutocaptureOptions.sessions` in the `autocapture` configuration to explicitly configure the SDK to track session events, or to enable session event tracking with other Autocapture configurations.

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .sessions
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.sessions]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

For more information about session tracking, refer to [User sessions](#user-sessions).

{% callout type="note" heading="" %}
`trackingSessionEvents` is deprecated. Use the `AutocaptureOptions.sessions` option of the `autocapture` configuration instead.
{% /callout %}

### Track application lifecycles

To enable Amplitude to track application lifecycle events, include `AutocaptureOptions.appLifecycles` in the `autocapture` configuration.

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .appLifecycles
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.appLifecycles]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

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

- `[Amplitude] Application Installed`: this event fires when a user opens the application for the first time after installation, by observing the `UIApplicationDidFinishLaunchingNotification` notification internally.
- `[Amplitude] Application Updated`: this event fires when a user opens the application after updating the application, by observing the `UIApplicationDidFinishLaunchingNotification` notification internally.
- `[Amplitude] Application Opened`: this event fires when a user launches or foregrounds the application after the first open, by observing the `UIApplicationDidFinishLaunchingNotification` or `UIApplicationWillEnterForegroundNotification` notification internally.
- `[Amplitude] Application Backgrounded`: this event fires when a user backgrounds the application, by observing the `UIApplicationDidEnterBackgroundNotification` notification internally.

### Track screen views

To enable Amplitude to track screen view events, include `AutocaptureOptions.screenViews` in the `autocapture` configuration.

{% callout type="warning" heading="" %}
This feature supports UIKit. For SwiftUI, track the corresponding event manually.
{% /callout %}

{% code-group %}
```swift Swift
// UIKit
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .screenViews
))

// Swift UI
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: []
))
amplitude.track(ScreenViewedEvent(screenName: "Screen Name"))
```

```objc Obj-C
// UIKit
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.screenViews]];
Amplitude *amplitude = [Amplitude initWithConfiguration:screenViews];

// Swift UI
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[]];
[amplitude track:[AMPScreenViewedEvent initWithScreenName:@"Screen Name"]];
```
{% /code-group %}

When you enable this setting, Amplitude tracks the `[Amplitude] Screen Viewed` event and sets the screen name property of this event to the name of the top-most view controller's class. Amplitude reads this value from the controller class metadata `viewDidAppear` method swizzling.

### Track network requests

To enable Amplitude to track network requests, include `AutocaptureOptions.networkTracking` in the `autocapture` configuration.

{% callout type="warning" heading="" %}
This feature doesn't work with requests sent by `URLConnection` or on watchOS and iOS 13.
{% /callout %}

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .networkTracking
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.networkTracking]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

With the default configuration, the SDK tracks network requests from all hosts (except `*.amplitude.com`) with status code `500` to `599`. To customize the tracking behavior, set `Configuration.networkTrackingOptions` with `NetworkTrackingOptions`.

{% accordion title="NetworkTrackingOptions" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `captureRules` | The rules for capturing network requests. Always append rules with specific hosts to the bottom of the list. | `none` |
| `ignoreHosts` | The hosts to ignore. Supports wildcard characters `*`. For example, `["*"]` ignores all hosts, and `["*.notmyapi.com", "notmyapi.com"]` ignores `notmyapi.com` and all subdomains. | `[]` |
| `ignoreAmplitudeRequests` | Whether to ignore Amplitude requests. | `true` |

{% /accordion %}

{% accordion title="NetworkTrackingOptions.CaptureRule" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `hosts` | The hosts to capture. Supports wildcard characters `*`. For example, `["*"]` matches all hosts, and `["*.example.com", "example.com"]` matches `example.com` and all subdomains. | `none` |
| `urls` | Experimental. Available in `1.15.0+`. The URLs to capture. Supports exact match and regex pattern. Includes query parameters and fragment identifier. For example, `URLPattern.exact("https://example.com/api/status")` matches `https://example.com/api/status`, and `URLPattern.regex("https://example.com/api/.*")` matches `https://example.com/api/status` and `https://example.com/api/error`. | `none` |
| `statusCodeRange` | The status code range to capture. Supports comma-separated ranges or single status codes. For example, `"0,200-299,413,500-599"`. | `"500-599"` |
| `methods` | Experimental. Available in `1.15.0+`. The HTTP methods to capture. Use `*` to match all methods. For example, `["POST", "PUT", "DELETE"]`. | `["*"]` |
| `requestHeaders` | Experimental. Available in `1.15.0+`. Captures request headers. | `nil` |
| `responseHeaders` | Experimental. Available in `1.15.0+`. Captures response headers. | `nil` |
| `requestBody` | Experimental. Available in `1.15.0+`. Captures fields in the request body (go to #CaptureBody). | `nil` |
| `responseBody` | Experimental. Available in `1.15.0+`. Captures fields in the response body (go to #CaptureBody). | `nil` |

{% /accordion %}

{% accordion title="NetworkTrackingOptions.CaptureHeader" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `allowlist` | Experimental. Available in `1.15.0+`. The headers to capture. Case-insensitive. | `[]` |
| `captureSafeHeaders` | Experimental. Available in `1.15.0+`. Whether to capture safe headers. | `true` |

{% callout type="note" heading="" %}
Amplitude considers `authorization`, `cookie`, and `proxy-authorization` headers sensitive and excludes them even when set to `allowlist`.
{% /callout %}

{% accordion title="Safe headers list" %}

- `access-control-allow-origin`
- `access-control-allow-credentials`
- `access-control-expose-headers`
- `access-control-max-age`
- `access-control-allow-methods`
- `access-control-allow-headers`
- `accept-patch`
- `accept-ranges`
- `age`
- `allow`
- `alt-svc`
- `cache-control`
- `connection`
- `content-disposition`
- `content-encoding`
- `content-language`
- `content-length`
- `content-location`
- `content-md5`
- `content-range`
- `content-type`
- `date`
- `delta-base`
- `etag`
- `expires`
- `im`
- `last-modified`
- `link`
- `location`
- `permanent`
- `p3p`
- `pragma`
- `proxy-authenticate`
- `public-key-pins`
- `retry-after`
- `server`
- `status`
- `strict-transport-security`
- `trailer`
- `transfer-encoding`
- `tk`
- `upgrade`
- `vary`
- `via`
- `warning`
- `www-authenticate`
- `x-b3-traceid`
- `x-frame-options`
{% /accordion %}

{% /accordion %}

{% accordion title="NetworkTrackingOptions.CaptureBody" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `allowlist` | Experimental. Available in `1.15.0+`. The fields to capture. Case-sensitive. Supports wildcards: `*` matches one level of field, `**` matches any number of levels of fields. | `[]` |
| `blocklist` | Experimental. Available in `1.15.0+`. The fields to exclude from capture. Case-sensitive. Supports wildcards: `*` matches one level of field, `**` matches any number of levels of fields. | `[]` |

{% /accordion %}

{% callout type="note" heading="" %}

- The `captureRules` and `ignoreHosts` properties are mutually exclusive. If you set both, `ignoreHosts` takes precedence.
- Amplitude matches incoming requests against the `captureRules` from bottom to top.
  For example, for the following configuration:

```swift
captureRules: [
    .init(hosts: ["*"], statusCodeRange: "400-499,500-599"),
    .init(hosts: ["*.example.com", "example.com"], statusCodeRange: "0,500-599"),
]
```

With the above configuration, the SDK processes the following requests:

- A request to `example.com` with response code 503: matches last rule's hosts, matches `statusCodeRange` filter, captured.
- A request to `example.com` with response code 401: matches last rule's hosts, doesn't match `statusCodeRange` filter, ignored.
- A request to `notmyapi.com` with response code 401: doesn't match last rule's hosts, matches first rule's hosts, matches `statusCodeRange` filter, captured.
- A request to `notmyapi.com` with response code 200: doesn't match last rule's hosts, matches first rule's hosts, doesn't match `statusCodeRange` filter, ignored.

{% /callout %}

The default configuration tracks all hosts except `*.amplitude.com` with status code `500` to `599`.

{% accordion title="NetworkTrackingOptions.default" %}
| Name | Description | Value |
| --- | --- | --- |
| `captureRules` | Captures all hosts (except _.amplitude.com) with status code 500 to 599. | `[AMPNetworkTrackingCaptureRule(hosts: ["_"], statusCodeRange: "500-599")]`|
|`ignoreHosts`| Don't ignore any other hosts by default. |`[]`|
|`ignoreAmplitudeRequests`| Don't capture Amplitude requests by default. |`true` |

{% /accordion %}

Example use:

{% code-group %}
```swift Swift
// Style 1: Use the default configuration and append a new rule
let networkTrackingOptions = NetworkTrackingOptions.default // contain a rule for all hosts, statusCodeRange: "500-599"
networkTrackingOptions.captureRules.append(
    .init(hosts: ["*.example.com", "example.com"], statusCodeRange: "0,500-599")
)
networkTrackingOptions.ignoreHosts.append("notmyapi.com")

let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .networkTracking,
    networkTrackingOptions: networkTrackingOptions,
))

// Style 2: Create a new configuration with a custom rule
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .networkTracking,
    networkTrackingOptions: .init(
        captureRules: [
            .init(hosts: ["*"]), // all hosts, statusCodeRange: "500-599"
            .init(hosts: ["*.example.com", "example.com"], statusCodeRange: "0,400-599"),
        ],
        ignoreHosts: ["notmyapi.com"]
    ),
))
```

```objc Obj-C
// Style 1: Use the default configuration and append a new rule
AMPNetworkTrackingOptions *networkTrackingOptions = AMPNetworkTrackingOptions.defaultOptions;  // contain a rule for all hosts, statusCodeRange: "500-599"
NSMutableArray<AMPNetworkTrackingCaptureRule *> *rules = [networkTrackingOptions.captureRules mutableCopy];
[rules addObject:[[AMPNetworkTrackingCaptureRule alloc] initWithHosts:@[@"*.example.com", @"example.com"] statusCodeRange:@"0,400-599"]];
networkTrackingOptions.captureRules = rules;

// Style 2: Create a new configuration with a custom rule
NSArray<AMPNetworkTrackingCaptureRule *> *rules = @[
    [[AMPNetworkTrackingCaptureRule alloc] initWithHosts: @[@"*"] statusCodeRange:@"500-599"],
    [[AMPNetworkTrackingCaptureRule alloc] initWithHosts: @[@"*.example.com", @"example.com"] statusCodeRange:@"0,400-599"]
];
AMPNetworkTrackingOptions *networkTrackingOptions = [[AMPNetworkTrackingOptions alloc] initWithCaptureRules:rules
                                                                                                ignoreHosts:@[@"notmyapi.com"]
                                                                                    ignoreAmplitudeRequests:true];

// Then use the configuration to initialize the Amplitude instance
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.networkTracking]];
configuration.networkTrackingOptions = networkTrackingOptions;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

When you enable this setting, Amplitude tracks the `[Amplitude] Network Request` event whenever the application makes a network request. The SDK swizzles URL loading system methods to instrument network activity.


{% callout type="note" heading="Experimental features" %}
Use `@_spi(NetworkTracking)` import to access the experimental properties.
{% /callout %}

{% code-group %}
```swift Swift
@_spi(NetworkTracking) import Amplitude-Swift

let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .networkTracking,
    networkTrackingOptions: .init(
        captureRules: [
            .init(hosts: ["*"]), // all hosts, statusCodeRange: "500-599"
            .init(urls: [.regex("^https://example\\.com/api/.*"), .exact("https://example.com/api2/status")],
                  methods: ["POST"],
                  statusCodeRange: "0,400-599",
                  requestHeaders: .init(allowlist: ["Link", "X-API-Key"]),
                  responseHeaders: .init(allowlist: ["Link", "X-API-Key"], captureSafeHeaders: false),
                  requestBody: .init(allowlist: ["user/*", "product/**/id"]),
                  responseBody: .init(allowlist: ["profile/**"], blocklist: ["**/password"])),
        ],
        ignoreHosts: ["notmyapi.com"],
        ignoreAmplitudeRequests: true
    ),
))
```
{% /code-group %}

{% accordion title="Event Properties Descriptions" %}
| Event property | Description |
| --- | --- |
| `[Amplitude] URL` | The URL of the network request with sensitive information masked. |
| `[Amplitude] URL Query` | The query parameters of the URL. |
| `[Amplitude] URL Fragment` | The fragment identifier of the URL. |
| `[Amplitude] Request Method` | The HTTP method used for the request (GET, POST, etc.). |
| `[Amplitude] Status Code` | The HTTP status code of the response. |
| `[Amplitude] Error Code` | The local error code if the request failed with out a status code. |
| `[Amplitude] Error Message` | The local error message if the request failed with out a status code. |
| `[Amplitude] Start Time` | The timestamp when the request started, in milliseconds since Unix epoch. |
| `[Amplitude] Completion Time` | The timestamp when the request completed, in milliseconds since Unix epoch. |
| `[Amplitude] Duration` | The duration of the request in milliseconds. |
| `[Amplitude] Request Body Size` | The size of the request body in bytes. |
| `[Amplitude] Response Body Size` | The size of the response body in bytes. |
| `[Amplitude] Request Body` | Experimental. The captured stringified JSON request body (when you configure a `requestBody` capture rule). |
| `[Amplitude] Response Body` | Experimental. The captured stringified JSON response body (when you configure a `responseBody` capture rule). |
| `[Amplitude] Request Headers` | Experimental. The captured request headers (when you configure a `requestHeaders` capture rule). |
| `[Amplitude] Response Headers` | Experimental. The captured response headers (when you configure a `responseHeaders` capture rule). |

{% /accordion %}

{% callout type="info" heading="" %}
For security purposes, the SDK automatically masks sensitive information in the URL, such as usernames and passwords.
{% /callout %}

### Track deep links

Deep link tracking isn't automated. To track deep links, track the corresponding events.

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY"
))

amplitude.track(DeepLinkOpenedEvent(url: URL()))
amplitude.track(DeepLinkOpenedEvent(url: "url", referrer:"referrer"))
amplitude.track(DeepLinkOpenedEvent(activity: activity))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];

[amplitude track:[AMPDeepLinkOpenedEvent initWithUrl:@"url"]];
[amplitude track:[AMPDeepLinkOpenedEvent initWithUrl:@"url" referrer:@"referrer"]];
[amplitude track:[AMPDeepLinkOpenedEvent initWithActivity:activity]];
```
{% /code-group %}

Amplitude tracks the `[Amplitude] Deep Link Opened` event with the URL and referrer information.

### Track element interactions

Amplitude can track user interactions with `UIControl` elements and `UIGestureRecognizer` objects in `UIKit` applications. To enable this option, include `AutocaptureOptions.elementInteractions` in the `autocapture` configuration.

{% callout type="note" heading="" %}
The `AutocaptureOptions.elementInteractions` option offers an early release version for early feedback. Share your thoughts on the Amplitude [GitHub](https://github.com/amplitude/Amplitude-Swift).
{% /callout %}

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .elementInteractions
))
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[AMPAutocaptureOptions.elementInteractions]];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

After you enable this setting, Amplitude tracks the `[Amplitude] Element Interacted` event whenever a user interacts with an element in the application. The SDK swizzles the `UIApplication.sendAction(_:to:from:for:)` method and the `UIGestureRecognizer.state` property setter to instrument `UIControl` action methods and `UIGestureRecognizer` within the application, respectively.

{% accordion title="Event Properties Descriptions" %}
| Event property | Description |
| --- | --- |
| `[Amplitude] Action` | The action that triggered the event. Defaults to `touch`. |
| `[Amplitude] Target View Class` | The name of the target view class. |
| `[Amplitude] Target Text` | The title of the target `UIControl` element. |
| `[Amplitude] Target Accessibility Label` | The accessibility label of the target element. |
| `[Amplitude] Target Accessibility Identifier` | The accessibility identifier of the target element. |
| `[Amplitude] Action Method` | The name of the function or method that triggers when the interaction occurs. |
| `[Amplitude] Gesture Recognizer` | The name of the `UIGestureRecognizer` class that recognizes the interaction. |
| `[Amplitude] Hierarchy` | A nested hierarchy of the target view's class inheritance, from the most specific to the most general. |
| `[Amplitude] Screen Name` | Refer to [Track screen views](#track-screen-views). |

{% /accordion %}

{% callout type="info" heading="" %}
Amplitude doesn't support tracking user interactions with UI elements in SwiftUI.
{% /callout %}

### Track frustration interactions

Available in version `1.15.0+`.

Amplitude can track frustration interactions (Rage Clicks and Dead Clicks) with `UIControl` elements and `UIGestureRecognizer` objects in `UIKit` applications. To enable this option, include `AutocaptureOptions.frustrationInteractions` in the `autocapture` configuration.

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .frustrationInteractions
))
```
{% /code-group %}

The `interactionsOptions` configuration accepts an `InteractionsOptions` object to configure the options for capturing rage clicks and dead clicks.

{% accordion title="InteractionsOptions" %}
| Name | Description | Default Value |
| --- | --- | --- |
| `rageClick` | The options for capturing rage clicks. | `RageClickOptions()` |
| `rageClick.enabled` | Whether to capture rage clicks. | `true` |
| `deadClick` | The options for capturing dead clicks. | `DeadClickOptions()` |
| `deadClick.enabled` | Whether to capture dead clicks. | `true` |

{% /accordion %}

{% code-group %}
```swift Swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "API_KEY",
    autocapture: .frustrationInteractions,
    interactionsOptions: .init(
        rageClick: .init(enabled: true),
        deadClick: .init(enabled: true)
    )
))
```
{% /code-group %}

Rage Click is a user interaction that occurs four (4) or more times in 1 second on the same element and the distance between each adjacent click is no more than 50 points.

When a Rage Click occurs, Amplitude tracks the `[Amplitude] Rage Click` event.

{% accordion title="Event Properties Descriptions" %}
| Event property | Description |
| --- | --- |
| `[Amplitude] Begin Time` | The timestamp when the interaction began in ISO 8601 format. |
| `[Amplitude] End Time` | The timestamp when the interaction ended in ISO 8601 format. |
| `[Amplitude] Duration` | The duration of the interaction in milliseconds. |
| `[Amplitude] Click Count` | The number of clicks that occurred. |
| `[Amplitude] Clicks` | The array of clicks that occurred. |
| `[Amplitude] Clicks[].X` | The x-coordinate of the click from the top-left corner of the screen. |
| `[Amplitude] Clicks[].Y` | The y-coordinate of the click from the top-left corner of the screen. |
| `[Amplitude] Clicks[].Time` | The timestamp of the click in ISO 8601 format. |
| `[Amplitude] Action` | The action that triggered the event. Defaults to `touch`. |
| `[Amplitude] Target View Class` | The name of the target view class. |
| `[Amplitude] Target Text` | The title of the target `UIControl` element. |
| `[Amplitude] Target Accessibility Label` | The accessibility label of the target element. |
| `[Amplitude] Target Accessibility Identifier` | The accessibility identifier of the target element. |
| `[Amplitude] Action Method` | The name of the function or method that triggers when the interaction occurs. |
| `[Amplitude] Gesture Recognizer` | The name of the `UIGestureRecognizer` class that recognizes the interaction. |
| `[Amplitude] Hierarchy` | A nested hierarchy of the target view's class inheritance, from the most specific to the most general. |
| `[Amplitude] Screen Name` | Go to [Track screen views](#track-screen-views). |

{% /accordion %}

Dead Click is a tap on an interactive element that results in no visible change in the following three (3) seconds.

When a Dead Click occurs, Amplitude tracks the `[Amplitude] Dead Click` event.

{% callout type="note" heading="Requirements" %}
Dead clicks requires the Amplitude Session Replay iOS Plugin version `0.5.0` or higher installed and running. Go to [Session Replay iOS Plugin](/docs/session-replay/session-replay-ios-plugin) for more information.
{% /callout %}

{% accordion title="Event Properties Descriptions" %}
| Event property | Description |
| --- | --- |
| `[Amplitude] X` | The x-coordinate of the click from the top-left corner of the screen. |
| `[Amplitude] Y` | The y-coordinate of the click from the top-left corner of the screen. |
| `[Amplitude] Action` | The action that triggered the event. Defaults to `touch`. |
| `[Amplitude] Target View Class` | The name of the target view class. |
| `[Amplitude] Target Text` | The title of the target `UIControl` element. |
| `[Amplitude] Target Accessibility Label` | The accessibility label of the target element. |
| `[Amplitude] Target Accessibility Identifier` | The accessibility identifier of the target element. |
| `[Amplitude] Action Method` | The name of the function or method that triggers when the interaction occurs. |
| `[Amplitude] Gesture Recognizer` | The name of the `UIGestureRecognizer` class that recognizes the interaction. |
| `[Amplitude] Hierarchy` | A nested hierarchy of the target view's class inheritance, from the most specific to the most general. |
| `[Amplitude] Screen Name` | Go to [Track screen views](#track-screen-views). |

{% /accordion %}

## User groups

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

For example, you want to group your users based on what organization they're in by 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 you set 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 set for that user's groupType, and the corresponding user property value. `groupType` is a string, and `groupName` accepts either a string or an array of strings to indicate that a user is in multiple groups.

{% callout type="example" heading="" %}
If Joe is in 'orgId' '15', then the `groupName` is '15'.

{% code-group %}
```swift Swift
// set group with a single group name
amplitude.setGroup(groupType: "orgId", groupName: "15")
```

```objc Obj-C
// set group with a single group name
[amplitude setGroup:@"orgId" groupName:@"15"];
```
{% /code-group %}

If Joe is in 'orgId' 'sport', then the `groupName` is '["tennis", "soccer"]'.

{% code-group %}
```swift Swift
// set group with multiple group names
amplitude.setGroup(groupType: "sport", groupName: ["tennis", "soccer"])
```

```objc Obj-C
// set group with multiple group names
[amplitude setGroup:@"sport" groupNames:@[@"tennis", @"soccer"]];
```
{% /code-group %}
{% /callout %}

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 event you log, and doesn't persist on the user unless you explicitly set it with `setGroup`.

{% code-group %}
```swift Swift
amplitude.track(
    event: BaseEvent(
        eventType: "event type",
        eventProperties: [
            "eventPropertyKey": "eventPropertyValue"
        ],
        groups: ["orgId": "15"]
    )
)
```

```objc Obj-C
AMPBaseEvent *event = [AMPBaseEvent initWithEventType:@"event type"
    eventProperties:@{@"eventPropertyKey": @"eventPropertyValue"}];
[event.groups set:@"orgId" value:@"15"];
[amplitude track:event];
```
{% /code-group %}

## Group identify

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

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

{% code-group %}
```swift Swift
let groupType = "plan"
let groupName = "enterprise"
let identify = Identify().set(property: "key", value: "value")
amplitude.groupIdentify(groupType: groupType, groupName: groupProperty, identify: identify)
```

```objc Obj-C
NSString *groupType = @"plan";
NSString *groupName = @"enterprise";
AMPIdentify *identify = [AMPIdentify new];
[identify set:@"key" value:@"value"];
[amplitude groupIdentify:groupType groupName:groupName identify:identify];
```
{% /code-group %}

## Track revenue

Amplitude can track revenue generated by a user. Amplitude tracks revenue through distinct revenue objects, which have special fields used in Amplitude's Event Segmentation and Revenue LTV charts. This lets Amplitude automatically display data relevant to revenue in the platform. Revenue objects support the following special properties, as well as user-defined properties through the `eventProperties` field.

{% code-group %}
```swift Swift
let revenue = Revenue()
revenue.price = 3.99
revenue.quantity = 3
revenue.productId = "com.company.productId"
amplitude.revenue(revenue: revenue)
```

```objc Obj-C
AMPRevenue *revenue = [AMPRevenue new];
revenue.price = 3.99;
revenue.quantity = 3;
revenue.productId = @"com.company.productId";
[amplitude revenue:revenue];
```
{% /code-group %}

| 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 its own login system that you want to track users with, you can call `setUserId` at any time.

{% code-group %}
```swift Swift
amplitude.setUserId(userId: "user@amplitude.com")
```

```objc Obj-C
[amplitude setUserId:@"user@amplitude.com"];
```
{% /code-group %}

## Custom device ID

You can 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.

{% code-group %}
```swift Swift
amplitude.setDeviceId(NSUUID().uuidString)
```

```objc Obj-C
[amplitude setDeviceId:[[NSUUID UUID] UUIDString]];
```
{% /code-group %}

## Custom storage

{% callout type="warning" heading="Swift only" %}
This feature supports Swift, but not Objective C
{% /callout %}

To store data outside the Amplitude-defined location, customize your own storage by implementing the [Storage protocol](https://github.com/amplitude/Amplitude-Swift/blob/211d0c05830fab47e74fa9a053615cf422618a02/Sources/Amplitude/Types.swift#L62-L86) and setting the `storageProvider` in your configuration.

Every iOS app gets a slice of storage for itself, which means that you can read and write your app's files there without colliding with other apps. By default, Amplitude uses this file storage and creates an "amplitude" prefixed folder inside the app "Documents" directory. If you need to expose the Documents folder in the native iOS "Files" app and don't want to expose the "amplitude" prefixed folder, you can customize your own storage provider to persist events on initialization.

```swift
Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        storageProvider: YourOwnStorage() // YourOwnStorage() should implement Storage
    )
)
```

## Reset when the user logs out

`reset` is a shortcut to anonymize users after they log out, by:

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

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

{% code-group %}
```swift Swift
amplitude.reset()
```

```objc Obj-C
[amplitude reset];
```
{% /code-group %}

## Plugins

Plugins let you extend Amplitude SDK's behavior, for example, by modifying event properties (enrichment type) or sending to third-party APIs (destination type). A plugin is an object with methods `setup()` and `execute()`.

### Plugin.setup

This method contains logic for preparing the plugin for use and has the `amplitude` instance as a parameter. A typical use for this method is to instantiate plugin dependencies. The SDK calls this method when you register the plugin to the client through `amplitude.add()`.

### Plugin.execute

This method contains the logic for processing events and has the `event` instance as a parameter. When used as an enrichment type plugin, the expected return value is the modified or enriched event. When used as a destination type plugin, the expected return value is `null`. The SDK calls this method for each event, including Identify, GroupIdentify, and Revenue events, that you instrument using the client interface.

### Enrichment type plugin example

Here's an example of a plugin that modifies each instrumented event by adding an extra event property.

{% code-group %}
```swift Swift
class EnrichmentPlugin: Plugin {
    let type: PluginType
    var amplitude: Amplitude?

    init() {
        self.type = PluginType.enrichment
    }

    func setup(amplitude: Amplitude) {
        self.amplitude = amplitude
    }

    func execute(event: BaseEvent?) -> BaseEvent? {
        event?.sessionId = -1
        if event?.eventProperties == nil {
            event?.eventProperties = [:]
        }
        event?.eventProperties?["event prop key"] = "event prop value"
        return event
    }
}

amplitude.add(plugin: EnrichmentPlugin())
```

```objc Obj-C
[amplitude add:[AMPPlugin initWithType:AMPPluginTypeEnrichment
    execute:^AMPBaseEvent *_Nullable(AMPBaseEvent * _Nonnull event) {
    event.sessionId = -1;
    [event.eventProperties set:@"event prop key" value:@"event prop value"];
    return event;
}]];
```
{% /code-group %}

### Destination type plugin example

In destination plugins, you can overwrite the `track()`, `identify()`, `groupIdentify()`, `revenue()`, and `flush()` functions.

{% callout type="warning" heading="Objective-C not supported" %}
Objective-C supports `flush()` and general `execute()` functions.
{% /callout %}

{% code-group %}
```swift Swift
class TestDestinationPlugin: DestinationPlugin {
    override func track(event: BaseEvent) -> BaseEvent? {
        return event
    }

    override func identify(event: IdentifyEvent) -> IdentifyEvent? {
        return event
    }

    override func groupIdentify(event: GroupIdentifyEvent) -> GroupIdentifyEvent? {
        return event
    }

    override func revenue(event: RevenueEvent) -> RevenueEvent? {
        return event
    }

    override func flush() {
    }

    override func setup(amplitude: Amplitude) {
        self.amplitude = amplitude
    }

    override func execute(event: BaseEvent?) -> BaseEvent? {
        return event
    }
}
```

```objc Obj-C
[amplitude add:[AMPPlugin initWithType:AMPPluginTypeDestination
    execute:^AMPBaseEvent * _Nullable(AMPBaseEvent * _Nonnull event) {
    if ([event.eventType isEqualToString:@"$identify"]) {
        // ...
    } else if ([event.eventType isEqualToString:@"$groupidentify"]) {
        // ...
    } else if ([event.eventType isEqualToString:@"revenue_amount"]) {
        // ...
    } else {
        // ...
    }
    return nil;
} flush:^() {
    // ...
}]];
```
{% /code-group %}

## Troubleshooting and debugging

Confirm that the configuration and payload are accurate and check for any unusual messages during debugging. If everything appears correct, check the value of `flushQueueSize` or `flushIntervalMillis`. The SDK queues events and sends them in batches by default, so it doesn't dispatch them to the server immediately. Wait for the SDK to send events to the server before checking for them in the charts.

### Log

- Set the log level to debug to collect useful information during debugging.
- Customize `loggerProvider` class from the `LoggerProvider` and implement your own logic, such as logging error messages on a server in a production environment.

### Plugin

Use a Destination Plugin to print the configuration value and event payload before sending them to the server. Set the logLevel to debug, copy the following `TroubleShootingPlugin` into your project, then add the plugin to the Amplitude instance.

[SwiftUI TroubleShootingPlugin example](https://github.com/amplitude/Amplitude-Swift/tree/main/Examples/AmplitudeSwiftUIExample/AmplitudeSwiftUIExample/ExamplePlugins/TroubleShootingPlugin.swift).

### Event callback

The event callback runs after the SDK sends the event, for both successful and failed events. Use this method to monitor event status and message. For more information, refer to [configuration > callback](#configuration).

## Advanced topics

### User sessions

Amplitude starts a session when the app moves into the foreground, or when the SDK tracks an event in the background. A session ends when the app remains in the background for more than the time set by `setMinTimeBetweenSessionsMillis()` without tracking any event. A session continues for the entire time the app is in the foreground, whether or not `configuration.defaultTracking` or `configuration.autocapture` enables session tracking.

When the app enters the foreground, Amplitude tracks a session start and starts a countdown based on `setMinTimeBetweenSessionsMillis()`. Amplitude extends the session and restarts the countdown any time it tracks a new event. If the countdown expires, Amplitude waits until the next event to track a session end event.

Amplitude doesn't set user properties on session events by default. To add these properties, use `identify()` and `setUserId()`. Amplitude aggregates the user property state and associates the user with events based on `device_id` or `user_id`.

Because of how Amplitude manages sessions, several scenarios may make events appear missing or session tracking inaccurate even when the SDK works as expected:

- If a user doesn't return to the app, Amplitude doesn't track a session end event to correspond with a session start event.
- If you track an event in the background, Amplitude may perceive the session length as longer than the time the user spends on the app in the foreground.
- If you modify user properties between the last event and the session end event, the session end event reflects the updated user properties, which may differ from other properties associated with events in the same session. To address this, use an enrichment plugin to set `event['$skip_user_properties_sync']` to `true` on the session end event, which prevents Amplitude from synchronizing properties for that specific event. To learn more, refer to [$skip_user_properties_sync](/docs/data/converter-configuration-reference#skipuserpropertiessync) in the Converter Configuration Reference article.

Amplitude groups events together by session. Events logged within the same session have the same `session_id`. Amplitude handles sessions automatically, so you don't have to manually call `startSession()` or `endSession()`.

You can adjust the time window during which Amplitude extends sessions. The default session expiration time is five minutes.

Use the helper method `getSessionId` to get the value of the current `sessionId`.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        minTimeBetweenSessionsMillis: 1000
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.minTimeBetweenSessionsMillis = 1000;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

{% callout type="note" heading="" %}
`trackingSessionEvents` is deprecated. Use the `AutocaptureOptions.sessions` option of `autocapture` instead.
{% /callout %}

You can also track events as out-of-session. Out-of-session events have a `sessionId` of `-1` and behave as follows:

1.  Aren't part of the current session.
2.  Don't extend the current session.
3.  Don't start a new session.
4.  Don't change the `sessionId` for subsequent events.

A potential use case is events tracked from push notifications, which are usually external to the customer's app usage.

Set the `sessionId` to `-1` in `EventOptions` to mark an event as out-of-session when you call `track(event, options)` or `identify(identify, options)`.

{% code-group %}
```swift Swift
let outOfSessionOptions = EventOptions(sessionId: -1)

amplitude.identify(
    event: Identify().set(property: "user-prop", value: true),
    options: outOfSessionOptions
)

amplitude.track(
    event: BaseEvent(eventType: "Button Clicked"),
    options: outOfSessionOptions
)
```

```objc Obj-C
AMPEventOptions *outOfSessionOptions = [AMPEventOptions new];
outOfSessionOptions.sessionId = -1;

AMPIdentify *identify = [AMPIdentify new];
[identify set:@"user-prop" value:YES];
[amplitude identify:identify options:outOfSessionOptions];

AMPBaseEvent *event = [AMPBaseEvent initWithEventType:@"Button Clicked"];
[amplitude track:event options:outOfSessionOptions];
```
{% /code-group %}

### Log level

Control the level of logs that print to the developer console.

- 'OFF': Suppresses all log messages.
- 'ERROR': Shows error messages only.
- 'WARN': Shows error messages and warnings. This level logs issues that might be a problem and cause some oddities in the data. For example, this level displays a warning for properties with null values.
- 'LOG': Shows informative messages about events.
- 'DEBUG': Shows error messages, warnings, and informative messages that may be useful for debugging.

Set the log level `logLevel` with the level you want.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        logLevel: LogLevelEnum.LOG
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.logLevel = AMPLogLevelLOG;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

Amplitude [merges user data](/docs/data/sources/instrument-track-unique-users), so any events associated with a known `userId` or `deviceId` link to the existing user.
If a user logs out, Amplitude can merge that user's logged-out events with the user's record. You can change this behavior and log those events to an anonymous user instead.

To log events to an anonymous user:

1. Set the `userId` to null.
2. Generate a new `deviceId`.

Events from the current user or device appear as a new user in Amplitude. Note: If you do this, you can't see that the two users were using the same device.

{% code-group %}
```swift Swift
amplitude.reset()
```

```objc Obj-C
[amplitude reset];
```
{% /code-group %}

### Disable tracking

By default, the iOS SDK tracks several user properties such as `carrier`, `city`, `country`, `ip_address`, `language`, and `platform`.
Use the provided `TrackingOptions` interface to customize and toggle individual fields.
Before you initialize the SDK with your apiKey, create a `TrackingOptions` instance with your configuration and set it on the SDK instance.

{% code-group %}
```swift Swift
let trackingOptions = TrackingOptions()
trackingOptions.disableTrackCity().disableTrackIpAddress()
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        trackingOptions: trackingOptions
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
[configuration.trackingOptions disableTrackCity];
[configuration.trackingOptions disableTrackIpAddress];
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

You can individually control tracking for each field, and each has a corresponding method (for example, `disableCountry`, `disableLanguage`).

| Method                             | Description                                             |
| ---------------------------------- | ------------------------------------------------------- |
| `disableTrackCarrier()`            | Disable tracking of device's carrier                    |
| `disableTrackCity()`               | Disable tracking of user's city                         |
| `disableTrackCountry()`            | Disable tracking of user's country                      |
| `disableTrackDeviceModel()`        | Disable tracking of device model                        |
| `disableTrackDeviceManufacturer()` | Disable tracking of device manufacturer                 |
| `disableTrackDMA()`                | Disable tracking of user's designated market area (DMA) |
| `disableTrackIpAddress()`          | Disable tracking of user's IP address                   |
| `disableTrackLanguage()`           | Disable tracking of device's language                   |
| `disableTrackIDFV()`               | Disable tracking of identifier for vendors (IDFV)       |
| `disableTrackOsName()`             | Disable tracking of device's OS Name                    |
| `disableTrackOsVersion()`          | Disable tracking of device's OS Version                 |
| `disableTrackPlatform()`           | Disable tracking of device's platform                   |
| `disableTrackRegion()`             | Disable tracking of user's region                       |
| `disableTrackVersionName()`        | Disable tracking of your app's version name             |

{% callout type="note" heading="" %}
Using `TrackingOptions` only prevents Amplitude from tracking default properties on newly created projects, where you haven't sent data yet. If you have a project with existing data and you want to stop collecting the default properties, get help in the [Amplitude Community](https://community.amplitude.com/?utm_source=devdocs&utm_medium=helpcontent&utm_campaign=devdocswebsite). Disabling tracking doesn't delete any existing data in your project.
{% /callout %}

### Carrier

Amplitude determines the user's mobile carrier using [`CTTelephonyNetworkInfo`](https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo), which returns the registered operator of the `sim`.

### COPPA control

You can enable or disable COPPA (Children's Online Privacy Protection Act) restrictions on IDFA, IDFV, city, IP address, and location tracking at one time. Apps that ask for information from children under 13 years of age must comply with COPPA.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        enableCoppaControl: true
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.enableCoppaControl = true;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

### Advertiser ID

Advertiser ID (also referred to as IDFA) is a unique identifier provided by the iOS and Google Play stores. Because it's unique to every person and not only their devices, it's useful for mobile attribution.

[Mobile attribution](https://www.adjust.com/blog/mobile-ad-attribution-introduction-for-beginners/) is the attribution of an installation of a mobile app to its original source (such as ad campaign, app store search). Mobile apps need permission to ask for IDFA, and apps targeted to children can't track at all. Consider using IDFV, device ID, or an email login system when IDFA isn't available.

To retrieve the IDFA and add it to tracking events, follow this [example plugin](https://github.com/amplitude/Amplitude-Swift/blob/main/Examples/AmplitudeSwiftUIExample/AmplitudeSwiftUIExample/ExamplePlugins/IDFACollectionPlugin.swift) to implement your own plugin.

### Device ID lifecycle

The SDK initializes the device ID in the following order, and sets the device ID to the first valid value encountered:

1. Device ID of Amplitude instance if you set it by `setDeviceId()`.
2. IDFV if it exists.
3. A randomly generated UUID string.

#### One user with multiple devices

A single user may have multiple devices, each with a different device ID. To ensure coherence, set the user ID consistently across all these devices. Even though the device IDs differ, Amplitude can still merge them into a single Amplitude ID and identify them as a unique user.

#### Transfer to a new device

Multiple devices can have the same device ID when a user switches to a new device. When users transition to a new device, they often transfer their applications along with other relevant data. The specific transferred content may vary by application. In general, it includes databases and file directories associated with the app. However, the exact items included depend on the app's design and the choices the developers made. If a user backed up databases or file directories from one device to another, the device ID stored within them may still be present. As a result, if the SDK retrieves it during initialization, different devices might end up using the same device ID.

#### Get device ID

Use the helper method `getDeviceId()` to get the value of the current `deviceId`.

{% code-group %}
```swift Swift
let deviceId = amplitude.getDeviceId()
```

```objc Obj-C
NSString *deviceId = [amplitude getDeviceId];
```
{% /code-group %}

To set the device, refer to [custom device ID](#custom-device-identifierentifier).

### Location tracking

Amplitude converts the IP of a user event into a location (GeoIP lookup) by default. An app's own tracking solution or user data can override this information.

### Opt users out of tracking

Users may want to opt out of tracking entirely, which means Amplitude doesn't track any of their events or browsing history. `OptOut` provides a way to fulfill a user's requests for privacy.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        optOut: true
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.optOut = true;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

### Set log callback

Implement a customized `loggerProvider` class from the LoggerProvider, and pass it in the configuration during initialization to help collect error messages from the SDK in a production environment.

{% code-group %}
```swift Swift
class SampleLogger: Logger {
    typealias LogLevel = LogLevelEnum

    var logLevel: Int

    init(logLevel: Int = LogLevelEnum.OFF.rawValue) {
        self.logLevel = logLevel
    }

    func error(message: String) {
        // TODO: handle error message
    }

    func warn(message: String) {
        // TODO: handle warn message
    }

    func log(message: String) {
        // TODO: handle log message
    }

    func debug(message: String) {
        // TODO: handle debug message
    }
}

let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: AMPLITUDE_API_KEY,
        loggerProvider: SampleLogger()
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.loggerProvider = ^(NSInteger logLevel, NSString * _Nonnull message) {
    switch(logLevel) {
    case AMPLogLevelERROR:
        // TODO: handle error message
        break;
    case AMPLogLevelWARN:
        // TODO: handle warn message
        break;
    case AMPLogLevelLOG:
        // TODO: handle log message
        break;
    case AMPLogLevelDEBUG:
        // TODO: handle debug message
        break;
    }
};
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

### Security

iOS automatically protects application data by storing each app's data in its own secure directory. Other applications usually can't access this directory. However, if a device is jailbroken, apps get root access to all directories on the device.

To prevent other apps from accessing your app's Amplitude data on a jailbroken device, Amplitude recommends setting a unique instance name for your SDK. This creates a unique database that's isolated from other apps.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: "API-KEY",
        instanceName: "my-unique-instance-name"
    )
)
```

```objc Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"API-KEY"
                                                    instanceName:@"my-unique-instance-name"];
Amplitude *amplitude = [Amplitude instanceWithConfiguration:configuration];
```
{% /code-group %}

### Offline mode

Beginning with version 1.3.0, the Amplitude iOS Swift SDK supports offline mode. The SDK checks network connectivity every time it tracks an event. If the device has a network connection, the SDK schedules a flush. If not, the SDK saves the event to storage. The SDK also listens for changes in network connectivity and flushes all stored events when the device reconnects.

To disable offline mode, add `offline: NetworkConnectivityCheckerPlugin.Disabled` on initialization as shown below.

{% code-group %}
```swift Swift
let amplitude = Amplitude(
    configuration: Configuration(
        apiKey: "API-KEY",
        offline: NetworkConnectivityCheckerPlugin.Disabled
    )
)
```

```obj-c Obj-C
AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:AMPLITUDE_API_KEY];
configuration.offline = AMPNetworkConnectivityCheckerPlugin.Disabled;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];
```
{% /code-group %}

You can also implement your own offline logic:

1. Disable the default offline logic as above.
2. Toggle `amplitude.configuration.offline` yourself.

### Apple privacy manifest

Starting December 8, 2020, Apple requires a privacy manifest file for all new apps and app updates. Apple expects to make this mandatory in the Spring of 2024. Because Amplitude is a third party to your app, you need to make sure you properly disclose to your users the ways you use Amplitude with their data.

{% callout type="note" heading="Update the privacy manifest based on your app" %}
Amplitude sets the privacy manifest based on a default configuration. Update the privacy manifest according to your configuration and your app.
{% /callout %}

#### NSPrivacyTracking

{% callout type="note" heading="Tracking definition" %}
Tracking refers to the act of linking user or device data collected from your app with user or device data collected from other companies' apps, websites, or offline properties for targeted advertising or advertising measurement purposes. For more information, refer to Apple's article [User privacy and data use](https://developer.apple.com/app-store/user-privacy-and-data-use/).
{% /callout %}

By default, Amplitude doesn't use data for tracking. Add this field and set it to true if your app does.

#### NSPrivacyCollectedDataTypes

| Date type           | Linked to user | Used for tracking | Reason for collection | Where it's tracked                                                                                                                                                                                   |
| ------------------- | -------------- | ----------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Product interaction | Yes            | No                | Analytics             | Such as app launches, taps, clicks, scrolling information, music listening data, video views, saved place in a game, video, or song, or other information about how the user interacts with the app. |
| Device ID           | Yes            | No                | Analytics             | Tracked by default. Refer to [Device ID lifecycle](#device-id-lifecycle).                                                                                                                            |
| Coarse Location     | Yes            | No                | Analytics             | Country, region, and city based on IP address. Amplitude doesn't collect them from device GPS or location features.                                                                                  |

By default, the SDK tracks `deviceId` only. You can use `setUserId()` to track `userId` as well. To do so, add the "User ID" Data type. For more information about data types, refer to Apple's article [Describing data use in privacy manifests](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests).

#### NSPrivacyTrackingDomains

If you set `NSPrivacyTracking` to true, provide at least one internet domain in `NSPrivacyTrackingDomains` based on your configuration.

| Domain                                 | Description                                                                               |
| -------------------------------------- | ----------------------------------------------------------------------------------------- |
| https://api2.amplitude.com/2/httpapi   | The default HTTP V2 endpoint.                                                             |
| https://api.eu.amplitude.com/2/httpapi | EU endpoint if `configuration.serverZone = EU`.                                           |
| https://api2.amplitude.com/batch       | Batch endpoint if `configuration.useBatch = true`.                                        |
| https://api.eu.amplitude.com/batch     | Batch EU endpoint if `configuration.useBatch = true` and `configuration.serverZone = EU`. |

#### NSPrivacyAccessedAPITypes

The SDK only uses `userDefaults` API for identity storage.

#### Create your app's privacy report

Follow the steps on how to [create your app's privacy](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests#4239187).
