[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
@@ -13,7 +13,6 @@ import {useLingui} from '@lingui/react'
import {JOINED_THIS_WEEK} from '#/lib/constants'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {logEvent} from '#/lib/statsig/statsig'
import {createStarterPackGooglePlayUri} from '#/lib/strings/starter-pack'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useStarterPackQuery} from '#/state/queries/starter-packs'
@@ -36,6 +35,7 @@ import {Default as ProfileCard} from '#/components/ProfileCard'
import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText'
import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {IS_WEB, IS_WEB_MOBILE_ANDROID} from '#/env'
import * as bsky from '#/types/bsky'
@@ -119,6 +119,7 @@ function LandingScreenLoaded({
}) {
const {creator, listItemsSample, feeds} = starterPack
const {_, i18n} = useLingui()
const ax = useAnalytics()
const t = useTheme()
const activeStarterPack = useActiveStarterPack()
const setActiveStarterPack = useSetActiveStarterPack()
@@ -146,7 +147,7 @@ function LandingScreenLoaded({
} else {
onContinue()
}
logEvent('starterPack:ctaPress', {
ax.metric('starterPack:ctaPress', {
starterPack: starterPack.uri,
})
}
+15 -10
View File
@@ -23,7 +23,6 @@ import {
type CommonNavigatorParams,
type NavigationProp,
} from '#/lib/routes/types'
import {logEvent} from '#/lib/statsig/statsig'
import {cleanError} from '#/lib/strings/errors'
import {getStarterPackOgCard} from '#/lib/strings/starter-pack'
import {logger} from '#/logger'
@@ -33,8 +32,10 @@ import {getAllListMembers} from '#/state/queries/list-members'
import {useResolvedStarterPackShortLink} from '#/state/queries/resolve-short-link'
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
import {useShortenLink} from '#/state/queries/shorten-link'
import {useDeleteStarterPackMutation} from '#/state/queries/starter-packs'
import {useStarterPackQuery} from '#/state/queries/starter-packs'
import {
useDeleteStarterPackMutation,
useStarterPackQuery,
} from '#/state/queries/starter-packs'
import {useAgent, useSession} from '#/state/session'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {
@@ -71,6 +72,7 @@ import {ProfilesList} from '#/components/StarterPack/Main/ProfilesList'
import {QrCodeDialog} from '#/components/StarterPack/QrCodeDialog'
import {ShareDialog} from '#/components/StarterPack/ShareDialog'
import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {IS_WEB} from '#/env'
import * as bsky from '#/types/bsky'
@@ -184,6 +186,7 @@ function StarterPackScreenLoaded({
const showFeedsTab = Boolean(starterPack.feeds?.length)
const showPostsTab = Boolean(starterPack.list)
const {_} = useLingui()
const ax = useAnalytics()
const tabs = [
...(showPeopleTab ? [_(msg`People`)] : []),
@@ -199,10 +202,10 @@ function StarterPackScreenLoaded({
const [imageLoaded, setImageLoaded] = React.useState(false)
React.useEffect(() => {
logEvent('starterPack:opened', {
ax.metric('starterPack:opened', {
starterPack: starterPack.uri,
})
}, [starterPack.uri])
}, [ax, starterPack.uri])
const onOpenShareDialog = React.useCallback(() => {
const rkey = new AtUri(starterPack.uri).rkey
@@ -243,7 +246,7 @@ function StarterPackScreenLoaded({
? ({headerHeight, scrollElRef}) => (
<ProfilesList
// Validated above
listUri={starterPack!.list!.uri}
listUri={starterPack.list!.uri}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
@@ -266,7 +269,7 @@ function StarterPackScreenLoaded({
? ({headerHeight, scrollElRef}) => (
<PostsList
// Validated above
listUri={starterPack!.list!.uri}
listUri={starterPack.list!.uri}
headerHeight={headerHeight}
// @ts-expect-error
scrollElRef={scrollElRef}
@@ -315,6 +318,7 @@ function Header({
const {record, creator} = starterPack
const isOwn = creator?.did === currentAccount?.did
const joinedAllTimeCount = starterPack.joinedAllTimeCount ?? 0
const ax = useAnalytics()
const navigation = useNavigation<NavigationProp>()
@@ -385,7 +389,7 @@ function Header({
})
Toast.show(_(msg`All accounts have been followed!`))
captureAction(ProgressGuideAction.Follow, dids.length)
logEvent('starterPack:followAll', {
ax.metric('starterPack:followAll', {
logContext: 'StarterPackProfilesList',
starterPack: starterPack.uri,
count: dids.length,
@@ -516,6 +520,7 @@ function OverflowMenu({
}) {
const t = useTheme()
const {_} = useLingui()
const ax = useAnalytics()
const {gtMobile} = useBreakpoints()
const {currentAccount} = useSession()
const reportDialogControl = useReportDialogControl()
@@ -528,7 +533,7 @@ function OverflowMenu({
error: deleteError,
} = useDeleteStarterPackMutation({
onSuccess: () => {
logEvent('starterPack:delete', {})
ax.metric('starterPack:delete', {})
deleteDialogControl.close(() => {
if (navigation.canGoBack()) {
navigation.popToTop()
@@ -554,7 +559,7 @@ function OverflowMenu({
rkey: routeParams.rkey,
listUri: starterPack.list.uri,
})
logEvent('starterPack:delete', {})
ax.metric('starterPack:delete', {})
}
return (
+4 -3
View File
@@ -22,7 +22,6 @@ import {
type CommonNavigatorParams,
type NavigationProp,
} from '#/lib/routes/types'
import {logEvent} from '#/lib/statsig/statsig'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
import {enforceLen} from '#/lib/strings/helpers'
@@ -58,6 +57,7 @@ import {ListMaybePlaceholder} from '#/components/Lists'
import {Loader} from '#/components/Loader'
import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog'
import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE} from '#/env'
import type * as bsky from '#/types/bsky'
import {Provider} from './State'
@@ -167,6 +167,7 @@ function WizardInner({
onSuccess?: () => void
}) {
const navigation = useNavigation<NavigationProp>()
const ax = useAnalytics()
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const [state, dispatch] = useWizardState()
@@ -222,7 +223,7 @@ function WizardInner({
const onSuccessCreate = (data: {uri: string; cid: string}) => {
const rkey = new AtUri(data.uri).rkey
logEvent('starterPack:create', {
ax.metric('starterPack:create', {
setName: state.name != null,
setDescription: state.description != null,
profilesCount: state.profiles.length,
@@ -236,7 +237,7 @@ function WizardInner({
onSuccess?.()
} else {
navigation.replace('StarterPack', {
name: profile!.handle,
name: profile.handle,
rkey,
new: true,
})