User → Customer Conversion Flow (MAI-23)

Last updated: May 6, 2026Section: Monetization & growth

User → Customer Conversion Flow (MAI-23)

This document defines how Mailoo converts a regular user into a paying customer: the canonical funnel, activation and value moments, paywall logic, pricing and checkout experience, and post-purchase lifecycle. It is the product and UX source of truth; analytics events and KPI formulas live in conversion-flow-analytics{.interpreted-text role="doc"}.

Design principle

Users pay to solve a problem, not to unlock abstract features. Paywalls and copy should anchor on outcomes (reliable capture, scale, team workflow, compliance), not feature checklists alone.

  • Hybrid: a free tier (Starter) for activation plus short, contextual trials for selected premium capabilities where seeing is believing.
  • Provider-ready checkout: the flow below assumes an external payment provider (e.g. Stripe-style Checkout + webhooks). This doc specifies states and contracts, not a concrete integration.

Canonical funnel

Stages (measurement definitions align with conversion-flow-analytics{.interpreted-text role="doc"}):

  1. Visit --- landing or deep link without authenticated session.
  2. Activate --- user completes the minimum setup to use Mailoo for their primary job (see per--use-case activation below).
  3. Value moment --- user observes a positive outcome tied to their intent (message captured, subscriber created, chat reply sent, campaign delivered, etc.).
  4. Paywall shown --- user hits a limit, premium gate, or trial boundary; the product surfaces upgrade UI.
  5. Checkout started --- user initiates paid plan selection / payment handoff.
  6. Purchase success --- provider confirms payment; entitlement updates.
  7. Retained --- e.g. D7/D30 active use post-purchase (cohort definitions in analytics doc).

User journey (linear funnel):

Visit → Activate → ValueMoment → PaywallShown → CheckoutStarted
     → PurchaseSuccess → RetainedD7

PaywallShown → Dismissed → ReminderLoop (capped) → CheckoutStarted

Extended journey (decision points):

  • Activation: Sign in/up → Create project → Create integration.
  • Value: First webhook or message → Subscriber or chat outcome (use-case specific).
  • Monetization: Limit / gate / trial end → Paywall modal or sheet → Pricing or checkout → Purchase success; dismiss path applies suppression rules before re-showing paywall.

Activation and value moments (by use case)

Use these as event definitions for product and analytics owners. Exact instrumentation names belong in conversion-flow-analytics{.interpreted-text role="doc"}.


Use case Activation (minimum setup) Value moment (primary) Secondary value signals


FORM / newsletter Project exists; FORM integration created; server or BFF can call webhook with scoped key; at least one allowed origin or endpoint configured. First production form submission creates a Message and Subscriber (or equivalent success path). Campaign created; resubscribe flow used; template used in send.

CONTACT_FORM / feedback CONTACT_FORM integration created; feedback webhook path verified. First production feedback submission stored as message with expected metadata. SLA-oriented teams: first export or dashboard triage action.

JSBOX chat JSBOX integration created; widget snippet deployed on allowed origin; operator session possible. First visitor message received and first operator reply (or resolved session), proving realtime loop. WebSocket stability in production window; CSAT if collected later.

Campaigns / subscribers Subscriber list non-empty OR template ready; integration linked. First campaign or bulk send completes without hard failure. Repeat sends; segment or source filters used.

Blog / MARKET (if in scope for billing) Integration + first published entity or first external API read. First consumer-facing page served from Mailoo content or first order submitted (per product packaging). Repeat orders or catalog sync jobs; editorial pipeline milestones.

If a user skips straight to limits without a value moment, prefer educational nudges (how to finish setup) before aggressive paywalls.

Paywall logic

Trigger families


Family Examples Typical UX


Usage / quota Messages per month, integrations count, API rate tier, storage, seats. Inline meter + modal at threshold; soft warning before hard block.

Premium feature gate Advanced analytics, team roles, custom domains, priority support SLAs, enterprise-only APIs. Contextual sheet on action click; short trial where applicable.

Time-based trial N-day trial of Professional-tier features after explicit opt-in or first premium action. Banner (days left) + final-day modal; never surprise-charge without checkout confirmation.

Priority order (deterministic):

  1. Critical path completion --- never block saving draft config, signing out, or viewing billing/support. Prefer deferring paywall until after save.
  2. Hard quota exceeded --- block only the specific action that consumes quota (e.g. reject new webhook), not entire dashboard navigation.
  3. Trial expired --- gate premium actions; keep read-only access where possible.
  4. Soft quota / approaching limit --- banner + optional light modal (respect frequency caps).
  5. Discovery upsell --- lowest priority; only on high-intent screens.

Anti-annoyance and suppression rules

  • Frequency cap: at most one paywall modal per session for the same trigger family; at most three per 7 days per user for non-blocking upsells.
  • Dismiss cool-down: after dismiss, suppress identical copy/trigger for 48 hours unless quota crosses next hard tier.
  • Purchase intent: if checkout_started fires, suppress competing paywall modals until checkout succeeds, fails, or expires (e.g. 24 h).
  • Post-success: no upgrade modals for 72 hours after purchase_success; show onboarding only.
  • Quiet hours: optional product policy --- no email reminders 22:00--08:00 local (if timezone known).
  • Power users: if user repeatedly hits limits without converting, switch to Contact sales / human outreach instead of stacked modals.

Screen inventory and trigger mapping


Screen / pattern Primary triggers Notes


Pricing hub (/{locale}/pricing) Marketing visit; nav/footer; "upgrade" from dashboard. Plan comparison, FAQ, trust; CTAs vary by audience (below).

Contextual paywall (usage) Soft/hard quota thresholds; API 402/429-style responses mirrored in UI. Show current usage, next tier benefit, link to checkout.

Feature-gate paywall Click on premium-only control or route. Offer trial start if eligible; else checkout.

Trial status banner Trial active, ending (≤3 days), expired. Persistent but dismissible per session for "ending soon" only.

Checkout handoff User chose plan on-site or from paywall CTA. Redirect or embedded provider session; preserve return_url intent.

Payment result Return from provider; webhook latency. Success / failure / pending states (see checkout model).

Post-purchase onboarding purchase_success entitlement active. Checklist: confirm limits, invite team, first premium action.

Lifecycle reminders (in-app + email) Dismissed paywall; trial ending; soft quota sustained. Tied to goals (e.g. "send first campaign"), not clock-only spam.

Pricing hub: contextual CTAs

The live pricing page is implemented in the web app (e.g. apps/web/src/app/[locale]/pricing/page.tsx). Product expectations:


Audience CTA emphasis Destination


Anonymous "Get started" / "Create account" Sign-in / sign-up, then dashboard project creation.

Free plan (logged in) "Upgrade" / "Compare plans" Plan selection or checkout with current project context.

Trialing "Add payment" / "Choose plan before trial ends" Checkout with trial metadata; clear renewal date copy.

Near limit "Raise your limit" with meter snippet Recommended tier pre-selected in checkout.

Enterprise needs "Contact sales" Support / sales form with project id.

Content blocks: hero, comparison table (limits + who each plan is for), FAQ (billing, trials, data, cancellation), optional social proof, footer CTA to support.

Provider-ready checkout state model

States

State machine (text):

[*] → PlanSelected
PlanSelected → CheckoutSessionCreated (create_checkout_session)
CheckoutSessionCreated → AwaitingPayment (redirect_to_provider)
AwaitingPayment → Succeeded (webhook: invoice paid)
AwaitingPayment → Failed (webhook or return_url: failed)
AwaitingPayment → Pending (async_payment_pending)
Pending → Succeeded (webhook: settled)
Pending → Failed (webhook: void or timeout)
Failed → PlanSelected (user_retry)
Succeeded → EntitlementsActive → [*]

Handoff contract (conceptual):

  • Client or BFF creates a checkout session with: user_id, price_id / plan_id, success_url, cancel_url, client_reference_id (e.g. project uid), optional trial_days.
  • Provider redirects user back with session id; app shows pending until webhook confirms (never trust return URL alone for entitlement).
  • Idempotent webhooks: processing the same event twice must not double-grant or corrupt state.
  • Failure recovery: show reason (card declined, authentication incomplete), preserve cart/plan selection, single primary "Try again" action.

Post-purchase onboarding and upgrade reminders

Onboarding (first 24--72 h)

  • Confirm plan name, renewal cadence, and new limits in plain language.
  • Guided checklist: invite teammate, rotate API key if needed, enable premium feature user purchased for.
  • One optional "celebration" modal; then tool-first UI.

Reminders (non-annoying)

  • Prefer goal-based prompts: e.g. user hit paywall for campaigns but has no template --- suggest template + single upgrade CTA, max once per week.
  • Trial ending: email + in-app at 7 days, 3 days, 1 day; in-app banner not more than once per day.
  • After dismiss: honor suppression; do not escalate to modal without new trigger (hard limit or new premium click).

Rollout recommendation

  • Phase 1 --- Baseline: instrument funnel + soft quotas only; paywall modals on hard limits and explicit premium clicks; ship pricing CTAs by audience.
  • Phase 2 --- Optimize: A/B copy on paywall headline (problem vs feature), trial length, and comparison table order; read cohort metrics in conversion-flow-analytics{.interpreted-text role="doc"}.
  • conversion-flow-analytics{.interpreted-text role="doc"} --- events, KPIs, baseline checklist
  • getting-started{.interpreted-text role="doc"} --- first-time setup aligned with activation