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

1

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.

2

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.

3

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.

4

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.

5

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.

iOS — DataflySignal.swiftSwift
// 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
])
Android — DataflySignal.ktKotlin
// 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.

ConcernStack of vendor SDKsDatafly Signal SDK
Third-party network calls per event4-61 (your domain)
Binary size added to app2-5 MB~250 KB
Web + app identity stitchingManual, often brokenBuilt-in, deterministic
Vendor format changesNew SDK release per vendorServer-side, no app release
Consent enforcementPer-vendor SDK, divergentServer-side gate, consistent
Offline retryPer-vendor implementationSingle 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.

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.