UniTrack
Universal mobile analytics SDK for Flutter. Auto-captures screens, taps, network calls, crashes, OOM warnings, and JSON parse errors with a persistent offline queue, session journey tracking, and W3C trace propagation.
- π¦ Tiny integration β one
initialize()call, the rest is automatic. - π° Offline-first β events are queued to SQLite + retried with exponential backoff; nothing is dropped when the network is down.
- π Session journey β persistent
session_id+session_indexacross cold starts; rotate manually on logout / context switch. - π§ W3C trace context β opt-in
traceparentinjection on outbound HTTP for backend correlation. - πͺ Provider fan-out β every event is forwarded to optional providers
(
unitrack_snowplow, built-in Firebase Analytics adapter, custom). - π± Per-platform β Swift on iOS, Kotlin on Android, C++ core inside both.
Install
dependencies:
unitrack: ^1.0.0
Initialize
import 'package:unitrack/unitrack.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await UniTrack.instance.initialize(
'utk_your_api_key',
config: const UniTrackConfig(
endpoint: 'https://your-portal.com/event-tracking/v1/events',
batchSize: 20,
flushIntervalMs: 5000,
),
);
runApp(const MyApp());
}
For Flutter route auto-tracking, add the navigator observer:
MaterialApp(
navigatorObservers: [UniTrackNavigatorObserver()],
...
);
Install HTTP auto-capture (URL + duration + status for every request):
UniTrack.installHttpAutoCapture(
excludeSubstrings: ['/heartbeat', 'firebaseinstallations'],
);
Track custom events
UniTrack.instance.track('checkout_completed', properties: {
'order_id': '1234',
'amount': 99.95,
'currency': 'USD',
});
Identify a user
UniTrack.instance.identify('user_42', traits: {
'plan': 'premium',
'email': 'jane@example.com',
});
Session helpers
The native core owns session_id rotation + persists session_index across
launches, so apps don't need to keep their own counter:
final id = await UniTrack.instance.currentSessionId();
final idx = await UniTrack.instance.sessionIndex(); // 1, 2, 3, β¦
final prev = await UniTrack.instance.previousSessionId(); // for chaining
// Force a rotation on logout / switch-account:
await UniTrack.instance.rotateSession();
Offline-queue debugging
While the device is offline, inspect what's still pending. Useful for a debug toast during airplane-mode testing:
final pending = await UniTrack.instance.pendingEventCounts();
// {'ev_screen_view': 7, 'ev_click': 3, 'ev_session': 1}
// Auto-fire when a batch lands server-side:
final sub = UniTrack.instance.onFlushCompleted((counts) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Flushed: $counts')),
);
});
Remote config
Resolve runtime flags / strings without a rebuild. Order:
- Portal
sdk_config.custom_values[key](operator-edited) - Firebase Remote Config (if host app links Firebase + calls
UniTrack.instance.attachFirebaseAdapter()) - Caller's
defaultValue
final on = await UniTrack.instance.getRemoteValue<bool>(
'feature_camera_grid', defaultValue: false);
final ttl = await UniTrack.instance.getRemoteValue<int>(
'retry_delay_ms', defaultValue: 1500);
W3C tracing
UniTrack.instance.setTracing(
enabled: true,
allowlistHosts: ['api.your-app.com', '*.your-app.com'],
);
Provider fan-out
Send the same events to Snowplow + Firebase. Snowplow is a separate package; Firebase Analytics mirror is built-in via reflection β host app links Firebase itself, SDK has zero Firebase dependency.
dependencies:
unitrack: ^1.0.0
unitrack_snowplow: ^1.0.0 # optional
# firebase_core + firebase_analytics β provided by host app
UniTrack.instance.addProvider(SnowplowProvider(
endpoint: 'https://collector.your-app.com',
appId: 'mobile-app',
));
UniTrack.instance.addProvider(FirebaseProvider());
await UniTrack.instance.initialize(apiKey);
What's auto-captured
| Source | Event names |
|---|---|
UniTrackNavigatorObserver |
screen_load_completed |
| Tap auto-capture (native swizzling) | click |
installHttpAutoCapture |
network_request |
FlutterError.onError, PlatformDispatcher.onError |
crash |
| Native OOM signal | memory_warning |
safeJsonParse |
json_parse_error |
| Lifecycle | app_foreground, app_background, session_started, session_ended |
License
MIT β see LICENSE.