VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Groups
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
React Native SDK
React Native quickstart
Display a paywall
Make and restore purchases
Check access
Identify users
Evaluate feature flags
Capture analytics
Groups
Track screens
Development mode
React Native SDK reference
Errors
Troubleshooting

Track screens

Record a $screen event for every screen with Expo Router, React Navigation or manual calls.

The SDK records a $screen event each time a new screen appears. Each event names the previous screen and how long the user stayed there, so one event describes a whole transition. Tracking is on by default; connect it to your router.

Expo Router

Render ScreenTracking once in the root layout, inside the provider:

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

import { voidhash } from "../src/lib/voidhash";

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

The screen name is the file route, such as /(tabs)/item/[id], and the path is the pathname, such as /item/42. useExpoRouterScreenTracking() is the same as a hook.

React Navigation

Pass the handlers from useScreenTracking to your navigation container:

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

export function AppNavigation() {
  const screenTracking = useScreenTracking();

  return (
    <NavigationContainer
      ref={screenTracking.ref}
      onReady={screenTracking.onReady}
      onStateChange={screenTracking.onStateChange}
    >
      <RootNavigator />
    </NavigationContainer>
  );
}

Call it in a component rendered inside <voidhash.Provider>. The screen name is the focused route's name and the path is the chain of navigators, such as /Tabs/Home/Feed. If you already have a container ref, pass it with useScreenTracking({ ref }) and call onReady and onStateChange from your own callbacks.

Manual screens

For screens a router doesn't see, such as onboarding pager pages, call screen(). Each call records a new screen.

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

Event properties

PropertyMeaning
$screen_nameStable screen identity, without IDs.
$screen_pathConcrete location, with dynamic segment values.
$screen_titleThe screen's title, when the router exposes one.
$previous_screen_name, $previous_screen_pathThe screen the user came from; null on the first screen.
$previous_screen_duration_msTime spent on the previous screen, background time included.
$screen_sourceexpo-router, react-navigation or manual.
$screen_paramsRoute params, when includeParams is on.

A screen is recorded once when it appears; returning from the background doesn't record it again. The same route with different params, such as /item/1 then /item/2, records both.

Options

import { createVoidhashClient } from "@voidhash/react-native";

export const voidhash = createVoidhashClient("vh_pk_...", {
  screenTracking: {
    includeParams: false,
    mapScreen: (view) => (view.name.startsWith("/debug") ? null : view),
  },
});
OptionDefaultDescription
enabledtruefalse turns off the integrations and screen().
includeParamsfalseAdds route params as $screen_params, string values, at most 20 keys. Off because params often hold IDs.
mapScreennoneRenames a screen, or drops it by returning null. If it throws, or returns a screen whose identity, name or path isn't a string, the screen is recorded unchanged and HOST_CALLBACK_FAILED is reported.

To stop storing $screen for a project without a release, turn it off in Settings → Events.

Next steps

  • Capture events
  • Events
  • Analytics reports

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousGroupsNextDevelopment mode

On this page

Expo RouterReact NavigationManual screensEvent propertiesOptionsNext steps