iOS & Android SDKs
Native mobile tracking that ships to your infrastructure
Datafly Signal's iOS (Swift) and Android (Kotlin) SDKs send mobile app events to your own first-party Ingestion Gateway. ATT-aware, SKAdNetwork-friendly, identity unified with the web pipeline. No Firebase, no Adjust SDK, no third-party network calls from the device unless you want them.
iOS + Android
Native SDKs
Swift Package Manager and Maven Central distribution
ATT-aware
By default
Respects Apple's App Tracking Transparency without breaking measurement
One identity
Web + app unified
Same anonymous_id, same vendor IDs across browser and native
0
Third-party calls
Events go only to your own first-party endpoint, not vendor SDKs
Why most mobile SDKs make measurement worse
The standard mobile measurement stack is a stack of vendor SDKs: Firebase for analytics, Adjust or AppsFlyer for attribution, Meta SDK for CAPI, the platform SDK for Pinterest / TikTok / LinkedIn / Snapchat, and a CMP SDK on top to coordinate consent. Each adds binary size, third-party network calls, and an independent privacy review.
Every vendor SDK is a third-party network call
A typical mobile app with 4-5 measurement SDKs makes 4-5 simultaneous network calls per tracked event, to four or five different vendor domains. Each is independently subject to ATT prompts, IDFA gating, and platform privacy reviews. Each has its own retry, batching, and failure mode that's opaque to your team.
ATT and Google Privacy Sandbox break the same setup differently
When a user denies App Tracking Transparency, the Meta SDK behaves differently from the TikTok SDK behaves differently from the Adjust SDK. Each vendor decides what fallback signals to send. You can't enforce a consistent policy across them because the decision is made inside each vendor's binary, not in your code.
Identity drifts between web and app
A user on web has a GA client_id, an _fbp cookie, a _ttp cookie. The same user on iOS has an IDFA (or no IDFA after ATT denial), an SKAdNetwork postback, an Adjust device ID. Stitching these is non-trivial and most teams just don't. The result: web and app conversions reported as separate users in attribution, downstream models trained on broken identity.
How the Datafly Signal SDK works on mobile
Single SDK, single endpoint
Add the Datafly Signal Swift Package or Maven dependency. Configure with your collect.yourbrand.com endpoint and pipeline key. The SDK's only network destination is your own first-party gateway, the same one your web traffic hits.
Identity persisted in Keychain / EncryptedSharedPreferences
The SDK's anonymous_id is stored in iOS Keychain (survives app uninstall on the same device) and Android EncryptedSharedPreferences. Cross-launch identity is deterministic, no probabilistic device fingerprinting needed.
ATT-aware identity strategy
The SDK respects ATT by default. If the user grants tracking, IDFA is included with events. If denied, the SDK falls back to its own first-party anonymous_id without sending IDFA. The Signal Core handles vendor-specific behaviour (SKAdNetwork postbacks, Meta CAPI app event formats) downstream.
Vendor identity unified server-side
GA app-instance ID, Meta _fbp app-event format, TikTok _ttp, LinkedIn li_id are all generated server-side and attached to events at the Signal Core. The same identity graph that connects web visitors connects app users.
Consent state passed to every vendor
When the user updates consent through your CMP, the SDK pushes the new state with subsequent events. Server-side gates evaluate consent per vendor before delivery, identical to the web pipeline.
SDK in practice
Configure once at app start. Track events with the same property shape as the web SDK so your blueprints work for both. Identify after sign-in, update consent when the CMP returns.
// AppDelegate.swift or App.swift
import DataflySignal
@main
struct MyApp: App {
init() {
Datafly.shared.configure(
endpoint: URL(string: "https://collect.yourbrand.com")!,
pipelineKey: "ios_app_production",
options: .init(
consentDefault: .denied,
attBehaviour: .respect,
identityKeychain: true
)
)
}
var body: some Scene {
WindowGroup { ContentView() }
}
}
// Track an event
Datafly.shared.track("purchase", properties: [
"value": 29.99,
"currency": "USD",
"items": ["sku_123"]
])
// Identify a user (after sign-in)
Datafly.shared.identify(userId: "u_4f9a", traits: [
"email": "user@example.com",
"plan": "premium"
])
// Update consent when CMP returns
Datafly.shared.setConsent([
"marketing": true,
"personalisation": false,
"analytics": true
])// MyApplication.kt
import com.datafly.signal.Datafly
import com.datafly.signal.Options
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Datafly.configure(
context = this,
endpoint = "https://collect.yourbrand.com",
pipelineKey = "android_app_production",
options = Options(
consentDefault = Options.Consent.DENIED,
identityEncryptedPrefs = true
)
)
}
}
// Track an event
Datafly.track("purchase", mapOf(
"value" to 29.99,
"currency" to "USD",
"items" to listOf("sku_123")
))
// Identify
Datafly.identify("u_4f9a", mapOf(
"email" to "user@example.com",
"plan" to "premium"
))Built for modern mobile measurement
The SDK is intentionally minimal. The platform-specific complexity (SKAdNetwork, ATT, Privacy Sandbox, vendor formats) lives server-side at the Signal Core, where it can change without an app store release.
Native APIs, modern toolchains
Swift Package Manager for iOS 14+, Maven Central for Android API 21+. Async/await on iOS, coroutines on Android. No Objective-C, no Java legacy.
ATT and consent-aware
Reads ATT status on iOS, respects platform privacy controls on Android. Consent state synchronised with your CMP and passed to every server-side delivery.
Web + app identity unified
Same anonymous_id format, same vendor IDs, same identity graph. Cross-device customers stitch deterministically when they sign in on web after starting in app, or vice versa.
Lean, no third-party deps
iOS SDK under 200KB, Android under 250KB. No Firebase, no Adjust, no Meta SDK on the device. Network calls only to your first-party gateway.
Offline batching and retry
Events buffered to disk when offline, replayed when connectivity returns. Retry with exponential backoff. No event loss on flaky mobile networks.
Vendor logic moves server-side
SKAdNetwork postbacks, Meta CAPI app events, TikTok app events, LinkedIn CAPI all formatted at the Signal Core. The SDK doesn't need to know about them, so vendor changes don't require a new app release.
Mobile SDK approaches compared
How a typical multi-vendor SDK stack compares to a single first-party SDK.
| Concern | Stack of vendor SDKs | Datafly Signal SDK |
|---|---|---|
| Third-party network calls per event | 4-6 | 1 (your domain) |
| Binary size added to app | 2-5 MB | ~250 KB |
| Web + app identity stitching | Manual, often broken | Built-in, deterministic |
| Vendor format changes | New SDK release per vendor | Server-side, no app release |
| Consent enforcement | Per-vendor SDK, divergent | Server-side gate, consistent |
| Offline retry | Per-vendor implementation | Single batched queue |
Frequently asked questions
- How does the SDK handle ATT denial on iOS?
- When App Tracking Transparency is denied, the SDK does not attach the IDFA to events and falls back to its own first-party anonymous_id stored in the iOS Keychain. Server-side, the Signal Core handles the rest of the vendor-specific behaviour (SKAdNetwork postbacks for ad networks that need them, Meta CAPI app event format) without the SDK needing per-vendor logic. The user's privacy choice is honoured end to end.
- Does the SDK send to vendor SDKs at all?
- No. The Datafly Signal SDK has only one network destination: your own first-party Ingestion Gateway, e.g. collect.yourbrand.com. There are no Firebase calls, no Adjust pings, no Meta SDK requests, no TikTok SDK traffic. Vendor delivery happens server-side once the event reaches the Signal Core. This dramatically simplifies app store privacy declarations and shrinks the third-party network surface.
- How does identity stitch between web and app?
- The same anonymous_id format is generated server-side for both web and app pipelines. When a user signs in on either surface, the identify call links the anonymous_id to a user_id. Subsequent web visits and app launches resolve to the same identity record. Cross-device and cross-surface attribution is deterministic, with no probabilistic stitching.
- What about SKAdNetwork postbacks?
- SKAdNetwork postbacks are received server-side by the Signal Core when ad networks send them. They're joined to the matching app install or conversion event using the SKAdNetwork conversion value, then delivered to your warehouse and to vendors that use them for attribution. The SDK doesn't handle SKAdNetwork directly — that complexity stays server-side where it can be updated without an app release.
- How big is the SDK in MB?
- The iOS SDK is under 200KB and the Android SDK is under 250KB. Compared to a typical multi-vendor stack (Firebase ~3MB, Adjust ~2MB, Meta SDK ~5MB, TikTok SDK ~2MB), removing those vendor SDKs in favour of one first-party SDK reduces app binary size by 5-10MB depending on the prior setup.
- Can I use it alongside my existing Firebase or Adjust setup?
- Yes, during migration. The Datafly Signal SDK runs in parallel with vendor SDKs without conflict. Most teams run both for a transition period while validating that server-side delivery matches client-side reporting, then remove the vendor SDKs once confidence is established. Migration is incremental, not big-bang.
Related
Identity Resolution
Web and app identity unified server-side, deterministic across devices.
Meta Conversions API
Mobile app events delivered to Meta CAPI server-side, no Meta SDK on device.
TikTok Events API
TikTok app events server-to-server, no ttq.js or TikTok SDK on device.
Page Performance
The web equivalent: a 5.2KB collector replacing every vendor tag.
One mobile SDK, every measurement vendor
Request a technical walkthrough. We'll show you the Swift and Kotlin integration, walk through web/app identity stitching, and demonstrate how vendor changes ship without an app release.