How to Achieve High‑Accuracy User Behavior Tracking in Flutter
This article explains how the Xianyu team migrated from native to Flutter and built a high‑accuracy user‑behavior tracking solution, covering page entry/exit detection, exposure calculations, click handling, code snippets, and future improvements for reliable analytics in mobile apps.
User Behavior Tracking Positioning
In Xianyu's workflow a user enters page A, sees button X, clicks it, and a new page B opens. Five tracking events occur:
Enter page A – first frame rendered and focus gained.
Expose slot X – button X is visible on screen for a sufficient time.
Click slot X – user taps the button, triggering navigation to page B.
Leave page A – page A loses focus.
Enter page B – first frame rendered and focus gained.
Implementation Plan
Enter/Leave Page
Native apps listen to onResume / onPause (Android) or viewWillAppear / viewDidDisappear (iOS). In Flutter, pages are hosted by FlutterActivity or FlutterViewController, which maintain their own page stack, so native lifecycle hooks cannot be used directly.
Registering a NavigatorObserver to listen for push/pop events has two problems:
If page A is pushed, then page B is pushed and later popped, page A becomes visible again but no push event is received.
Dialogs or BottomSheets also trigger push events even though the underlying page has not left.
Solution: maintain an index list that mirrors the Flutter page stack. When a push event arrives, insert the new page index; when a pop occurs, remove the top index and trigger leave/enter events based on the remaining top page. For dialogs, check the overlayEntries of the Route and ignore non‑full‑screen overlays.
// Listen to scroll container offset
double _scrollContainerOffset = scrollNotification.metrics.pixels; // Get offset of a widget relative to the screen
final RenderObject childRenderObject = context.findRenderObject();
final RenderAbstractViewport viewport = RenderAbstractViewport.of(childRenderObject);
if (viewport == null) return;
final RevealedOffset offsetToRevealTop = viewport.getOffsetToReveal(childRenderObject, 0.0);Exposure Slot
A slot is considered exposed when:
At least half of its area is within the visible screen region.
It remains in the visible region for more than 500 ms.
To compute the visible proportion, obtain:
Container offset relative to the screen.
Slot offset relative to the container.
Slot dimensions.
Container dimensions.
if (slotIsInvisible && exposureRatio >= 0.5) {
// mark as visible and record start time
} else if (slotIsVisible && exposureRatio < 0.5) {
// mark as invisible
}
if (currentTime - startTime > 500ms) {
// trigger exposure tracking API
}Click Slot
Click tracking is straightforward: attach a listener to the widget and report the click event to the tracking backend.
Effect
After multiple iterations, the online Flutter page tracking accuracy has reached 100%, providing reliable data for business analysis. The solution is non‑intrusive: developers do not need to manually trigger page‑enter, page‑leave, or exposure events.
Future
Currently the solution works with Xianyu's Flutter‑Boost hybrid stack. As more pure Flutter pages appear, a native‑only implementation will be added to make the approach universally applicable.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
