iOS SDK

Install the Swift package and send your first analytics event.

Use the official AppMetricsKit Swift Package to capture onboarding, paywall, purchase, subscription, and app-health events without sending raw account IDs, advertising IDs, or cross-app identifiers.

Agent ready

Implement the complete iOS integration

Copy a repository aware prompt covering architecture, consent, identity, revenue events, privacy, tests, and release verification.

Install from GitHub

In Xcode, open File > Add Package Dependencies, paste the package URL, choose Up to Next Minor Version from 0.1.6, then select AppMetricsKit or AppMetricsKitUnlinked.

View package
Code
https://github.com/appmetricskit/appmetrikskit-ios-swift.git

Package details

Repository
appmetricskit/appmetrikskit-ios-swift
Product
AppMetricsKit or AppMetricsKitUnlinked
Platforms
iOS 15+, macOS 12+
Swift tools
5.9+

Swift Package manifest

If your app uses its own Package.swift, add the package and product manually.

Code
.package(  url: "https://github.com/appmetricskit/appmetrikskit-ios-swift.git",  .upToNextMinor(from: "0.1.6"))
Code
.product(  name: "AppMetricsKit",  package: "appmetrikskit-ios-swift")
Code
.product(  name: "AppMetricsKitUnlinked",  package: "appmetrikskit-ios-swift")

Configure once at app launch

Generate an ingest key in AppMetricsKit, then configure the SDK with your deployed ingest endpoint. Initialize collection from your app's persisted consent state.

Code
import Foundationimport AppMetricsKitimport SwiftUI
@mainstruct ExampleApp: App {  @Environment(\.scenePhase) private var scenePhase
  init() {    // Read this value from your app's persisted consent state.    let analyticsConsentGranted = false
    AppMetricsKit.configure(      AppMetricsConfiguration(        ingestURL: URL(string: "https://appmetricskit.com/api/ingest")!,        ingestKey: "amk_live_...",        testMode: false,        allowedPayloadKeys: ["plan", "source", "productId", "price", "errorCode"],        collectionEnabled: analyticsConsentGranted,        automaticAppLaunchTracking: false      )    )  }
  var body: some Scene {    WindowGroup {      ContentView()    }    .onChange(of: scenePhase) { newPhase in      if newPhase == .background {        AppMetricsKit.persistPendingEvents()      }    }  }}

Unlinked product

Choose AppMetricsKitUnlinked when the app needs aggregate analytics for a Data Not Linked to User label. This product does not send account hashes, session IDs, exact device models, timezones, or exact event timestamps. Unique-user and retention views require the regular pseudonymous product.

Code
import AppMetricsKitUnlinkedimport Foundationimport SwiftUI
AppMetricsKit.configure(  AppMetricsConfiguration(    ingestURL: URL(string: "https://appmetricskit.com/api/ingest")!,    ingestKey: "amk_live_...",    testMode: false,    allowedPayloadKeys: ["plan", "source", "productId", "price", "errorCode"],    collectionEnabled: analyticsConsentGranted,    automaticAppLaunchTracking: false  ))
AppMetricsKit.setCollectionEnabled(true)AppMetricsKit.trackAppLaunch()AppMetricsKit.track("Paywall.viewed", payload: ["plan": "pro_monthly"])

Track events

Event names use Namespace.action. The SDK hashes user IDs on device before sending them as anonymousUserId. Identify before recording the launch when retention should use the stable account hash.

Code
// Call after the user grants analytics consent.AppMetricsKit.setCollectionEnabled(true)AppMetricsKit.identify(userId: user.id)AppMetricsKit.trackAppLaunch()
AppMetricsKit.track(  "Paywall.viewed",  payload: ["plan": "pro_monthly", "source": "onboarding"])
AppMetricsKit.track(  "Purchase.completed",  payload: ["plan": "pro_monthly"],  floatValue: 29.99)

Built-in helpers

Use helper methods for the event names that power AppMetricsKit dashboards.

Code
AppMetricsKit.trackOnboardingStarted()AppMetricsKit.trackOnboardingCompleted()AppMetricsKit.trackPaywallViewed(plan: "pro_monthly")AppMetricsKit.trackPurchaseCompleted(plan: "pro_monthly", amount: 29.99)AppMetricsKit.trackError(name: "network_timeout")

Privacy defaults

  • Raw user IDs are hashed on device with SHA-256.
  • The bundled manifest declares product interaction, purchase history, other diagnostic data, and the optional hashed user ID as linked data for analytics, with tracking disabled.
  • The unlinked product bundles a separate manifest that declares product interaction, purchase history, and diagnostics as not linked to the user.
  • Payloads are flat string, number, or boolean values only.
  • Blocked keys such as email, phone, name, IP, location, and IDFA are dropped.
  • Values that look like email addresses, phone numbers, or card numbers are dropped.
Review Apple privacy guidance

Offline queue and flushing

Events are persisted to disk, batched, and protected by stable event IDs. The SDK retries network failures, HTTP 408, HTTP 429, and HTTP 5xx responses. Other non-success responses are treated as permanent and dropped so they cannot block the queue. Queue writes are coalesced for up to one second, so persist pending events when the app enters the background as shown in the configuration example.

Code
let result = await AppMetricsKit.flush()print("Delivered events:", result.delivered)

Consent and collection

Disabling collection rejects new events, purges queued events, and resets the in-memory account hash and session. A network request that was already in flight may still complete.

Code
// Disabling collection purges queued events and the in-memory identity.AppMetricsKit.setCollectionEnabled(false)
// Identify again after the user opts back in.AppMetricsKit.setCollectionEnabled(true)AppMetricsKit.identify(userId: user.id)AppMetricsKit.trackAppLaunch()