Event tracking spec

Auth v2: Mixpanel events

Audience Product & Engineering
Surface Mobile · React Native
Source auth-v2/ANALYTICS.md
Distribution Internal
TL;DR
  • auth-v2 reuses the established all:* auth events. The auth_v2_* prefix from the earlier draft is dropped.
  • Eight events already exist in @ifgengineering/client-analytics, already emit, and signupAttempt / login already handle identity.
  • Six new events (failures, login success, 2FA required) need a case adding to the switch.
  • The current useAuthV2Analytics hook fires dead auth_v2_* names; rework it to fire the real keys.
  • Identity (alias / identify on email) is handled by the reused events, keyed on email.

The Mixpanel event tracking spec for the auth-v2 flow: the landing carousel, sign-up, login, email verification, two-factor and password reset. The code lives at cur8-mob/src/screens/auth-v2/.

This doc covers Mixpanel events, the identity model and people-profile traits. The companion onboarding-v2/ANALYTICS.md covers the flow that runs straight after auth.

Note: auth-v2 reuses the existing auth events in @ifgengineering/client-analytics. An earlier draft of this spec invented a new auth_v2_* event prefix; that prefix is dropped. The events below are the established all:* auth events, which are already wired and already handle identity, plus a short list of new events for signals the legacy set never had.

1. What the events answer

Question Events
Sign-up conversion all:signup_attempted to all:signup_success
Login success rate all:login_attempted vs all:login_success / all:login_failed
Two-factor drop-off all:2fa_required to all:2fa_success
Where sign-up or login fails all:signup_failed.reason, all:login_failed.reason
Password reset completion all:forgotPassword_clicked to all:forgotPasswordSetPassword_clicked
Auth method mix method property (email / apple / google / biometrics)

2. The flow

auth-v2 has eight registered routes (cur8-mob/src/navigation/authV2.tsx, AuthV2StackParamList). Landing is the entry point.

  • Landing carousel, with Get started and Log in CTAs plus Apple / Google buttons.
  • Sign up: CreateAccount (email then password) to VerifyEmail (OTP) to the onboarding-v2 handoff.
  • Login: Login (email and password) to BiometricsModal (if Face ID or Touch ID is enrolled) to TwoFactorVerification (if 2FA is on) to the onboarding-v2 handoff.
  • Password reset: Login to ForgotPassword (enter email) to ResetPassword (new password, plus OTP when 2FA is on).

Auth ends by handing off to onboarding-v2, which begins at cur8:onboardingWelcomeBridge_pageViewed.

3. How events are wired

Events go through the shared @ifgengineering/client-analytics package. A screen hook gets a fire function from useAnalytics(eventKey), which returns a promise, and invokes it with the event's properties:

const fireSignup = useAnalytics("signupAttempt");
(await fireSignup)({ email, method: "email" });

The eight reused events in section 5.1 already have handlers in the client-analytics switch, already emit to Mixpanel and Customer.io, and signupAttempt / login already perform the identity calls (section 6). Wiring auth-v2 to them is a matter of calling the right keys.

The current auth-v2 code routes through useAuthV2Analytics (auth-v2/components/shared/useAuthV2Analytics.ts), a hook that fires 16 auth_v2_* names. Those names have no handler in the switch, so they fall through to the default: no-op and never reach Mixpanel. useAuthV2Analytics should be reworked to fire the real event keys below, or removed in favour of calling useAnalytics directly.

The six new events in section 5.2 need a case adding to the switch in packages/client-analytics/src/index.ts, and their keys adding to the Event union in types.ts.

4. Naming

auth-v2 events live in the established all: auth namespace, the same one the legacy auth events already use (all:signup_attempted). There is no auth_v2_ prefix. New events follow the same all:<area>_<verb> shape.

Note: the legacy event keys carry a spelling slip: forogtPasswordClick and friends (forgot misspelled). The keys are what useAnalytics is called with, so the typo must be matched exactly. The emitted Mixpanel names are spelled correctly (all:forgotPassword_clicked). Fixing the key spelling is a separate cleanup, noted in section 8.

Event properties stay minimal and privacy-safe: no passwords, OTP codes, or unnecessary raw email values beyond what the identity calls already require.

5. Event taxonomy

5.1 Reused events

These already exist in client-analytics. auth-v2 fires them as-is.

Mixpanel event Event key Auth-v2 trigger Properties
all:signup_attempted signupAttempt Create Account form submitted email, method, attribution, utm
all:signup_success signupSuccess Verify Email OTP accepted, sign-up complete email
all:login_attempted login Login form submitted email, method
all:2fa_attempted twoFaAttempted 2FA code entered channel, method
all:2fa_success twoFaSuccess 2FA code verified channel, method
all:forgotPassword_clicked forogtPasswordClick "Forgot password?" tapped on Login none
all:forgotPasswordSubmitEmail_clicked forogtPasswordSubmitEmailClick Email submitted on Forgot Password email
all:forgotPasswordSetPassword_clicked forogtPasswordSetPasswordClick New password set on Reset Password none

Note: signupAttempt already filters out @test.com and @delete.com addresses and fires a Google Ads sign-up conversion. auth-v2 inherits both by reusing it.

5.2 New events

auth-v2 surfaces signals the legacy set never had: failures, the login-success terminal, and the 2FA-required branch. These need adding to client-analytics, in the same all: namespace.

Mixpanel event Auth-v2 trigger Properties
all:signup_failed Create Account errors method, reason
all:login_success Login authenticated email, method
all:login_failed Login errors method, reason
all:2fa_required Password auth succeeds but the account has 2FA on channel, method
all:2fa_failed 2FA code rejected channel, method, reason
all:emailVerification_failed Verify Email OTP rejected or errors reason

method: email / apple / google / biometrics. reason: a short failure code such as api_error, never a raw exception string.

6. Identity model

auth-v2 is where an anonymous device becomes an identified user. The reused events handle this already, so there is no separate work to do:

  • signupAttempt calls mixpanel.alias(email) then mixpanel.identify(email), sets the people-profile traits below with set_once, and calls Customer.io identify.
  • login calls mixpanel.identify(email), updates LatestLoginDate, and appends to list_logins.

The identity key is the email address. investorId would be a more durable join key, but email is the established convention across the codebase and the onboarding-v2 doc, so auth-v2 keeps it.

People-profile traits set during auth (legacy trait names, kept as-is):

Trait Set by
$email signupAttempt (set_once)
Sign Up Date signupAttempt (set_once)
Account Type signupAttempt (set_once)
LatestLoginDate login
list_logins login (appended)

Logout should call mixpanel.reset(). That is handled in session / Redux teardown, not in auth-v2; confirm it fires.

7. Auth funnel

Sign-up funnel

Step Event
1 all:signup_attempted
2 all:signup_success
3 cur8:onboardingWelcomeBridge_pageViewed (onboarding-v2 handoff)

Login funnel

Step Event
1 all:login_attempted
2 all:login_success
3 cur8:onboardingWelcomeBridge_pageViewed (onboarding-v2 handoff)

Slice both by method. When 2FA is on, all:2fa_required to all:2fa_success sits between login and the onboarding handoff. signupAttempt does the heavy lifting (identity, conversion), so it anchors the sign-up funnel even though its name says "attempted".

8. Gaps and open questions

  • The new events (section 5.2) need wiring. Six case blocks in the client-analytics switch, plus Event-union entries. Until then, failures and the 2FA-required branch are unmeasured.
  • useAuthV2Analytics fires dead names. The hook's 16 auth_v2_* events hit the default: no-op. Rework the hook to fire the keys in section 5, or drop it.
  • Legacy key spelling. forogtPasswordClick, forogtPasswordSubmitEmailClick and forogtPasswordSetPasswordClick are misspelled. Renaming the keys is a clean-up that touches every call site; the Mixpanel names are already correct so analytics is unaffected either way.
  • Screen-level granularity. The legacy auth events track actions, not screen views. There is no per-screen _viewed event, so within-screen drop-off (for example, landing on Login but never submitting) is not visible. Add screen-view events later if that funnel detail is needed.
  • signupAttempt naming. It fires on form submit but performs the full identity and a Google Ads conversion, so it behaves as the real sign-up event. The name is legacy and kept for reuse.
  • Namespace split. auth-v2 uses all:, onboarding-v2 uses cur8:onboarding<Screen>_<action>. Two conventions across one user journey. Worth a deliberate decision, but reusing all: for auth is the lower-risk path because those events already exist and work.