Skip to content

BaaS free→paid: funnel tracking, direct checkout from paywalls, yearly default - #835

Merged
charles-ramos merged 15 commits into
production2from
baas-upgrade-instrumentation
Oct 5, 2026
Merged

charles-ramos merged 15 commits into
production2from
baas-upgrade-instrumentation

Conversation

@alyssoncm

@alyssoncm alyssoncm commented Oct 1, 2026 •

Copy link
Copy Markdown

Why

Last 90 days (Amplitude, excluding @back4app.com):

  • 1,191 users opened Plan Usage → 154 clicked "Choose MVP" (13%) → 70 bought (45% of those who clicked).
  • 87% leave the plan page without picking a plan; 55% abandon the checkout once it is open.
  • 82% of in-app MVP purchases are monthly, since the page opened on monthly ($25) while the site opens on yearly ($15).

What changed (one commit per item)

0. Measure the funnel (4e2967cd)
New Amplitude events, prefixed baas_ so the Agent's upgrade_* charts are unaffected:

Event When Props
baas_upgrade_gate_viewed a paywall is shown gate, app_id
baas_upgrade_gate_clicked its Upgrade is clicked gate, app_id
baas_checkout_opened Paddle checkout opens plan, cycle, source (gate / plan_page), gate, app_id
baas_checkout_cycle_changed monthly ↔ yearly inside the direct checkout same
baas_checkout_closed closed without paying same
At Checkout - Subscription Successful (existing) purchase + source, gate

Gates: web_hosting, custom_domain, email_templates, parse_options, jobs, collaborators, mongodb_8, db_profiler, overview_plan_card, compliance_hipaa / soc2 / iso27001. Links into plan-usage carry ?gate=.

4. Yearly first + checkout title (4837beab)
billingCycle defaults to yearly on Plan Usage; Paddle title used plan.planName (undefined) → plan.name.

3. Sell what free apps lack (7d0f85cc)
MVP card and the upgrade box lead with custom domain, backups, MongoDB 8.0, email templates and collaborators instead of "20x more requests".

1 + 2. Direct checkout from paywalls (5b9af1f6)
New UpgradeGateButton / UpgradeCheckoutModal: the paywall opens the Paddle checkout for the plan that unlocks that feature (headline about the feature, price, monthly/yearly switch via Checkout.updateCheckout, "Compare all plans" link). Collaborators, compliance and MongoDB 8.0 no longer send users to the public pricing page.
Unchanged: Jobs limit, overview plan card and paid-plan "Add More Spots" still go to the plan page; DB profiler already had its own checkout. The direct checkout preselects yearly (like the pricing page), monthly one click away.

Naming (c88b2ee2)
"Web hosting" meant two things. Now:

  • Real-time Updates (was Server URL & Live Query): b4a.io server URL for LiveQuery. Every plan; Free needs card validation.
  • Domains (was Domain Settings): b4a.app Web URL for the public folder + custom domains. MVP+. HTTPS on a custom domain: Pay As You Go+, enabled by support.
    Routes unchanged; serverInfo keeps old and new names because menu access matches by name.

Overview Web URL (d27ee713)
"Web Hosting" fact → Web URL, showing the custom domain when there is one. CTA by state: Get a Web URL (MVP checkout when the plan can't), Use your domain, Enable HTTPS (MVP + custom domain → Pay As You Go checkout, then "open a support ticket"), Manage.

Direct checkout theme (4009e0a7): single surface following the OS light/dark preference; Paddle opens with the matching theme.

Not in this PR

  • Public pricing table (site repo): rename row "Webhosting" → "Real-time Updates", add "Domains (b4a.app Web URL + custom domain)", fix Custom Domain shown ✗ on MVP, and fix every ✓ icon having alt="not included".
  • Other "Web Hosting" strings: Cloud Code "Functions & Web Hosting", the public-folder empty state, collaborator permission "Web Hosting and Live Query".
  • Checkout copy review (parked, not approved): per-trigger headlines/sublines. Ideas: move the triggering benefit to the top of the plan's list (HTTPS is 6th on PAYG, compliance last); HIPAA should speak to US health apps storing patient data ("we sign a BAA") rather than "customer security review"; MongoDB and HIPAA need a post-purchase next step; "API on your own domain" only if self-serve on MVP; clearer copy for email templates, Parse options and collaborators.
  • API URL on the Overview still shows parseapi.back4app.com; showing the b4a.io server URL needs the Real-time settings call on the Overview.

Shared Paddle bits (lib/paddleCheckout.js) keep the same side effects as plan-usage: save-subscription, GTM paddle_purchase, Amplitude purchase event.

Please verify before merging

  • MVP feature claims on the card: Web URL & custom domain (confirmed), MongoDB 8.0, custom email templates, up to 3 collaborators.
  • HTTPS flow: after buying Pay As You Go from "Enable HTTPS", support enables it from the ticket.
  • Paddle sandbox, end to end: from a free app, click Upgrade on Domain Settings → pay with a test card → plan is linked to the app (save-subscription) and the page reloads unlocked. Also switch to Yearly before paying.
  • customData keeps the existing { appId, planId } shape; the completion handler reads app_id || appId to be safe.

Tests run locally

  • jest: new suites upgradeEvents.test.js and UpgradeCheckout.test.js, 14 tests passing. The full suite shows the same 8 failing suites as untouched production2 (B4AAlert, CloudCodeView, CodeEditor, CodeTree, CodeView, ColumnPreferences, PermissionsCollaboratorDialog, e2e).
  • eslint: no new errors in changed files (baseline errors are pre-existing); new files clean.
  • npm run build (production): passes. Needed local ajv@8 / uuid@3.4.0 because there is no lockfile; the same failure happens on untouched production2.
  • madge --circular: only the pre-existing dashboard/Settings/Util cycle.
  • Not run: the UI in a browser and a real Paddle checkout.

Known, not touched here

  • AppPlan Paddle callback is a plain function that reads this.context on checkout.closed, so that redirect never runs.
  • Button.propTypes.trackClick is declared as object but defaults to true, which warns in dev.

🤖 Generated with Claude Code

alyssoncm and others added 15 commits October 1, 2026 12:20
Adds baas_upgrade_gate_viewed / baas_upgrade_gate_clicked on every paywall
(web hosting, custom domain, email templates, parse options, jobs,
collaborators, compliance, MongoDB 8.0, DB profiler, overview plan card)
and baas_checkout_opened / baas_checkout_closed around the Paddle checkout.
Paywall links pass ?gate= to plan-usage so the checkout events and
"At Checkout - Subscription Successful" carry source and gate.

Events are prefixed baas_ so the Agent's upgrade_* charts are unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The site pricing page defaults to yearly (MVP $15) while the in-app page
defaulted to monthly ($25). Also pass plan.name to Paddle; plan.planName
does not exist, so the checkout had no title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Free apps use a tiny fraction of their 25K requests, so "20x more requests"
does not land. Lead the MVP card and the upgrade box with custom domain,
backups, MongoDB 8.0, email templates and collaborators.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clicking "Upgrade" on a paywall used to land on the three-plan comparison
page (87% leave it without choosing a plan). Now it opens a checkout for
the plan that unlocks that feature, with a headline about what the user
asked for, the price, a monthly/yearly switch and a "Compare all plans"
escape hatch.

Covers web hosting, custom domain, email templates, Parse options,
collaborators and MongoDB 8.0 (MVP), SOC 2 / ISO 27001 (Pay As You Go)
and HIPAA (Dedicated). Collaborators, compliance and MongoDB 8.0 used to
send users to the public pricing page, losing the app they were on.

Jobs, the overview plan card and paid-plan upsells keep going to the
plan page. The DB profiler already had its own checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The summary panel was dark navy next to a white Paddle frame. The modal is
now a single surface in the OS/browser color scheme, and Paddle opens with
the matching theme. Billing cycles render as selectable cards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Real-time Updates

"Web hosting" meant two different things: the Server URL subdomain used by
LiveQuery (every plan, Free with card validation) and the b4a.app Web URL +
custom domains for the public folder (MVP+). Name them after what they do.

Routes stay the same. serverInfo keeps the old names next to the new ones,
because menu access is matched by name. Plan cards: MVP lists "Web URL &
custom domain", Pay As You Go lists "HTTPS on your custom domain".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The "Web Hosting" fact becomes "Web URL" and shows the custom domain when
there is one. Its call to action follows the user's state:
- plan cannot get a Web URL -> "Get a Web URL" opens the MVP checkout
- MVP with a custom domain -> "Enable HTTPS" opens the Pay As You Go
  checkout; after paying, the modal tells them to open a support ticket,
  since support turns HTTPS on
- no Web URL yet -> "Get a Web URL"; b4a.app only -> "Use your domain";
  otherwise "Manage" (all go to Domains)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each paywall headline now states the outcome (e.g. "Bring your team into
this app", "Pass your customer's security review"), with an optional
supporting line. MongoDB is sold as "Get the latest MongoDB" with no
version number, since versions date the copy; the Overview button reads
"Upgrade database".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to MVP

- A badge beside the app name shows the plan. "Free · Upgrade" opens the
  MVP checkout; paid plans and paused apps link to Plan Usage.
- The plan card's "Upgrade Plan" also opens the MVP checkout on Free;
  paid plans still go to Plan Usage to compare the next tier.
- Both generic entry points sell MVP as a whole ("Take this app to
  production") and are tracked as overview_plan_badge / overview_plan_card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Server URL & Live Query menu and page: "Real-time (Live Query)".
- "Web URL" goes back to "Web Hosting" for now (Overview column, Domains
  page copy, plan cards, checkout headline). The Overview CTA reads
  "Enable web hosting". The Domains menu name stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… button

- The direct checkout preselects yearly (MVP $15/month, billed $180),
  matching the pricing page; monthly stays one click away.
- Collaborators' "Upgrade Plan" was a plain text link; it is now the same
  green button as the other paywalls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@charles-ramos
charles-ramos merged commit cfaead0 into production2 Oct 5, 2026
0 of 7 checks passed
@alyssoncm alyssoncm mentioned this pull request Oct 5, 2026
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants