Menu

Tracking events

Screen views

One event for every screen, with the screen’s name, sent from your navigation code.

One event, with the screen’s name#

Send one event name for every screen, with the screen’s name in a screen property:

kotlin
mixpanel.track("Screen Viewed", JSONObject().put("screen", "Chat"))
  • Use the same event name everywhere (Screen Viewed) and put the screen in a property. Don’t create one event per screen (Chat Viewed, Home Viewed…). That’s harder to query in Mixpanel, and Tapmap can’t merge screens that show different data.
  • Property name: screen is best. Tapmap also reads screen_name, page, page_name, tab and view.

Name screens, not data#

Use a fixed name: "Chat", not "Chat with Alice". Then every conversation becomes one “Chat” page on the map instead of dozens. Put the data in other properties:

kotlin
mixpanel.track(
    "Screen Viewed",
    JSONObject().put("screen", "Chat").put("chat_type", "group"),
)
  • Tabs count as screens. Send the event when the user switches tabs, too.
  • Dialogs and bottom sheets belong to the page they open on. Give one its own screen view only if it’s a real step in a flow, like a paywall or a checkout sheet.

On the map

Pages without a screen-view event get an amber dot: “No event when it opens”. Their visits can’t be counted.

Where to put it#

Hook into navigation once, so new screens are covered without anyone remembering to add the event.

Jetpack Compose / Navigation component

kotlin
navController.addOnDestinationChangedListener { _, destination, _ ->
    val screen = destination.label?.toString()
        ?: destination.route
        ?: return@addOnDestinationChangedListener
    mixpanel.track("Screen Viewed", JSONObject().put("screen", screen))
}

Give each destination a readable label, or a clean route like chat rather than chat/{id}.

Activities and Fragments

Track in onResume() of a shared base class, with a name each screen provides:

kotlin
abstract class TrackedFragment : Fragment() {
    abstract val screenName: String

    override fun onResume() {
        super.onResume()
        mixpanel.track("Screen Viewed", JSONObject().put("screen", screenName))
    }
}

Flutter

Add a NavigatorObserver and name every route:

dart
class ScreenTracker extends NavigatorObserver {
  @override
  void didPush(Route route, Route? previousRoute) => _track(route);

  @override
  void didPop(Route route, Route? previousRoute) {
    if (previousRoute != null) _track(previousRoute);
  }

  void _track(Route route) {
    final name = route.settings.name;
    if (name != null) mixpanel.track("Screen Viewed", properties: {"screen": name});
  }
}

// MaterialApp(navigatorObservers: [ScreenTracker()], ...)