Docs
grovs.io Start for free

Events & screen tracking

Track custom events and React Navigation screen views in your React Native app with the Grovs SDK.

Requires react-native-grovs-wrapper 3.0 or later (native SDKs 3.0).

Tracking custom events

track records an event with optional properties and tags:

typescript
import Grovs from 'react-native-grovs-wrapper';
 
Grovs.track('checkout_completed', { sku: 'abc', total: 42 }, ['shop']);
Grovs.track('level_complete', { level: 5, score: 1200 });
Grovs.track('button_tap');

The native SDK validates, stores and batches the event. Events stay on the device until delivered and are held during install attribution so they credit the right link. Details: Android and iOS.

Event name rules

Names can't be empty or a reserved system name:

view, open, install, reinstall, app_open, time_spent, reactivation, user_referred, custom, screen_view

From 3.1.0 (native SDKs 3.1), the in-app, push and journey event names are reserved too:

in_app_viewed, in_app_clicked, in_app_dismissed, in_app_answered, in_app_commented, in_app_held, push_open, push_delivered, push_held, journey_entered, journey_held, journey_path

Rejected events are logged natively and dropped; track doesn't throw. Use trackScreenView for screen views, not track('screen_view').

Property values

Properties are { [key: string]: Any }, where Any is a string, number, boolean or flat array of those. Nested objects, null and Date aren't part of the type. Native limits apply: over 8 KB serialized drops all properties, and the event is still recorded. On Android, values the bridge can't represent as Serializable are dropped.

Tags

Tags are strings: up to 20 per event, each up to 255 characters. Global tags attach to every later event:

typescript
Grovs.setGlobalTags(['beta', 'experiment-A']);
 
Grovs.setGlobalTags(); // clear

Global and per-event tags are merged, up to 20 combined.

Tracking screen views

typescript
Grovs.trackScreenView('Checkout', { section: 'payment' });

The same screen name sent twice within one second is dropped natively, so re-renders and quick tab switches don't flood the dashboard. A genuine later return still counts.

Automatic screen tracking with React Navigation

The wrapper can report every React Navigation route change as a screen view. Pass the container ref from onReady:

TSX
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import Grovs from 'react-native-grovs-wrapper';
 
function App() {
  const navigationRef = useNavigationContainerRef();
 
  return (
    <NavigationContainer
      ref={navigationRef}
      onReady={() => Grovs.startScreenTracking(navigationRef)}>
      {/* navigators */}
    </NavigationContainer>
  );
}

startScreenTracking reports the current route immediately, then each state change whose route name differs from the last. Navigating away and back reports the screen again. The name is the route name from getCurrentRoute(); rename with aliases.

It returns an unsubscribe function. Calling it again replaces the previous subscription, so a container remount never double-tracks. A ref without getCurrentRoute and addListener is rejected with a logged error and a no-op unsubscribe.

The wrapper doesn't depend on @react-navigation/native. Any object matching NavigationContainerRefLike works:

typescript
interface NavigationContainerRefLike {
  getCurrentRoute(): { name: string } | undefined;
  addListener(type: 'state', callback: () => void): () => void;
}

A ref from createNavigationContainerRef() works like one from the hook.

Expo Router and other navigators

With Expo Router or custom navigation, call trackScreenView when the visible screen changes:

typescript
Grovs.trackScreenView('Checkout');

Turn off native automatic screen tracking

Native automatic tracking (on by default in 3.0) only sees the one Activity or view controller hosting React Native. Pass autoTrackScreenViews: false in the native configure calls, as in the Quick Start, and track from JavaScript. The Expo config plugin injects this; when upgrading an Expo project, re-run npx expo prebuild --clean to regenerate the configure line.

Screen views and events you track from JavaScript also trigger in-app messages, and the screen names are what setInAppExcludedScreens matches.

Grovs.setSDK(false) stops all collection natively, including screen views from JavaScript. See Privacy & Consent.

Screen name aliases

Map reported screen names to friendlier dashboard names:

typescript
Grovs.setScreenAliases({ Home: 'Home Page', ProductDetail: 'Product' });

Keys are names passed to trackScreenView or read by startScreenTracking from your routes. Only string values are forwarded. Aliases sync natively after authentication and are held while the SDK is disabled.

What the wrapper does not expose

Android trackNavigation(navController) and iOS screenNameProvider and .grovsScreen() are for native UI, with no React Native equivalent. Use startScreenTracking or trackScreenView.

Next steps

Last updated 2026-10-27
Was this page helpful?