* Only send analytics events when the user is logged in * Only send analytics events when the user is logged in (web) * Add analytics identify() callzio/stable
parent
92b80ff048
commit
8e28d3c6be
|
@ -21,7 +21,7 @@
|
||||||
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all"
|
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atproto/api": "0.2.1",
|
"@atproto/api": "0.2.3",
|
||||||
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
||||||
"@expo/webpack-config": "^18.0.1",
|
"@expo/webpack-config": "^18.0.1",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
"@fortawesome/fontawesome-svg-core": "^6.1.1",
|
||||||
|
|
|
@ -1,19 +1,56 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {AppState, AppStateStatus} from 'react-native'
|
import {AppState, AppStateStatus} from 'react-native'
|
||||||
import {createClient, AnalyticsProvider} from '@segment/analytics-react-native'
|
import {
|
||||||
|
createClient,
|
||||||
|
AnalyticsProvider,
|
||||||
|
useAnalytics as useAnalyticsOrig,
|
||||||
|
} from '@segment/analytics-react-native'
|
||||||
import {RootStoreModel, AppInfo} from 'state/models/root-store'
|
import {RootStoreModel, AppInfo} from 'state/models/root-store'
|
||||||
|
import {useStores} from 'state/models/root-store'
|
||||||
|
import {sha256} from 'js-sha256'
|
||||||
|
|
||||||
const segmentClient = createClient({
|
const segmentClient = createClient({
|
||||||
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
|
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
|
||||||
trackAppLifecycleEvents: false,
|
trackAppLifecycleEvents: false,
|
||||||
})
|
})
|
||||||
export const track = segmentClient?.track?.bind?.(segmentClient)
|
|
||||||
|
|
||||||
export {useAnalytics} from '@segment/analytics-react-native'
|
export function useAnalytics() {
|
||||||
|
const store = useStores()
|
||||||
|
const methods = useAnalyticsOrig()
|
||||||
|
return React.useMemo(() => {
|
||||||
|
if (store.session.hasSession) {
|
||||||
|
return methods
|
||||||
|
}
|
||||||
|
// dont send analytics pings for anonymous users
|
||||||
|
return {
|
||||||
|
screen: () => {},
|
||||||
|
track: () => {},
|
||||||
|
identify: () => {},
|
||||||
|
flush: () => {},
|
||||||
|
group: () => {},
|
||||||
|
alias: () => {},
|
||||||
|
reset: () => {},
|
||||||
|
}
|
||||||
|
}, [store, methods])
|
||||||
|
}
|
||||||
|
|
||||||
export function init(store: RootStoreModel) {
|
export function init(store: RootStoreModel) {
|
||||||
|
store.onSessionLoaded(() => {
|
||||||
|
const sess = store.session.currentSession
|
||||||
|
if (sess) {
|
||||||
|
if (sess.email) {
|
||||||
|
store.log.debug('Ping w/hash')
|
||||||
|
const email_hashed = sha256(sess.email)
|
||||||
|
segmentClient.identify(email_hashed, {email_hashed})
|
||||||
|
} else {
|
||||||
|
store.log.debug('Ping w/o hash')
|
||||||
|
segmentClient.identify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// NOTE
|
// NOTE
|
||||||
// this method is a copy of segment's own lifecycle event tracking
|
// this is a copy of segment's own lifecycle event tracking
|
||||||
// we handle it manually to ensure that it never fires while the app is backgrounded
|
// we handle it manually to ensure that it never fires while the app is backgrounded
|
||||||
// -prf
|
// -prf
|
||||||
segmentClient.isReady.onChange(() => {
|
segmentClient.isReady.onChange(() => {
|
||||||
|
@ -33,11 +70,14 @@ export function init(store: RootStoreModel) {
|
||||||
store.log.debug('Recording app info', {new: newAppInfo, old: oldAppInfo})
|
store.log.debug('Recording app info', {new: newAppInfo, old: oldAppInfo})
|
||||||
|
|
||||||
if (typeof oldAppInfo === 'undefined') {
|
if (typeof oldAppInfo === 'undefined') {
|
||||||
|
if (store.session.hasSession) {
|
||||||
segmentClient.track('Application Installed', {
|
segmentClient.track('Application Installed', {
|
||||||
version: newAppInfo.version,
|
version: newAppInfo.version,
|
||||||
build: newAppInfo.build,
|
build: newAppInfo.build,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
} else if (newAppInfo.version !== oldAppInfo.version) {
|
} else if (newAppInfo.version !== oldAppInfo.version) {
|
||||||
|
if (store.session.hasSession) {
|
||||||
segmentClient.track('Application Updated', {
|
segmentClient.track('Application Updated', {
|
||||||
version: newAppInfo.version,
|
version: newAppInfo.version,
|
||||||
build: newAppInfo.build,
|
build: newAppInfo.build,
|
||||||
|
@ -45,11 +85,14 @@ export function init(store: RootStoreModel) {
|
||||||
previous_build: oldAppInfo.build,
|
previous_build: oldAppInfo.build,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (store.session.hasSession) {
|
||||||
segmentClient.track('Application Opened', {
|
segmentClient.track('Application Opened', {
|
||||||
from_background: false,
|
from_background: false,
|
||||||
version: newAppInfo.version,
|
version: newAppInfo.version,
|
||||||
build: newAppInfo.build,
|
build: newAppInfo.build,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let lastState: AppStateStatus = AppState.currentState
|
let lastState: AppStateStatus = AppState.currentState
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {createClient, AnalyticsProvider} from '@segment/analytics-react'
|
import {
|
||||||
|
createClient,
|
||||||
|
AnalyticsProvider,
|
||||||
|
useAnalytics as useAnalyticsOrig,
|
||||||
|
} from '@segment/analytics-react'
|
||||||
import {RootStoreModel} from 'state/models/root-store'
|
import {RootStoreModel} from 'state/models/root-store'
|
||||||
|
import {useStores} from 'state/models/root-store'
|
||||||
|
import {sha256} from 'js-sha256'
|
||||||
|
|
||||||
const segmentClient = createClient(
|
const segmentClient = createClient(
|
||||||
{
|
{
|
||||||
|
@ -16,10 +22,40 @@ const segmentClient = createClient(
|
||||||
)
|
)
|
||||||
export const track = segmentClient?.track?.bind?.(segmentClient)
|
export const track = segmentClient?.track?.bind?.(segmentClient)
|
||||||
|
|
||||||
export {useAnalytics} from '@segment/analytics-react'
|
export function useAnalytics() {
|
||||||
|
const store = useStores()
|
||||||
|
const methods = useAnalyticsOrig()
|
||||||
|
return React.useMemo(() => {
|
||||||
|
if (store.session.hasSession) {
|
||||||
|
return methods
|
||||||
|
}
|
||||||
|
// dont send analytics pings for anonymous users
|
||||||
|
return {
|
||||||
|
screen: () => {},
|
||||||
|
track: () => {},
|
||||||
|
identify: () => {},
|
||||||
|
flush: () => {},
|
||||||
|
group: () => {},
|
||||||
|
alias: () => {},
|
||||||
|
reset: () => {},
|
||||||
|
}
|
||||||
|
}, [store, methods])
|
||||||
|
}
|
||||||
|
|
||||||
export function init(_store: RootStoreModel) {
|
export function init(store: RootStoreModel) {
|
||||||
// no init needed on web
|
store.onSessionLoaded(() => {
|
||||||
|
const sess = store.session.currentSession
|
||||||
|
if (sess) {
|
||||||
|
if (sess.email) {
|
||||||
|
store.log.debug('Ping w/hash')
|
||||||
|
const email_hashed = sha256(sess.email)
|
||||||
|
segmentClient.identify(email_hashed, {email_hashed})
|
||||||
|
} else {
|
||||||
|
store.log.debug('Ping w/o hash')
|
||||||
|
segmentClient.identify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ export const accountData = z.object({
|
||||||
accessJwt: z.string().optional(),
|
accessJwt: z.string().optional(),
|
||||||
handle: z.string(),
|
handle: z.string(),
|
||||||
did: z.string(),
|
did: z.string(),
|
||||||
|
email: z.string().optional(),
|
||||||
displayName: z.string().optional(),
|
displayName: z.string().optional(),
|
||||||
aviUrl: z.string().optional(),
|
aviUrl: z.string().optional(),
|
||||||
})
|
})
|
||||||
|
@ -201,6 +202,7 @@ export class SessionModel {
|
||||||
accessJwt,
|
accessJwt,
|
||||||
|
|
||||||
handle: session?.handle || existingAccount?.handle || '',
|
handle: session?.handle || existingAccount?.handle || '',
|
||||||
|
email: session?.email || existingAccount?.email || '',
|
||||||
displayName: addedInfo
|
displayName: addedInfo
|
||||||
? addedInfo.displayName
|
? addedInfo.displayName
|
||||||
: existingAccount?.displayName || '',
|
: existingAccount?.displayName || '',
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {sha256} from 'js-sha256'
|
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
|
@ -22,7 +21,7 @@ import {Step3} from './Step3'
|
||||||
|
|
||||||
export const CreateAccount = observer(
|
export const CreateAccount = observer(
|
||||||
({onPressBack}: {onPressBack: () => void}) => {
|
({onPressBack}: {onPressBack: () => void}) => {
|
||||||
const {track, screen, identify} = useAnalytics()
|
const {track, screen} = useAnalytics()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const model = React.useMemo(() => new CreateAccountModel(store), [store])
|
const model = React.useMemo(() => new CreateAccountModel(store), [store])
|
||||||
|
@ -57,14 +56,12 @@ export const CreateAccount = observer(
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await model.submit()
|
await model.submit()
|
||||||
const email_hashed = sha256(model.email)
|
|
||||||
identify(email_hashed, {email_hashed})
|
|
||||||
track('Create Account')
|
track('Create Account')
|
||||||
} catch {
|
} catch {
|
||||||
// dont need to handle here
|
// dont need to handle here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [model, identify, track])
|
}, [model, track])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView testID="createAccount" style={pal.view}>
|
<ScrollView testID="createAccount" style={pal.view}>
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
tlds "^1.234.0"
|
tlds "^1.234.0"
|
||||||
typed-emitter "^2.1.0"
|
typed-emitter "^2.1.0"
|
||||||
|
|
||||||
"@atproto/api@0.2.1":
|
"@atproto/api@0.2.3":
|
||||||
version "0.2.1"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.2.1.tgz#034cab5928e1a6b0059e7237f6a82c57daadb264"
|
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.2.3.tgz#0eb9cb542c113b2c839f2c5ca284c30b117f489a"
|
||||||
integrity sha512-ub92BFrHrm/r1En9IedqRc9r9BZy0i7J8mmFZ5EMxRJwdCJeMYB8CdmLfgNXQcsTPswbYF94pyZkrpeQNJWr1A==
|
integrity sha512-i0tWdOPQyZuSlkd2MY3s7QTac2ovH104tzy5rJwTZXZyhpf2Zom1xedaHb+pQmFzug7YaD7tx7OMSPlJIV0dpg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@atproto/common-web" "*"
|
"@atproto/common-web" "*"
|
||||||
"@atproto/uri" "*"
|
"@atproto/uri" "*"
|
||||||
|
|
Loading…
Reference in New Issue