The exact analytics events you must track for subscription onboarding on next.js sites

The exact analytics events you must track for subscription onboarding on next.js sites

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

  • Events should be actionable: If you can’t tie an event to a specific decision or experiment, don’t track it.
  • Keep events consistent: Same event name and property schema across client and server paths.
  • Track identity changes carefully: Distinguish anonymous IDs from authenticated user IDs.
  • Prefer small, focused payloads: Record essential props; store heavy payloads elsewhere.
  • 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:

  • On first visit, generate an anonymous_id (client cookie/localStorage).
  • Track events with anonymous_id until authentication.
  • When account_created or login happens, call your analytics SDK's identify/alias API to link anonymous_id to user_id.
  • 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:

  • IDs: user_id (hashed), subscription_id
  • Monetary: currency, amount, plan_price
  • Context: referrer, experiment_variant, utm_*
  • Technical: platform (web, iOS, Android), browser
  • 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:

  • Server-rendered initial page_view: Capture UTM params and referrer server-side in getServerSideProps or middleware and persist them to user session or a short-lived cookie. Emit a page_view server event or attach those UTM params to the first client event.
  • Client-side SPA navigation: Use next/router’s events (routeChangeComplete) to send page_view for client navigations.
  • API route emits for critical events: During signup and subscription creation, emit server events from API routes that also perform DB writes. That guarantees event delivery even if user closes the browser during payment.
  • Webhooks as source of truth: For payments, rely on your billing provider webhooks (Stripe, Paddle) to emit subscription_created / payment_failed. Tie those events to user_id server-side by matching email or internal customer ID.
  • Testing and validation

    Test the flow end-to-end:

  • Use a staging workspace in Mixpanel/GA/Segment and verify each event payload using SDK debug modes (e.g., Mixpanel debug, GA4 measurement protocol debug).
  • Simulate failure paths: declined card, abandoned checkout, canceled email verification.
  • Reconcile server-side events with client-side events weekly: a large divergence indicates instrumentation bugs.
  • Mapping events to metrics and diagnostics

    Each event maps to a funnel or diagnostic:

  • page_view -> awareness and acquisition funnels (use UTM to break down channels)
  • signup_started -> conversion friction points (high drop-off indicates UI/UX or pricing confusion)
  • account_created -> signed-up conversion rate
  • checkout_started -> purchase intent
  • payment_failed -> payment health; monitor by payment_method and error_code
  • subscription_created -> revenue events; feed to LTV and cohort analysis
  • activation_step_completed -> product activation and onboarding effectiveness
  • 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)

  • Implement page_view on initial SSR and client-side navigations.
  • Emit signup_started on CTA click.
  • Emit account_created from server at user creation; include hashed user_id.
  • Use billing webhooks to emit subscription_created and payment_failed.
  • Alias anonymous_id to user_id at signup/login.
  • Track plan_viewed and checkout_started client-side with plan properties.
  • Capture activation_step_completed to measure onboarding activation.
  • Sanitise PII, use hashed IDs, and respect consent.
  • 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.


    You should also check the following news:

    Product Reviews

    How to run a product review lab: testing methodology, scoring rubric and publishing cadence

    02/12/2025

    I run a small product review lab at Mediaflash Co where the emphasis is simple: test like a skeptical user, measure like an analyst, and write like a...

    Read more...
    How to run a product review lab: testing methodology, scoring rubric and publishing cadence
    Social Media

    Why your brand voice feels generic and a simple framework to make it shareable on social

    02/12/2025

    I used to get asked all the time: “Why does our brand voice feel...forgettable?” It’s a polite way of saying “generic.” I’ve seen teams...

    Read more...
    Why your brand voice feels generic and a simple framework to make it shareable on social