Skip to content
trackd.one

App analytics

App analytics without device IDs

SDKs for Android, iOS, Flutter and React Native. Screens, events and in-app purchases land in the same dashboard and the same event pool as your websites — hosted in the EU.

Built for apps — and for data minimisation

All SDKs behave the same: one format, the same rules, no dependencies beyond the essentials.

Batching

Events are collected in memory and sent in batches — at 20 events, after 30 seconds or when the app goes to the background.

Offline queue

Short dead zones are bridged: retries with exponential backoff, the same batch_id prevents duplicates, events keep their timestamp.

No device IDs

No ANDROID_ID, no IDFA/IDFV, no advertising id, no device model, no fingerprinting. The user agent is neutral (trackd-android/1.1.0).

In-memory session

The session id is random, lives in memory only and rotates after 30 minutes of inactivity. The SDKs write nothing to the device.

Copy one file

Copy-in install without a package manager: drop Trackd.kt, Trackd.swift or trackd.dart into your project — done. Registry packages are coming.

Events for games

Helpers for game_start, level_complete, game_over, ad_view, video_watch and in-app purchases — ready for funnels and revenue.

Integrated in a few lines

Initialise once at app start, then track screens and events. You find YOUR_WEBSITE_ID in the dashboard.

Platform
MyApp.kt
// Copy Trackd.kt to app/src/main/java/one/trackd/sdk/Trackd.kt
import one.trackd.sdk.Trackd

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Trackd.init(this, "YOUR_WEBSITE_ID", debug = BuildConfig.DEBUG)
    }
}

// Screens and events
Trackd.screen("Home")
Trackd.event("signup", mapOf("plan" to "pro"))
MyApp.swift
// Add Trackd.swift (+ TrackScreenModifier.swift for SwiftUI) to your app target
import SwiftUI

@main
struct MyApp: App {
    init() {
        Trackd.configure(websiteId: "YOUR_WEBSITE_ID")
    }
    var body: some Scene { WindowGroup { ContentView() } }
}

// Screens and events
Trackd.screen("Home")                     // or .trackScreen("Home") on a SwiftUI view
Trackd.event("signup", data: ["plan": "pro"])
lib/main.dart
// Copy trackd.dart to lib/trackd.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'trackd.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Trackd.init(
    websiteId: 'YOUR_WEBSITE_ID',
    appVersion: '1.0.0',
    debug: kDebugMode,
  );
  runApp(MaterialApp(
    navigatorObservers: [TrackdNavigatorObserver()], // automatic screen tracking (named routes)
    home: const HomePage(),
  ));
}

// Events
Trackd.event('signup', {'plan': 'pro'});
analytics.js
import { AppState, Platform } from 'react-native'
import { Trackd } from './lib/trackd.mjs'   // copy-in: https://trackd.one/sdk/trackd.mjs

export const trackd = new Trackd({
  websiteId: 'YOUR_WEBSITE_ID',
  platform: Platform.OS,                   // "ios" | "android"
  appVersion: '1.4.0',
})

// flush when the app goes to the background
AppState.addEventListener('change', (state) => {
  if (state === 'background') trackd.onBackground()
  else if (state === 'active') trackd.onForeground()
})

trackd.screen('Home')
trackd.event('signup', { plan: 'pro' })
ES module
// 1. Download https://trackd.one/sdk/trackd.mjs into your project (e.g. src/lib/trackd.mjs)
import { Trackd } from './lib/trackd.mjs'

const trackd = new Trackd({ websiteId: 'YOUR_WEBSITE_ID', host: 'https://trackd.one' })

trackd.screen('Home')                       // screen / page view
trackd.event('signup', { plan: 'pro' })     // custom event (SDK: event, t.js: trackd.track)
trackd.revenue(9.99, 'EUR', 'order-123')

What is sent — and what is not

Every request is a batch with coarse context. Nothing else leaves the app.

POST https://trackd.one/api/collect
{
  "website_id": "8f0c…",
  "batch_id": "Qm3x9TzK0aP7bL2vR8cW1yNe",
  "sent_at": 1760000005000,
  "context": {
    "platform": "android", "app_version": "2.3.1", "os_version": "Android 15",
    "screen": "1080x2400", "language": "de-DE", "device": "mobile",
    "session_id": "k3J9x0aQ7bP2m1LzQ8vT", "sdk": "trackd-android/1.1.0"
  },
  "events": [
    { "type": "screen_view", "name": "Home", "timestamp": 1760000000000 },
    { "type": "event", "event_name": "level_complete", "event_data": { "level": 5 } }
  ]
}

Never sent or stored

  • Device identifiers (ANDROID_ID, IDFA, IDFV, advertising id, install id, MAC/IMEI)
  • Device model or serial number
  • Cookies, SharedPreferences, UserDefaults or files
  • Fingerprinting signals (canvas, fonts, sensors)
  • The IP address — only a daily rotating salted hash

Your part

Do not put personal data (names, emails, user ids) into screen names or event data — that is the one thing the SDKs cannot check for you.

Privacy answers for the App Store and Google Play

These answers describe the trackd SDK only. Add whatever else your app collects.

Google Play — Data safety

  • Data collected: App activity → App interactions (screens, events); with revenue also → Other actions
  • Location → Approximate location (country, derived server-side from the IP)
  • Shared with third parties: No (trackd.one is your processor)
  • Encrypted in transit: Yes (HTTPS) · Purpose: Analytics
  • Device or other IDs: not collected

Apple — App Privacy

  • Usage Data → Product Interaction: not linked, not used for tracking, purpose Analytics
  • Location → Coarse Location (country): not linked, no tracking
  • With revenue: Purchases → Purchase History, not linked
  • Tracking: No — the SDK triggers no App Tracking Transparency prompt
  • PrivacyInfo.xcprivacy is included — merge its entries into your privacy manifest

Consent: please assess it yourself

Unlike the web script, the app SDKs read device and app information on the device (e.g. app and OS version, screen size, language). Whether you need consent for this under § 25 TDDDG / Art. 5(3) ePrivacy has to be assessed for your app — which is why we deliberately do not advertise apps as "consent-free". Offer a way to switch analytics off in any case: setEnabled(false) stops tracking and drops the queue. Not legal advice.

App analytics questions

How are users counted without a device ID?
Sessions, screen views and events are exact. "Users" are approximate: they are counted from a salted hash of the IP address that rotates daily — one user per IP and day. People on the same network count once, switching between Wi-Fi and mobile data counts twice, and nobody is recognised the next day.
What happens offline?
Events stay in memory (max. 500, oldest dropped first) and are retried with backoff once the network is back. Because nothing is written to disk, events are lost if the system kills the app before they could be sent.
Are there packages on Maven, Swift Package Index, pub.dev or npm?
Not yet — they are coming. Until then install by copy-in (one source file) or as a local git / path package. All downloads are listed in the documentation.
Can I measure a website and an app in the same account?
Yes. Every website and app is a project; all share your plan’s event pool. The Free plan includes two projects — for example one website and one app.
Does trackd.one work for apps?
Yes. SDKs for Android, iOS, Flutter and JavaScript capture screens and events in the same account — websites and apps share one event pool. Important: the app SDKs read device and app information on the device. Whether you need consent for this is something you have to check for your app.

Measure your first app in minutes

Start for free — the Free plan works without payment details.