
Analytics is one of those things every app needs, but very few teams enjoy implementing. A typical...
Analytics is one of those things every app needs, but very few teams enjoy implementing.
A typical mobile app might send events to multiple analytics providers -- Firebase Analytics, Mixpanel, Amplitude, Adobe Analytics, and Adobe Edge / CJA. Each provider comes with its own SDK and API, which often leads to duplicated analytics code spread throughout the app.
firebase.logEvent("purchase", bundle)
mixpanel.track(
"purchase",
mapOf("value" to 19.99)
)
amplitude.track(
"purchase",
mapOf("value" to 19.99)
)
This approach works at first, but over time it becomes painful to maintain:
Instead of calling analytics SDKs directly, the app sends events into a single analytics pipeline that routes them to any configured provider.
The application code becomes much simpler:
TrackFlow.track("purchase_completed",
"order_id" to "order_456",
"total" to 99.99
)
Behind the scenes, TrackFlow forwards the event to every registered provider -- Firebase, Mixpanel, Amplitude, Adobe Analytics, and Adobe Edge / CJA. You define the event once. That's it.
TrackFlow is built as a Kotlin Multiplatform SDK, so it works across both Android and iOS.
Analytics calls can live in shared Kotlin code while still routing events to native platform SDKs:
App Code
|
v
TrackFlow.track(...)
|
v
Analytics Pipeline
|
+-- Firebase
+-- Mixpanel
+-- Amplitude
+-- Adobe Analytics
+-- Adobe Edge
Each provider implements the same interface, so TrackFlow can route events to multiple destinations -- without the app ever needing to know about the underlying SDKs.
Two simple functions power the entire system:
TrackFlow.track(...)
TrackFlow.trackState(...)
These map automatically to provider-specific APIs like FirebaseAnalytics.logEvent, MobileCore.trackAction, Mixpanel.track, and Amplitude.logEvent.
If the device is offline, events are safely queued to disk and replayed when connectivity returns. No data loss, even on spotty connections.
Events are automatically batched before being sent to providers, reducing network overhead and improving performance:
.batchSize(25)
.flushInterval(15_000L)
Provider failures are automatically retried with exponential backoff. The goal: analytics pipelines should never crash your application.
Attach global properties to every event:
TrackFlow.Builder(context)
.superProperties(
"app_version" to "1.0.0",
"environment" to "production"
)
Every event automatically includes these fields -- no manual wiring needed.
Propagate user identity across all providers in a single call:
TrackFlow.identify(
"user_123",
"email" to "user@example.com",
"plan" to "premium"
)
All supported providers receive identity updates automatically.
Intercept, transform, or filter events before they're sent. For example, strip out sensitive fields:
.addMiddleware { payload ->
payload.copy(
properties = payload.properties.filterKeys {
it !in setOf("email", "phone", "ssn")
}
)
}
You can also enrich events, sample traffic, and apply custom transformations.
One of the most painful aspects of analytics: every provider expects different parameter names.
| Your Event | Firebase | Adobe | Mixpanel | Amplitude |
|---|---|---|---|---|
product_id | item_id | eVar5 | $product_id | Product ID |
TrackFlow solves this with per-provider key maps. You write a single event:
TrackFlow.track("product_viewed",
"product_id" to "SKU-123",
"price" to 29.99
)
Each provider receives the keys in the format it expects -- automatically.
Initialize TrackFlow in Application.onCreate():
TrackFlow.initialize(
TrackFlow.Builder(applicationContext)
.addProvider(FirebaseProvider())
.addProvider(MixpanelProvider("YOUR_TOKEN"))
.addProvider(AmplitudeProvider("YOUR_API_KEY"))
.build()
)
Then track events anywhere in the app:
TrackFlow.track("button_clicked",
"button_name" to "checkout",
"screen" to "cart"
)
For Compose apps, TrackFlow provides a helper for automatic screen tracking:
@Composable
fun HomeScreen() {
TrackScreen("home_screen")
}
This automatically calls trackState() when the screen appears.
TrackFlow integrates with iOS using CocoaPods.
Register providers:
FirebaseIosProviderKt.registerFirebaseProvider(keyMap: nil)
AmplitudeIosProviderKt.registerAmplitudeProvider(apiKey: "YOUR_API_KEY", keyMap: nil)
AdobeAnalyticsIosProviderKt.registerAdobeAnalyticsProvider(appId: "YOUR_APP_ID", keyMap: nil)
Initialize:
TrackFlowIos.shared.initialize(
logLevel: .debug,
batchSize: 10,
flushIntervalMs: 15000,
licenseKey: nil
)
Track events:
TrackFlow.shared.track(
name: "purchase",
properties_: [
"product_id": "SKU-123",
"price": "29.99"
]
)
TrackFlow.track()
|
v
[ Super Properties ]
|
v
[ Middleware Pipeline ]
|
v
[ Event Batching ]
|
v
[ Dispatcher ]
|
+-- Firebase
+-- Mixpanel
+-- Amplitude
+-- Adobe
If the device is offline, events are queued to disk and replayed when the connection returns.
Analytics is critical for product teams, but the implementation often becomes messy over time. TrackFlow aims to make analytics infrastructure:
Instead of analytics being scattered throughout the app, it becomes a centralized pipeline.
I'd love to hear how other teams manage analytics in their apps:
Always interested to hear how others approach this problem.
Analytics is rarely the most exciting part of building an app -- but it becomes critical as products scale.
A small abstraction layer can go a long way toward keeping analytics code clean and flexible. Kotlin Multiplatform makes it even more interesting by allowing analytics infrastructure to live in shared code while still integrating with native SDKs.
TrackFlow is an experiment in pushing that idea further.
Github Repo: https://github.com/lecrane54/TrackFlow
gemmaI ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...
communityHey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...
ai(yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...
aiMy laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...
githubactionsI Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...
aiI've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...
Workflows from the Neura Market marketplace related to this DeepSeek resource