about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2024-03-21 11:04:02 +0000
committerGitHub <noreply@github.com>2024-03-21 11:04:02 +0000
commit396d183dfcc303eb5056eca52f7cd62254f8f5c4 (patch)
tree60f0c02da71f77fdfdeb65cc3e77af226d40de03 /src
parentad3dd9f6dccaa4b73da0000f41f23ac2fea5d1b2 (diff)
downloadvoidsky-396d183dfcc303eb5056eca52f7cd62254f8f5c4.tar.zst
[Statsig] Onboarding and routing events (#3302)
Diffstat (limited to 'src')
-rw-r--r--src/Navigation.tsx120
-rw-r--r--src/lib/statsig/events.ts34
-rw-r--r--src/lib/statsig/statsig.tsx13
-rw-r--r--src/screens/Onboarding/StepAlgoFeeds/index.tsx30
-rw-r--r--src/screens/Onboarding/StepFinished.tsx31
-rw-r--r--src/screens/Onboarding/StepFollowingFeed.tsx31
-rw-r--r--src/screens/Onboarding/StepInterests/index.tsx34
-rw-r--r--src/screens/Onboarding/StepModeration/index.tsx25
-rw-r--r--src/screens/Onboarding/StepSuggestedAccounts/index.tsx34
-rw-r--r--src/screens/Onboarding/StepTopicalFeeds.tsx28
-rw-r--r--src/screens/Signup/index.tsx4
-rw-r--r--src/state/session/index.tsx18
-rw-r--r--src/view/com/auth/LoggedOut.tsx35
13 files changed, 259 insertions, 178 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index 83aede722..ab40ff422 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -1,86 +1,86 @@
 import * as React from 'react'
-import {
-  NavigationContainer,
-  createNavigationContainerRef,
-  CommonActions,
-  StackActions,
-  DefaultTheme,
-  DarkTheme,
-} from '@react-navigation/native'
+import {JSX} from 'react/jsx-runtime'
+import {i18n, MessageDescriptor} from '@lingui/core'
+import {msg} from '@lingui/macro'
 import {
   BottomTabBarProps,
   createBottomTabNavigator,
 } from '@react-navigation/bottom-tabs'
 import {
-  HomeTabNavigatorParams,
-  SearchTabNavigatorParams,
+  CommonActions,
+  createNavigationContainerRef,
+  DarkTheme,
+  DefaultTheme,
+  NavigationContainer,
+  StackActions,
+} from '@react-navigation/native'
+
+import {timeout} from 'lib/async/timeout'
+import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
+import {usePalette} from 'lib/hooks/usePalette'
+import {buildStateObject} from 'lib/routes/helpers'
+import {
+  AllNavigatorParams,
+  BottomTabNavigatorParams,
   FeedsTabNavigatorParams,
-  NotificationsTabNavigatorParams,
   FlatNavigatorParams,
-  AllNavigatorParams,
+  HomeTabNavigatorParams,
   MyProfileTabNavigatorParams,
-  BottomTabNavigatorParams,
+  NotificationsTabNavigatorParams,
+  SearchTabNavigatorParams,
 } from 'lib/routes/types'
-import {BottomBar} from './view/shell/bottom-bar/BottomBar'
-import {buildStateObject} from 'lib/routes/helpers'
-import {State, RouteParams} from 'lib/routes/types'
+import {RouteParams, State} from 'lib/routes/types'
+import {bskyTitle} from 'lib/strings/headings'
 import {isAndroid, isNative} from 'platform/detection'
-import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
+import {PreferencesExternalEmbeds} from '#/view/screens/PreferencesExternalEmbeds'
+import {AppPasswords} from 'view/screens/AppPasswords'
+import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
+import {ModerationMutedAccounts} from 'view/screens/ModerationMutedAccounts'
+import {PreferencesFollowingFeed} from 'view/screens/PreferencesFollowingFeed'
+import {PreferencesThreads} from 'view/screens/PreferencesThreads'
+import {SavedFeeds} from 'view/screens/SavedFeeds'
+import HashtagScreen from '#/screens/Hashtag'
+import {ModerationScreen} from '#/screens/Moderation'
+import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy'
+import {init as initAnalytics} from './lib/analytics/analytics'
+import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
+import {attachRouteToLogEvents, logEvent} from './lib/statsig/statsig'
 import {router} from './routes'
-import {usePalette} from 'lib/hooks/usePalette'
-import {bskyTitle} from 'lib/strings/headings'
-import {JSX} from 'react/jsx-runtime'
-import {timeout} from 'lib/async/timeout'
+import {useModalControls} from './state/modals'
 import {useUnreadNotifications} from './state/queries/notifications/unread'
 import {useSession} from './state/session'
-import {useModalControls} from './state/modals'
 import {
-  shouldRequestEmailConfirmation,
   setEmailConfirmationRequested,
+  shouldRequestEmailConfirmation,
 } from './state/shell/reminders'
-import {init as initAnalytics} from './lib/analytics/analytics'
-import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
-
-import {HomeScreen} from './view/screens/Home'
-import {SearchScreen} from './view/screens/Search'
+import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
+import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy'
+import {DebugModScreen} from './view/screens/DebugMod'
 import {FeedsScreen} from './view/screens/Feeds'
-import {NotificationsScreen} from './view/screens/Notifications'
+import {HomeScreen} from './view/screens/Home'
+import {LanguageSettingsScreen} from './view/screens/LanguageSettings'
 import {ListsScreen} from './view/screens/Lists'
-import {ModerationScreen} from '#/screens/Moderation'
+import {LogScreen} from './view/screens/Log'
 import {ModerationModlistsScreen} from './view/screens/ModerationModlists'
 import {NotFoundScreen} from './view/screens/NotFound'
-import {SettingsScreen} from './view/screens/Settings'
-import {LanguageSettingsScreen} from './view/screens/LanguageSettings'
+import {NotificationsScreen} from './view/screens/Notifications'
+import {PostLikedByScreen} from './view/screens/PostLikedBy'
+import {PostRepostedByScreen} from './view/screens/PostRepostedBy'
+import {PostThreadScreen} from './view/screens/PostThread'
+import {PrivacyPolicyScreen} from './view/screens/PrivacyPolicy'
 import {ProfileScreen} from './view/screens/Profile'
-import {ProfileFollowersScreen} from './view/screens/ProfileFollowers'
-import {ProfileFollowsScreen} from './view/screens/ProfileFollows'
 import {ProfileFeedScreen} from './view/screens/ProfileFeed'
 import {ProfileFeedLikedByScreen} from './view/screens/ProfileFeedLikedBy'
+import {ProfileFollowersScreen} from './view/screens/ProfileFollowers'
+import {ProfileFollowsScreen} from './view/screens/ProfileFollows'
 import {ProfileListScreen} from './view/screens/ProfileList'
-import {PostThreadScreen} from './view/screens/PostThread'
-import {PostLikedByScreen} from './view/screens/PostLikedBy'
-import {PostRepostedByScreen} from './view/screens/PostRepostedBy'
+import {SearchScreen} from './view/screens/Search'
+import {SettingsScreen} from './view/screens/Settings'
 import {Storybook} from './view/screens/Storybook'
-import {DebugModScreen} from './view/screens/DebugMod'
-import {LogScreen} from './view/screens/Log'
 import {SupportScreen} from './view/screens/Support'
-import {PrivacyPolicyScreen} from './view/screens/PrivacyPolicy'
 import {TermsOfServiceScreen} from './view/screens/TermsOfService'
-import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
-import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy'
-import {AppPasswords} from 'view/screens/AppPasswords'
-import {ModerationMutedAccounts} from 'view/screens/ModerationMutedAccounts'
-import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
-import {SavedFeeds} from 'view/screens/SavedFeeds'
-import {PreferencesFollowingFeed} from 'view/screens/PreferencesFollowingFeed'
-import {PreferencesThreads} from 'view/screens/PreferencesThreads'
-import {PreferencesExternalEmbeds} from '#/view/screens/PreferencesExternalEmbeds'
+import {BottomBar} from './view/shell/bottom-bar/BottomBar'
 import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStackNavigatorWithAuth'
-import {msg} from '@lingui/macro'
-import {i18n, MessageDescriptor} from '@lingui/core'
-import HashtagScreen from '#/screens/Hashtag'
-import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy'
-import {logEvent, attachRouteToLogEvents} from './lib/statsig/statsig'
 
 const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
 
@@ -554,10 +554,14 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
       ref={navigationRef}
       linking={LINKING}
       theme={theme}
+      onStateChange={() => {
+        logEvent('router:navigate', {})
+      }}
       onReady={() => {
         attachRouteToLogEvents(getCurrentRouteName)
         logModuleInitTime()
         onReady()
+        logEvent('router:navigate', {})
       }}>
       {children}
     </NavigationContainer>
@@ -693,11 +697,11 @@ function logModuleInitTime() {
 }
 
 export {
+  FlatNavigator,
+  handleLink,
   navigate,
-  resetToTab,
   reset,
-  handleLink,
-  TabsNavigator,
-  FlatNavigator,
+  resetToTab,
   RoutesContainer,
+  TabsNavigator,
 }
diff --git a/src/lib/statsig/events.ts b/src/lib/statsig/events.ts
index b83095976..2de15b64e 100644
--- a/src/lib/statsig/events.ts
+++ b/src/lib/statsig/events.ts
@@ -1,4 +1,5 @@
 export type LogEvents = {
+  // App events
   init: {
     initMs: number
   }
@@ -14,6 +15,35 @@ export type LogEvents = {
     secondsActive: number
   }
   'state:foreground': {}
+  'router:navigate': {}
+
+  // Screen events
+  'splash:signInPressed': {}
+  'splash:createAccountPressed': {}
+  'signup:nextPressed': {
+    activeStep: number
+  }
+  'onboarding:interests:nextPressed': {
+    selectedInterests: string[]
+    selectedInterestsLength: number
+  }
+  'onboarding:suggestedAccounts:nextPressed': {
+    selectedAccountsLength: number
+    skipped: boolean
+  }
+  'onboarding:followingFeed:nextPressed': {}
+  'onboarding:algoFeeds:nextPressed': {
+    selectedPrimaryFeeds: string[]
+    selectedPrimaryFeedsLength: number
+    selectedSecondaryFeeds: string[]
+    selectedSecondaryFeedsLength: number
+  }
+  'onboarding:topicalFeeds:nextPressed': {
+    selectedFeeds: string[]
+    selectedFeedsLength: number
+  }
+  'onboarding:moderation:nextPressed': {}
+  'onboarding:finished:nextPressed': {}
   'feed:endReached': {
     feedType: string
     itemCount: number
@@ -22,6 +52,10 @@ export type LogEvents = {
     feedType: string
     reason: 'pull-to-refresh' | 'soft-reset' | 'load-latest'
   }
+
+  // Data events
+  'account:create:begin': {}
+  'account:create:success': {}
   'post:create': {
     imageCount: number
     isReply: boolean
diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx
index 9fa6cce2d..9bccedc6e 100644
--- a/src/lib/statsig/statsig.tsx
+++ b/src/lib/statsig/statsig.tsx
@@ -1,13 +1,14 @@
 import React from 'react'
 import {Platform} from 'react-native'
+import {AppState, AppStateStatus} from 'react-native'
+import {sha256} from 'js-sha256'
 import {
   Statsig,
   StatsigProvider,
   useGate as useStatsigGate,
 } from 'statsig-react-native-expo'
-import {AppState, AppStateStatus} from 'react-native'
+
 import {useSession} from '../../state/session'
-import {sha256} from 'js-sha256'
 import {LogEvents} from './events'
 
 export type {LogEvents}
@@ -24,7 +25,13 @@ const statsigOptions = {
 
 type FlatJSONRecord = Record<
   string,
-  string | number | boolean | null | undefined
+  | string
+  | number
+  | boolean
+  | null
+  | undefined
+  // Technically not scalar but Statsig will stringify it which works for us:
+  | string[]
 >
 
 let getCurrentRouteName: () => string | null | undefined = () => null
diff --git a/src/screens/Onboarding/StepAlgoFeeds/index.tsx b/src/screens/Onboarding/StepAlgoFeeds/index.tsx
index 1a4e4c493..35f525ef2 100644
--- a/src/screens/Onboarding/StepAlgoFeeds/index.tsx
+++ b/src/screens/Onboarding/StepAlgoFeeds/index.tsx
@@ -1,26 +1,26 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
-import {IS_PROD} from '#/env'
-import {atoms as a, tokens, useTheme} from '#/alf'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import * as Toggle from '#/components/forms/Toggle'
-import {Text} from '#/components/Typography'
-import {Loader} from '#/components/Loader'
-import {ListSparkle_Stroke2_Corner0_Rounded as ListSparkle} from '#/components/icons/ListSparkle'
 import {useAnalytics} from '#/lib/analytics/analytics'
-
-import {Context} from '#/screens/Onboarding/state'
+import {logEvent} from '#/lib/statsig/statsig'
 import {
-  Title,
   Description,
   OnboardingControls,
+  Title,
 } from '#/screens/Onboarding/Layout'
+import {Context} from '#/screens/Onboarding/state'
 import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
+import {atoms as a, tokens, useTheme} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import * as Toggle from '#/components/forms/Toggle'
 import {IconCircle} from '#/components/IconCircle'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {ListSparkle_Stroke2_Corner0_Rounded as ListSparkle} from '#/components/icons/ListSparkle'
+import {Loader} from '#/components/Loader'
+import {Text} from '#/components/Typography'
+import {IS_PROD} from '#/env'
 
 export type FeedConfig = {
   default: boolean
@@ -89,6 +89,12 @@ export function StepAlgoFeeds() {
       selectedSecondaryFeeds: secondaryFeedUris,
       selectedSecondaryFeedsLength: secondaryFeedUris.length,
     })
+    logEvent('onboarding:algoFeeds:nextPressed', {
+      selectedPrimaryFeeds: primaryFeedUris,
+      selectedPrimaryFeedsLength: primaryFeedUris.length,
+      selectedSecondaryFeeds: secondaryFeedUris,
+      selectedSecondaryFeedsLength: secondaryFeedUris.length,
+    })
   }, [primaryFeedUris, secondaryFeedUris, dispatch, track])
 
   React.useEffect(() => {
diff --git a/src/screens/Onboarding/StepFinished.tsx b/src/screens/Onboarding/StepFinished.tsx
index 944dcb96d..0c81d2d25 100644
--- a/src/screens/Onboarding/StepFinished.tsx
+++ b/src/screens/Onboarding/StepFinished.tsx
@@ -1,33 +1,33 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
+import {useAnalytics} from '#/lib/analytics/analytics'
+import {logEvent} from '#/lib/statsig/statsig'
 import {logger} from '#/logger'
-import {atoms as a, useTheme} from '#/alf'
-import {Button, ButtonText, ButtonIcon} from '#/components/Button'
-import {News2_Stroke2_Corner0_Rounded as News} from '#/components/icons/News2'
-import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
-import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
-import {Trending2_Stroke2_Corner2_Rounded as Trending} from '#/components/icons/Trending2'
-import {Text} from '#/components/Typography'
-import {useOnboardingDispatch} from '#/state/shell'
-import {Loader} from '#/components/Loader'
 import {useSetSaveFeedsMutation} from '#/state/queries/preferences'
 import {getAgent} from '#/state/session'
-import {useAnalytics} from '#/lib/analytics/analytics'
-
-import {Context} from '#/screens/Onboarding/state'
+import {useOnboardingDispatch} from '#/state/shell'
 import {
-  Title,
   Description,
   OnboardingControls,
+  Title,
 } from '#/screens/Onboarding/Layout'
-import {IconCircle} from '#/components/IconCircle'
+import {Context} from '#/screens/Onboarding/state'
 import {
   bulkWriteFollows,
   sortPrimaryAlgorithmFeeds,
 } from '#/screens/Onboarding/util'
+import {atoms as a, useTheme} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import {IconCircle} from '#/components/IconCircle'
+import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
+import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
+import {News2_Stroke2_Corner0_Rounded as News} from '#/components/icons/News2'
+import {Trending2_Stroke2_Corner2_Rounded as Trending} from '#/components/icons/Trending2'
+import {Loader} from '#/components/Loader'
+import {Text} from '#/components/Typography'
 
 export function StepFinished() {
   const {_} = useLingui()
@@ -76,6 +76,7 @@ export function StepFinished() {
     onboardDispatch({type: 'finish'})
     track('OnboardingV2:StepFinished:End')
     track('OnboardingV2:Complete')
+    logEvent('onboarding:finished:nextPressed', {})
   }, [state, dispatch, onboardDispatch, setSaving, saveFeeds, track])
 
   React.useEffect(() => {
diff --git a/src/screens/Onboarding/StepFollowingFeed.tsx b/src/screens/Onboarding/StepFollowingFeed.tsx
index 898afad13..e886a0891 100644
--- a/src/screens/Onboarding/StepFollowingFeed.tsx
+++ b/src/screens/Onboarding/StepFollowingFeed.tsx
@@ -1,28 +1,28 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
-import {atoms as a} from '#/alf'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
-import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/components/icons/FilterTimeline'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import {Text} from '#/components/Typography'
-import {Divider} from '#/components/Divider'
-import * as Toggle from '#/components/forms/Toggle'
 import {useAnalytics} from '#/lib/analytics/analytics'
-
-import {Context} from '#/screens/Onboarding/state'
-import {
-  Title,
-  Description,
-  OnboardingControls,
-} from '#/screens/Onboarding/Layout'
+import {logEvent} from '#/lib/statsig/statsig'
 import {
   usePreferencesQuery,
   useSetFeedViewPreferencesMutation,
 } from 'state/queries/preferences'
+import {
+  Description,
+  OnboardingControls,
+  Title,
+} from '#/screens/Onboarding/Layout'
+import {Context} from '#/screens/Onboarding/state'
+import {atoms as a} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import {Divider} from '#/components/Divider'
+import * as Toggle from '#/components/forms/Toggle'
 import {IconCircle} from '#/components/IconCircle'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/components/icons/FilterTimeline'
+import {Text} from '#/components/Typography'
 
 export function StepFollowingFeed() {
   const {_} = useLingui()
@@ -46,6 +46,7 @@ export function StepFollowingFeed() {
   const onContinue = React.useCallback(() => {
     dispatch({type: 'next'})
     track('OnboardingV2:StepFollowingFeed:End')
+    logEvent('onboarding:followingFeed:nextPressed', {})
   }, [track, dispatch])
 
   React.useEffect(() => {
diff --git a/src/screens/Onboarding/StepInterests/index.tsx b/src/screens/Onboarding/StepInterests/index.tsx
index ea23b74f0..8f34cced9 100644
--- a/src/screens/Onboarding/StepInterests/index.tsx
+++ b/src/screens/Onboarding/StepInterests/index.tsx
@@ -1,32 +1,32 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 import {useQuery} from '@tanstack/react-query'
 
+import {useAnalytics} from '#/lib/analytics/analytics'
+import {logEvent} from '#/lib/statsig/statsig'
+import {capitalize} from '#/lib/strings/capitalize'
 import {logger} from '#/logger'
-import {atoms as a, useBreakpoints, useTheme} from '#/alf'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
-import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
-import {EmojiSad_Stroke2_Corner0_Rounded as EmojiSad} from '#/components/icons/Emoji'
-import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateCounterClockwise} from '#/components/icons/ArrowRotateCounterClockwise'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import {Loader} from '#/components/Loader'
-import * as Toggle from '#/components/forms/Toggle'
 import {getAgent} from '#/state/session'
-import {useAnalytics} from '#/lib/analytics/analytics'
-import {Text} from '#/components/Typography'
 import {useOnboardingDispatch} from '#/state/shell'
-import {capitalize} from '#/lib/strings/capitalize'
-
-import {Context, ApiResponseMap} from '#/screens/Onboarding/state'
 import {
-  Title,
   Description,
   OnboardingControls,
+  Title,
 } from '#/screens/Onboarding/Layout'
+import {ApiResponseMap, Context} from '#/screens/Onboarding/state'
 import {InterestButton} from '#/screens/Onboarding/StepInterests/InterestButton'
+import {atoms as a, useBreakpoints, useTheme} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import * as Toggle from '#/components/forms/Toggle'
 import {IconCircle} from '#/components/IconCircle'
+import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateCounterClockwise} from '#/components/icons/ArrowRotateCounterClockwise'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {EmojiSad_Stroke2_Corner0_Rounded as EmojiSad} from '#/components/icons/Emoji'
+import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
+import {Loader} from '#/components/Loader'
+import {Text} from '#/components/Typography'
 
 export function StepInterests() {
   const {_} = useLingui()
@@ -107,6 +107,10 @@ export function StepInterests() {
         selectedInterests: interests,
         selectedInterestsLength: interests.length,
       })
+      logEvent('onboarding:interests:nextPressed', {
+        selectedInterests: interests,
+        selectedInterestsLength: interests.length,
+      })
     } catch (e: any) {
       logger.info(`onboading: error saving interests`)
       logger.error(e)
diff --git a/src/screens/Onboarding/StepModeration/index.tsx b/src/screens/Onboarding/StepModeration/index.tsx
index 9b52f9f43..c5bdf5622 100644
--- a/src/screens/Onboarding/StepModeration/index.tsx
+++ b/src/screens/Onboarding/StepModeration/index.tsx
@@ -1,27 +1,27 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
-import {msg, Trans} from '@lingui/macro'
 import {LABELS} from '@atproto/api'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
-import {atoms as a} from '#/alf'
-import {usePreferencesSetAdultContentMutation} from 'state/queries/preferences'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
-import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
-import {usePreferencesQuery} from '#/state/queries/preferences'
-import {Loader} from '#/components/Loader'
 import {useAnalytics} from '#/lib/analytics/analytics'
-
+import {logEvent} from '#/lib/statsig/statsig'
+import {usePreferencesQuery} from '#/state/queries/preferences'
+import {usePreferencesSetAdultContentMutation} from 'state/queries/preferences'
 import {
   Description,
   OnboardingControls,
   Title,
 } from '#/screens/Onboarding/Layout'
-import {ModerationOption} from '#/screens/Onboarding/StepModeration/ModerationOption'
-import {AdultContentEnabledPref} from '#/screens/Onboarding/StepModeration/AdultContentEnabledPref'
 import {Context} from '#/screens/Onboarding/state'
+import {AdultContentEnabledPref} from '#/screens/Onboarding/StepModeration/AdultContentEnabledPref'
+import {ModerationOption} from '#/screens/Onboarding/StepModeration/ModerationOption'
+import {atoms as a} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
 import {IconCircle} from '#/components/IconCircle'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash'
+import {Loader} from '#/components/Loader'
 
 export function StepModeration() {
   const {_} = useLingui()
@@ -45,6 +45,7 @@ export function StepModeration() {
   const onContinue = React.useCallback(() => {
     dispatch({type: 'next'})
     track('OnboardingV2:StepModeration:End')
+    logEvent('onboarding:moderation:nextPressed', {})
   }, [track, dispatch])
 
   React.useEffect(() => {
diff --git a/src/screens/Onboarding/StepSuggestedAccounts/index.tsx b/src/screens/Onboarding/StepSuggestedAccounts/index.tsx
index bdf94d824..2e6161362 100644
--- a/src/screens/Onboarding/StepSuggestedAccounts/index.tsx
+++ b/src/screens/Onboarding/StepSuggestedAccounts/index.tsx
@@ -1,33 +1,33 @@
 import React from 'react'
 import {View} from 'react-native'
 import {AppBskyActorDefs} from '@atproto/api'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
-import {atoms as a, useBreakpoints} from '#/alf'
-import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
-import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import {Text} from '#/components/Typography'
-import {useProfilesQuery} from '#/state/queries/profile'
-import {Loader} from '#/components/Loader'
-import * as Toggle from '#/components/forms/Toggle'
-import {useModerationOpts} from '#/state/queries/preferences'
 import {useAnalytics} from '#/lib/analytics/analytics'
+import {logEvent} from '#/lib/statsig/statsig'
 import {capitalize} from '#/lib/strings/capitalize'
-
-import {Context} from '#/screens/Onboarding/state'
+import {useModerationOpts} from '#/state/queries/preferences'
+import {useProfilesQuery} from '#/state/queries/profile'
 import {
-  Title,
   Description,
   OnboardingControls,
+  Title,
 } from '#/screens/Onboarding/Layout'
+import {Context} from '#/screens/Onboarding/state'
 import {
   SuggestedAccountCard,
   SuggestedAccountCardPlaceholder,
 } from '#/screens/Onboarding/StepSuggestedAccounts/SuggestedAccountCard'
 import {aggregateInterestItems} from '#/screens/Onboarding/util'
+import {atoms as a, useBreakpoints} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import * as Toggle from '#/components/forms/Toggle'
 import {IconCircle} from '#/components/IconCircle'
+import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
+import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
+import {Loader} from '#/components/Loader'
+import {Text} from '#/components/Typography'
 
 export function Inner({
   profiles,
@@ -110,12 +110,20 @@ export function StepSuggestedAccounts() {
     track('OnboardingV2:StepSuggestedAccounts:End', {
       selectedAccountsLength: dids.length,
     })
+    logEvent('onboarding:suggestedAccounts:nextPressed', {
+      selectedAccountsLength: dids.length,
+      skipped: false,
+    })
   }, [dids, setSaving, dispatch, track])
 
   const handleSkip = React.useCallback(() => {
     // if a user comes back and clicks skip, erase follows
     dispatch({type: 'setSuggestedAccountsStepResults', accountDids: []})
     dispatch({type: 'next'})
+    logEvent('onboarding:suggestedAccounts:nextPressed', {
+      selectedAccountsLength: 0,
+      skipped: true,
+    })
   }, [dispatch])
 
   const isLoading = isProfilesLoading && moderationOpts
diff --git a/src/screens/Onboarding/StepTopicalFeeds.tsx b/src/screens/Onboarding/StepTopicalFeeds.tsx
index 089363c23..26b1c243b 100644
--- a/src/screens/Onboarding/StepTopicalFeeds.tsx
+++ b/src/screens/Onboarding/StepTopicalFeeds.tsx
@@ -1,28 +1,28 @@
 import React from 'react'
 import {View} from 'react-native'
-import {useLingui} from '@lingui/react'
 import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
 
-import {atoms as a} from '#/alf'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
-import {ListMagnifyingGlass_Stroke2_Corner0_Rounded as ListMagnifyingGlass} from '#/components/icons/ListMagnifyingGlass'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import * as Toggle from '#/components/forms/Toggle'
-import {Loader} from '#/components/Loader'
 import {useAnalytics} from '#/lib/analytics/analytics'
+import {logEvent} from '#/lib/statsig/statsig'
 import {capitalize} from '#/lib/strings/capitalize'
-
-import {Context} from '#/screens/Onboarding/state'
+import {IS_TEST_USER} from 'lib/constants'
+import {useSession} from 'state/session'
 import {
-  Title,
   Description,
   OnboardingControls,
+  Title,
 } from '#/screens/Onboarding/Layout'
+import {Context} from '#/screens/Onboarding/state'
 import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
 import {aggregateInterestItems} from '#/screens/Onboarding/util'
+import {atoms as a} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import * as Toggle from '#/components/forms/Toggle'
 import {IconCircle} from '#/components/IconCircle'
-import {IS_TEST_USER} from 'lib/constants'
-import {useSession} from 'state/session'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {ListMagnifyingGlass_Stroke2_Corner0_Rounded as ListMagnifyingGlass} from '#/components/icons/ListMagnifyingGlass'
+import {Loader} from '#/components/Loader'
 
 export function StepTopicalFeeds() {
   const {_} = useLingui()
@@ -62,6 +62,10 @@ export function StepTopicalFeeds() {
       selectedFeeds: selectedFeedUris,
       selectedFeedsLength: selectedFeedUris.length,
     })
+    logEvent('onboarding:topicalFeeds:nextPressed', {
+      selectedFeeds: selectedFeedUris,
+      selectedFeedsLength: selectedFeedUris.length,
+    })
   }, [selectedFeedUris, dispatch, track])
 
   React.useEffect(() => {
diff --git a/src/screens/Signup/index.tsx b/src/screens/Signup/index.tsx
index f19823b4f..b84f4d0d7 100644
--- a/src/screens/Signup/index.tsx
+++ b/src/screens/Signup/index.tsx
@@ -5,6 +5,7 @@ import {useLingui} from '@lingui/react'
 
 import {useAnalytics} from '#/lib/analytics/analytics'
 import {FEEDBACK_FORM_URL} from '#/lib/constants'
+import {logEvent} from '#/lib/statsig/statsig'
 import {createFullHandle} from '#/lib/strings/handles'
 import {useServiceQuery} from '#/state/queries/service'
 import {getAgent} from '#/state/session'
@@ -99,6 +100,9 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
     }
 
     dispatch({type: 'next'})
+    logEvent('signup:nextPressed', {
+      activeStep: state.activeStep,
+    })
   }, [
     _,
     state.activeStep,
diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx
index b6748bfad..c7dba3089 100644
--- a/src/state/session/index.tsx
+++ b/src/state/session/index.tsx
@@ -1,26 +1,26 @@
 import React from 'react'
 import {
-  BskyAgent,
   AtpPersistSessionHandler,
   BSKY_LABELER_DID,
+  BskyAgent,
 } from '@atproto/api'
 import {useQueryClient} from '@tanstack/react-query'
 import {jwtDecode} from 'jwt-decode'
 
-import {IS_DEV} from '#/env'
-import {IS_TEST_USER} from '#/lib/constants'
-import {isWeb} from '#/platform/detection'
+import {track} from '#/lib/analytics/analytics'
 import {networkRetry} from '#/lib/async/retry'
+import {IS_TEST_USER} from '#/lib/constants'
+import {logEvent, LogEvents} from '#/lib/statsig/statsig'
+import {hasProp} from '#/lib/type-guards'
 import {logger} from '#/logger'
+import {isWeb} from '#/platform/detection'
 import * as persisted from '#/state/persisted'
 import {PUBLIC_BSKY_AGENT} from '#/state/queries'
-import {emitSessionDropped} from '../events'
 import {useLoggedOutViewControls} from '#/state/shell/logged-out'
 import {useCloseAllActiveElements} from '#/state/util'
-import {track} from '#/lib/analytics/analytics'
-import {hasProp} from '#/lib/type-guards'
+import {IS_DEV} from '#/env'
+import {emitSessionDropped} from '../events'
 import {readLabelers} from './agent-config'
-import {logEvent, LogEvents} from '#/lib/statsig/statsig'
 
 let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
 
@@ -230,6 +230,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
     }: any) => {
       logger.info(`session: creating account`)
       track('Try Create Account')
+      logEvent('account:create:begin', {})
 
       const agent = new BskyAgent({service})
 
@@ -290,6 +291,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
 
       logger.debug(`session: created account`, {}, logger.DebugContext.session)
       track('Create Account')
+      logEvent('account:create:success', {})
     },
     [upsertAccount, queryClient, clearCurrentAccount],
   )
diff --git a/src/view/com/auth/LoggedOut.tsx b/src/view/com/auth/LoggedOut.tsx
index b22bbb7fe..c8c81dd77 100644
--- a/src/view/com/auth/LoggedOut.tsx
+++ b/src/view/com/auth/LoggedOut.tsx
@@ -1,27 +1,28 @@
 import React from 'react'
-import {View, Pressable} from 'react-native'
+import {Pressable, View} from 'react-native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
-import {Trans, msg} from '@lingui/macro'
 import {useNavigation} from '@react-navigation/native'
 
-import {isIOS, isNative} from '#/platform/detection'
-import {Login} from '#/screens/Login'
-import {Signup} from '#/screens/Signup'
-import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
-import {s} from '#/lib/styles'
-import {usePalette} from '#/lib/hooks/usePalette'
 import {useAnalytics} from '#/lib/analytics/analytics'
-import {SplashScreen} from './SplashScreen'
-import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
+import {usePalette} from '#/lib/hooks/usePalette'
 import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
+import {logEvent} from '#/lib/statsig/statsig'
+import {s} from '#/lib/styles'
+import {isIOS, isNative} from '#/platform/detection'
+import {useSession} from '#/state/session'
 import {
   useLoggedOutView,
   useLoggedOutViewControls,
 } from '#/state/shell/logged-out'
-import {useSession} from '#/state/session'
-import {Text} from '#/view/com/util/text/Text'
+import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
 import {NavigationProp} from 'lib/routes/types'
+import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
+import {Text} from '#/view/com/util/text/Text'
+import {Login} from '#/screens/Login'
+import {Signup} from '#/screens/Signup'
+import {SplashScreen} from './SplashScreen'
 
 enum ScreenState {
   S_LoginOrCreateAccount,
@@ -133,10 +134,14 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
 
         {screenState === ScreenState.S_LoginOrCreateAccount ? (
           <SplashScreen
-            onPressSignin={() => setScreenState(ScreenState.S_Login)}
-            onPressCreateAccount={() =>
+            onPressSignin={() => {
+              setScreenState(ScreenState.S_Login)
+              logEvent('splash:signInPressed', {})
+            }}
+            onPressCreateAccount={() => {
               setScreenState(ScreenState.S_CreateAccount)
-            }
+              logEvent('splash:createAccountPressed', {})
+            }}
           />
         ) : undefined}
         {screenState === ScreenState.S_Login ? (