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

{% callout type="warning" heading="Carrier tracking unsupported in iOS 16+" %}
The SDK fetches carrier information using `serviceSubscriberCellularProviders` and `CTCarrier`, which Apple [deprecated](https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3024511-servicesubscribercellularprovide) with [no replacement](https://developer.apple.com/forums/thread/714876?answerId=728276022#728276022) starting from iOS 16. Amplitude tracks Apple's updates and re-enables carrier tracking when Apple releases a replacement.
{% /callout %}

## Install the SDK

Install the iOS SDK with CocoaPods, Carthage, or Swift Package Manager.

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

1. Add dependency to `Podfile`.

```bash
pod '@{{packageName}}', '~> @{{version}}'
```

2. Run `pod install` in the project directory to install the dependency.
{% /tab %}
{% tab name="Carthage" %}
Add the following line to your `Cartfile`.

```bash
github "@{{repo}}" ~> @{{version}}
```

Review the [Carthage documentation](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for more information.
{% /tab %}
{% tab name="Swift Package Manager" %}

1.  Navigate to *File > Swift Package Manager > Add Package Dependency*. A dialog opens where you can add a package dependency.
2.  Enter the URL `https://github.com/@{{repo}}` in the search bar.
3.  Xcode resolves to the latest version, or select a specific version.
4.  Select **Next** to confirm the addition of the package as a dependency.
5.  Build your project to make sure the package is integrated.
{% /tab %}
{% /tabs %}

## Initialize the SDK

Initialize the SDK before you instrument. The API key for your Amplitude project is required.

Initialize the SDK in the `application:didFinishLaunchingWithOptions:` method of your `YourAppAppDelegate.m` file.

{% code-group %}
```objc Obj-c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Enable sending automatic session events
    [Amplitude instance].defaultTracking.sessions = YES;
    // Initialize SDK
    [[Amplitude instance] initializeApiKey:@"API_KEY"];
    // Set userId
    [[Amplitude instance] setUserId:@"userId"];
    // Log an event
    [[Amplitude instance] logEvent:@"app_start"];

    return YES;
}
```

```swift Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Enable sending automatic session events
    Amplitude.instance().defaultTracking.sessions = true
    // Initialize SDK
    Amplitude.instance().initializeApiKey("API_KEY")
    // Set userId
    Amplitude.instance().setUserId("userId")
    // Log an event
    Amplitude.instance().logEvent("app_start")

    return true
}
```
{% /code-group %}

## Configure the SDK

| Name                             | Description                                                                                                                                                                                                                          | Default Value            |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ |
| `eventUploadPeriodSeconds`       | The amount of time the SDK attempts to upload unsent events to the server or reaches the `eventUploadThreshold` threshold.                                                                                                           | `30`                     |
| `eventUploadThreshold`           | The SDK attempts to upload after unsent event count exceeds the event upload threshold or reaches the `eventUploadPeriodSeconds` interval.                                                                                           | `30`                     |
| `eventUploadMaxBatchSize`        | The maximum number of events sent with each upload request.                                                                                                                                                                          | `100`                    |
| `eventMaxCount`                  | The maximum number of unsent events to keep on the device.                                                                                                                                                                           | `1000`                   |
| `minTimeBetweenSessionsMillis`   | When a user closes and reopens the app within minTimeBetweenSessionsMillis milliseconds, the reopen counts as part of the same session and the session continues. Otherwise, the SDK creates a new session. The default is 5 minutes. | `5 minutes`              |
| `trackingSessionEvents`          | Deprecated. Whether to automatically log start and end session events that correspond to the start and end of a user's session.                                                                                                      | `NO`                     |
| `setServerUrl`                   | Sends events to a custom URL.                                                                                                                                                                                                        | `Amplitude HTTP API URL` |
| `setOptOut`                      | Opt the user out of tracking.                                                                                                                                                                                                        | `NO`                     |
| `setTrackingOptions`             | By default, the iOS SDK tracks several user properties such as carrier, city, country, ip_address, language, and platform. Use the `AMPTrackingOptions` interface to customize and disable individual fields.                        | `NO`                     |
| `setOffline`                     | Disables sending logged events to Amplitude servers. The SDK sends events when set to `true`.                                                                                                                                        | `NO`                     |
| `setIdentifyUploadPeriodSeconds` | The amount of time the SDK attempts to batch intercepted identify events.                                                                                                                                                            | `30`                     |

### EU data residency

Starting with version 8.5.0, you can configure the server zone after initializing the client to send data to Amplitude's EU servers. The SDK sends data based on the server zone if you set it. The server zone configuration also supports dynamic configuration.

For earlier versions, configure the `serverURL` property after initializing the client.

{% callout type="note" heading="" %}
For EU data residency, set up the project inside Amplitude EU. Initialize the SDK with the API key from Amplitude EU.
{% /callout %}

{% code-group %}
```objc Obj-c
// For versions starting from 8.5.0
// No need to call setServerUrl for sending data to Amplitude's EU servers

[[Amplitude instance] setServerZone:AMPServerZone.EU];

// For earlier versions
[[Amplitude instance] setServerUrl: @"https://api.eu.amplitude.com"];
```

```swift Swift
// For versions starting from 8.5.0
// No need to call setServerUrl for sending data to Amplitude's EU servers

Amplitude.instance().setServerZone(AMPServerZone.EU)

// For earlier versions

Amplitude.instance().setServerUrl("https://api.eu.amplitude.com")
```
{% /code-group %}

## Send events

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

{% code-group %}
```objc Obj-c
[[Amplitude instance] logEvent:@"Button Clicked"];
```

```swift Swift
Amplitude.instance().logEvent("Button Click")
```
{% /code-group %}

### Send events with properties

Events can also contain properties, which give more context about the event. For example, "hover time" can be a relevant event property for "button click".

{% code-group %}
```objc Obj-c
NSMutableDictionary *eventProperties = [NSMutableDictionary dictionary];
[eventProperties setValue:@"100ms" forKey:@"Hover Time"];
[[Amplitude instance] logEvent:@"Button Clicked" withEventProperties:eventProperties];
```

```swift Swift
Amplitude.instance().logEvent("Button Clicked", withEventProperties: ["Hover Time": "100ms"] )
```
{% /code-group %}

## User properties

{% callout type="warning" heading="User privacy" %}
Don't track any user data that may be against your privacy terms.
{% /callout %}

User properties help you understand your users at the time they performed an action in your app. For example, you can learn about their device details, their preferences, or language.

Amplitude-iOS's `AMPIdentity` class manages these features. Identify sets the user properties of a particular user without sending any event. The SDK supports these operations on individual user properties: `set`, `setOnce`, `unset`, `add`, `append`, `prepend`, `preInsert`, `postInsert`, and `remove`. Declare the operations through the Identify interface. You can chain multiple operations in a single Identify object.

Pass the `AMPIdentify` object to the Amplitude client to send it to the server. Starting from release v8.15.0, the SDK batches identify events with set operations and sends them with fewer events. This change doesn't affect the result of the set operations. Manage the flush interval for batched Identify events with `setIdentifyUploadPeriodSeconds`.

### Set a user property

`set` sets the value of a user property. You can also chain together multiple identify calls.

{% code-group %}
```objc Obj-c
AMPIdentify *identify = [[[AMPIdentify identify] set:@"gender" value:@"female"] set:@"age"
    value:[NSNumber numberWithInt:20]];
[[Amplitude instance] identify:identify];
```

```objc Swift
AMPIdentify *identify = [[[AMPIdentify identify] set:@"gender" value:@"female"] set:@"age"
    value:[NSNumber numberWithInt:20]];
[[Amplitude instance] identify:identify];
```
{% /code-group %}

### Set a user property once

`setOnce` sets the value of a user property only once. The SDK ignores subsequent calls using `setOnce`.

{% code-group %}
```objc Obj-c
AMPIdentify *identify1 = [[AMPIdentify identify] setOnce:@"sign_up_date" value:@"2015-08-24"];
[[Amplitude instance] identify:identify1];

AMPIdentify *identify2 = [[AMPIdentify identify] setOnce:@"sign_up_date" value:@"2015-09-14"];
[[Amplitude instance] identify:identify2]; // Is ignored
```

```swift Swift
let identify1 = AMPIdentify().setOnce("sign_up_date", value: "2015-08-24")
Amplitude.instance().identify(identify1)

let identify2 = AMPIdentify().setOnce("sign_up_date", value: "2015-09-14")
Amplitude.instance().identify(identify2) // Is ignored
```
{% /code-group %}

### Increment a user property

`add` increments a user property by some numerical value. If the user property doesn't have a value set yet, the SDK initializes it to `0` before incrementing.

{% code-group %}
```objc Obj-c
AMPIdentify *identify = [[[AMPIdentify identify] add:@"karma" value:[NSNumber numberWithFloat:0.123]]
    add:@"friends" value:[NSNumber numberWithInt:1]];
[[Amplitude instance] identify:identify];
```

```swift Swift
let identify = AMPIdentify()
    .add("karma", value: NSNumber(value: 0.123))
    .add("friends",value: NSNumber(value: 1))
Amplitude.instance().identify(identify)
```
{% /code-group %}

### Remove values from a user property

`remove` removes a value or values from a user property. If the item doesn't exist in the user property, the SDK removes nothing.

```objc
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"some_string"];
[array addObject:[NSNumber numberWithInt:56]];
AMPIdentify *identify = [[[AMPIdentify identify] remove:@"ab-tests" value:@"new-user-test"]
    remove:@"some_list" value:array];
[[Amplitude instance] identify:identify];
```

### Set multiple user properties

Use `setUserProperties` as a shorthand to set multiple user properties at once. This method is a wrapper around `Identify.set` and `identify`.

{% code-group %}
```objc Obj-c
NSMutableDictionary *userProperties = [NSMutableDictionary dictionary];
[userProperties setValue:@"VALUE" forKey:@"KEY"];
[userProperties setValue:@"OTHER_VALUE" forKey:@"OTHER_KEY"];
[[Amplitude instance] setUserProperties:userProperties];
```

```swift Swift
var userProperties: [AnyHashable : Any] = [:]
userProperties["KEY"] = "VALUE"
userProperties["OTHER_KEY"] = "OTHER_VALUE"
Amplitude.instance().userProperties = userProperties
```
{% /code-group %}

### Use arrays in user properties

Directly set arrays or use `append` to generate an array.

{% code-group %}
```objc Obj-c
NSMutableArray *colors = [NSMutableArray array];
[colors addObject:@"rose"];
[colors addObject:@"gold"];
NSMutableArray *numbers = [NSMutableArray array];
[numbers addObject:[NSNumber numberWithInt:4]];
[numbers addObject:[NSNumber numberWithInt:5]];
AMPIdentify *identify = [[[[AMPIdentify identify] set:@"colors" value:colors] append:@"ab-tests"
    value:@"campaign_a"] append:@"existing_list" value:numbers];
[[Amplitude instance] identify:identify];
```

```swift Swift
var colors: [AnyHashable] = []
colors.append("rose")
colors.append("gold")
var numbers: [AnyHashable] = []
numbers.append(NSNumber(value: 4))
numbers.append(NSNumber(value: 5))
let identify = AMPIdentify().set("colors", value: colors)
    .append("ab-tests", value: "campaign_a")
    .append("existing_list",value: numbers)
Amplitude.instance().identify(identify)
```
{% /code-group %}

#### Append or prepend user property data

- `append` appends a value or values to a user property array.
- `prepend` prepends a value or values to a user property.

If the user property doesn't have a value set yet, the SDK initializes it to an empty list before adding the new values. If the user property has an existing value and it isn't a list, the SDK converts it into a list and adds the new value.

`append` and `prepend` don't check for duplicates. For duplicate checking, refer to `preInsert` and `postInsert`.

{% code-group %}
```objc Obj-c
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"some_string"];
[array addObject:[NSNumber numberWithInt:56]];
AMPIdentify *identify = [[[AMPIdentify identify] append:@"ab-tests" value:@"new-user-test"]
    append:@"some_list" value:array];
[[Amplitude instance] identify:identify];
```

```swift Swift
var array: [AnyHashable] = []
array.append("some_string")
array.append(NSNumber(value: 56))
let identify = AMPIdentify()
    .append("ab-tests", value: "new-user-test")
    .append("some_list",value: array)
Amplitude.instance().identify(identify)
```
{% /code-group %}

#### Preinsert and postinsert

- `preInsert` inserts a value or values to the front of a user property array if the value doesn't exist in the array yet.
- `postInsert` inserts a value or values to the end of a user property array if the value doesn't exist in the array yet.

If the user property doesn't exist, the SDK initializes it to an empty list before pre-inserting the new values. If the user property has an existing value, the SDK inserts nothing.

{% code-group %}
```objc Obj-c
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"some_string"];
[array addObject:[NSNumber numberWithInt:56]];
AMPIdentify *identify = [[[AMPIdentify identify] preInsert:@"ab-tests" value:@"new-user-test"]
    preInsert:@"some_list" value:array];
[[Amplitude instance] identify:identify];
```

```swift Swift
var array: [AnyHashable] = []
array.append("some_string")
array.append(NSNumber(value: 56))
let identify = AMPIdentify()
    .preInsert("ab-tests", value: "new-user-test")
    .preInsert("some_list",value: array)
Amplitude.instance().identify(identify)
```
{% /code-group %}

### Remove user properties

`clearUserProperties` removes all the current user's user properties.

{% callout type="warning" heading="This action is irreversible" %}
If you clear user properties, Amplitude can't sync the user's user property values from before the wipe to any future events.
{% /callout %}

{% code-group %}
```objc Obj-c
[[Amplitude instance] clearUserProperties];
```

```swift Swift
Amplitude.instance().clearUserProperties()
```
{% /code-group %}

#### Remove a value or values from a user property

`remove` removes an existing value or values from a user property. If the item doesn't exist in the user property, the SDK removes nothing.

{% code-group %}
```objc Obj-c
NSMutableArray *array = [NSMutableArray array];
[array addObject:@"some_string"];
[array addObject:[NSNumber numberWithInt:56]];
AMPIdentify *identify = [[[AMPIdentify identify] remove:@"ab-tests" value:@"new-user-test"]
    remove:@"some_list" value:array];
[[Amplitude instance] identify:identify];
```

```swift Swift
var array: [AnyHashable] = []
array.append("some_string")
array.append(NSNumber(value: 56))
let identify = AMPIdentify()
    .remove("ab-tests", value: "new-user-test")
    .remove("some_list", value: array)
Amplitude.instance().identify(identify)
```
{% /code-group %}

## Track default events

Starting from release v8.17.0, the SDK can track more default events. Configure the SDK to track the following events automatically:

- Sessions.
- App lifecycles.
- Screen views.
- Deep links.
- `defaultTracking.sessions`
  - **Type**: Optional. `boolean`.
  - **Default Value**: `NO`.
  - **Description**:
    - Enables session tracking. This configuration replaces [`trackingSessionEvents`](#configuration). If the value is `YES`, Amplitude tracks session start and session end events.
    - Refer to [Tracking sessions](#track-sessions) for more information.
- `defaultTracking.appLifecycles`
  - **Type**: Optional. `boolean`.
  - **Default Value**: `NO`.
  - **Description**:
    - Enables application lifecycle events tracking. If the value is `YES`, Amplitude tracks application installed, application updated, application opened, and application backgrounded events.
    - Tracked event properties include: `[Amplitude] Version`, `[Amplitude] Build`, `[Amplitude] Previous Version`, `[Amplitude] Previous Build`, and `[Amplitude] From Background`.
    - Refer to [Tracking application lifecycles](#tracking-application-lifecycles) for more information.
- `defaultTracking.screenViews`
  - **Type**: Optional. `boolean`.
  - **Default Value**: `NO`.
  - **Description**:
    - Enables screen views tracking. If the value is `YES`, Amplitude tracks screen viewed events.
    - Tracked event properties include: `[Amplitude] Screen Name`.
    - Refer to [Tracking screen views](#tracking-screen-views) for more information.
- `defaultTracking.deepLinks`
  - **Type**: Optional. `boolean`.
  - **Default Value**: `NO`.
  - **Description**:
    - Enables deep link tracking. If the value is `YES`, Amplitude tracks deep link opened events. You still need to call `continueUserActivity` or `openURL` manually to track this event.
    - Tracked event properties include: `[Amplitude] Link URL` and `[Amplitude] Link Referrer`.
    - Refer to [Tracking deep links](#tracking-deep-links) for more information.

Use the following code sample to enable default event tracking.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithAllEnabled];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithAllEnabled()
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

Disable default event tracking with the following code sample.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithNoneEnabled];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithNoneEnabled()
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

Default event tracking accepts options that define which events to track.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithSessions:YES
                                                                        appLifecycles:NO
                                                                            deepLinks:NO
                                                                        screenViews:NO];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithSessions(
    true,
    appLifecycles: false,
    deepLinks: false,
    screenViews: false
)
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

### Track sessions

To start tracking session events, set `defaultTracking.sessions` to `true`. Refer to the following code sample.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithSessions:YES
                                                                        appLifecycles:NO
                                                                            deepLinks:NO
                                                                        screenViews:NO];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithSessions(
    true,
    appLifecycles: false,
    deepLinks: false,
    screenViews: false
)
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

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

{% callout type="note" heading="" %}
`trackingSessionEvents` is deprecated. Use `defaultTracking.sessions` instead.
{% /callout %}

### Track application lifecycle

To start tracking application lifecycle events, set `defaultTracking.appLifecycles` to `true`. Refer to the following code sample.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithSessions:NO
                                                                      appLifecycles:YES
                                                                          deepLinks:NO
                                                                        screenViews:NO];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithSessions(
    false,
    appLifecycles: true,
    deepLinks: false,
    screenViews: false
)
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

After enabling this setting, Amplitude tracks the following events:

- `[Amplitude] Application Installed`: fires when a user opens the application for the first time after installation. The SDK observes the `UIApplicationDidFinishLaunchingNotification` notification.
- `[Amplitude] Application Updated`: fires when a user opens the application after updating it. The SDK observes the `UIApplicationDidFinishLaunchingNotification` notification.
- `[Amplitude] Application Opened`: fires when a user launches or foregrounds the application after the first open. The SDK observes the `UIApplicationDidFinishLaunchingNotification` or `UIApplicationWillEnterForegroundNotification` notification.
- `[Amplitude] Application Backgrounded`: fires when a user backgrounds the application. The SDK observes the `UIApplicationDidEnterBackgroundNotification` notification.

### Track screen views

To start tracking screen view events, set `defaultTracking.screenViews` to `true`. Refer to the following code sample.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithSessions:NO
                                                                        appLifecycles:NO
                                                                            deepLinks:NO
                                                                        screenViews:YES];
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithSessions(
    false,
    appLifecycles: false,
    deepLinks: false,
    screenViews: true
)
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

After enabling this setting, Amplitude tracks the `[Amplitude] Screen Viewed` event with the screen name property. The SDK reads the property value from the controller class metadata using `viewDidAppear` method swizzling.

### Track deep links

To start tracking deep link events, set `defaultTracking.deepLinks` to `true`. Refer to the following code sample.

{% code-group %}
```objc Obj-c
// Enable tracking deep links.
[Amplitude instance].defaultTracking = [AMPDefaultTrackingOptions initWithSessions:NO
                                                                        appLifecycles:NO
                                                                            deepLinks:YES
                                                                        screenViews:NO];
[[Amplitude instance] initializeApiKey:@"API_KEY"];

// Call helper method to track, e.g., in `onOpenURL` callback.
[[Amplitude instance] openURL:url];
[[Amplitude instance] continueUserActivity:activity];
```

```swift Swift
// Enable tracking deep links.
Amplitude.instance().defaultTracking = AMPDefaultTrackingOptions.initWithSessions(
    false,
    appLifecycles: false,
    deepLinks: true,
    screenViews: false
)
Amplitude.instance().initializeApiKey("API_KEY")

// Call helper method to track, e.g., in `onOpenURL` callback.
Amplitude.instance().openURL(url: url)
Amplitude.instance().continueUserActivity(activity: activity)
```
{% /code-group %}

After enabling this setting, Amplitude tracks the `[Amplitude] Deep Link Opened` event with the URL and referrer information. You still need to call `continueUserActivity` or `openURL` manually to track deep links.

## Set user groups

Amplitude supports assigning users to groups and performing queries, such as Count by Distinct, on those groups. If at least one member of the group has performed the specific event, then 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 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` is 'sport', with `groupName` values like 'tennis' and 'baseball'.

Setting a group also sets the `groupType:groupName` as a user property. It overwrites any existing `groupName` value set 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 to indicate that a user is in multiple groups.

{% callout type="example" heading="" %}
Joe is in 'orgID' with the groupName 15. Joe is also in "sport" with groupNames "tennis" and "soccer". Here is what your code might look like:

{% code-group %}
```objc Obj-c
[[Amplitude instance] setGroup:@"orgId" groupName:[NSNumber numberWithInt:15]];
[[Amplitude instance] setGroup:@"sport" groupName:[NSArray arrayWithObjects: @"tennis", @"soccer", nil]];
```

```swift Swift
Amplitude.instance().setGroup("orgId", groupName: NSNumber(value: 15))
    Amplitude.instance().setGroup("sport", groupName: NSArray(objects: "tennis", "soccer"))
```
{% /code-group %}

{% /callout %}

You can also use `logEventWithGroups` to set event-level groups. The group designation only applies for the specific event you log, and doesn't persist on the user unless you explicitly set it with `setGroup`:

{% code-group %}
```objc Obj-c
NSDictionary *eventProperties = [NSDictionary dictionaryWithObjectsAndKeys: @"value", @"key", nil];
NSDictionary *groups = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:10],
    @"orgId", @"soccer", @"sport", nil];
[[Amplitude instance] logEvent:@"initialize_game" withEventProperties:eventProperties withGroups:groups];
```

```swift Swift
let eventProperties: [String: Any] = ["key": "value"]
let groups: [String: Any] = ["orgId": 10]

Amplitude.instance().logEvent("initialize_game", withEventProperties: eventProperties, withGroups: groups)
```
{% /code-group %}

## Group identify

Use the Group Identify API to set or update the properties of particular groups. These updates only affect events going forward.

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

{% code-group %}
```objc Obj-c
NSString *groupType = @"plan";
NSObject *groupName = @"enterprise";
AMPIdentify *identify = [[AMPIdentify identify] set:@"key" value:@"value"];
[[Amplitude instance] groupIdentifyWithGroupType:groupType groupName:groupName groupIdentify:identify];
```

```swift Swift
let identify = AMPIdentify()
    .set("key", value: "value")
Amplitude.instance().groupIdentifyWithGroupType("plan", groupName:NSString(string:"enterprise"), groupIdentify:identify)
```
{% /code-group %}

You can add an optional `outOfSession` boolean input as a fourth argument to `groupIdentifyWithGroupType`.

## Track revenue

Instances of `AMPRevenue` store revenue transactions and define special revenue properties (such as `revenueType`) used in Amplitude's Event Segmentation and Revenue LTV charts. Pass each instance to `Amplitude.logRevenueV2`. This lets Amplitude automatically display data relevant to revenue.

To track revenue from a user, call `logRevenueV2` each time a user generates revenue. Here is an example:

{% code-group %}
```objc Obj-c
AMPRevenue *revenue = [[[AMPRevenue revenue] setProductIdentifier:@"productIdentifier"] setQuantity:3];
[revenue setPrice:[NSNumber numberWithDouble:3.99]];
[[Amplitude instance] logRevenueV2:revenue];
```

```swift Swift
let revenue = AMPRevenue()
revenue.setProductIdentifier("productIdentifier")
revenue.setQuantity(3)
revenue.setPrice(NSNumber(value: 3.99))
Amplitude.instance().logRevenueV2(revenue)
```
{% /code-group %}

Calling `logRevenueV2` generates up to 2 different event types in the platform:

- `[Amplitude] Revenue`: Amplitude logs this event for all revenue events, regardless of whether verification is on.
- `[Amplitude] Revenue (Verified/Unverified)`: These revenue events contain the actual `$revenue` property.

You can't change the default names that Amplitude gives these client-side revenue events in the raw data, but you can change the [display name](/docs/admin/account-management/account-settings). Learn more about tracking revenue in the [Help Center](/docs/data/sources/instrument-track-revenue).

{% callout type="note" heading="" %}
Amplitude doesn't support currency conversion. Normalize all revenue data to your currency of choice before sending.
{% /callout %}

Each revenue event has fields available, and each field has a corresponding set method (such as `price` and `setPrice`). Refer to the [API docs for `AMPRevenue`](http://amplitude.github.io/Amplitude-iOS/Classes/AMPRevenue.html#//api/name/productId) for a full list of fields.

Like `logEvent`, you can attach event properties for each call to `logRevenueV2`. However, these event properties only appear in the [Event Segmentation](/docs/analytics/charts/event-segmentation/event-segmentation-build) chart, not in the Revenue charts.

| Name               | Description                                                                                                                                    |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `productId`        | Optional. NSString. An identifier for the product. Amplitude recommends something like the "Google Play Store product ID". Defaults to `null`. |
| `quantity`         | Required. NSInteger. The quantity of products purchased. `revenue = quantity * price`. Defaults to 1.                                          |
| `price`            | Required. NSNumber. The price of the products purchased, and this can be negative. `revenue = quantity * price`. Defaults to `null`.           |
| `revenueType`      | Optional, but required for revenue verification. NSString. The revenue type. For example tax, refund, income. Defaults to `null`.              |
| `receipt`          | Optional, but required for revenue verification. NSData. Defaults to `null`                                                                    |
| `receiptSignature` | Optional, but required for revenue verification. Defaults to `null`.                                                                           |
| `eventProperties`  | Optional. NSDictionary. An object of event properties to include in the revenue event. Defaults to `null`.                                     |

{% callout type="note" heading="" %}
Price can be negative, which can be useful for tracking revenue lost (such as refunds or costs).
{% /callout %}

## Advanced topics

### User sessions

A session is a period of time that a user has the app in the foreground. Events logged within the same session share the same `session_id`. The SDK handles sessions automatically, so you don't have to manually call an API like `startSession()` or `endSession()`.

To adjust the time window for which sessions extend, change the variable `minTimeBetweenSessionsMillis`.

Amplitude groups events together by session. A session represents a single period of user activity with a start and end time. Different SDKs track sessions differently, depending on the requirements of the platform. Configure the minimum duration of a session within the SDK.

{% code-group %}
```objc Obj-c
[Amplitude instance].defaultTracking.sessions = YES;
[Amplitude instance].minTimeBetweenSessionsMillis = 10 * 60 * 1000; // 10 minutes
[[Amplitude instance] initializeApiKey:@"API_KEY"];
```

```swift Swift
Amplitude.instance().defaultTracking.sessions = true
Amplitude.instance().minTimeBetweenSessionsMillis = 10 * 60 * 1000 // 10 minutes
Amplitude.instance().initializeApiKey("API_KEY")
```
{% /code-group %}

You can also log events as out-of-session. Out-of-session events have a `session_id` of -1 and don't count as part of the current session, meaning they don't extend the current session. This can be useful when you log events triggered by push notifications, for example. Log events as out-of-session by setting the input parameter `outOfSession` to true when calling `logEvent`.

{% code-group %}
```objc Obj-c
[[Amplitude instance] logEvent:@"EVENT_TYPE" withEventProperties:nil outOfSession:YES];
```

```swift Swift
Amplitude.instance().logEvent("Push Notification", withEventProperties: nil, outOfSession: true)
```
{% /code-group %}

You can also log identify events as out-of-session. This is useful when you update user properties in the background and don't want to start a new session. Set the input parameter `outOfSession` to `true` when calling `identify`.

{% code-group %}
```objc Obj-c
AMPIdentify *identify = [[AMPIdentify identify] set:@"key" value:@"value"];
[[Amplitude instance] identify:identify outOfSession:YES];
```

```swift Swift
let identify = AMPIdentify()
    .set("key", value: "value")
Amplitude.instance().identify(identify, outOfSession: true)
```
{% /code-group %}

You can use the helper method getSessionId to get the value of the current `sessionId`.

{% code-group %}
```objc Obj-c
long sessionId = [[Amplitude instance] getSessionId];
```

```swift Swift
Amplitude.instance().getSessionId()
```
{% /code-group %}

### Set a custom user ID

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

{% code-group %}
```objc Obj-c
[[Amplitude] instance] setUserId:@"USER_ID"];
```

```swift Swift
Amplitude.instance().setUserId("USER_ID")
```
{% /code-group %}

You can also add the User ID as an argument to the init call.

{% code-group %}
```objc Obj-c
[[Amplitude] instance] initializeApiKey:@"API_KEY" userId:@"USER_ID"];
```

```swift Swift
Amplitude.instance().initializeApiKey("API_KEY", userId: "USER_ID")
```
{% /code-group %}

Don't assign users a user ID that could change, because each unique user ID is a unique user in Amplitude. For more information, refer to [Track unique users](/docs/data/sources/instrument-track-unique-users).

### Debug logging

By default, the SDK logs only critical errors to the console. To enable debug logging in iOS, change `AMPLITUDE_DEBUG` from 0 to 1 at the top of the Objective-C file you want to examine. The SDK prints error messages by default. To disable error logging, change `AMPLITUDE_LOG_ERRORS` from 1 to 0 in Amplitude.m.

### Logged out and anonymous users

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 to 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 coming 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 %}
```objc Obj-c
[[Amplitude instance] setUserId:nil]; // not string nil
[[Amplitude instance] regenerateDeviceId];
```

```swift Swift
Amplitude.instance().setUserId("userId")
Amplitude.instance().regenerateDeviceId()
```
{% /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 `AMPTrackingOptions` interface to customize and disable individual fields.

Each operation on the `AMPTrackingOptions` object returns the same instance, letting you chain multiple operations together.

To use the `AMPTrackingOptions` interface, first include the header:

```objc
#import "AMPTrackingOptions.h"
```

Before initializing the SDK with your `apiKey`, create an `AMPTrackingOptions` instance with your configuration and set it on the SDK instance.

{% code-group %}
```objc Obj-c
AMPTrackingOptions *options = [[[[AMPTrackingOptions options] disableCity] disableIPAddress] disablePlatform];
[[Amplitude instance] setTrackingOptions:options];
```

```swift Swift
let trackingOptions = AMPTrackingOptions().disableCity()
                                            .disableCarrier();
Amplitude.instance().setTrackingOptions(trackingOptions!);
```
{% /code-group %}

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

| Method                      | Description                                                            |
| --------------------------- | ---------------------------------------------------------------------- |
| `disableCarrier`            | Disable tracking of device's carrier.                                  |
| `disableCity`               | Disable tracking of user's city.                                       |
| `disableCountry`            | Disable tracking of user's country.                                    |
| `disableDeviceManufacturer` | Disable tracking of device manufacturer.                               |
| `disableDeviceModel`        | Disable tracking of device model.                                      |
| `disableDMA`                | Disable tracking of user's DMA.                                        |
| `disableIDFA`               | Disable tracking of user's IDFA.                                       |
| `disableIDFV`               | Disable tracking of user's IDFV.                                       |
| `disableIPAddress`          | Disable tracking of user's IP address.                                 |
| `disableLanguage`           | Disable tracking of device's language.                                 |
| `disableLatLng`             | Disable tracking of user's current latitude and longitude coordinates. |
| `disableOSName`             | Disable tracking of device's OS Name.                                  |
| `disableOSVersion`          | Disable tracking of device's OS Version.                               |
| `disablePlatform`           | Disable tracking of device's platform.                                 |
| `disableRegion`             | Disable tracking of user's region.                                     |
| `disableVersionName`        | Disable tracking of your app's version name.                           |

{% callout type="note" heading="" %}
`AMPTrackingOptions` only prevents the SDK from tracking default properties on newly created projects, where you haven't yet sent data. 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). Amplitude doesn't delete existing data.
{% /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 all at once. Apps that ask for information from children under 13 years of age must comply with COPPA.

{% code-group %}
```objc Obj-c
[[Amplitude instance] enableCoppaControl];
```

```swift Swift
Amplitude.instance().enableCoppaControl()
```
{% /code-group %}

### Advertiser ID

Advertiser ID (also called IDFA) is a unique identifier that the iOS and Google Play stores provide. Because IDFA is unique to every person and not just their devices, IDFA is 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 at children can't track at all. Consider using IDFV, device ID, or an email login system when IDFA isn't available.

{% code-group %}
```objc Obj-c
amplitude.adSupportBlock = ^{
    return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
};
```

```swift Swift
//  Converted to Swift 5.3 by Swiftify v5.3.22312 - https://swiftify.com/
amplitude.adSupportBlock = {
    return ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
```
{% /code-group %}

Remember to add `AdSupport.framework` to your project.

### Set IDFA as device ID

Amplitude uses the IDFV as the device ID by default, but you can change this behavior. After you set up the logic to fetch IDFA, call the [useAdvertisingIdForDeviceId](http://amplitude.github.io/Amplitude-iOS/Classes/Amplitude.html#//api/name/useAdvertisingIdForDeviceId) API to set the IDFA as your `deviceId`.

### Device ID lifecycle

The SDK initializes the device ID in the following order. The SDK sets the device ID to the first valid value it encounters:

1. Device id fetched from the SQLite database.
2. IDFA if `useAdvertisingIdForDeviceId` is true and you didn't call `disableIDFA()`.
3. IDFV if you didn't call `disableIDFV()`.
4. A randomly generated UUID.

#### One user with multiple devices

A single user may have multiple devices, each having 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, thus identifying 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 transitioning to a new device, users often transfer their applications along with other relevant data. The specific transferred content can vary depending on the application. It generally includes databases and file directories associated with the app. The exact items included depend on the app's design and the developers' choices. If databases or file directories were backed up from one device to another, the device ID stored within them can still be present. As a result, when the SDK retrieves the device ID during initialization, different devices might end up using the same device ID.

#### Get device ID

You can use the helper method `getDeviceId()` to get the value of the current `deviceId`.

{% code-group %}
```objc Obj-c
NSString *deviceId = [[Amplitude instance] getDeviceId];
```

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

#### Custom device ID

You can assign a new device ID using `setDeviceId()`. When setting a custom device ID, make sure the value is sufficiently unique. Amplitude recommends using a UUID.

{% code-group %}
```objc Obj-c
[[Amplitude instance] setDeviceId:@"DEVICE_ID"];
```

```swift Swift
Amplitude.instance().setDeviceId("DEVICE_ID")
```
{% /code-group %}

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

### Carrier information

Amplitude-iOS can help report carrier information.

To enable the SDK to report this information from devices, add `CoreTelephony.framework` as a dependency.

### Dynamic configuration

The iOS SDK lets you configure your apps to use [dynamic configuration](/docs/sdks/dynamic-configuration). This feature finds the best server URL automatically based on app users' location.

To use it, enable the `useDynamicConfig` flag.

- If you have your own proxy server and use `apiEndPoint` API, leave dynamic configuration off.
- If you have users in China Mainland, Amplitude recommends using dynamic configuration.
- By default, this feature returns the server URL of Amplitude's US servers. If you need to send data to Amplitude's EU servers, use `setServerZone` to set it to the EU zone.

{% code-group %}
```objc Obj-c
[Amplitude instance].useDynamicConfig = YES;
```

```swift Swift
Amplitude.instance().useDynamicConfig = true
```
{% /code-group %}

### SSL pinning

SSL Pinning is a client-side technique that helps prevent man-in-the-middle attacks by validating server certificates again after SSL handshaking. Only use SSL pinning if you have a specific reason to do so. Contact Support before you ship any products with SSL pinning enabled.

If you installed the SDK using CocoaPods, enable the preprocessor macro through your Podfile by adding this post install hook:

```ruby
post_install do |installer_representation|
   installer_representation.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
         config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'AMPLITUDE_SSL_PINNING=1']
      end
   end
end
```

If you installed the SDK directly from the source or Swift Package Manager, enable SSL pinning by adding the following preprocessor macro. Refer to this [StackOverflow post](https://stackoverflow.com/questions/26928622/add-preprocessor-macro-to-a-target-in-xcode-6) to learn how to add a preprocessor macro.

```bash title="xCode Settings"
AMPLITUDE_SSL_PINNING=1
```

### Opt users out of tracking

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

{% code-group %}
```objc Obj-c
[[Amplitude instance] setOptOut:YES]; // disables instrumentation
[[Amplitude instance] setOptOut:NO]; // enables instrumentation
```

```swift Swift
Amplitude.instance().optOut = true // disables instrumentation
Amplitude.instance().optOut = false // enables instrumentation
```
{% /code-group %}

### tvOS and watchOS

This SDK works with tvOS and watchOS apps. To begin, follow the same setup instructions for iOS apps.

{% callout type="note" heading="" %}
tvOS apps don't have persistent storage (they only have temporary storage), so for tvOS the SDK uploads events as soon as you log them.

This means `eventUploadThreshold` defaults to 1 for tvOS. Apple TV devices typically have a stable internet connection, so uploading events immediately is reasonable.

To revert to the iOS batching behavior, change `eventUploadThreshold` (the default for iOS is 30).
{% /callout %}

```objc
[[Amplitude instance] setEventUploadThreshold:30];
```

### iOS extensions

The SDK allows for tracking in iOS extensions. To set up tracking in iOS extensions, follow the same setup instructions but initialize the SDK in your extension's `viewDidLoad` method instead of `application:didFinishLaunchingWithOptions:`.

A few things to highlight:

- The system calls the `viewDidLoad` method every time your extension opens. This means the SDK's `initializeApiKey` method runs every time. This is safe because the SDK ignores calls after the first one. You can protect the initialization with something like a `dispatch_once` block.
- Amplitude's sessions are defined for an app use case. Depending on your expected extension use case, you might not want to enable `defaultTracking.sessions`, or you might want to extend `minTimeBetweenSessionsMillis` to be longer than five minutes. Experiment with these two settings to get the session definition you want.
- If you don't expect users to keep your extension open long, decrease `eventUploadPeriodSeconds` to something shorter than 30 seconds to upload events at shorter intervals. You can also manually call `[[Amplitude instance] uploadEvents];` to force an upload.

### App Clips

The SDK also allows for tracking in App Clips. To set up tracking in App Clips, install Amplitude-iOS under your App Clip target. Make sure the amplitude-iOS SDK is installed on your main app first.

#### CocoaPods

After creating an App Clip target, open your project Podfile and append the following code.

```ruby
target 'appClipTarget' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'Amplitude', :git => 'https://github.com/Amplitude/Amplitude-iOS.git'
end
```

Save the Podfile and run `pod install`.

#### Swift Package Manager

1. Open your App Clip target in Xcode and select the **+** button under the *Framework, Libraries, and Embedded Content* section.
2. Select **Amplitude** under *Amplitude Package* and select **Add**.

### Push notification events

Don't send push notification events client-side through the iOS SDK. Because a user must open the app to initialize the Amplitude SDK before the SDK can send the event, the SDK doesn't send events to the Amplitude servers until the next time the user opens the app. This can cause data delays.

You can use [mobile marketing automation partners](https://amplitude.com/integrations?category=mobile-marketing-automation) or the [HTTP API V2](https://developers.amplitude.com/docs/http-api-v2) to send push notification events to Amplitude.

### Offline mode

The Amplitude SDK supports offline usage through the `setOffline(isOffline)` method. Offline mode is off by default.

When offline mode is on, the SDK saves events to local storage but doesn't send them to the Amplitude servers.

When offline mode is off, the SDK sends any pending events to Amplitude's servers immediately.

To limit the permissions required by the SDK, the SDK doesn't automatically detect network connectivity. Instead, manually call `setOffline()` to enable or disable offline mode.

{% code-group %}
```objc Obj-c
[[Amplitude instance] setOffline:YES]; // enables offline mode
[[Amplitude instance] setOffline:NO]; // disables offline mode
```

```swift Swift
Amplitude.instance().setOffline(true); // enables offline mode
Amplitude.instance().setOffline(false) // disables offline mode
```
{% /code-group %}

### Middleware

Middleware lets you extend Amplitude by running a sequence of custom code on every event. This pattern is flexible and supports event enrichment, transformation, filtering, routing to third-party destinations, and more.

Each middleware is a simple interface with a run method:

```objc
- (void)run:(AMPMiddlewarePayload *_Nonnull)payload next:(AMPMiddlewareNext _Nonnull)next;
```

The `payload` contains the `event` the SDK sends and an optional `extra` that lets you pass custom data to your own middleware implementations.

To invoke the next middleware in the queue, use the `next` function. Call `next(payload)` to continue the middleware chain. If a middleware doesn't call `next`, event processing stops after the current middleware completes.

Add middleware to Amplitude through `client.addEventMiddleware`. You can add as many middleware as you like. Each middleware runs in the order you added it.

You can find examples for [Objective-C](https://github.com/amplitude/ampli-examples/blob/main/ios/objective-c/AmpliObjectiveCSampleApp/AmpliObjectiveCSampleApp/AppDelegate.m#L65) and [Swift](https://github.com/amplitude/ampli-examples/blob/main/ios/swift/AmpliSwiftSampleApp/Shared/AmpliSwiftSampleAppApp.swift#L48).

### Security

iOS automatically protects application data by storing each app's data in its own secure directory. Other applications generally can't access this directory. However, if a device is jailbroken, apps gain 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 is isolated from other apps.

{% code-group %}
```objc Obj-c
Amplitude* amplitude = [Amplitude instanceWithName:@"my-unique-instance-name"];
```

```swift Swift
let amplitude = Amplitude.instanceWithName("my-unique-instance-name")
```
{% /code-group %}

### 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 Spring 2024. Because Amplitude is a third-party to your app, properly disclose to your users how you use Amplitude with their data.

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

#### NSPrivacyTracking

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

| Data 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. Learn more [here](#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. 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            | The default HTTP V2 endpoint.                                                                                                   |
| https://api.eu.amplitude.com          | EU endpoint if `Amplitude.instance().setServerZone(AMPServerZone.EU)`.                                                          |
| https://regionconfig.amplitude.com    | Batch endpoint if `Amplitude.instance().useDynamicConfig = true`.                                                               |
| https://regionconfig.eu.amplitude.com | Batch EU endpoint if `Amplitude.instance().setServerZone(AMPServerZone.EU)` and `Amplitude.instance().useDynamicConfig = true`. |

#### NSPrivacyAccessedAPITypes

The SDK doesn't use any API by default. Learn more [here](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api).

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