about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--src/lib/analytics.tsx75
-rw-r--r--src/lib/analytics.web.tsx44
-rw-r--r--src/state/models/session.ts2
-rw-r--r--src/view/com/auth/create/CreateAccount.tsx7
-rw-r--r--yarn.lock8
6 files changed, 108 insertions, 30 deletions
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" "*"