Skip to content
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

yarn lint && yarn typescript
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,49 @@ To set the page name
```js
SiftReactNative.setPageName("HomePage");
```
## Track Screen Navigation

##### 1. If you don't have root.js, create it, which file serves as the root component of the React Native application. It sets up the navigation using React Navigation and integrates with the `sift-react-native` library for tracking screen views. Install and import neccessary dependencies.

##### 2. Create a stack navigator using createNativeStackNavigator() from @react-navigation/native-stack
`const Stack = createNativeStackNavigator();`

##### 3. Define the Root component and set up the navigation container
` import { NavigationContainer } from '@react-navigation/native';`

##### 4. Inside the Root component, the useEffect hook is used to track the initial screen view by setting the page name with `SiftReactNative.setPageName()` and uploading the event with `SiftReactNative.upload()`.
`SiftReactNative.setPageName(`screen_${currentRouteName}`);`
` SiftReactNative.upload();`

##### 5. The ref and event handlers are used to track and update the current screen name dynamically.
` const routeNameRef = React.useRef();`
` const navigationRef = React.useRef();`

##### 6. The NavigationContainer component wraps the stack navigator and provides the navigation context.
`<NavigationContainer
ref={navigationRef}
onReady={() =>
(routeNameRef.current = navigationRef.current.getCurrentRoute().name)
}
onStateChange={() => {
const previousRouteName = routeNameRef.current;
const currentRouteName = navigationRef.current.getCurrentRoute().name;

if (previousRouteName !== currentRouteName) {
console.log('Screen focused is:', currentRouteName);
SiftReactNative.setPageName(`screen_${currentRouteName}`);
SiftReactNative.upload();
}

routeNameRef.current = currentRouteName;
}}>
<Stack.Navigator>
<Stack.Screen name="your screen name" component={your component} />
<Stack.Screen name="your screen name" component={your component} />
</Stack.Navigator>
</NavigationContainer>`


## Example

To see `sift-react-native` in action you can check out the source in the `example` folder.
Expand Down
188 changes: 4 additions & 184 deletions example/App.js
Original file line number Diff line number Diff line change
@@ -1,192 +1,12 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow strict-local
*/

import React, {useState} from 'react';
import {
Alert,
Platform,
StyleSheet,
View,
TextInput,
Text,
KeyboardAvoidingView,
Keyboard,
TouchableOpacity,
ScrollView,
SafeAreaView,
} from 'react-native';
import SiftReactNative from 'sift-react-native';
**/
import React from 'react';
import Root from './root';
const App = () => {
let [accountId, setAccountId] = useState('');
let [beaconKey, setBeaconKey] = useState('');
let defaultUrl =
Platform.OS === 'ios'
? 'https://api3.siftscience.com/v3/accounts/%@/mobile_events'
: 'https://api3.siftscience.com/v3/accounts/%s/mobile_events';
let [serverUrlFormat, setServerUrlFormat] = useState(defaultUrl);
let [userId, setUserId] = useState('');
let [errortext, setErrortext] = useState('');
const handleSubmitButton = () => {
setErrortext('');
if (!accountId) {
Alert.alert('Missing Fields', 'Please fill Account ID');
return;
}
if (!beaconKey) {
Alert.alert('Missing Fields', 'Please fill Beacon Key');
return;
}
SiftReactNative.setSiftConfig(accountId, beaconKey, true, serverUrlFormat);
SiftReactNative.setUserId(userId);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<ScrollView keyboardShouldPersistTaps="handled">
<KeyboardAvoidingView enabled>
<Text style={styles.titleTextStyle}>Sift SDK Example</Text>
<View style={styles.SectionStyle}>
<TextInput
style={styles.inputStyle}
value={accountId}
onChangeText={AccountId => setAccountId(AccountId)}
placeholder="Enter Account ID"
placeholderTextColor="gray"
autoCapitalize="sentences"
onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={false}
/>
</View>
<View style={styles.SectionStyle}>
<TextInput
style={styles.inputStyle}
value={beaconKey}
onChangeText={BeaconKey => setBeaconKey(BeaconKey)}
placeholder="Enter Beacon Key"
placeholderTextColor="gray"
onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={false}
/>
</View>
<View style={styles.SectionStyle}>
<TextInput
style={styles.inputStyle}
value={userId}
onChangeText={UserId => setUserId(UserId)}
placeholder="Enter User ID"
placeholderTextColor="gray"
keyboardType="email-address"
onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={false}
/>
</View>
<View style={styles.SectionStyleMultiline}>
<TextInput
style={styles.inputStyle}
value={serverUrlFormat}
onChangeText={ServerUrlFormat =>
setServerUrlFormat(ServerUrlFormat)
}
placeholder="Enter Server URL Format"
placeholderTextColor="gray"
multiline={true}
numberOfLines={2}
onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={false}
/>
</View>
<Text style={styles.hintTextStyle}>Default: {defaultUrl}</Text>
{errortext !== '' ? (
<Text style={styles.errorTextStyle}> {errortext} </Text>
) : null}
<TouchableOpacity
style={styles.buttonStyle}
activeOpacity={0.5}
onPress={handleSubmitButton}>
<Text style={styles.buttonTextStyle}>UPLOAD</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</ScrollView>
</View>
</SafeAreaView>
);
return <Root />;
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
SectionStyle: {
flexDirection: 'row',
height: 40,
marginTop: 20,
marginLeft: 35,
marginRight: 35,
margin: 10,
},
SectionStyleMultiline: {
flexDirection: 'row',
height: 50,
marginTop: 20,
marginLeft: 35,
marginRight: 35,
margin: 10,
},
buttonStyle: {
backgroundColor: '#307ecc',
borderWidth: 0,
color: '#FFFFFF',
borderColor: '#7DE24E',
height: 40,
alignItems: 'center',
borderRadius: 30,
marginLeft: 35,
marginRight: 35,
marginTop: 20,
marginBottom: 20,
},
buttonTextStyle: {
fontWeight: 'bold',
color: 'white',
paddingVertical: 10,
fontSize: 16,
},
inputStyle: {
flex: 1,
color: 'black',
paddingLeft: 15,
paddingRight: 15,
borderWidth: 1,
borderRadius: 30,
borderColor: '#307ecc',
},
titleTextStyle: {
color: '#307ecc',
textAlign: 'center',
fontSize: 40,
},
hintTextStyle: {
color: 'black',
textAlign: 'center',
fontSize: 10,
},
errorTextStyle: {
color: 'red',
textAlign: 'center',
fontSize: 14,
},
successTextStyle: {
color: '#307ecc',
textAlign: 'center',
fontSize: 18,
padding: 30,
},
});

export default App;
1 change: 1 addition & 0 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

buildscript {
ext {
kotlinVersion = "1.6.0"
buildToolsVersion = "31.0.0"
minSdkVersion = 21
compileSdkVersion = 31
Expand Down
4 changes: 1 addition & 3 deletions example/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};
export const presets = ['module:metro-react-native-babel-preset'];
7 changes: 7 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@
"lint": "eslint ."
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.11",
"@react-navigation/native": "^6.1.6",
"@react-navigation/native-stack": "^6.9.12",
"react": "18.1.0",
"react-native": "0.70.6",
"react-native-gesture-handler": "^2.9.0",
"react-native-reanimated": "^3.1.0",
"react-native-safe-area-context": "^4.5.2",
"react-native-screens": "^3.20.0",
"sift-react-native": "^0.1.8"
},
"devDependencies": {
Expand Down
49 changes: 49 additions & 0 deletions example/root.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, {useEffect} from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import SiftReactNative from 'sift-react-native';
import ScreenTwo from './screens/screentwo';
import ScreenOne from './screens/screenone';

const Stack = createNativeStackNavigator();

const Root = () => {
const routeNameRef = React.useRef();
const navigationRef = React.useRef();

useEffect(() => {
const initialRouteName = routeNameRef.current;
console.log('Initial screen is:', initialRouteName);
SiftReactNative.setPageName(`screen_${initialRouteName}`);
SiftReactNative.upload();
}, []);

return (
<NavigationContainer
ref={navigationRef}
onReady={() =>
(routeNameRef.current = navigationRef.current.getCurrentRoute().name)
}
onStateChange={() => {
const previousRouteName = routeNameRef.current;
const currentRouteName = navigationRef.current.getCurrentRoute().name;

if (previousRouteName !== currentRouteName) {
// Replace the line below to add the tracker from a mobile analytics SDK
//alert(`The route changed to ${currentRouteName}`);
console.log('Screen focused is:', currentRouteName);
SiftReactNative.setPageName(`screen_${currentRouteName}`);
SiftReactNative.upload();
}

// Save the current route name for later comparison
routeNameRef.current = currentRouteName;
}}>
<Stack.Navigator>
<Stack.Screen name="ScreenOne" component={ScreenOne} />
<Stack.Screen name="ScreenTwo" component={ScreenTwo} />
</Stack.Navigator>
</NavigationContainer>
);
};
export default Root;
Loading