diff --git a/package.json b/package.json
index c997a3764..35efccc68 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all"
},
"dependencies": {
- "@atproto/api": "0.2.1",
+ "@atproto/api": "0.2.3",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@expo/webpack-config": "^18.0.1",
"@fortawesome/fontawesome-svg-core": "^6.1.1",
diff --git a/src/lib/analytics.tsx b/src/lib/analytics.tsx
index 725dd2328..d0a8f1243 100644
--- a/src/lib/analytics.tsx
+++ b/src/lib/analytics.tsx
@@ -1,19 +1,56 @@
import React from 'react'
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 {useStores} from 'state/models/root-store'
+import {sha256} from 'js-sha256'
const segmentClient = createClient({
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
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) {
+ 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
- // 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
// -prf
segmentClient.isReady.onChange(() => {
@@ -33,23 +70,29 @@ export function init(store: RootStoreModel) {
store.log.debug('Recording app info', {new: newAppInfo, old: oldAppInfo})
if (typeof oldAppInfo === 'undefined') {
- segmentClient.track('Application Installed', {
- version: newAppInfo.version,
- build: newAppInfo.build,
- })
+ if (store.session.hasSession) {
+ segmentClient.track('Application Installed', {
+ version: newAppInfo.version,
+ build: newAppInfo.build,
+ })
+ }
} else if (newAppInfo.version !== oldAppInfo.version) {
- segmentClient.track('Application Updated', {
+ if (store.session.hasSession) {
+ segmentClient.track('Application Updated', {
+ version: newAppInfo.version,
+ build: newAppInfo.build,
+ previous_version: oldAppInfo.version,
+ previous_build: oldAppInfo.build,
+ })
+ }
+ }
+ if (store.session.hasSession) {
+ segmentClient.track('Application Opened', {
+ from_background: false,
version: newAppInfo.version,
build: newAppInfo.build,
- previous_version: oldAppInfo.version,
- previous_build: oldAppInfo.build,
})
}
- segmentClient.track('Application Opened', {
- from_background: false,
- version: newAppInfo.version,
- build: newAppInfo.build,
- })
})
let lastState: AppStateStatus = AppState.currentState
diff --git a/src/lib/analytics.web.tsx b/src/lib/analytics.web.tsx
index 97f456893..467ae278b 100644
--- a/src/lib/analytics.web.tsx
+++ b/src/lib/analytics.web.tsx
@@ -1,6 +1,12 @@
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 {useStores} from 'state/models/root-store'
+import {sha256} from 'js-sha256'
const segmentClient = createClient(
{
@@ -16,10 +22,40 @@ const segmentClient = createClient(
)
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) {
- // no init needed on web
+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()
+ }
+ }
+ })
}
export function Provider({children}: React.PropsWithChildren<{}>) {
diff --git a/src/state/models/session.ts b/src/state/models/session.ts
index c2e10880d..96e058c02 100644
--- a/src/state/models/session.ts
+++ b/src/state/models/session.ts
@@ -25,6 +25,7 @@ export const accountData = z.object({
accessJwt: z.string().optional(),
handle: z.string(),
did: z.string(),
+ email: z.string().optional(),
displayName: z.string().optional(),
aviUrl: z.string().optional(),
})
@@ -201,6 +202,7 @@ export class SessionModel {
accessJwt,
handle: session?.handle || existingAccount?.handle || '',
+ email: session?.email || existingAccount?.email || '',
displayName: addedInfo
? addedInfo.displayName
: existingAccount?.displayName || '',
diff --git a/src/view/com/auth/create/CreateAccount.tsx b/src/view/com/auth/create/CreateAccount.tsx
index 6ece903d6..467b87948 100644
--- a/src/view/com/auth/create/CreateAccount.tsx
+++ b/src/view/com/auth/create/CreateAccount.tsx
@@ -8,7 +8,6 @@ import {
View,
} from 'react-native'
import {observer} from 'mobx-react-lite'
-import {sha256} from 'js-sha256'
import {useAnalytics} from 'lib/analytics'
import {Text} from '../../util/text/Text'
import {s, colors} from 'lib/styles'
@@ -22,7 +21,7 @@ import {Step3} from './Step3'
export const CreateAccount = observer(
({onPressBack}: {onPressBack: () => void}) => {
- const {track, screen, identify} = useAnalytics()
+ const {track, screen} = useAnalytics()
const pal = usePalette('default')
const store = useStores()
const model = React.useMemo(() => new CreateAccountModel(store), [store])
@@ -57,14 +56,12 @@ export const CreateAccount = observer(
} else {
try {
await model.submit()
- const email_hashed = sha256(model.email)
- identify(email_hashed, {email_hashed})
track('Create Account')
} catch {
// dont need to handle here
}
}
- }, [model, identify, track])
+ }, [model, track])
return (
<ScrollView testID="createAccount" style={pal.view}>
diff --git a/yarn.lock b/yarn.lock
index 2312b55a5..979bbdc17 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -30,10 +30,10 @@
tlds "^1.234.0"
typed-emitter "^2.1.0"
-"@atproto/api@0.2.1":
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.2.1.tgz#034cab5928e1a6b0059e7237f6a82c57daadb264"
- integrity sha512-ub92BFrHrm/r1En9IedqRc9r9BZy0i7J8mmFZ5EMxRJwdCJeMYB8CdmLfgNXQcsTPswbYF94pyZkrpeQNJWr1A==
+"@atproto/api@0.2.3":
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.2.3.tgz#0eb9cb542c113b2c839f2c5ca284c30b117f489a"
+ integrity sha512-i0tWdOPQyZuSlkd2MY3s7QTac2ovH104tzy5rJwTZXZyhpf2Zom1xedaHb+pQmFzug7YaD7tx7OMSPlJIV0dpg==
dependencies:
"@atproto/common-web" "*"
"@atproto/uri" "*"
|