On subscription products, the onboarding flow is where you win or lose customers. I’ve spent years instrumenting flows for SaaS and content subscription businesses, and one thing keeps coming up: teams either track too little (so they can’t diagnose churn/handoff points) or they track too much (raw data with no action). Below I share the exact analytics events I recommend for subscription onboarding on Next.js sites — what to capture, when to fire them, and practical implementation notes for server/client side routing and privacy.
What I mean by "subscription onboarding"
I’m talking about the period between a new visitor discovering your product and the moment they become a paying subscriber (or hit a trial). That typically includes account creation, verification, plan selection, payment, first login, and early-product activation steps.
Principles I follow when instrumenting
Core events to track
Below is the set I implement by default. Names are intentionally simple and explicit so they’re easy to query in Mixpanel, Segment, GA4 or a cloud warehouse.
| Event | When to fire | Key properties | Server vs Client note |
|---|---|---|---|
| page_view | On every Next.js page render (client-side nav + server render) | path, title, referrer, utm_source, utm_medium, utm_campaign | Client-side for full SPA nav; capture initial SSR render on server to preserve UTM |
| signup_started | User initiates sign-up (clicks 'Get started', opens sign-up modal) | method (email, oauth), experiment_variant, referrer | Client-side |
| account_created | Successful account creation (user record created) | user_id (hashed), signup_method, signup_channel, experiment_variant | Server-side (emit at user creation to ensure reliability) |
| email_verified | User verifies email | user_id, verification_method | Server-side (webhook or verification handler) |
| plan_viewed | User opens pricing/plan selector | plan_id, plan_price, plan_type, experiment_variant | Client-side |
| checkout_started | User begins checkout/payment flow | plan_id, currency, amount, coupon_code (if present) | Client-side then server confirmation |
| payment_failed | Payment attempt failed | error_code, payment_method_type, retry_count | Server-side (payment gateway webhook) |
| subscription_created | Subscription is successfully created (billing system webhook) | subscription_id, plan_id, user_id, initial_amount, trial_days | Server-side |
| first_login_after_sub | User first logs in after subscription | user_id, days_since_signup | Client-side |
| activation_step_completed | Product-specific activation (e.g., connected billing, uploaded asset) | step_name, step_index, user_id | Client-side |
| trial_started | Trial activation (if using trials) | user_id, trial_length_days, plan_id | Server-side |
| cancel_attempt | User initiates cancellation (before confirming) | user_id, reason_hint, URL | Client-side |
Why server-side events matter
High-value events like account_created, subscription_created and payment_failed should always be emitted from the server (or via webhook handlers) so you don’t lose data when the client fails, is offline, or blocks scripts. In Next.js that usually means placing event emission logic in API routes, server actions, or in background jobs that react to your database/webhook events.
Identity management: anonymous vs authenticated
One mistake I see often: teams don’t reconcile anonymous activity with the authenticated user. Use a consistent identity flow:
In Segment, you call analytics.alias(anonymous_id, user_id) then analytics.identify(user_id, traits). In Mixpanel you call alias() and identify(). For GA4 you set user_id on the server or client after login. Be explicit about the order — alias before identify — or you’ll fragment user paths.
Event property hygiene
Keep properties limited and typed. A good starting point:
Avoid sending PII (email, full name, card numbers) into analytics platforms — instead, send a hashed user ID or reference to an internal id. This reduces privacy risk and keeps you GDPR-compliant.
Implementation patterns in Next.js
Practical patterns I use:
Testing and validation
Test the flow end-to-end:
Mapping events to metrics and diagnostics
Each event maps to a funnel or diagnostic:
Privacy and consent
Respect consent flows. If you’re in an EU/UK jurisdiction, gate non-essential tracking behind consent. Implement a consent layer that prevents sending analytics calls until the user has consented. For critical server-to-server events (like subscription_created), you may still send anonymized events that contain no PII if legally required.
Final practical checklist (copy-paste)
If you want, I can produce a small Next.js sample that implements these events with Segment or a short script for emitting server-side webhook events from Stripe — tell me which vendor you use and I’ll tailor the code to your stack.