Added google analytics tracking.

This commit is contained in:
Patrick Fic
2021-03-09 17:03:19 -08:00
parent 3e1dd78c85
commit b5176b4d61
12 changed files with 163 additions and 10 deletions

2
App.js
View File

@@ -9,6 +9,7 @@ import { PersistGate } from "redux-persist/integration/react";
import * as Sentry from "sentry-expo"; import * as Sentry from "sentry-expo";
import ScreenMainComponent from "./components/screen-main/screen-main.component"; import ScreenMainComponent from "./components/screen-main/screen-main.component";
import env from "./env"; import env from "./env";
import { logImEXEvent } from "./firebase/firebase.utils";
import { client } from "./graphql/client"; import { client } from "./graphql/client";
import { persistor, store } from "./redux/store"; import { persistor, store } from "./redux/store";
import "./translations/i18n"; import "./translations/i18n";
@@ -32,6 +33,7 @@ export default class App extends React.Component {
} }
async componentDidMount() { async componentDidMount() {
logImEXEvent("imexmobile_app_start");
await Font.loadAsync({ await Font.loadAsync({
Roboto: require("native-base/Fonts/Roboto.ttf"), Roboto: require("native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"), Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),

36
GoogleService-Info.plist Normal file
View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>253497221485-qgnj5ve8q0gk2jsmsbsf8qh1i8q04enq.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.253497221485-qgnj5ve8q0gk2jsmsbsf8qh1i8q04enq</string>
<key>API_KEY</key>
<string>AIzaSyAVKJ2eHZpKxsA0a3qyZImg-ePfuwcuCrE</string>
<key>GCM_SENDER_ID</key>
<string>253497221485</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.imex.imexmobile</string>
<key>PROJECT_ID</key>
<string>imex-prod</string>
<key>STORAGE_BUCKET</key>
<string>imex-prod.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:253497221485:ios:fcbe67f6c6f7da68227a64</string>
<key>DATABASE_URL</key>
<string>https://imex-prod.firebaseio.com</string>
</dict>
</plist>

View File

@@ -8,11 +8,13 @@
"ios": { "ios": {
"supportsTablet": true, "supportsTablet": true,
"bundleIdentifier": "com.imex.imexmobile", "bundleIdentifier": "com.imex.imexmobile",
"buildNumber": "1.0.3" "buildNumber": "1.0.3",
"googleServicesFile": "./GoogleService-Info.plist"
}, },
"android": { "android": {
"package": "com.imex.imexmobile", "package": "com.imex.imexmobile",
"versionCode": 1 "versionCode": 1,
"googleServicesFile": "./google-services.json"
}, },
"splash": { "splash": {
"image": "./assets/logo1024.png", "image": "./assets/logo1024.png",
@@ -28,7 +30,19 @@
"assetBundlePatterns": ["**/*"], "assetBundlePatterns": ["**/*"],
"web": { "web": {
"favicon": "./assets/logo192noa.png" "favicon": "./assets/logo192noa.png",
"config": {
"firebase": {
"apiKey": "AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU",
"authDomain": "imex-prod.firebaseapp.com",
"databaseURL": "https://imex-prod.firebaseio.com",
"projectId": "imex-prod",
"storageBucket": "imex-prod.appspot.com",
"messagingSenderId": "253497221485",
"appId": "1:253497221485:web:9b65736a635a45ce227a64",
"measurementId": "G-96694D66L2"
}
}
}, },
"description": "", "description": "",
"hooks": { "hooks": {

View File

@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
import { View } from "react-native"; import { View } from "react-native";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions";
import { selectCurrentCameraJobId } from "../../redux/app/app.selectors"; import { selectCurrentCameraJobId } from "../../redux/app/app.selectors";
@@ -48,6 +49,7 @@ export function CameraSelectJob({
<Picker <Picker
selectedValue={cameraJobId} selectedValue={cameraJobId}
onValueChange={(value, idx) => { onValueChange={(value, idx) => {
logImEXEvent("imexmobile_setcamerajobid");
setCameraJobId(value); setCameraJobId(value);
setCameraJob(data.jobs[idx]); setCameraJob(data.jobs[idx]);
}} }}

View File

@@ -8,6 +8,7 @@ import { TouchableOpacity } from "react-native-gesture-handler";
import Swipeable from "react-native-gesture-handler/Swipeable"; import Swipeable from "react-native-gesture-handler/Swipeable";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions";
import styles from "../styles"; import styles from "../styles";
@@ -32,6 +33,7 @@ export function JobListItem({ setCameraJob, setCameraJobId, item }) {
<TouchableOpacity <TouchableOpacity
style={[styles.swipe_view, styles.swipe_view_blue]} style={[styles.swipe_view, styles.swipe_view_blue]}
onPress={() => { onPress={() => {
logImEXEvent("imexmobile_setcamerajobid_swipe");
setCameraJobId(item.id); setCameraJobId(item.id);
setCameraJob(item); setCameraJob(item);
navigation.navigate("MediaBrowserTab"); navigation.navigate("MediaBrowserTab");
@@ -50,6 +52,7 @@ export function JobListItem({ setCameraJob, setCameraJobId, item }) {
}; };
const onPress = () => { const onPress = () => {
logImEXEvent("imexmobile_view_job_detail");
navigation.push("JobDetail", { navigation.push("JobDetail", {
jobId: item.id, jobId: item.id,
title: item.ro_number || t("general.labels.na"), title: item.ro_number || t("general.labels.na"),

View File

@@ -9,6 +9,7 @@ import { useTranslation } from "react-i18next";
import { StyleSheet, Text, View } from "react-native"; import { StyleSheet, Text, View } from "react-native";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { import {
selectCurrentCameraJobId, selectCurrentCameraJobId,
selectDeleteAfterUpload, selectDeleteAfterUpload,
@@ -51,6 +52,7 @@ export function ImageBrowserScreen({
async function handleOnSuccess(uri, id) { async function handleOnSuccess(uri, id) {
console.log("Succesful upload!", uri); console.log("Succesful upload!", uri);
logImEXEvent("imexmobile_successful_upload");
if (deleteAfterUpload) { if (deleteAfterUpload) {
try { try {
const result = await MediaLibrary.deleteAssetsAsync([id]); const result = await MediaLibrary.deleteAssetsAsync([id]);
@@ -64,6 +66,7 @@ export function ImageBrowserScreen({
const onDone = async (data) => { const onDone = async (data) => {
console.log("Assets :>> ", data); console.log("Assets :>> ", data);
logImEXEvent("imexmobile_upload_documents", { count: data.length });
const actions = []; const actions = [];
data.forEach(function (p) { data.forEach(function (p) {
let filename; let filename;
@@ -205,6 +208,7 @@ const styles = StyleSheet.create({
function handleOnError(...props) { function handleOnError(...props) {
console.log("HandleOnError", props); console.log("HandleOnError", props);
logImEXEvent("imexmobile_upload_documents_error", { props });
} }
export default connect(mapStateToProps, null)(ImageBrowserScreen); export default connect(mapStateToProps, null)(ImageBrowserScreen);

View File

@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
import { StyleSheet, Switch, Text, View } from "react-native"; import { StyleSheet, Switch, Text, View } from "react-native";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { toggleDeleteAfterUpload } from "../../redux/app/app.actions"; import { toggleDeleteAfterUpload } from "../../redux/app/app.actions";
import { selectDeleteAfterUpload } from "../../redux/app/app.selectors"; import { selectDeleteAfterUpload } from "../../redux/app/app.selectors";
@@ -29,7 +30,10 @@ export function UploadDeleteSwitch({
trackColor={{ false: "#767577", true: "#81b0ff" }} trackColor={{ false: "#767577", true: "#81b0ff" }}
thumbColor={deleteAfterUpload ? "tomato" : "#f4f3f4"} thumbColor={deleteAfterUpload ? "tomato" : "#f4f3f4"}
ios_backgroundColor="#3e3e3e" ios_backgroundColor="#3e3e3e"
onValueChange={() => toggleDeleteAfterUpload()} onValueChange={() => {
logImEXEvent("imexmobile_toggle_delete_after_upload");
toggleDeleteAfterUpload();
}}
value={deleteAfterUpload} value={deleteAfterUpload}
/> />
</View> </View>

View File

@@ -1,5 +1,7 @@
import * as Analytics from "expo-firebase-analytics";
import * as firebase from "firebase/app"; import * as firebase from "firebase/app";
import "firebase/auth"; import "firebase/auth";
import { store } from "../redux/store";
//const config = JSON.parse(process.env.REACT_APP_FIREBASE_CONFIG); //const config = JSON.parse(process.env.REACT_APP_FIREBASE_CONFIG);
// const config = { // const config = {
@@ -52,3 +54,25 @@ export const updateCurrentUser = (userDetails) => {
}, reject); }, reject);
}); });
}; };
export const logImEXEvent = (eventName, additionalParams, stateProp = null) => {
const state = stateProp || store.getState();
const eventParams = {
shop:
(state.user && state.user.bodyshop && state.user.bodyshop.shopname) ||
null,
user:
(state.user && state.user.currentUser && state.user.currentUser.email) ||
null,
...additionalParams,
};
console.log(
"%c[Analytics]",
"background-color: green ;font-weight:bold;",
eventName,
eventParams
);
Analytics.logEvent(eventName, eventParams);
};
//export const ExpoAnalytics = Analytics;

47
google-services.json Normal file
View File

@@ -0,0 +1,47 @@
{
"project_info": {
"project_number": "253497221485",
"firebase_url": "https://imex-prod.firebaseio.com",
"project_id": "imex-prod",
"storage_bucket": "imex-prod.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:253497221485:android:c48f224bc1afd537227a64",
"android_client_info": {
"package_name": "com.imex.imexmobile"
}
},
"oauth_client": [
{
"client_id": "253497221485-1tjt8aflekk0s4d1jibd8p7cbtkoocv1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDfmdrww4t6cnHbB4yNpJv0qLLRTwzIyUs"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "253497221485-1tjt8aflekk0s4d1jibd8p7cbtkoocv1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "253497221485-qgnj5ve8q0gk2jsmsbsf8qh1i8q04enq.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.imex.imexmobile"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@@ -23,6 +23,7 @@
"expo-av": "~8.7.0", "expo-av": "~8.7.0",
"expo-camera": "~9.1.0", "expo-camera": "~9.1.0",
"expo-file-system": "~9.3.0", "expo-file-system": "~9.3.0",
"expo-firebase-analytics": "~2.6.0",
"expo-font": "~8.4.0", "expo-font": "~8.4.0",
"expo-images-picker": "https://github.com/snaptsoft/expo-images-picker/", "expo-images-picker": "https://github.com/snaptsoft/expo-images-picker/",
"expo-localization": "~9.1.0", "expo-localization": "~9.1.0",

View File

@@ -1,12 +1,17 @@
import * as Analytics from "expo-firebase-analytics";
import { all, call, put, takeLatest } from "redux-saga/effects"; import { all, call, put, takeLatest } from "redux-saga/effects";
import { import {
auth, auth,
getCurrentUser, getCurrentUser,
logImEXEvent,
updateCurrentUser, updateCurrentUser,
} from "../../firebase/firebase.utils"; } from "../../firebase/firebase.utils";
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
import { client } from "../../graphql/client";
import { import {
sendPasswordResetFailure, sendPasswordResetFailure,
sendPasswordResetSuccess, sendPasswordResetSuccess,
setBodyshop,
signInFailure, signInFailure,
signInSuccess, signInSuccess,
signOutFailure, signOutFailure,
@@ -15,18 +20,15 @@ import {
updateUserDetailsSuccess, updateUserDetailsSuccess,
validatePasswordResetFailure, validatePasswordResetFailure,
validatePasswordResetSuccess, validatePasswordResetSuccess,
setBodyshop,
} from "./user.actions"; } from "./user.actions";
import UserActionTypes from "./user.types"; import UserActionTypes from "./user.types";
import { client } from "../../graphql/client";
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
export function* onEmailSignInStart() { export function* onEmailSignInStart() {
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail); yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
} }
export function* signInWithEmail({ payload: { email, password } }) { export function* signInWithEmail({ payload: { email, password } }) {
try { try {
//logImEXEvent("redux_sign_in_attempt", { user: email }); logImEXEvent("imexmobile_sign_in_attempt", { user: email });
const { user } = yield auth.signInWithEmailAndPassword(email, password); const { user } = yield auth.signInWithEmailAndPassword(email, password);
yield put( yield put(
signInSuccess({ signInSuccess({
@@ -74,7 +76,7 @@ export function* onSignOutStart() {
} }
export function* signOutStart() { export function* signOutStart() {
try { try {
//logImEXEvent("redux_sign_out"); logImEXEvent("imexmobile_sign_out");
yield auth.signOut(); yield auth.signOut();
yield put(signOutSuccess()); yield put(signOutSuccess());
@@ -102,8 +104,10 @@ export function* onSignInSuccess() {
export function* signInSuccessSaga({ payload }) { export function* signInSuccessSaga({ payload }) {
try { try {
const shop = yield client.query({ query: QUERY_BODYSHOP }); Analytics.setUserId(payload.email);
const shop = yield client.query({ query: QUERY_BODYSHOP });
logImEXEvent("imexmobile_sign_in_success", payload);
yield put(setBodyshop(shop.data.bodyshops[0])); yield put(setBodyshop(shop.data.bodyshops[0]));
} catch (error) { } catch (error) {
console.log("UH-OH. Couldn't get shop details.", error); console.log("UH-OH. Couldn't get shop details.", error);

View File

@@ -4282,6 +4282,18 @@ expo-file-system@~9.3.0:
dependencies: dependencies:
uuid "^3.4.0" uuid "^3.4.0"
expo-firebase-analytics@~2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/expo-firebase-analytics/-/expo-firebase-analytics-2.6.0.tgz#6c549ed2dceecb22d7d7160034a00896963d38a3"
integrity sha512-ciLHxYKfS0Oih184ckVJyYj95fWvK+xfDXG9yOkpzow/NIf9snp8ziXSMyJTwFg93bNr3uqvKxk985LSvEPe9Q==
dependencies:
expo-firebase-core "~1.2.0"
expo-firebase-core@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/expo-firebase-core/-/expo-firebase-core-1.2.0.tgz#1f41d777cb04e19f495d27491b1596bdeb233f95"
integrity sha512-ojqiJLlH5BXQsrElPOtYsO0tHR2333mRDxV625Y0NQyjFBF17NQxlmCCkyh2uGO94LgcZTfB13SMiNHOe9RcZQ==
expo-font@~8.4.0: expo-font@~8.4.0:
version "8.4.0" version "8.4.0"
resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-8.4.0.tgz#7cb4cc9d852dd8d0977ce425146b94221b40c1d5" resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-8.4.0.tgz#7cb4cc9d852dd8d0977ce425146b94221b40c1d5"