Flutter SDK / Identity & analytics
Identity & analytics
The SDK measures the funnel for you: every flow session reports its lifecycle automatically. Identity APIs connect those sessions to your users, and track() covers everything beyond the flow.
Automatic events
No instrumentation needed — each flow session emits these on its own:
| Event | Type | Description |
|---|---|---|
| flow_started | auto | A flow session began, with its entry screen. |
| screen_changed | auto | Navigation between screens (from → to). |
| variable_set | auto | An answer was recorded — powers per-screen answer breakdowns in analytics. |
| purchase_<stage> | auto | Paywall funnel stages: attempted, succeeded, cancelled, failed, pending. |
| flow_completed / flow_abandoned | auto | Terminal events with the end reason and collected variables. |
Events carry context automatically — platform, OS version, locale, SDK version, your appVersion, attribution, and experiment assignment when one is active.
Identity
Users start anonymous: the SDK generates a persistent anonymous ID on first launch and attaches it to every event. When the user authenticates, link the two:
// After your own auth completes:
await UpliftFunnel.identify(
user.id,
attributes: {'plan': 'free', 'signup_source': 'organic'},
);
// On logout — rotates to a fresh anonymous ID:
await UpliftFunnel.resetIdentity();Custom events & attribution
// Custom events: lowercase, [a-z0-9_:] after the first letter.
await UpliftFunnel.track('workout_saved', properties: {
'duration_min': 32,
'type': 'strength',
});
// Ad attribution — joins campaigns to funnel + revenue analytics.
await UpliftFunnel.setAttribution({
'source': 'meta',
'campaign': 'summer_launch',
'ad_set': 'lookalike_us',
'creative': 'video_a',
});Events tracked while a flow is on screen are tied to that session and variant automatically; events outside a flow get an app-level session. Attribution keys are limited to source, campaign, ad_set, and creative, and feed the campaign table in analytics.
Delivery you don't have to think about
- Events are batched and flushed every few seconds, and immediately when the app goes to background.
- The queue is persisted to disk — events survive app kills and offline stretches, with exponential-backoff retries once the network returns.
- Client-side event IDs make delivery idempotent: retries never double count.
- Need a manual flush (e.g. right before logout)?
await UpliftFunnel.flushEvents().