Analytics for Apple platforms

No IPs. No ad IDs. No idea who your users are.

SwiftStats measures how your app is used without collecting anything that identifies the person using it. Privacy isn't a setting you turn on — the SDK has no code path that gathers it.

Retained
Event names, counts, day, app version, OS version, device model, locale.
Never retained
IP addresses, IDFA, email, name, location, free text, anything linking one app to another.
Install id
A random UUID salted and hashed on device, scoped to one app. It counts installs; it does not describe a person.
No ATT prompt
NSPrivacyTracking is false and there are no tracking domains. A test in the repo asserts it.
OverwatchLAST 30 DAYS
OPENS
12,481
+8.2% vs prev 30d
ACTIVE INSTALLS
1,904
+3.1% · installs, not people
READ-OUT

Opens rose 8.2% while active installs rose 3.1%. Existing installs are opening the app more often rather than new ones arriving.

rule:opens_delta − installs_delta > 3pp

It tells you what changed

Every read-out is a deterministic rule over your own numbers. No model, no guessing — the rule that produced each sentence is shown next to it.

It admits what it doesn't know

When a figure is an upper bound, when consent limited it, when a batch never arrived — the dashboard says so on the tile, not in a support article.

Yours if you want it

The SDK and the Cloudflare backend are MIT. Run the whole pipeline in your own account, or let us host it and skip the ops.

Quickstart

One package, one key, first event in minutes

Add the Swift package, paste the write key the setup wizard hands you, and watch the page flip to Connected when your first batch lands. Zero dependencies, Swift 6 language mode, actor-based.

  • iOS 18+, iPadOS 18+, macOS 15+
  • Foundation and os only — nothing else to audit
  • track() returns once the event is on disk, so a kill doesn't lose it
  • Write keys are append-only and scoped to one project
Full docs and API reference →
Swift
import Stats
import StatsCloudflare

let stats = StatsClient(configuration: StatsConfiguration(
    appId: "com.example.MyApp",
    projectId: "myapp",
    installIdSalt: "a-constant-per-app-string",
    sink: CloudflareSink(
        endpoint: try CloudflareEndpoint(string: "https://api.swiftstats.co"),
        writeKey: writeKey
    ),
    autoEvents: [.appOpen, .appBackground, .sessions]
))

await stats.track("paywall_shown", props: ["variant": "b"])

Three tiers, no per-event billing

Full pricing →
Free
$0forever
One app on one platform. Everything honest about the numbers, nothing held back on privacy.
Pro
$10/ month
Five apps and a quarter of history, plus the comparison screens and programmatic access.
Studio
$25/ month
Ten apps and a full year of history, for people shipping on behalf of others.

Start free, or run it yourself

Unlimited events on every tier. Self-hosting always free. One app on one platform, free forever. No card required.