Skip to content

Phase 5 — In-Product Conversion Mechanics

Status: slices 1 & 2 BUILT; slices 3 & 4 not pursued. The cap instrumentation + near-cap nudge (slice 1) and the blocked-report paywall (slice 2) are implemented on the report hot path — no gate needed (they upgrade messages the bot already sends, and reuse the deployed Phase 4 button handlers). Reverse trial (slice 3) and Telegram Stars (slice 4) were explicitly descoped; the sections below are retained as future reference only.

Phase 5 is the inbound half of conversion: the moments inside the product where a FREE group meets the value ceiling. Where Phase 4 reaches out, Phase 5 converts at the point of friction — the blocked report and the near-cap report.

Goal: lift free→paid at the highest-intent moments, with the least friction, measured end-to-end. Objective unchanged: increase conversion to a paid plan.


Prime directive (live, paying product, real money)

Phase 5 touches billing state and the hot report path, so it's staged by risk and each customer-facing lever is flag-gated, default OFF, staging-first.

LeverRiskGate
Cap events + richer nudge/paywall copylow (upgrades a message already shown)roll in place, watch metrics
Telegram Stars checkoutmedium (new payment path, additive)STARS_ENABLED (default false)
Reverse trialhigh (changes new-group entitlement + auto-downgrade)TRIAL_ENABLED (default false)

Hard rules: never grant a trial to a chat that already pays; the trial-expiry downgrade must never clobber a real subscription (PAYMENT=SUBSCRIPTION) or ETH credit balance; every money/permission mutation is idempotent and logged.


1. Cap-crossing instrumentation + nudges (low risk — ship first)

The gate already computes usage — utils/database/stats.mjs :: validateUserCredits (availableCredits = CREDITS − FETCHED_POSTS, XBotCredits FREE 100 / PRO 1000). It just doesn't emit or nudge well.

  • Emit the cap events (types already exist, no emitters today): when a FREE chat's monthly FETCHED_POSTS crosses 80% → CAP_80; when it reaches the cap → CAP_100. Fire once per period per threshold (idempotent — guard on a SEGMENTS/STATS marker so a chat isn't spammed each fetch). These already drive the near_cap / capped classifier segments and the Behavior funnel.
  • Upgrade the near-cap nudge at commands/report.mjs:248 (currently a bare "<n> credits left — open /setup → 💳 Buy Credits"): make it value-framed and digit-free (consistent with the agreed copy rules), with an inline [⬆️ Upgrade] button into /buy. Append it to the report itself (the moment the group is looking at the value they'd lose).

2. The paywall (highest-intent moment)

commands/report.mjs:84 currently sends a plain string when a report is blocked by the cap: "Your available credits have been exhausted. Please upgrade your plan…". Replace it with a real paywall:

  • Value-framed, kind copy — why the group hit this (they're active!) + what PRO keeps flowing — no plan numbers.
  • Inline [⬆️ Upgrade to PRO]/buy (or the new Stars flow, §4).
  • A 1-tap "what's holding you back?" micro-survey — reuse Phase 4's survey:<key>:<option> handler verbatim (commands/outreach.mjs), key paywall. Options: too expensive / not right now / missing a feature.
  • Emit PAYWALL_SHOWN on display and SURVEY_RESPONSE on tap; the eventual LICENSE_CHANGED within 14d is the conversion signal.

This is the single highest-leverage change in Phase 5 — a group that hit the cap has proven demand and is staring at a blocked deliverable.

3. Reverse trial (high risk — ship last, gated)

New groups can't feel PRO value on FREE. A reverse trial flips that: grant PRO on arrival, let them experience the ceiling-free product, then land the paywall when it ends.

  • Grant on first activation (BOT_ADDED → first successful /setup), gated by TRIAL_ENABLED: set LICENSES.LICENSE=PRO + new field TRIAL_UNTIL=<ms> (e.g. 7–14 days), PAYMENT='TRIAL'. Emit TRIAL_STARTED. Skip any chat that already has PAYMENT=SUBSCRIPTION/CREDITS or a positive REMAINING_CREDITS.
  • Expiry sweep: extend the nightly classifier Lambda (or a sibling) to find PAYMENT='TRIAL' chats past TRIAL_UNTIL → downgrade to FREE (updateXBotLicense(id, FREE, preservePayment:false) — but only when still PAYMENT='TRIAL', so it can't touch a chat that converted mid-trial), emit TRIAL_ENDED, and send the §2 paywall (framed as "your trial wrapped up").
  • Mid-trial nudges: a "3 days of PRO left" style heads-up (digit-free variant) via the existing report-append path.
  • Needs licenses.mjs changes: a startTrial() grant + a trial-aware guard so the auto-downgrade logic in billing.mjs (which already downgrades exhausted PRO·CREDITS chats) never fights the trial state.

4. Telegram Stars checkout (medium risk — additive)

commands/buy.mjs has exactly two providers today — Stripe (card/subscription) and ETH/BWS credits (payment_stripe_direct, payment_bws_direct). Neither is frictionless on mobile Telegram. Add Telegram Stars (XTR) as a third option:

  • New bot.action('payment_stars')ctx.replyWithInvoice / sendInvoice with currency: 'XTR' and a Stars price for the credit pack / PRO month.
  • bot.on('pre_checkout_query') → answer true (validate first).
  • bot.on('successful_payment') → credit/upgrade the chat via the existing billing setters (setProLicenseWithSubscription / credit top-up), emit LICENSE_CHANGED, confirm in-chat.
  • Gate the button behind STARS_ENABLED. No change to the Stripe/ETH paths.

Stars is native, in-app, one-tap — the lowest-friction path for the mobile, crypto-native audience these groups skew toward.

5. Admin surface + measurement

  • The Behavior funnel (Phase 6) already reads events; add a paywall→upgrade and trial→paid conversion tile, plus survey-reason breakdown, from PAYWALL_SHOWN / SURVEY_RESPONSE / TRIAL_STARTED / TRIAL_ENDED / LICENSE_CHANGED.
  • Admin toggles for TRIAL_ENABLED / STARS_ENABLED (env or a settings row) so rollout doesn't need a redeploy — mirror the Phase 4 master-switch pattern.

6. File-level task list

  • utils/database/stats.mjs — emit CAP_80/CAP_100 from validateUserCredits (idempotent per period).
  • commands/report.mjs — richer near-cap nudge (:248) + real paywall (:84) with [Upgrade] + survey:paywall:* + PAYWALL_SHOWN.
  • utils/database/licenses.mjsstartTrial(), TRIAL_UNTIL/PAYMENT='TRIAL', trial-aware downgrade guard; coordinate with billing.mjs auto-downgrade.
  • SegmentClassification_Handler.mjs (or sibling) — trial-expiry sweep.
  • commands/buy.mjs + commands/outreach.mjs (survey reuse) — Stars invoice, pre_checkout_query, successful_payment.
  • IaC — TRIAL_ENABLED / STARS_ENABLED env on the bot + relevant Lambdas.
  • Admin — conversion tiles + rollout toggles.

7. Rollout sequence

  1. Cap events + paywall/nudge copy (in place) → measure paywall view→upgrade.
  2. Enable Stars on a staging group → verify invoice → pre_checkout → payment → entitlement → LICENSE_CHANGED; then enable in prod.
  3. Enable reverse trial for new installs only, short window first; watch trial→paid and the expiry-downgrade safety (no subscription/credits touched); tune the window from the data.

8. Success metrics

Paywall view→upgrade rate, trial→paid rate, Stars share of checkouts, and overall FREE→PRO LICENSE_CHANGED lift — all already flowing through the Phase 1 event log into the Phase 6 admin funnel. Kill or retune any lever that doesn't move its metric.

X Bot Documentation