Internal Product & Engineering

Onboarding v2 — Mixpanel events

The Mixpanel event tracking spec for the Cur8 onboarding-v2 flow. What we measure, what each event carries, and how to wire it up.

Last updated 18 May 2026 Mirrors onboarding-v2/ANALYTICS.md

Product calls this flow "Onboarding v1.5"; the code lives at cur8-mob/src/screens/onboarding-v2/. They are the same thing.

This document covers Mixpanel events and people-profile traits only. Customer.io, Avo, Google Ads, session replay and compliance are out of scope here. The older ANALYTICS_ARCHITECTURE.md (v3.2) is kept as a reference for the wider design, including the deferred navigation-listener and abandonment-tracking work.

onboarding-v2 currently ships with no analytics calls. This document is the spec for what to add, screen by screen.

1What the events answer

QuestionEvents
Where in onboarding do users drop? every _pageViewed, each _completed, cur8:onboarding_completed
Quiz pass rate cur8:onboardingQuiz_passed vs _failed
Accreditation type mix cur8:onboardingAccreditation_certificationSelected · certification
KYC upload success rate cur8:onboardingVerification_documentUploaded vs _uploadFailed
Attribution source mix profile attribution_source filtered on cur8:onboarding_completed
Personalisation inputs profile traits set across the flow (see section 5)

2How events are wired

Every event goes through the shared @ifgengineering/client-analytics package, the same path every other cur8-mob event already uses. Screens never call mixpanel.track directly.

A screen gets a fire function from the useAnalytics hook and invokes it. The hook returns a promise, so callers await it. Wrap the call so a failure never blocks the user, matching existing screens such as home.tsx.

There are two shapes.

Page views

Page views reuse the generic pageView event key. Add the event-name string to the cur8PageViewEvents union in packages/client-analytics/src/types.ts, then fire it. The pageView handler attaches app and channel for you.

const firePageView = useAnalytics("pageView");
// on screen focus:
(await firePageView)({ eventName: "cur8:onboardingPersonalInfo_pageViewed" });

Action and outcome events

Action and outcome events get their own entry:

  1. In types.ts, add the key to the Event union and a <Name>Props interface.
  2. In packages/client-analytics/src/index.ts, add a case that calls track("cur8:onboarding…_…", { ...args, app: APP_NAME }).
  3. Fire it from the screen:
const fireCertificationSelected = useAnalytics("onboardingCertificationSelected");
(await fireCertificationSelected)({ certification: "HIGH_NET_WORTH" });

People-profile traits are set inside the same case via mixpanel.people.set, the way nps_set already does it. The fire function is the only thing a screen imports.

3Naming

Open question — v1 vs v2 names

cur8:onboardingQuiz_pageViewed already exists as a v1 event. This spec assumes v2 replaces v1, so it reuses the clean names. If v1 and v2 ever run side by side, reusing a name merges the two in Mixpanel — namespace the v2 events in that case.

4Event taxonomy

Re-derived from the shipped screens. Every screen fires one _pageViewed on focus. Each module fires one _completed on its final screen, carrying that module's captured outputs as properties. No raw PII goes on any event (age_band, not date of birth).

4.1 Entry & Mandatory Questionnaire

EventPropertiesTrigger
cur8:onboardingWelcomeBridge_pageViewed None Welcome bridge screen appears. Funnel entry.
cur8:onboardingMandatoryQuestion_pageViewed question_index Each of the 3 questionnaire questions appears (paginated route).
cur8:onboardingEmailPreferences_pageViewed None Email preferences screen appears.
cur8:onboardingSocialAttribution_pageViewed None Social attribution screen appears.
cur8:onboardingMandatoryQuestionnaire_completed email_preference
attribution_source
Social attribution submitted. The questionnaire batch is POSTed at email preferences. Headline funnel anchor.

email_preference: cur8_capital / cur8_and_ifg.
attribution_source: google / instagram / tiktok / youtube / friend_family / podcast / ifg / other.

4.2 Basic Info

Seven screens: one explainer, six single-purpose data screens.

EventPropertiesTrigger
cur8:onboardingBasicInfoExplainer_pageViewed None Explainer appears.
cur8:onboardingPersonalInfo_pageViewed None Personal info screen appears.
cur8:onboardingResidentialInfo_pageViewed None Residential info screen appears.
cur8:onboardingTaxNINumber_pageViewed None NI number screen appears.
cur8:onboardingTaxResidency_pageViewed None Tax residency screen appears.
cur8:onboardingTaxSourceOfFunds_pageViewed None Source of funds screen appears.
cur8:onboardingTaxOccupation_pageViewed None Occupation screen appears.
cur8:onboardingBasicInfo_completed age_band country nationality is_uk_tax_resident source_of_funds_count occupation Occupation screen submitted. Headline funnel anchor.

4.3 Accreditation

Code folder: eligibility/. Four screens. UNACCREDITED users skip the questionnaire.

EventPropertiesTrigger
cur8:onboardingAccreditationExplainer_pageViewed None Explainer appears.
cur8:onboardingCertification_pageViewed None Certification screen appears.
cur8:onboardingAccreditation_certificationSelected certification User confirms a certification. Routes to the questionnaire or straight to the declaration.
cur8:onboardingAccreditationQuestionnaire_pageViewed question_index Each questionnaire question appears (paginated route).
cur8:onboardingDeclaration_pageViewed None Declaration screen appears (4 risk-acknowledgement checkboxes).
cur8:onboardingAccreditation_completed certification Declaration submitted. Headline funnel anchor.

certification: SELF_CERTIFIED / HIGH_NET_WORTH / UNACCREDITED.

4.4 Quiz

FCA appropriateness check. There are no cooldown or "blocked" screens in v2; a failed or rate-limited attempt shows a toast on the same screen.

EventPropertiesTrigger
cur8:onboardingQuizExplainer_pageViewed None Explainer appears.
cur8:onboardingQuiz_pageViewed question_index Each quiz question appears (paginated route).
cur8:onboardingQuiz_passed question_count Server returns a passing result. Headline funnel anchor.
cur8:onboardingQuiz_failed blocked_until (ISO or null) Server returns failed and/or blockedUntil. blocked_until carries the rate-limit window.

4.5 Verification (KYC)

Two document types in v2: proof of address and source of funds. No ID-document scan.

EventPropertiesTrigger
cur8:onboardingVerificationExplainer_pageViewed None Explainer / intro requirements screen appears.
cur8:onboardingProofOfAddress_pageViewed None Proof of address screen appears.
cur8:onboardingSourceOfFunds_pageViewed None Source of funds screen appears.
cur8:onboardingVerificationStatus_pageViewed None Verification status screen appears.
cur8:onboardingVerification_documentUploaded doc_type file_format A file upload succeeds. No filename.
cur8:onboardingVerification_uploadFailed doc_type failure_reason A file upload errors.
cur8:onboardingVerification_completed document_count Verification status submitted (descriptions PUT, KYC marked submitted). Headline funnel anchor.

doc_type: proof_of_address / source_of_funds.
file_format: pdf / jpg / png / heic / other.

4.6 Completion & cross-flow

EventPropertiesTrigger
cur8:onboardingCompletion_pageViewed None Completion splash appears.
cur8:onboarding_completed None POST /onboarding/completion succeeds. Terminal funnel event.
cur8:onboarding_backPressed from_screen to_screen Back button pressed inside onboarding.
cur8:onboarding_helpTapped screen help_target A help / info / support affordance is tapped.

5People-profile traits

User state lives on the Mixpanel people-profile, not on events. Each trait is set with mixpanel.people.set inside the event handler named below, alongside the track call.

TraitSet by
email_preferencecur8:onboardingMandatoryQuestionnaire_completed
attribution_sourcecur8:onboardingMandatoryQuestionnaire_completed
age_bandcur8:onboardingBasicInfo_completed
countrycur8:onboardingBasicInfo_completed
nationalitycur8:onboardingBasicInfo_completed
is_uk_tax_residentcur8:onboardingBasicInfo_completed
occupationcur8:onboardingBasicInfo_completed
investor_certificationcur8:onboardingAccreditation_certificationSelected
quiz_passed_atcur8:onboardingQuiz_passed
kyc_statuscur8:onboardingVerification_completed
onboarding_completed_atcur8:onboarding_completed

Identity

onboarding-v2 runs post-signup. The user is already identified at signup (email-keyed, via safeMixpanelIdentify). onboarding-v2 fires no identify, alias or reset calls. Mixpanel's mobile SDK auto-properties ($os, $app_version_string, $device, etc.) are free; do not duplicate them.

6Headline funnel

StepEvent
1cur8:onboardingWelcomeBridge_pageViewed
2cur8:onboardingMandatoryQuestionnaire_completed
3cur8:onboardingBasicInfo_completed
4cur8:onboardingAccreditation_completed
5cur8:onboardingQuiz_passed
6cur8:onboardingVerification_completed
7cur8:onboarding_completed

Slice by profile properties country, attribution_source, investor_certification, email_preference. Per-screen _pageViewed events give the within-module drop-off.

7Not covered here

Deliberately cut from the v3.2 architecture doc for this simplified spec:

See cur8-mob/ANALYTICS_ARCHITECTURE.md for the fuller v3.2 design if any of the above is revived.