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.
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.
https://github.com/appmetricskit/appmetrikskit-ios-swift.gitPackage 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.
.package( url: "https://github.com/appmetricskit/appmetrikskit-ios-swift.git", .upToNextMinor(from: "0.1.6")).product( name: "AppMetricsKit", package: "appmetrikskit-ios-swift").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.
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.
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.
// 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.
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.
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.
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.
// 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()