X3 App tracking
Every app install. With its source.
Where your users come from, who signs up and what they buy. In one profile with your website.
- iOS · Android · React Native · Flutter
- No fingerprinting
- Consent your way
01The problem
- 01
The store eats the click.
Between the ad and the first open sits the store. The campaign does not make it through.
- 02
Logins without a source.
Whoever signs up in the app is a stranger. Even if they were a lead on your website yesterday.
- 03
Purchases without a person.
Subscriptions run through the App Store and Google Play. Your campaigns never learn who buys.
What the app store swallows.
Your ad works. But the trail breaks in the store.
02How it works
- AdtoLanding pageClick with utm_* and fbclid
- Landing pagetoX3Page view: session and journey
- Landing pagetoX3Tap “Get the app”: the X3 link issues a click token
- X3toStoreRedirect: Android with referrer, iOS to the App Store
- StoretoNordlicht appInstalland first open
- Nordlicht apptoX3First open reports the sourcePlay referrer · Apple Ads tokenAndroid: the click token finds the web sessioniOS: Apple Ads exact, otherwise open for nowno IP matching, no fingerprinting
- Nordlicht apptoX3Sign-up: identify()User ID hash · email hashSame email hash as in the web journeyThe iOS install becomes “Via login” afterwards
- StoretoX3Apple postback copy, aggregated, after 24 to 48 h
- X3toAd“Subscription” conversion to Meta, with the web fbclid
From click to account.
Android is exact, through the Play referrer. iOS through Apple Ads, or at login at the latest.
03Accuracy
Every number shows its accuracy.
Android delivers the campaign through the Play referrer. iOS shows Apple Ads exactly, the rest per campaign. At login you see the journey, if the person is known.
| Situation | iOS | Android |
|---|---|---|
| X3 link on your website, then the store | Via loginwhen the web journey carries an identity, otherwise aggregated | Exact (Play referrer)the referrer carries UTMs and the click token |
| Apple Ads campaign | Exact (Apple Ads)campaign down to the keyword, no ATT needed | does not exist on Android |
| Meta app campaign | AggregatedApple postbacks per campaign, per person via login | Exact (Play referrer)Meta Install Referrer inside the Play referrer |
| Google app campaign | AggregatedApple postbacks per campaign, per person via login | Exact (Play referrer)gclid inside the Play referrer |
| Store search, word of mouth | Unknownno source until a login links it | OrganicPlay reports the install as organic |
| Match a login to an existing lead | Via loginthrough the email hash or user ID hash | Via loginthrough the email hash or user ID hash |
| Purchase with user data to ad platforms | only with ATT permission, otherwise without user data | with the “Ad measurement” consent |
04One profile
- Meta instant form3 OctLead · email hash
- Email hashWeb session5 Octfbclid · campaign autumnPlan by email: email hash
- Email hashiPhone app5 OctInstall · sign-upUser ID hash · email hash
- Account tokenApp Store purchase7 OctSubscription · account token
- User ID hashiPad app20 OctLogin · user ID hash
- 3 OctInstant form, source Meta
- 5 OctWebsite, campaign autumn
- 5 OctApp installed (iOS)
- 5 OctAccount created
- 7 OctSubscribed, €59.99
- to 26 Oct12 logins, 2 devices
One person. One profile.
Login connects everything, without fingerprinting. App usage lands on the lead you already know.
- Only hashes. At login, email and user ID leave the device only as SHA-256.
- No lead from a login. A lead appears only when you want one.
- Every device. iPhone, iPad and browser end up in one journey.
05Purchases and conversions
- Nordlicht app
X3.purchase(…)Hint with the order id - X3 holds the purchaseuntil the order id is confirmedWaiting
- Confirmation
- App Store Server Notifications
- Google Play RTDN
- RevenueCat
- Your server
- Purchase countsGoal, revenue, lead profile
- Ad platformsonly with “Ad measurement”
Meta
Google Ads
TikTok
LinkedIniOS without ATT permission: Meta and TikTok without user data, Google Ads and LinkedIn are skipped.
Only purchases that really happened.
The app reports the purchase, the store confirms it. Only then does it count and go to your ad accounts.
- Straight from the store. Store notifications come to X3 and are verified cryptographically.
- Purchase and person. The account token links both: appAccountToken at Apple, obfuscatedAccountId at Google.
- Leads from the app. X3.lead() sends an inquiry just like a form on your website.
06Recordings
- Read the screenUIKit, SwiftUI, Compose, React Native
- Maskinput never, text and images masked
- Wireframe diffplus taps, rage taps and dead taps
- Buffergzip, at most 8 MB, optionally Wi-Fi only
- Uploadthrough your domain, only with consent
- PII checka second safeguard on the server
- Storage in the EUretention as set in your project
- Playerwith a phone frame, screen instead of URL
- On the leadrecording in the visit and the lead profile
See sessions. Never what's typed.
A wireframe instead of video, light and masked. It plays in the same player as your website.
- Typed input is never recorded, not even passwords or card data.
- Text and images are masked by default.
- A visible recording indicator in the app is on by default.
- Screenshots only for screens you allow in code.
- Pauses in low power mode.
08Privacy
What X3 never does.
No fingerprinting, no advertising IDs. Only what you allow gets measured.
Never
- Fingerprinting or IP matching between app and web
- IDFA, GAID or the device name
- Typed text, clipboard, contacts or location
- Third-party tracking domains: only your domain or X3
Always
- A random install ID, never backed up, only a hash at X3
- Email and user ID from identify() only as SHA-256
- Privacy manifest and store details ready to use
- Erase per user: by user ID, email or install ID
09App stacks
For every app stack.
Swift, Kotlin, React Native, Expo and Flutter. Data runs through your own domain.
import X3Kit
X3.configure(key: "pk_3x_…", options: X3Options(
consent: X3ConsentOptions(mode: .optIn),
host: URL(string: "https://nordlicht.app/n3")!))
X3.identify(userId: user.id, email: user.email)
import io.x3growth.sdk.*
X3.configure(this, "pk_3x_…", X3Options(
consent = X3ConsentOptions(mode = X3ConsentMode.OPT_IN),
host = "https://nordlicht.app/n3"))
X3.identify(userId = user.id, email = user.email)
import { X3 } from "@x3growth/react-native";
X3.configure("pk_3x_…", {
consent: { mode: "opt_in" },
host: "https://nordlicht.app/n3" });
X3.identify(user.id, { email: user.email });
import 'package:x3growth/x3growth.dart';
await X3.configure('pk_3x_…', const X3Options(
consent: X3ConsentOptions(mode: X3ConsentMode.optIn),
host: 'https://nordlicht.app/n3'));
X3.identify(user.id, email: user.email);
Here in opt-in mode: X3 measures only after consent, through the ready-made dialog or X3.consent().
- @x3growth/react-nativeExpo module, hooks
- Expo config pluginInfo.plist, manifest
- x3growth (Flutter)Plugin for iOS and Android
- X3Kit · SwiftiOS 15+CoreReplayUI
- io.x3growth:sdk · KotlinAPI 24+sdkreplaycompose
- iOSAdServices · AdAttributionKit
- SKAdNetwork · StoreKit 2 · ATT
- AndroidPlay Install Referrer
- NeverIDFA · GAID · fingerprinting
/v1/m/* · /go/* · /.well-known/appattribution · /.well-known/skadnetworkFAQ
Questions about app tracking
Does it work on iOS without ATT permission?
Does X3 use fingerprinting?
Who decides on consent?
When does a purchase count?
What do recordings capture?
What does app tracking cost?
How much work is the setup?
Where are the docs?
10Get started
Find out where they come from.
Free forever, no credit card. App and website in one project.