feat(flutter): record screen views (Navigate) from Dart#627
feat(flutter): record screen views (Navigate) from Dart#627abelonogov-ld wants to merge 1 commit into
Conversation
Flutter renders into a single native Activity/UIViewController, so the native
SDK's automatic screen detection never sees Flutter route changes. Add a
trackScreenView path so navigation shows up on the Session Replay timeline as a
Navigate event (and as a screen_view span):
- Pigeon LDNativeApi.trackScreenView bridged to LDObserve.trackScreenView on
iOS and Android.
- Public LDObserve.trackScreenView(name, {screenClass, screenId, category,
properties}) with a platform-split recorder (native bridge on mobile,
screen_view span gated by analytics.pageViews on web/stub).
- LDNavigatorObserver to auto-emit screen views on route push/pop/replace,
with a customizable screen-name extractor.
- ScreenViewConvention + tests; README docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ca47068. Configure here.
| super.didPop(route, previousRoute); | ||
| // After a pop the previously-underlying route becomes visible again, so it | ||
| // is the screen the user navigates back to. | ||
| _record(previousRoute); |
There was a problem hiding this comment.
Pop emits duplicate screen views
Medium Severity
LDNavigatorObserver always calls trackScreenView for previousRoute on every didPop, even when the popped route was skipped on didPush because it had no screen name. Dismissing unnamed overlays (typical dialogs and bottom sheets) therefore emits an extra Navigate / screen_view for the route already underneath, duplicating the prior screen view in Session Replay and analytics.
Reviewed by Cursor Bugbot for commit ca47068. Configure here.
| // After a pop the previously-underlying route becomes visible again, so it | ||
| // is the screen the user navigates back to. | ||
| _record(previousRoute); | ||
| } |
There was a problem hiding this comment.
Route removal skips screen tracking
Low Severity
Auto-capture listens only to didPush, didReplace, and didPop. When the top route is removed with Navigator.removeRoute (or similar APIs that notify didRemove instead of didPop), the newly visible route never triggers trackScreenView, so Session Replay and spans miss that navigation.
Reviewed by Cursor Bugbot for commit ca47068. Configure here.


Summary
Phase 1 of adding Flutter-sourced Session Replay events (see plan). Flutter renders into a single native
Activity/UIViewController, so the native SDK's automatic screen detection never sees Flutter route changes. This adds atrackScreenViewpath so navigation appears on the Session Replay timeline as aNavigateevent (and as ascreen_viewspan).LDNativeApi.trackScreenView(name, screenClass, screenId, category, properties), wired on iOS/Android to the existing publicLDObserve.trackScreenView(which funnels into thescreen_viewspan + Session ReplayNavigate).LDObserve.trackScreenView(name, {screenClass, screenId, category, properties}), with a platform-splitScreenViewRecorder(native bridge on mobile; ascreen_viewspan gated byanalytics.pageViewson web/stub).LDNavigatorObserver(aNavigatorObserver) emits screen views ondidPush/didPop/didReplaceusingroute.settings.name, with a customizablescreenNameExtractorand optionalcategory.ScreenViewConvention(span namescreen_view,event.name/event.screen_class/event.screen_id/event.category); newpageViewsEnabledconfig mapped fromanalytics.pageViews.Why
AnalyticsOptions.pageViewsis native-only (Android lifecycle / iOS no-op) and cannot observe Flutter'sNavigator, so screen views had no way to reach Session Replay from a Flutter app.Test plan
dart analyzeclean,dart formatcleanflutter test(153 tests) pass, incl. newscreen_view_convention_test.dartLDObserve.trackScreenView('Home')andLDNavigatorObserverproduceNavigateevents in a Session Replay recording (iOS + Android)screen_viewspan emitted whenanalytics.pageViewsis enabled, suppressed when disabledFollow-up
Phase 2 (proper RRWeb
Clickwith Flutter widget info) is tracked separately and requires native additions across all three repos.Made with Cursor