Instrument signup (#8037)

This commit is contained in:
Samuel Newman
2025-03-27 20:17:07 +02:00
committed by GitHub
parent 7d1ebf6a02
commit 5ceaee5793
8 changed files with 182 additions and 57 deletions
+79 -11
View File
@@ -2,7 +2,7 @@ import React, {useCallback} from 'react'
import {LayoutAnimation} from 'react-native'
import {
ComAtprotoServerCreateAccount,
ComAtprotoServerDescribeServer,
type ComAtprotoServerDescribeServer,
} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -56,6 +56,11 @@ export type SignupState = {
isLoading: boolean
pendingSubmit: null | SubmitTask
// Tracking
signupStartTime: number
fieldErrors: Record<ErrorField, number>
backgroundCount: number
}
export type SignupAction =
@@ -74,6 +79,7 @@ export type SignupAction =
| {type: 'clearError'}
| {type: 'setIsLoading'; value: boolean}
| {type: 'submit'; task: SubmitTask}
| {type: 'incrementBackgroundCount'}
export const initialState: SignupState = {
hasPrev: false,
@@ -93,6 +99,17 @@ export const initialState: SignupState = {
isLoading: false,
pendingSubmit: null,
// Tracking
signupStartTime: Date.now(),
fieldErrors: {
'invite-code': 0,
email: 0,
handle: 0,
password: 0,
'date-of-birth': 0,
},
backgroundCount: 0,
}
export function is13(date: Date) {
@@ -169,6 +186,23 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
case 'setError': {
next.error = a.value
next.errorField = a.field
// Track field errors
if (a.field) {
next.fieldErrors[a.field] = (next.fieldErrors[a.field] || 0) + 1
// Log the field error
logger.metric(
'signup:fieldError',
{
field: a.field,
errorCount: next.fieldErrors[a.field],
errorMessage: a.value,
activeStep: next.activeStep,
},
{statsig: true},
)
}
break
}
case 'clearError': {
@@ -180,6 +214,20 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
next.pendingSubmit = a.task
break
}
case 'incrementBackgroundCount': {
next.backgroundCount = s.backgroundCount + 1
// Log background/foreground event during signup
logger.metric(
'signup:backgrounded',
{
activeStep: next.activeStep,
backgroundCount: next.backgroundCount,
},
{statsig: true},
)
break
}
}
next.hasPrev = next.activeStep !== SignupStep.INFO
@@ -212,6 +260,7 @@ export function useSubmitSignup() {
return dispatch({
type: 'setError',
value: _(msg`Please enter your email.`),
field: 'email',
})
}
if (!EmailValidator.validate(state.email)) {
@@ -219,6 +268,7 @@ export function useSubmitSignup() {
return dispatch({
type: 'setError',
value: _(msg`Your email appears to be invalid.`),
field: 'email',
})
}
if (!state.password) {
@@ -226,6 +276,7 @@ export function useSubmitSignup() {
return dispatch({
type: 'setError',
value: _(msg`Please choose your password.`),
field: 'password',
})
}
if (!state.handle) {
@@ -233,6 +284,7 @@ export function useSubmitSignup() {
return dispatch({
type: 'setError',
value: _(msg`Please choose your handle.`),
field: 'handle',
})
}
if (
@@ -253,15 +305,26 @@ export function useSubmitSignup() {
dispatch({type: 'setIsLoading', value: true})
try {
await createAccount({
service: state.serviceUrl,
email: state.email,
handle: createFullHandle(state.handle, state.userDomain),
password: state.password,
birthDate: state.dateOfBirth,
inviteCode: state.inviteCode.trim(),
verificationCode: state.pendingSubmit?.verificationCode,
})
await createAccount(
{
service: state.serviceUrl,
email: state.email,
handle: createFullHandle(state.handle, state.userDomain),
password: state.password,
birthDate: state.dateOfBirth,
inviteCode: state.inviteCode.trim(),
verificationCode: state.pendingSubmit?.verificationCode,
},
{
signupDuration: Date.now() - state.signupStartTime,
fieldErrorsTotal: Object.values(state.fieldErrors).reduce(
(a, b) => a + b,
0,
),
backgroundCount: state.backgroundCount,
},
)
/*
* Must happen last so that if the user has multiple tabs open and
* createAccount fails, one tab is not stuck in onboarding — Eric
@@ -275,6 +338,7 @@ export function useSubmitSignup() {
value: _(
msg`Invite code not accepted. Check that you input it correctly and try again.`,
),
field: 'invite-code',
})
dispatch({type: 'setStep', value: SignupStep.INFO})
return
@@ -284,7 +348,11 @@ export function useSubmitSignup() {
const isHandleError = error.toLowerCase().includes('handle')
dispatch({type: 'setIsLoading', value: false})
dispatch({type: 'setError', value: error})
dispatch({
type: 'setError',
value: error,
field: isHandleError ? 'handle' : undefined,
})
dispatch({type: 'setStep', value: isHandleError ? 2 : 1})
logger.error('Signup Flow Error', {