Appearance
Install in an app
A mobile, desktop, server or game app needs no SDK. It sends its events to the collector over HTTP, as one JSON batch, and they arrive in the same reports as a website's or an extension's. Every platform below has a runnable example that does the same four things, so they compare line for line: it reads the write key, keeps a random anonymous id, sends its events as one batch, and retries a failed send with the same event ids.
1. Create an App project
From Projects, choose New project and pick An app. Its Setup screen shows the write key, and the code for each language below with the key already in it. An App project accepts requests from anywhere, with or without an Origin header: its write key is its credential, and it can only write.
2. Send a batch
json
{
"writeKey": "wk_your_key_here",
"client": "app",
"clientVersion": "my-app-1.0.0",
"appVersion": "2.4.0",
"anonymousId": "5f0c6c0e-7f7e-4a51-9d0b-1f9f3c1b2a77",
"os": "iOS",
"deviceType": "mobile",
"events": [
{ "id": "0b6f4c2e-7a1d-4f0e-9c8b-2d3e4f5a6b7c", "name": "app_opened", "ts": "2026-10-15T09:00:00.000Z" }
]
}POST it to https://analyticstrend.com/v1/collect with content-type: application/json.
clientis always"app".appVersionis your app's own version, so you can tell releases apart.osanddeviceTypesay what the app runs on, because a native app's User-Agent names neither.osis one of"iOS","Android","macOS","Windows","Linux"or"ChromeOS", anddeviceTypeone of"mobile","tablet"or"desktop". Never a version or a model. A value off these lists is left out, not refused. An app in a webview, such as a Tauri app, can send them too; the webview's User-Agent is used first.- Each event's
idis made once, when the event happens. Retry a network error or a5xxwith the same body, so the collector stores each event once. Do not retry a4xx: sending it again would not help.
Event names follow the naming rules, and every limit is on the limits page.
iOS and macOS
The Swift example is one file to copy into an iOS or macOS app. It uses URLSession only, keeps the anonymous id in a file (an app keeps it in UserDefaults), and declares "iOS" or "macOS" at compile time, with an iPad as a tablet. Send from a background task so the interface never waits on the network.
Android
The Kotlin example uses HttpURLConnection, which Android has, so its Analytics class works unchanged in an Android app. Keep the anonymous id in SharedPreferences, and send off the main thread, for example from a coroutine on Dispatchers.IO or a WorkManager job.
Desktop apps
- Tauri: the Tauri example sends from the app's Rust side. The page calls a
trackcommand, and the anonymous id lives in the app's data directory. - Rust: the Rust example is the same client on its own, for any native app.
- .NET: the C# example uses
HttpClient, for a WPF, WinUI or .NET MAUI app.
Servers
The Node and Python examples send from a server, with nothing but the standard library. A server sends "location": false, because its address is not its user's, and sends no os or deviceType, because its system is not its user's either. When it acts for one of your app's users, it sends that user's anonymous id, so the event joins the rest of their activity.
Games
The C# example carries over to Unity: keep the anonymous id in PlayerPrefs and send with UnityWebRequest. The batch is the same.
The anonymous id
The anonymous id is how AnalyticsTrend counts people, so make it once, randomly (a UUID), keep it, and send the same one every time. Never use an email address, an account id, the advertising identifier (the IDFA on iOS, the advertising ID on Android), identifierForVendor or the Android ID. Each of those would make your data personal data, and could be joined with other data in a way a random value cannot.
Uninstalls
A user's first event is their install, shown on the Overview as Installs (first opens). An uninstall is counted when your app sends an uninstall event. A desktop uninstaller can send one before it removes the app; a mobile app is removed without running anything, so iOS and Android apps never send one.
App Store and Google Play privacy
What AnalyticsTrend collects, for the stores' privacy forms. Your own events may collect more: answer for those too.
Apple's App Privacy details:
- Identifiers: Device ID, for the random anonymous id. Not linked to the user's identity, and not used for tracking.
- Usage Data: Product Interaction, for the events you send. Not linked to the user's identity, and not used for tracking.
- Location: Coarse Location, only if you leave location on. Leave it out when every batch sends
"location": false. - The purpose of each is Analytics.
Google Play's Data safety form:
- App activity: App interactions, for the events you send.
- Device or other IDs, for the random anonymous id.
- Location: Approximate location, only if you leave location on.
- Each is collected, not shared, for Analytics, and encrypted in transit. None is linked to the user's identity.
Verify it
Run your app, then check the Events screen in your dashboard. To try a batch without a project, the examples repository has a mock collector that checks each batch with the collector's own rules.