[APP-1782] Analytics migration (#9734)

* WIP

* Clean up growthbook code, integrate into init and sessions

* Move everything out of React

* Add metrics client

* Move to separate file

* Shared metadata cache

* Ensure we update metadata when session ID changes

* Ensure userMetadata is cleared when logging out

* WIP revamp

* Integrate feature gates into analytics context

* Clean up old code

* Fix useMeta util

* Some comments and cleanup

* Add logger to base analytics context

* Refactor current route handling

* Rip out LogEvent from navigation

* Update tracking endpoint

* Migrate toClout

* Clear out statsig client

* Add todo, reset logger readme

* Ope fix statsig noop

* Refactor logging in feed-feedback, add debug logging to metrics client

* Remove LogEvents alias for Metrics

* Prefer root package export

* Remove Metrics alias from logger

* [APP-1782] Migrate to new analytics APIs (#9735)

* Migrate logEvent to useAnalytics

* Migrate logger.metric to useAnalytics

* Migrate tricky spot, fix types

* Migrate remaining tricky spot

* Missed one

* Remove metric() from logger

* Migrate useGate to useAnalytics

* Remove all other StatSig mentions

* Update event payload

* Update logger tests

* Mock expo method

* Fix session ID bug

* Add session ID test

* Add test for metrics client

* Clarify intent

* Clean up core analytics file

* Clean up the call once utils

* Fix TODO

* Fix TODO

* Fix TODO

* Fix TODO

* Fix TODO

* Remove debug code

* Fix navigation context

* OK nav context is not working, todo

* Checkpoint: works but feels hacky

* Fix navigation context issue

* Improve feature API

* Improve metric logging

* Update logger tests
This commit is contained in:
Eric Bailey
2026-01-22 15:33:45 -06:00
committed by GitHub
parent 8614e5e105
commit 25a1ed1209
190 changed files with 2358 additions and 1689 deletions
@@ -5,7 +5,6 @@ import {LinearGradient} from 'expo-linear-gradient'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {logger} from '#/logger'
import {atoms as a, useTheme, web} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import {isFindContactsFeatureEnabled} from '#/components/contacts/country-allowlist'
@@ -16,8 +15,8 @@ import {
isExistingUserAsOf,
} from '#/components/dialogs/nuxs/utils'
import {Text} from '#/components/Typography'
import {IS_NATIVE, IS_WEB} from '#/env'
import {IS_E2E} from '#/env'
import {useAnalytics} from '#/analytics'
import {IS_E2E, IS_NATIVE, IS_WEB} from '#/env'
import {navigate} from '#/Navigation'
export const enabled = createIsEnabledCheck(props => {
@@ -35,6 +34,7 @@ export const enabled = createIsEnabledCheck(props => {
export function FindContactsAnnouncement() {
const t = useTheme()
const {_} = useLingui()
const ax = useAnalytics()
const nuxDialogs = useNuxDialogContext()
const control = Dialog.useDialogControl()
@@ -115,7 +115,7 @@ export function FindContactsAnnouncement() {
size="large"
color="primary"
onPress={() => {
logger.metric('contacts:nux:ctaPressed', {})
ax.metric('contacts:nux:ctaPressed', {})
control.close(() => {
navigate('FindContactsFlow')
})
@@ -5,7 +5,6 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {urls} from '#/lib/constants'
import {logger} from '#/logger'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
@@ -14,11 +13,13 @@ import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons
import {VerifierCheck} from '#/components/icons/VerifierCheck'
import {Link} from '#/components/Link'
import {Span, Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE} from '#/env'
export function InitialVerificationAnnouncement() {
const t = useTheme()
const {_} = useLingui()
const ax = useAnalytics()
const {gtMobile} = useBreakpoints()
const nuxDialogs = useNuxDialogContext()
const control = Dialog.useDialogControl()
@@ -161,13 +162,9 @@ export function InitialVerificationAnnouncement() {
color="primary"
style={[a.justify_center, a.w_full]}
onPress={() => {
logger.metric(
'verification:learn-more',
{
location: 'initialAnnouncementeNux',
},
{statsig: false},
)
ax.metric('verification:learn-more', {
location: 'initialAnnouncementeNux',
})
}}>
<ButtonText>
<Trans>Read blog post</Trans>
@@ -24,7 +24,7 @@ export const enabled = createIsEnabledCheck(props => {
'2026-01-16T00:00:00.000Z',
props.currentProfile.createdAt,
) &&
!props.gate('disable_live_now_beta')
!props.features.enabled(props.features.DisableLiveNowBeta)
)
})
+4 -4
View File
@@ -8,7 +8,6 @@ import {
} from 'react'
import {type AppBskyActorDefs} from '@atproto/api'
import {useGate} from '#/lib/statsig/statsig'
import {logger} from '#/logger'
import {STALE} from '#/state/queries'
import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs'
@@ -25,6 +24,7 @@ import {
} from '#/components/dialogs/nuxs/LiveNowBetaDialog'
import {isSnoozed, snooze, unsnooze} from '#/components/dialogs/nuxs/snoozing'
import {type EnabledCheckProps} from '#/components/dialogs/nuxs/utils'
import {useAnalytics} from '#/analytics'
import {useGeolocation} from '#/geolocation'
type Context = {
@@ -88,7 +88,7 @@ function Inner({
currentProfile: AppBskyActorDefs.ProfileViewDetailed
preferences: UsePreferencesQueryResponse
}) {
const gate = useGate()
const ax = useAnalytics()
const geolocation = useGeolocation()
const {nuxs} = useNuxs()
const [snoozed, setSnoozed] = useState(() => {
@@ -133,7 +133,7 @@ function Inner({
if (
enabled &&
!enabled({
gate,
features: ax.features,
currentAccount,
currentProfile,
preferences,
@@ -165,11 +165,11 @@ function Inner({
break
}
}, [
ax.features,
nuxs,
snoozed,
snoozeNuxDialog,
saveNux,
gate,
currentAccount,
currentProfile,
preferences,
+2 -2
View File
@@ -1,12 +1,12 @@
import {type AppBskyActorDefs} from '@atproto/api'
import {type useGate} from '#/lib/statsig/statsig'
import {type UsePreferencesQueryResponse} from '#/state/queries/preferences'
import {type SessionAccount} from '#/state/session'
import {type AnalyticsContextType} from '#/analytics'
import {type Geolocation} from '#/geolocation'
export type EnabledCheckProps = {
gate: ReturnType<typeof useGate>
features: AnalyticsContextType['features']
currentAccount: SessionAccount
currentProfile: AppBskyActorDefs.ProfileViewDetailed
preferences: UsePreferencesQueryResponse