App tracking troubleshooting
Start with debug logs (debug: true; iOS os.Logger subsystem io.x3growth.sdk, Android Logcat
tag X3) and the setup checklist in Einstellungen › Apps › Nordlicht › Einrichtung (Settings ›
Apps › Setup). The checklist links to the matching section below for every open item.
Nothing arrives
| Debug log or symptom | Cause | Fix |
|---|---|---|
| "not configured" | configure is not called, or after the first calls | call it first, in App.init, application(_:didFinishLaunchingWithOptions:) or Application.onCreate |
| "invalid key" | the key is not an app key (pk_3x_ plus 30 characters) | copy the key from Einstellungen › Apps; a website key does not work |
| consent pending | mode opt_in and the user has not decided | show the consent sheet; with bufferUntilDecision events of this launch are sent after the grant |
403 app_mismatch | the platform or bundle id of the build differs from the registered app | register the exact bundle id or package name (flavours and .debug suffixes count) |
403 key | the key was revoked or belongs to another app | create or roll the key under Schlüssel (Keys) |
403 disabled | the app is switched off in the dashboard | switch it on; the SDK resumes after the next config fetch |
stored: false, reason: consent | analytics is not granted in the batch | check X3.consentState() |
429 rate_limited | too many batches from one device | the SDK backs off; check for a loop calling flush() |
| nothing in reports, but on the Einrichtung (Setup) tab | debug builds are test traffic, which reports exclude unless include_test=true (test traffic) | look at the session list, or set test: false for a release check |
React Native: TypeError at start | consent.mode missing | add consent: { mode: "opt_in" } (or another mode) |
Through a proxy: the proxy must run @x3growth/sdk 1.3.0 or later, otherwise /n3/v1/m/* answers
- Check with
curl -I https://nordlicht.app/n3/v1/m/config/pk_3x_…?plat=ios&bid=app.nordlicht
(expect 200 or 403, never 404).
Wrong or missing screens
- UIKit: containers and
UIHostingControllerare skipped on purpose. SwiftUI screens need.x3Screen("Name")orX3.screen. - React Native, Flutter: native auto screens are off; use
useX3NavigationTracking,useX3ExpoRouterTrackingorX3NavigatorObserver. Unnamed Flutter routes are skipped (debug log). - Android Fragments: tracked only through
X3.screen. - A screen never appears: it may match the project's excluded screen paths (Einstellungen › Erweitert), or its name normalizes to the same path as the previous screen.
- Events before the first screen attach to a screen view
/after 2 seconds; callscreenearlier.
Install source missing
| Symptom | Check |
|---|---|
every install unknown | the purpose attribution is not granted, or the app is used only in the simulator (no AdServices token) |
Android X3 link installs not referrer | the link went through a proxy older than 1.3.0, the store URL lost the referrer parameter (link shorteners), or the install happened more than 30 days after the click |
| Meta installs without campaign | the Meta Install Referrer key is missing or wrong (Installationsquelle) |
iOS Apple Ads installs not apple_ads | wait: Apple answers with a delay (tier pending); the token is retried for one hour |
| iOS installs from Meta or Google not exact | expected: these are aggregated on iOS; exact only after a login with a known identity (accuracy) |
| X3 link opens the store although the app is installed | Universal Links or App Links are not verified: check apple-app-site-association (path /n3/go/*) and assetlinks.json |
Purchases stay held
A purchase conversion waits for a server confirmation with the same order id:
- iOS: the hint uses
Transaction.id; the App Store notification carries the sametransactionId. Check that App Store Connect sends to the X3 URL (Production and Sandbox) and that a test notification arrived. - Android: the hint uses the Play
orderId(GPA.…); without a Play service account X3 cannot read order ids from RTDN, so confirmations fail. Upload the service account or confirm from your server. - RevenueCat: the
Authorizationheader must match the value in X3. - Your server: send the store transaction id, not your internal order number, as
orderId.
The Store-Benachrichtigungen table shows every notification, whether it was linked and the forwarding state.
No postback copies
NSAdvertisingAttributionReportEndpointandAdAttributionKit › AttributionCopyEndpointname your registrable domain (https://nordlicht.app, no path).POST https://nordlicht.app/.well-known/skadnetwork/report-attribution/must reach the proxy without a redirect (Next.js:skipTrailingSlashRedirect: true).- The proxy has a proxy key; postbacks without one are refused.
- The App Store id is set on the app in X3.
- Postbacks arrive at the earliest 24 to 48 hours after the end of a conversion window, and only for installs from ads that use AdAttributionKit or SKAdNetwork.
No recordings
recording.mode = wireframe,purposes.recordings = trueand the purpose granted;- recordings enabled in the project and today's caps not reached; health projects need
opt_in; - the screen is not excluded;
sampleRateis not 0; - Low Power Mode, battery saver or a hot device pause recording;
- Flutter: 1.0.0 records the Flutter view as one masked area, not its widgets (Flutter).
Conversions not sent to ad platforms
The conversion's sync status names the reason. Common ones: adPlatforms not granted in the app
session, iOS without ATT authorized (Google Ads and LinkedIn skipped, Meta and TikTok without user
data), a health project without an opt-in grant, test traffic. See
the ATT rule.
Support
Send the install id and session id (X3.ids(), X3.installId) and the SDK version (X3.version)
with a support request; never send keys or user data.