Problem
checkout_started captures the final { plan, tier, source } (UpgradeModal.jsx ~line 163), but nothing before that moment is instrumented. We can see which tier a user paid for, never how they chose it:
- No event when the pricing view renders (which tiers were shown, which was default-highlighted, what
initialTier/initialCycle a deep link preset)
- No event on billing-cycle toggle (monthly ↔ yearly, ~lines 438–449)
- No event distinguishing "clicked MAX card directly" from "browsed Pro first, then switched"
Both MAX-tier (/mo) conversions to date are attribution-blind on this exact question. MAX is 5× Pro ARPU — if the side-by-side presentation is doing the upsell, we should know and lean into it; if MAX buyers arrive pre-decided, the presentation work matters less. Right now the funnel can't distinguish these.
Proposed events
upgrade_modal_pricing_viewed — fired once per modal open when the pricing (tier-selection) view renders: { source, trigger, initialTier, initialCycle, defaultTier }
upgrade_billing_cycle_toggled — { from, to, source } on the monthly/yearly toggle
upgrade_tier_selected — fired in handleGoPro alongside the existing state change (or as an enrichment of checkout_started): include whether the chosen tier matches the deep-link preset and whether the user toggled cycle or changed tiers first
Keep checkout_started as-is for continuity; new events are additive.
Files
src/shared/components/UpgradeModal/UpgradeModal.jsx — pricing view render, cycle toggle, handleGoPro
src/editor/components/EditorUpgradeModal.jsx — parsePaymentHash provides initialTier/initialCycle to pass through
Related: #1892 (deep-link entries currently mis-report checkout_started source=editor — the source property these new events inherit should land after/with that fix so pricing-page deep links are attributed correctly here too).
🤖 Generated with Claude Code
Problem
checkout_startedcaptures the final{ plan, tier, source }(UpgradeModal.jsx~line 163), but nothing before that moment is instrumented. We can see which tier a user paid for, never how they chose it:initialTier/initialCyclea deep link preset)Both MAX-tier (/mo) conversions to date are attribution-blind on this exact question. MAX is 5× Pro ARPU — if the side-by-side presentation is doing the upsell, we should know and lean into it; if MAX buyers arrive pre-decided, the presentation work matters less. Right now the funnel can't distinguish these.
Proposed events
upgrade_modal_pricing_viewed— fired once per modal open when the pricing (tier-selection) view renders:{ source, trigger, initialTier, initialCycle, defaultTier }upgrade_billing_cycle_toggled—{ from, to, source }on the monthly/yearly toggleupgrade_tier_selected— fired inhandleGoProalongside the existing state change (or as an enrichment ofcheckout_started): include whether the chosen tier matches the deep-link preset and whether the user toggled cycle or changed tiers firstKeep
checkout_startedas-is for continuity; new events are additive.Files
src/shared/components/UpgradeModal/UpgradeModal.jsx— pricing view render, cycle toggle,handleGoProsrc/editor/components/EditorUpgradeModal.jsx—parsePaymentHashprovidesinitialTier/initialCycleto pass throughRelated: #1892 (deep-link entries currently mis-report
checkout_started source=editor— thesourceproperty these new events inherit should land after/with that fix so pricing-page deep links are attributed correctly here too).🤖 Generated with Claude Code