API reference

StatsClient is an actor; every method below is awaited. Value types are Sendable across every boundary.

StatsClient(configuration:)Constructs the client. Performs no disk I/O, so it is safe on the main actor during launch.
track(_ name: String, props:)Captures an event. Returns once it is on disk, so a kill does not lose it. Names are snake_case; props are flat and carry no user text.
record(_ name: String, props:)The same capture without await: nonisolated and returns immediately, so it suits a button action or a view body. It returns before the event is on disk; use track() when you need that guarantee.
identify(userID:)Opt-in and hashed with your salt before it leaves the device. Under the default consent the hashed userId is then sent with every event and persisted, so an app that calls it declares User ID and marks what it collects as linked. Most apps should never call it.
currentConsentThe consent groups in force — the stored choice if setConsent has ever been called, otherwise the configured value. An async getter: read with await.
hasStableInstallIdentityTrue when the consent in force includes .identity, so sessions started from now on carry a stable install id. An async getter: read with await.
setConsent(_:)Sets the three consent groups. Revoking discards the queue and deletes the stored install UUID.
setEnabled(_:)The master opt-out you ship for a person. Persists; keeps the install UUID unused rather than deleting it.
isEnabledThe master opt-out’s current value; true unless setEnabled(false) was called. An async getter: read with await.
flush()Sends what is queued now, instead of waiting for the count or interval trigger.
waitForFlushes()Returns once every flush already triggered has finished. Never waits on a scheduled retry or the interval timer.
reset()Flushes (or, while not collecting, discards) the queue, then forgets the install: with identity consent (the default) a fresh install id, without it the stored id is deleted. Resets seq to 0, clears the hashed userId and starts a new session.
shutdown()Cancels the interval timer and any pending retry, leaving queued events on disk for the next launch. For a client you are tearing down.
applicationDidBecomeActive()Starts or continues a session and emits app_open. Call it from scenePhase.
applicationDidEnterBackground()Emits app_background and flushes. Call it from scenePhase.
StatsQuery.summary(projectId:from:to:)Reads your own numbers back with a read key. Never embed a read key in a shipped app.

Consent groups

Three independent groups, persisted: usage, diagnostics, identity. Since 0.3.0 the default is all three (.default and .all are the same set): a stable, salted, random install id, and no user id unless you call identify(userID:). The SDK's privacy manifest declares Device ID for it. Pass [.usage, .diagnostics] to keep install ids per session — then installs count sessions and there is no retention. Configured consent applies on every launch until the app first calls setConsent(_:); from then on the stored value wins — so a choice recorded on 0.2.0, including setConsent(.default) (stored then as [.usage, .diagnostics]), stays as recorded after the upgrade. Pass .none and nothing is collected at all — no queue file, no id, no context.