After init, the SDK captures the most useful events with no extra code. This page
lists what is tracked and how to turn any of it off.
On every launch the SDK emits a session-context burst: app launch, platform, device type, OS, RAM, screen resolution, and system language. This is what the backend expects at the start of each session, so it always fires.
Note
These read only what pure React Native exposes, so they carry token-level
granularity (Platform.OS, Platform.Version, a coarse device class, the IETF
language tag) rather than exact hardware strings. For richer metadata (exact model,
OS name) pass a custom PlatformAdapter via Keewano.init({ platform }) - backed by
react-native-device-info on bare RN, or expo-device / expo-application on Expo.
| Tracker | Captures | Turn off with |
|---|---|---|
| Button taps | taps on Pressable components |
disableButtonTracking |
| App state | foreground / background transitions | disableAppStateTracking |
| Back button | the Android hardware back button | disableBackHandlerTracking |
| Deep links | links that open your app | disableLinkingTracking |
| Errors | uncaught JavaScript errors | disableErrorTracking |
| Network | connectivity changes (opt-in) | enableNetworkTracking to turn ON |
Keewano.init({ apiKey: '...', disableBackHandlerTracking: true });Important
We do not recommend disabling automatic capture without a specific reason. If a
particular button is not being captured, prefer reporting it manually with
reportButtonClick over turning the whole patch off.
Note
Network tracking is the one tracker that is off by default, because it needs the
optional native peer @react-native-community/netinfo. Install it and set
enableNetworkTracking: true to opt in.
Full-screen route changes (scenes) are not patched automatically - you opt in with the
useKeewanoNavigation hook, which emits SCENE_LOADED / SCENE_UNLOADED as the
player navigates. Pass your navigation library's source into the hook:
// Expo Router - @keewano/react-native-expo-sdk
import { usePathname } from 'expo-router';
import { useKeewanoNavigation } from '@keewano/react-native-expo-sdk';
function RootLayout() {
useKeewanoNavigation(usePathname);
// ...
}// React Navigation - @keewano/react-native-sdk
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import { useKeewanoNavigation } from '@keewano/react-native-sdk';
function App() {
const navigationRef = useNavigationContainerRef();
useKeewanoNavigation(navigationRef);
return <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>;
}The hook emits SCENE_LOADED on the first non-empty route and SCENE_UNLOADED(previous)
SCENE_LOADED(next)on each subsequent change; blank route names are no-op, and the scene cursor survives Strict Mode / Fast Refresh remounts without duplicate emits. For modals and in-screen overlays, usereportWindowOpen/reportWindowCloseinstead. If your navigation is custom and the hook does not fit, callKeewano.reportSceneLoaded(name)andKeewano.reportSceneUnloaded(name)directly.
Uncaught JavaScript errors are captured automatically (the ErrorTracker listed above). For errors you catch and handle yourself, report them manually:
try {
riskyOperation();
} catch (err) {
Keewano.logError(String(err));
}Need to capture something the built-ins do not - a gesture library, a third-party UI
kit? Implement the KeewanoTracker contract and pass it through plugins.
const myTracker = {
name: 'paper-button-tracker',
attach() {
const subscription = subscribeToMyUiKit(() => Keewano.reportButtonClick('...'));
return () => subscription.remove(); // detach on shutdown
},
};
Keewano.init({ apiKey: '...', plugins: [myTracker] });A tracker has a name, an attach() that wires up its listeners and returns a
detach function, and runs until Keewano.shutdown().
Related: Configuration | Windows and Buttons | Event Types