Flutter SDK
Capture events from Flutter apps with azfive_capture — identity, sessions, feature flags, surveys and opt-in session replay.
azfive_capture brings AZ-Five product analytics to Flutter: events, identity, sessions, persistence, feature flags & experiments, surveys, and opt-in session replay. Dart 3; a single dependency (shared_preferences, plus image for replay JPEG encoding), under the shared behavioral spec.
Install
flutter pub add azfive_capture
Create a public ingest token with “Mobile app token” enabled (Settings → API Keys) — native requests carry no browser Origin, and tokens without that flag fail closed.
Initialize
final azfive = await AzFive.init('azfive_pub_…',
const AzFiveConfig(host: 'https://app.az-five.com'));
AzFive.init is async: it hydrates shared_preferences persistence before returning, so identity and cached flags survive restarts. After init, the static facade (AzFive.capture(…), AzFive.getFlag(…)) mirrors the instance API.
Capture events
azfive.capture('signed_up', {'plan': 'pro'});
azfive.screen('Checkout'); // az.screen_view + survey eligibility re-check
// Super properties — merged into every event
azfive.register({'deployment': 'eu-1'});
azfive.registerOnce({'first_touch': 'ad-campaign'});
azfive.unregister('deployment');
Automatic screen tracking (which also drives survey eligibility) comes from the bundled navigator observer:
MaterialApp(navigatorObservers: [AzFiveNavigatorObserver(azfive)], …)
Identify & person properties
azfive.identify('ava@example.com', set: {'plan': 'pro'});
azfive.alias('legacy-77');
azfive.peopleSet({'favorite_color': 'teal'});
azfive.peopleSetOnce({'signup_date': '2026-08-01'});
// on logout:
azfive.reset(); // new anonymous id; reset(resetDeviceId: true) also rotates the device id
identify merges the anonymous session into the person (az.identify with $anonymous_id) and refetches flags; calling it again with the same id only updates properties. Opt-out controls — optInCapturing() / optOutCapturing() — drop events at capture time, persist, and survive reset().
Feature flags
Flags load from /v1/decide on init, persist for stale-while-revalidate startup, and refetch on identify / reset:
final unsubscribe = azfive.onFlags((flags) {
final variant = azfive.getFlag('exp-checkout'); // true | false | 'variant' | null
if (azfive.isFlagEnabled('new-billing')) {
final payload = azfive.getFlagPayload('new-billing'); // no exposure event
}
});
await azfive.reloadFlags(); // force a refetch
getFlag and isFlagEnabled capture an az.flag_called exposure automatically, deduped per session:flag:value. getFlagPayload never does.
Surveys
Mount the survey host once, above your app:
AzFiveSurveyHost(coordinator: azfive.surveys, child: const MyApp())
Survey selection reacts to screen() changes; responses ship as az.survey_shown / az.survey_dismissed / az.survey_sent events, and suppression persists per survey.
Session replay (opt-in, default off)
Set enableSessionRecording: true, enable recording server-side, and mount an AzFiveReplayBoundary at your root. Capture is ~1 fps masked JPEG frames plus touches; masking is best-effort — review your screens before enabling in production.
Flush & shutdown
Delivery is automatic (10 events / 5 s), and the queue flushes when the app backgrounds. flush() forces delivery and returns a Future; dispose() tears the client down:
await azfive.flush();
Reference
AzFiveConfig
| Parameter | Default | Notes |
|---|---|---|
host | required | AZ-Five deployment base URL |
project | 'default' | Target project slug |
batchSize | 10 | Queue length that triggers a flush |
flushInterval | Duration(seconds: 5) | Background flush period |
maxQueueSize | 1000 | Queue bound; oldest events dropped on overflow |
gzip | false | Content-Encoding: gzip on event POSTs |
optOut | false | Start opted out (persisted opt-out wins) |
disableDecide | false | Skip flags/surveys/recording bootstrap |
enableSessionRecording | false | Session replay opt-in; recording still requires the server to enable it |
sessionIdleTimeout | Duration(minutes: 30) | Session rotation on inactivity |
storage | SharedPreferencesStore | Custom Store persistence backend |
platformProps | auto-detected | Override the computed static platform properties |
API
capture · screen · identify · alias · reset · getDistinctId · getSessionId · register / registerOnce / unregister · peopleSet / peopleSetOnce · optInCapturing / optOutCapturing · getFlag / isFlagEnabled / getFlagPayload / onFlags / reloadFlags · flush · dispose.
Behavior notes
- Sessions rotate after 30 minutes idle or 24 hours total;
$session_idis stamped on every event. - Failed batches —
429included — re-queue at the front and retry next flush; the public API never throws for delivery or flag problems. - Custom event names: anything except the reserved
az.prefix, ≤ 200 characters; properties ≤ 64 KiB serialized.