AutoTrack Page events with React Navigation in React Native Apps
The following documentation segment is for integrating the auto page listeners for React Native applications using React Navigation, for such, CF SDK provides a way to add the listener to your Navigation Component so that you can easily track the page changes.
First, you need to add helper file in your project as provided below, that contains all the necessary components.
import {useEffect, useReducer} from "react";
import {AppState, AppStateStatus} from "react-native";
type Action =
| { type: "state"; state: AppStateStatus }
| { type: "page"; pathName: string };
type PageState = {
lastPage: string;
nextPage: string;
timestamp: number;
previousTimestamp: number;
};
const stateTimesReducer = (state: PageState, action: Action) => {
const newState = {...state};
switch (action.type) {
case "state":
if (action.state === "background") {
newState.previousTimestamp = newState.timestamp;
newState.timestamp = Date.now();
newState.lastPage = newState.nextPage;
//newState.nextPage = ""; // commented -> assuming that page after background
// will be the same as before
} else {
newState.timestamp = Date.now();
newState.previousTimestamp = 0;
}
break;
case "page":
newState.lastPage = newState.nextPage;
newState.nextPage = action.pathName;
const ts = newState.timestamp;
newState.timestamp = Date.now();
newState.previousTimestamp = ts;
break;
}
return newState;
};
const usePageTracking = () => {
const [stateTimes, dispatchStateTimes] = useReducer(stateTimesReducer, {
lastPage: "",
nextPage: "",
timestamp: 0,
previousTimestamp: 0,
});
useEffect(() => {
const handleAppStateChange = (nextAppState: AppStateStatus) => {
dispatchStateTimes({type: "state", state: nextAppState});
};
const subscription = AppState.addEventListener(
"change",
handleAppStateChange
);
return () => {
subscription.remove();
};
}, []);
useEffect(() => {
const MIN_DURATION_THRESHOLD = 1;
if (!stateTimes.previousTimestamp) {
return;
}
const duration =
(stateTimes.timestamp - stateTimes.previousTimestamp) / 1000;
if (duration < MIN_DURATION_THRESHOLD) {
return;
}
if (stateTimes.lastPage.trim() === "") {
return;
}
cfSdkPageEvent(
"com.example.app_name",
stateTimes.lastPage,
parseFloat(duration.toFixed(2)),
0
);
}, [stateTimes]);
return {
dispatchStateTimes,
};
};
export default usePageTracking;
Once you have added the above, then in your root stack, add the following for
NavigationContainer
for onStateChange
:
const {dispatchStateTimes} = usePageTracking();
<NavigationContainer
theme={navigatorTheme}
...
onStateChange = {async(state: any)
=>
{
const currentRoute = state.routes[state.index];
const routePath = state.routes[state.index].state.routes[
currentRoute.state.index
].state.routes.map((route) => route.name);
dispatchStateTimes({type: "page", pathName: routePath.join(" > ")});
}}
...
After adding the above, build your app, and you should now be able to see the logs coming in for page events when you put the app in the background.