Track screens

Record every screen your users visit with one line in your root layout.

The SDK records a built-in $screen event each time the user lands on a new screen. Each event carries the screen the user came from and how long they stayed there, so one event describes a whole transition. Screen tracking is on by default. You only need to connect it to your router.

Expo Router

Render the tracker once inside your root layout, below the Voidhash provider:

import { Stack } from "expo-router";
import { ScreenTracking } from "@voidhash/react-native/expo-router";
import { voidhash } from "../utils/voidhash";

export default function RootLayout() {
  return (
    <voidhash.Provider>
      <ScreenTracking />
      <Stack />
    </voidhash.Provider>
  );
}

The screen name is the file route pattern, such as /(tabs)/item/[id], and the screen path is the resolved pathname, such as /item/42.

React Navigation

Attach the tracker to your navigation container:

import { NavigationContainer } from "@react-navigation/native";
import { useScreenTracking } from "@voidhash/react-native/react-navigation";

export function App() {
  const screenTracking = useScreenTracking();
  return (
    <NavigationContainer
      ref={screenTracking.ref}
      onReady={screenTracking.onReady}
      onStateChange={screenTracking.onStateChange}
    >
      <RootNavigator />
    </NavigationContainer>
  );
}

The screen name is the focused route name and the screen path is the chain of navigators leading to it, such as /Tabs/Home/Feed. If you already own a container ref, pass it in with useScreenTracking({ ref }) and call the returned handlers from your own callbacks.

Custom navigation

Call screen() yourself when your app drives navigation without a router, for example in an onboarding pager:

voidhash.client.screen("Onboarding step 2", { step: 2 });

Event properties

PropertyMeaning
$screen_nameStable identity of the screen. Never contains ids.
$screen_pathConcrete location, including dynamic segment values.
$screen_titleHuman title when the router exposes one.
$previous_screen_nameScreen the user came from. null on the first screen.
$previous_screen_pathPath of the previous screen.
$previous_screen_duration_msMilliseconds spent on the previous screen, including time in the background.
$screen_sourceWhich integration produced the event.
$screen_paramsRoute params. Only sent when you opt in.

A screen is recorded once when it becomes visible. Returning from the background does not record it again. Opening the same route with different params, such as /item/1 and then /item/2, records each one.

Options

Configure tracking when you create the client:

const voidhash = createVoidhashClient("vh_pk_...", {
  screenTracking: {
    enabled: true,
    includeParams: false,
    mapScreen: (view) => (view.name.startsWith("/debug") ? null : view),
  },
});

Set enabled to false to turn screen tracking off entirely. includeParams adds route params to each event. It is off by default because params often carry ids. mapScreen lets you rename a screen or drop it by returning null.

Screen views can also be switched off per project without an app release from the events settings page in the dashboard.