Instrument and configure the iOS Swift SDK

이 페이지는 아직 귀하의 언어로 번역되지 않았습니다. 현재 작업 중이므로 곧 다시 확인해 주십시오.

After you get started, use the iOS Swift SDK (AmplitudeSwift) to track your own events, manage identity and sessions, choose Autocapture features, control how events reach Amplitude, and extend the SDK with plugins. For exact signatures and every option, go to the Reference. To find the release that added or changed a feature, go to iOS Swift SDK release notes.

The samples use Swift. For the Objective-C names of each class and method, go to Objective-C.

Track events

The iOS Swift SDK sends five kinds of data: custom events, user properties, group membership, group properties, and revenue. Each has its own method on the Amplitude instance. Every method returns immediately. The SDK does the work on a background queue, then stores the event and uploads it in a batch. Use these methods for events your tracking plan defines. For sessions, app lifecycle events, screen views, and other events the SDK can collect without code, go to Autocapture.

Track a custom event

Pass an event name and, optionally, a dictionary of event properties.

swift
amplitude.track(
    eventType: "Song Played",
    eventProperties: [
        "title": "Here Comes the Sun",
        "duration_seconds": 185,
        "genres": ["rock", "pop"],
    ]
)

Use strings, numbers, booleans, arrays, or nested dictionaries as property values. The SDK doesn't set app_version for you. To send it, set appVersion on a BaseEvent, or add it to every event with a plugin.

Pass a BaseEvent

To set more fields than the name and properties, pass a BaseEvent. Its initializer accepts every field the HTTP V2 API accepts, such as timestamp, insertId, appVersion, and groups. Swift requires labeled arguments in declaration order, so eventType comes after the event options fields.

swift
let event = BaseEvent(
    timestamp: Int64(Date().timeIntervalSince1970 * 1000) - 60_000,
    insertId: "song-played-8f2c",
    appVersion: "4.2.0",
    eventType: "Song Played",
    eventProperties: ["title": "Here Comes the Sun"]
)
amplitude.track(event: event)

Set insertId when the same event might send twice, for example after a retry from your own code. Amplitude ignores a second event with the same insert_id and device_id within seven days. The SDK generates an insertId for every event that doesn't have one.

Override fields for one event

Pass an EventOptions object in options. The values apply to this event only. Later events still use the identity from setUserId() and setDeviceId().

swift
amplitude.track(
    eventType: "Invite Sent",
    eventProperties: ["channel": "email"],
    options: EventOptions(userId: "user-12345")
)

identify() behaves differently. When its options include userId or deviceId, the SDK also changes its identity to those values, so every later event carries them.

Get the upload result for one event

Pass a closure to track(event:options:callback:). The SDK calls the closure after Amplitude accepts or rejects the event. The SDK doesn't call it while the upload is still retrying.

swift
amplitude.track(event: BaseEvent(eventType: "Checkout Started")) { event, code, message in
    print("\(event.eventType): \(code) \(message)")
}

A successful upload reports code 200 and the message Successfully send event. The SDK keeps per-event closures in memory only, so the SDK loses a closure if the app quits before the upload. To receive the result of every event, set the callback configuration option. When you set both, both fire.

Set user properties

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

swift
let identify = Identify()
    .set(property: "plan", value: "pro")
    .setOnce(property: "first_seen_at", value: "2026-10-26")
    .add(property: "login_count", value: 1)
    .append(property: "visited_sections", value: "billing")

amplitude.identify(identify: identify)

The SDK sends an $identify event. It doesn't appear as an event in charts, but it updates the user's properties. The update shows on the user's profile right away, and it applies to the events the user sends after it.

Each property can appear in only one operation per Identify object. The SDK ignores a second operation on the same property and logs Already used property <name> in previous operation, ignoring operation <operation>. Split conflicting operations across two identify() calls.

To set a few properties without building an Identify object, pass a dictionary. The SDK sends each key as a $set operation:

swift
amplitude.identify(userProperties: ["plan": "pro", "theme": "dark"])

Identify calls that only set properties wait for the next event

When an $identify contains only $set operations, the SDK holds it instead of uploading it at once. It merges every held identify into one $identify and sends it when one of these happens first:

  • You track an event other than an identify or group identify. The merged identify goes ahead of that event.
  • You send an identify with any other operation. The merged identify goes ahead of it.
  • An event arrives with a different user ID or device ID than the held identify.
  • You call flush().
  • 30 seconds pass.

An identify with any other operation goes into the upload queue right away. A clearAll() identify also discards every held identify. The identifyBatchIntervalMillis option has no effect as of 1.19.4: the SDK always waits 30 seconds.

Assign a user to a group

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

setGroup(groupType:groupName:) assigns the current user to one group, or to several groups of the same type when you pass an array. The SDK sends an $identify event with groups set, and also sets the group type as a user property, replacing any earlier value.

swift
amplitude.setGroup(groupType: "orgId", groupName: "15")
amplitude.setGroup(groupType: "sport", groupName: ["tennis", "soccer"])

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

swift
amplitude.track(event: BaseEvent(
    eventType: "Report Exported",
    groups: ["orgId": "15"]
))

Set group properties

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

swift
let groupProperties = Identify()
    .set(property: "plan", value: "enterprise")
    .set(property: "seats", value: 250)

amplitude.groupIdentify(groupType: "orgId", groupName: "15", identify: groupProperties)

Track revenue

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

swift
let revenue = Revenue()
revenue.productId = "com.example.pro_annual"
revenue.price = 3.99
revenue.quantity = 3
revenue.revenueType = "subscription"
revenue.currency = "USD"
revenue.properties = ["coupon": "FALL26"]
revenue.setReceipt(receipt: receiptData, receiptSignature: receiptSignature)

amplitude.revenue(revenue: revenue)

price is required. Without it, the SDK drops the call and logs Invalid revenue object, missing required fields. Amplitude computes revenue as price * quantity unless you set revenue, which sets the total directly. quantity defaults to 1 and ignores values of 0 or less. price accepts negative values, for example for a refund. Use the App Store product identifier as productId. Revenue verification requires revenueType and the receipt signature. For every property, go to Revenue class.

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

logRevenue() is deprecated and has no effect as of 1.19.4. It doesn't send an event. Use revenue(revenue:).

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

The SDK doesn't capture deep links automatically. When your app opens a URL, track a DeepLinkOpenedEvent. The SDK sends [Amplitude] Deep Link Opened with [Amplitude] Link URL and, when you pass one, [Amplitude] Link Referrer.

swift
// From a URL, for example in onOpenURL or scene(_:openURLContexts:)
amplitude.track(event: DeepLinkOpenedEvent(url: url))

// From strings, with a referrer
amplitude.track(event: DeepLinkOpenedEvent(
    url: "https://www.example.com/products/42",
    referrer: "https://www.google.com"
))

// From a universal link, which reads webpageURL and referrerURL
amplitude.track(event: DeepLinkOpenedEvent(activity: userActivity))

Send events to more than one project

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

swift
let production = Amplitude(configuration: Configuration(
    apiKey: "PRODUCTION_API_KEY"
))
let marketing = Amplitude(configuration: Configuration(
    apiKey: "MARKETING_API_KEY",
    instanceName: "marketing"
))

production.track(eventType: "Signup Completed")
marketing.track(eventType: "Signup Completed")

Each instance keeps its own user ID, device ID, session, event queue, and plugins. The SDK scopes storage by API key and instance name. Keep a strong reference to each instance for the life of your app.

Identity and sessions

The iOS Swift SDK attaches three identifiers to every event: a device ID, an optional user ID, and a session ID. Amplitude uses them to merge events into users and sessions. The SDK persists the device ID, user ID, and session state in UserDefaults, scoped to the API key and instance name, so they survive app launches.

How the SDK chooses identifiers on launch

When you create the Amplitude instance, the SDK takes each identifier from the first source that has a value.

Device ID

  1. The deviceId configuration option. Requires 1.19.0 or later.
  2. The device ID stored from an earlier launch.
  3. The identifier for vendor (IDFV), unless you turned it off with trackingOptions.disableTrackIDFV().
  4. A new random UUID.

On macOS, the SDK uses the MAC address of the en0 network interface, in the form xx:xx:xx:xx:xx:xx, as the IDFV. On macOS 27 and later, the system reports the placeholder 02:00:00:00:00:00 for every Mac, so the SDK skips it and uses a UUID. On watchOS, the SDK uses WKInterfaceDevice.identifierForVendor.

The SDK replaces a stored device ID that's a known shared value, such as an all-zero UUID or the macOS placeholder address. It keeps a configured deviceId even then, and logs a warning. The SDK doesn't collect the advertising identifier (IDFA). For attribution, set idfa on events yourself from a plugin, after the user grants App Tracking Transparency permission. For an example, go to IDFACollectionPlugin.swift in the SDK repository.

User ID

  1. The userId configuration option. Requires 1.19.0 or later.
  2. The user ID stored from an earlier launch.

A configured value replaces the stored one, and the SDK stores it for later launches. With nil, the SDK keeps the stored value.

Session ID

The session ID is the start time of the session, in milliseconds since the Unix epoch. The SDK reads the last session ID and last event time from storage, then decides with the first event whether the session continues. Go to How sessions work.

Set the user ID

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

swift
amplitude.setUserId(userId: "user-12345")

The new user ID applies to every later event and persists across launches. User IDs and device IDs must be at least five characters, or Amplitude rejects the event. To allow shorter IDs, set minIdLength. To read the current value, call getUserId().

If you know the user ID at launch, pass it to the configuration instead, so the first session event and any lifecycle events carry it. The userId configuration option requires 1.19.0 or later.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    userId: "user-12345"
))

When one user signs in on several devices, set the same user ID on each. Amplitude merges the devices into one user.

Reset when a user logs out

Call reset() when a user logs out. It clears the user ID and the user properties the SDK tracks locally, then chooses a device ID again, so later activity doesn't merge into the signed-out user.

swift
amplitude.reset()

reset() chooses the device ID the same way the SDK does on a first launch. With IDFV tracking on, which is the default on iOS, the new device ID is the same IDFV, so Amplitude can still link the two users through the device. To get a new random device ID on every reset, turn off IDFV tracking:

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    trackingOptions: TrackingOptions().disableTrackIDFV()
))

reset() doesn't start a new session, send a $clearAll to Amplitude, change opt-out, or remove queued events. The SDK notifies plugins that implement onReset().

Set the device ID

The SDK chooses a device ID on first launch. Set your own only when you already have a stable anonymous identifier, for example one shared with your server.

swift
amplitude.setDeviceId(deviceId: UUID().uuidString)

Use a value that's unique per device and at least five characters long. Two devices with the same device ID merge into one user in Amplitude. The SDK stores the device ID in UserDefaults, which device backups include, so restoring a backup on a new device can carry the old device ID with it. To read the current value, call getDeviceId().

How sessions work

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

  • While the app is in the foreground, the session never times out, no matter how long the user stays.
  • When the app moves to the background, the SDK records the time. If the app returns to the foreground within minTimeBetweenSessionsMillis (default 5 minutes), the session continues. Later, a new session starts.
  • An event tracked while the app is in the background continues the session if it comes within minTimeBetweenSessionsMillis of the previous event. Otherwise, it starts a new session. Background events therefore lengthen a session.
  • With session autocapture on (the default), the SDK sends session_start at the start of each session and session_end at the end of the previous one. Amplitude shows them as [Amplitude] Start Session and [Amplitude] End Session. The SDK sends session_end when the next session starts, not when the user leaves, so a user who never returns has no session_end.
  • With session autocapture off, events still carry a session ID. Only the session_start and session_end events stop.
  • On macOS, the SDK treats the app as in the background whenever it isn't the active app, for example when the user switches to another app.

Session events carry the current user ID and device ID, but not user properties. A user property set during a session shows on later events, not on the earlier session_start.

To change the timeout, set minTimeBetweenSessionsMillis:

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    minTimeBetweenSessionsMillis: 15 * 60 * 1000 // 15 minutes
))

To read the current session ID, call getSessionId(). For how Amplitude counts session length and session metrics, go to Track sessions.

Track an event outside any session

Set sessionId to -1 in the event options. The event doesn't belong to a session, doesn't extend the current one, and doesn't start a new one. Use it for activity the user didn't start, such as a received push notification.

swift
amplitude.track(
    eventType: "Push Notification Received",
    options: EventOptions(sessionId: -1)
)

The same option works with identify(identify:options:).

Start or end a session yourself

setSessionId(timestamp:) ends the current session and starts one with the ID you pass, in milliseconds since the Unix epoch. setSessionId(date:) does the same with a Date. A negative timestamp ends the current session without starting a new one. The next event then starts a session.

swift
amplitude.setSessionId(date: Date())

The SDK treats the ID as the session's last activity time. If the app is in the background and you pass an ID older than minTimeBetweenSessionsMillis, the next event starts a new session instead of joining yours.

Autocapture

Autocapture is the set of events the iOS Swift SDK can track without code. You choose features with the autocapture option, and your Amplitude project's remote configuration can turn features on or off. For a general introduction, go to Autocapture.

Choose features

autocapture takes an AutocaptureOptions option set. The default is .sessions.

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

Pass .all for every feature, or [] to turn off Autocapture, including session events. Set autocapture when you create the configuration. You can't change it on the instance afterward.

UIKit platforms are iOS, iPadOS, tvOS, visionOS, and Mac Catalyst. On macOS and watchOS, only sessions work, plus network requests on macOS. The SDK has no SwiftUI-native capture: in a SwiftUI app, element interactions and frustration interactions skip SwiftUI views, and screen views see only UIKit view controllers. For SwiftUI screens, track screen views yourself. If you build with the AMPLITUDE_DISABLE_UIKIT flag, the UIKit features are off on every platform.

autocapture replaces the deprecated defaultTracking option. Setting defaultTracking overwrites autocapture with its sessions, app lifecycles, and screen views values, and turns off every other feature.

Remote configuration overrides local settings

With enableAutoCaptureRemoteConfig on (the default), the SDK reads your project's Autocapture settings from Amplitude and applies them on top of your autocapture value. For each feature that remote configuration sets, its value replaces yours, in either direction: it can turn on a feature you left off, or turn off one you turned on. Features it doesn't set keep your local value. Remote configuration can also replace your network tracking rules and turn rage clicks and dead clicks on or off. Changes apply to events tracked after the SDK receives them, without an app update. Requires 1.13.0 or later.

To use only your local settings, turn off enableAutoCaptureRemoteConfig. The option is read-only after you create the configuration.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    autocapture: [.sessions, .appLifecycles],
    enableAutoCaptureRemoteConfig: false
))

App lifecycles

With .appLifecycles, the SDK observes UIApplication notifications and sends:

The version is CFBundleShortVersionString and the build is CFBundleVersion.

Screen views

With .screenViews, the SDK sends [Amplitude] Screen Viewed when a view controller from your app's main bundle appears as the top view controller. It swizzles UIViewController.viewDidAppear(_:) to detect this. [Amplitude] Screen Name is the view controller's title, or its class name without the ViewController suffix. The SDK skips a view controller that's already the last one it reported.

In SwiftUI, track screens yourself, for example from onAppear:

swift
amplitude.track(event: ScreenViewedEvent(screenName: "Settings"))

Element interactions

With .elementInteractions, the SDK sends [Amplitude] Element Interacted when a user interacts with a UIControl or a UIGestureRecognizer. It swizzles UIApplication.sendAction(_:to:from:for:) and the gesture recognizer state setter. It skips SwiftUI views and pan and pinch gestures on scroll views.

Frustration interactions

With .frustrationInteractions, the SDK detects rage clicks and dead clicks on UIKit controls and gesture recognizers. Requires 1.14.0 or later.

  • Rage click: four or more taps on the same element within one second, each within 50 points of the previous one. The SDK sends [Amplitude] Rage Click with the element properties above, plus [Amplitude] Begin Time, [Amplitude] End Time (ISO 8601), [Amplitude] Duration (milliseconds), [Amplitude] Click Count, and [Amplitude] Clicks, an array of X, Y, and Time for each tap. Coordinates start at the top left of the screen.
  • Dead click: a tap on an interactive element followed by no visible change within three seconds. The SDK sends [Amplitude] Dead Click with the element properties, plus [Amplitude] X and [Amplitude] Y. Taps inside a WKWebView don't count.

Dead clicks need a plugin that reports interface changes to the SDK, such as the Session Replay iOS plugin, installed and recording. Without one, the SDK never sends [Amplitude] Dead Click.

To turn off one kind, set interactionsOptions:

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    autocapture: [.sessions, .frustrationInteractions],
    interactionsOptions: InteractionsOptions(
        rageClick: RageClickOptions(enabled: true),
        deadClick: DeadClickOptions(enabled: false)
    )
))

To exclude a view and its subviews, call amp_ignoreInteractionEvent(rageClick:deadClick:) on it. Both parameters default to true.

swift
canvasView.amp_ignoreInteractionEvent()
carouselView.amp_ignoreInteractionEvent(rageClick: true, deadClick: false)

Network requests

With .networkTracking, the SDK sends [Amplitude] Network Request for requests your app makes with URLSession. It swizzles URLSessionTask methods to observe them. It doesn't see NSURLConnection requests, and it doesn't run on watchOS. Requires 1.12.0 or later.

By default, the SDK captures requests to every host except *.amplitude.com that end with a status code from 500 through 599. To change that, set networkTrackingOptions:

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    autocapture: [.sessions, .networkTracking],
    networkTrackingOptions: NetworkTrackingOptions(
        captureRules: [
            .init(hosts: ["*"], statusCodeRange: "400-599"),
            .init(hosts: ["api.example.com"], statusCodeRange: "0,500-599"),
        ],
        ignoreHosts: ["*.notmyapi.com"]
    )
))

For each request, the SDK checks ignoreHosts first, then uses the last rule in captureRules whose hosts, URLs, and methods match. Only that rule's statusCodeRange decides whether the SDK captures the request. With the configuration above:

  • api.example.com returns 503: captured, by the second rule.
  • api.example.com returns 401: not captured. The second rule matches the host, and 401 isn't in its range.
  • cdn.example.net returns 401: captured, by the first rule.
  • ads.notmyapi.com returns 500: not captured, because the host is ignored.

Status code 0 means the request failed before a response, for example with no connection. Host patterns accept * wildcards and ignore case. Put rules for specific hosts after general ones.

The event includes these properties:

Capture headers and bodies

To capture headers and JSON bodies, create a rule with urls, which takes exact URLs or regular expressions. With urls set, the rule ignores hosts. URL rules and header and body capture require 1.15.0 or later.

swift
let rule = NetworkTrackingOptions.CaptureRule(
    urls: [
        .exact("https://api.example.com/v1/orders"),
        .regex("^https://api\\.example\\.com/v1/users/.*"),
    ],
    methods: ["POST", "PUT"],
    statusCodeRange: "400-599",
    requestHeaders: .init(allowlist: ["X-Request-ID"]),
    responseHeaders: .init(allowlist: ["X-Trace-ID"]),
    requestBody: .init(allowlist: ["user/*", "product/**/id"]),
    responseBody: .init(allowlist: ["data/**"], excludelist: ["**/password"])
)

let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    autocapture: [.sessions, .networkTracking],
    networkTrackingOptions: NetworkTrackingOptions(captureRules: [.init(hosts: ["*"]), rule])
))
  • Header allowlists ignore case. With captureSafeHeaders on (the default), the SDK also captures a fixed list of non-sensitive headers, such as content-type and cache-control. It never captures authorization, cookie, or proxy-authorization, even when you allow them.
  • Body paths are case-sensitive. * matches one level and ** matches any number of levels. excludelist removes paths that allowlist selected.
  • The SDK can capture a response body only for data tasks created with a completion handler.

Data delivery

The iOS Swift SDK doesn't send each event as it's tracked. It saves events to files on the device, uploads them in batches, and retries failed uploads. This section covers each setting that changes that behavior. The defaults suit most apps.

How the SDK uploads events

  1. The SDK writes each event to the current storage file in the app's Application Support directory (Caches on tvOS). The SDK excludes the directory from device backups.
  2. An upload starts when the first of these happens:
    • flushIntervalMillis (default 30000) passes. The timer repeats.
    • The number of events since the last upload reaches flushQueueSize (default 30).
    • The app moves to the background, when flushEventsOnClose is true (the default).
    • You call flush().
    • The device reconnects to a network.
  3. The upload closes the current file and sends each stored file, oldest first, as one request. Only one request is in flight at a time. A file can hold more than flushQueueSize events, for example after a period offline.
  4. The SDK handles the response:
    • 2xx: deletes the file and reports success to callbacks.
    • 400 with an invalid API key: drops every event in the file and reports 400 with the message Invalid API key: <key>.
    • 400 for specific events: drops the events Amplitude lists as invalid or silenced, reports 400 for them, and queues the rest again.
    • 413: splits the file in half and sends each half. The SDK drops a single event that's still too large and reports 413.
    • 429, 408, 5xx, and other codes: keeps the file and retries. Callbacks don't fire.
  5. After each failed retry, the SDK waits 1, 2, 4, and then up to 60 seconds before the next attempt. After more than flushMaxRetries (default 6) failures in a row, it sets offline to true and stops uploading. Default changed in 1.11.9. Uploads resume when the network status changes, when you set offline to false, or on the next launch. The events stay on the device until then.
  6. A connection error, such as no internet connection, an unreachable host, or an App Transport Security block, sets offline to true right away.

The SDK asks iOS for background execution time while an upload runs, so a request can finish after the user leaves the app.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    flushQueueSize: 50,
    flushIntervalMillis: 10_000,
    flushMaxRetries: 10
))

// Upload the queue now, for example before a long-running task.
amplitude.flush()

flushIntervalMillis takes effect only when you create the instance. Changing it later has no effect.

Tune upload performance

track() doesn't wait for the network, so most tuning is a tradeoff between request count and delay:

  • Fewer requests: raise flushIntervalMillis or flushQueueSize. Events wait longer on the device before they upload.
  • Faster delivery: lower flushIntervalMillis or flushQueueSize. The SDK sends more, smaller requests and uses more battery.
  • High-volume sources: set useBatch: true to send to the Batch Event Upload API, which has higher rate limits. It doesn't change how the SDK batches events on the device.

To cap how many events the SDK keeps on the device, set maxQueuedEventCount. When you create the instance, the SDK deletes the oldest storage files until the newest files hold at least that many events. It deletes whole files and checks only at launch. More events than the limit can remain, especially after a long time offline, when every event is in one file. Requires 1.9.1 or later.

Choose a data region

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

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    serverZone: .EU
))

serverZone also selects the region for remote configuration and SDK diagnostics. Set it when you create the configuration.

Send events through a proxy

Use a proxy on your own domain to route events through infrastructure you control. Point serverUrl at the proxy, and forward each request body unchanged to the Amplitude endpoint for your region.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    serverUrl: "https://collect.example.com/amplitude",
    enableRequestBodyCompression: true
))

serverUrl overrides serverZone and useBatch for event uploads. Remote configuration and diagnostics still use the Amplitude endpoints for serverZone.

The SDK gzip-compresses request bodies and sets Content-Encoding: gzip for Amplitude's endpoints. For a custom serverUrl, it sends uncompressed bodies unless you set enableRequestBodyCompression: true, because your proxy must accept gzip bodies. Compression requires 1.17.1 or later, and enableRequestBodyCompression requires 1.17.3 or later.

Your proxy must:

  • Forward the request body and Content-Encoding header unchanged, or decompress before forwarding.
  • Forward the client's IP address, for example in X-Forwarded-For, if you want Amplitude to derive location from it. Otherwise, Amplitude records the proxy's IP.
  • Return Amplitude's status code and JSON body unchanged. The SDK reads them to decide whether to retry, split, or drop events.
  • Use HTTPS, or add an App Transport Security exception for its domain.

For setup examples, go to Proxy requests.

Use offline mode

By default, the SDK watches network connectivity with NWPathMonitor. While the device has no connection, it sets offline to true, keeps tracking events to storage, and skips uploads. When the connection returns, it sets offline to false and uploads the stored events. Requires 1.3.0 or later. watchOS has no connectivity monitor, so the SDK relies on connection errors and retries there.

To decide connectivity yourself, turn off the monitor and set offline from your own logic:

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    offline: NetworkConnectivityCheckerPlugin.Disabled
))

// Stop uploads, for example while the user is on a metered connection.
amplitude.configuration.offline = true

// Resume uploads and send what's stored.
amplitude.configuration.offline = false
amplitude.flush()

NetworkConnectivityCheckerPlugin.Disabled is nil. With the monitor off, nothing resets offline after the SDK sets it to true because of failed retries or a connection error, so set it back yourself.

Store events somewhere else

storageProvider replaces the file storage for events and identity, and identifyStorageProvider replaces the storage for held identify events. Pass any type that implements the Storage protocol. The built-in storage classes aren't public, so a custom provider implements every method itself. This option isn't available in Objective-C. For the protocol, go to Storage.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    storageProvider: MyEventStorage()
))

The default storage keeps event files in Application Support, which the Files app doesn't show, and excludes them from backups. Default changed in 1.18.2. On tvOS, the files are in Caches. Default changed in 1.18.7. The SDK moves files from the earlier location on first launch.

Set the log level

The SDK writes its own log messages with os_log, under the subsystem Amplitude and category Logging. Set logLevel to choose how much it logs. The default is .warn.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    logLevel: .debug
))

The SDK applies logLevel when you create the instance. Changing it afterward has no effect. The lowercase names require 1.17.0 or later. The uppercase names, such as LogLevelEnum.DEBUG, still work but are deprecated.

To send SDK messages somewhere else, such as your error reporting, set loggerProvider to a type that implements Logger. The SDK sets the logger's logLevel from the logLevel option at init, so filter on it in each method.

swift
final class ErrorReportingLogger: Logger {
    typealias LogLevel = LogLevelEnum
    var logLevel: Int = LogLevelEnum.warn.rawValue

    func error(message: String) {
        // Forward to your error reporting at every level, then print.
        if logLevel >= LogLevelEnum.error.rawValue { print("Amplitude error: \(message)") }
    }
    func warn(message: String) {
        if logLevel >= LogLevelEnum.warn.rawValue { print("Amplitude warn: \(message)") }
    }
    func log(message: String) {
        if logLevel >= LogLevelEnum.log.rawValue { print("Amplitude log: \(message)") }
    }
    func debug(message: String) {
        if logLevel >= LogLevelEnum.debug.rawValue { print("Amplitude debug: \(message)") }
    }
}

let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    logLevel: .error,
    loggerProvider: ErrorReportingLogger()
))

To trace a missing event through the SDK, go to Verify events.

Privacy

The iOS Swift SDK collects device and app context with every event. This section covers how to stop tracking for a user, reduce what the SDK collects, and describe the SDK's data use to Apple.

Opt users out of tracking

Set optOut to true to stop the SDK from tracking events for this user.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    optOut: true
))

// Later, after the user consents:
amplitude.optOut = false

While opt-out is on:

  • The SDK drops every new event, including identify, group, revenue, and session events, and logs Skip event based on opt out configuration at the .log level.
  • Events already stored before opt-out still upload.
  • The SDK notifies plugins that implement onOptOutChanged(_:) when the value changes.

The SDK doesn't persist opt-out. Each new Amplitude instance starts with the configured value, so store the user's choice yourself and pass it to the configuration on every launch.

Choose which device properties the SDK collects

By default, the SDK adds the app version name, OS name and version, device manufacturer and model, carrier, language, platform, and the IDFV to every event. It also sends ip: "$remote", so Amplitude records the request IP and derives location from it. On iOS, the SDK reads the carrier from CTTelephonyNetworkInfo on devices with a SIM, and sends Unknown elsewhere.

To stop collecting a field, pass a TrackingOptions object with the matching disableTrack method. Each method returns the object, so calls chain.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    trackingOptions: TrackingOptions()
        .disableTrackCarrier()
        .disableTrackIpAddress()
        .disableTrackLanguage()
))

To keep Amplitude from deriving city, region, and DMA from the IP, use disableTrackIpAddress(). Tracking options control only what the SDK sends from now on. They don't delete data Amplitude already has.

Pass a new TrackingOptions() object, as in the sample, rather than changing configuration.trackingOptions in place. Every configuration created without trackingOptions shares one default object, so a change to it affects every instance in the app.

Comply with COPPA

For apps directed at children under 13, set enableCoppaControl to true. With each event, the SDK turns off IDFV, IP address, city, and IDFA tracking on the configuration's tracking options.

swift
let amplitude = Amplitude(configuration: Configuration(
    apiKey: "YOUR_API_KEY",
    trackingOptions: TrackingOptions().disableTrackIDFV(),
    enableCoppaControl: true
))

Pass TrackingOptions().disableTrackIDFV() as in the sample, for two reasons:

  • The SDK chooses the device ID before it applies COPPA settings to the first event. Without disableTrackIDFV(), the device ID on a new install is still the IDFV.
  • COPPA control changes the tracking options object in place. Without your own object, it changes the shared default, which turns off IDFV and IP tracking for every other instance in the app.

The SDK never collects the IDFA or the city, so COPPA control removes the IDFV and the IP address in practice. With IP tracking off, the SDK sends the country from the device locale.

Describe data use in your privacy manifest

The SDK ships a privacy manifest, PrivacyInfo.xcprivacy, in its Swift package and CocoaPods resource bundle. Xcode includes it in your app's privacy report. It declares the SDK's defaults:

Update your app's own manifest to match how you use the SDK:

  • If you call setUserId() or set userId, declare the User ID data type.
  • If your app uses Amplitude data for tracking, as Apple defines it in User privacy and data use, set NSPrivacyTracking to true. Then list the endpoint domains you send to in NSPrivacyTrackingDomains: api2.amplitude.com for the US region, api.eu.amplitude.com for the EU region, or your proxy's domain.

For how to read the combined report, go to Apple's privacy manifest documentation.

Plugins

Plugins change events before Amplitude receives them, send events to other destinations, or react to identity changes. The SDK's own features, such as device context and uploads, are plugins too.

How plugins run

Each plugin has a type. For each event, the SDK runs every .before plugin, then every .enrichment plugin, then every .destination plugin, in the order you added them within each type.

A before or enrichment plugin that returns nil from execute(event:) drops the event for every later plugin, including the Amplitude upload. execute(event:) runs for every event, including identify, group identify, and revenue events. Every destination gets the event that the enrichment plugins returned, and its return value doesn't affect other destinations.

Add a plugin

Subclass a base class, override execute(event:), and pass an instance to add(plugin:). The SDK calls the plugin's setup(amplitude:) right away.

swift
class AppSectionPlugin: EnrichmentPlugin {
    override func execute(event: BaseEvent) -> BaseEvent? {
        var properties = event.eventProperties ?? [:]
        properties["app_section"] = "checkout"
        event.eventProperties = properties
        return event
    }
}

let appSection = AppSectionPlugin()
amplitude.add(plugin: appSection)

To stop a plugin, pass the same instance to remove(plugin:):

swift
amplitude.remove(plugin: appSection)

To drop events, return nil:

swift
class DropDebugEventsPlugin: BeforePlugin {
    override func execute(event: BaseEvent) -> BaseEvent? {
        return event.eventType.hasPrefix("Debug ") ? nil : event
    }
}

The base classes don't declare name or onReset(), so plugin(name:) doesn't find a subclass that adds them, and the SDK doesn't notify it on reset(). When you need either, conform a class to the Plugin protocol directly. The SDK skips a plugin whose name matches one already added.

swift
final class ResetAwarePlugin: Plugin {
    let type: PluginType = .enrichment
    let name: String? = "reset-aware"

    func execute(event: BaseEvent) -> BaseEvent? { event }
    func onReset() {
        // Clear state tied to the signed-out user.
    }
}

Send events to another destination

Subclass DestinationPlugin and override the methods for the event kinds you need. The SDK calls track(event:) for custom events, group identify events, and autocaptured events. It calls identify(event:) for $identify and revenue(event:) for revenue_amount. flush() runs when you call amplitude.flush().

swift
class WarehouseDestinationPlugin: DestinationPlugin {
    override func track(event: BaseEvent) -> BaseEvent? {
        // Send the event to your own endpoint.
        return event
    }

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

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

    override func flush() {
        // Send anything your plugin buffers.
    }
}

amplitude.add(plugin: WarehouseDestinationPlugin())

Your destination receives every event as it's tracked. It doesn't receive the SDK's held identify batching or its retries.

React to identity changes

Subclass ObservePlugin and override the hooks you need: onUserIdChanged(_:), onDeviceIdChanged(_:), onSessionIdChanged(_:), and onOptOutChanged(_:).

swift
class SignInObserverPlugin: ObservePlugin {
    override func onUserIdChanged(_ userId: String?) {
        // For example, update another SDK with the new user ID.
    }
}

amplitude.add(plugin: SignInObserverPlugin())

For every hook and the Plugin protocol, go to Plugin. For a plugin that prints each event while you debug, go to Verify events.

Objective-C

The SDK exposes an Objective-C interface through wrapper classes. The instance class is Amplitude, and the other classes use the AMP prefix, such as AMPConfiguration, AMPBaseEvent, AMPIdentify, and AMPRevenue. Import the module, and also import AmplitudeCore to use AMPServerZone values:

objc
@import AmplitudeSwift;
@import AmplitudeCore;

AMPConfiguration *configuration = [AMPConfiguration initWithApiKey:@"YOUR_API_KEY"];
configuration.autocapture = [[AMPAutocaptureOptions alloc] initWithOptionsToUnion:@[
    AMPAutocaptureOptions.sessions,
    AMPAutocaptureOptions.appLifecycles,
]];
configuration.serverZone = AMPServerZoneEU;
configuration.logLevel = AMPLogLevelDEBUG;
Amplitude *amplitude = [Amplitude initWithConfiguration:configuration];

AMPBaseEvent *event = [AMPBaseEvent initWithEventType:@"Song Played"
                                      eventProperties:@{@"title": @"Here Comes the Sun"}];
[amplitude track:event];

AMPIdentify *identify = [AMPIdentify new];
[identify set:@"plan" value:@"pro"];
[amplitude identify:identify];

[amplitude setUserId:@"user-12345"];
[amplitude reset];

Write plugins with blocks:

objc
AMPPlugin *plugin = [AMPPlugin initWithType:AMPPluginTypeEnrichment
                                    execute:^AMPBaseEvent * _Nullable(AMPBaseEvent * _Nonnull event) {
    [event.eventProperties set:@"app_section" value:@"checkout"];
    return event;
}];
[amplitude add:plugin];

The Objective-C interface has these limits:

  • No storageProvider, identifyStorageProvider, maxQueuedEventCount, or enableDiagnostics configuration options.
  • optOut is a property of AMPConfiguration, not of Amplitude. Set it on amplitude.configuration.
  • Network tracking rules take only hosts and statusCodeRange. URL patterns, methods, headers, and bodies need Swift.
  • AMPPlugin supports setup, execute, and flush blocks only, not the per-kind destination methods or the observe hooks. You can also pass a Swift plugin to add:.
  • The loggerProvider block receives the configured log level, not the level of each message.

For the selector of each method, go to Objective-C names.

이 내용이 도움이 되었나요?

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

이 페이지에서