Sharpen upgrade copy on usage limit modal and plan page#2391
Merged
Conversation
Lead with the concrete value prop ($1,000 of Claude & Codex usage / month for $200) instead of vague phrases like "higher usage limits" and "unlimited usage." Frames Pro as 20× the Free allowance in the modal and plan cards, and 5× what you pay in the upgrade confirm dialog where price is the anchor. Sidebar usage bar is intentionally left unchanged — kept percentage- based rather than introducing $ values in a constrained space. Values are inlined for now; if billing changes the $50 / $1,000 / $200 numbers, three spots need updating. A follow-up could plumb the limit through usageBucketSchema so the renderer reads it from the API. Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Add two events following the Object-verbed + discriminator pattern from
docs/conventions.md:
- `Upgrade prompt shown` with surface ∈ {usage_limit_modal, upgrade_dialog}
- `Upgrade prompt clicked` with surface ∈ {usage_limit_modal, sidebar,
plan_page_card, upgrade_dialog}
Wired into UsageLimitModal (impression + CTA), SidebarUsageBar (CTA),
and PlanUsageSettings (Pro card upgrade CTA, confirm dialog impression,
and Subscribe button intent fired before upgradeToPro() so the gap to
the existing `Subscription started` event captures payment/API
failures).
Once shipped, the funnel "saw the limit but didn't subscribe" becomes
answerable: Upgrade prompt shown (surface=usage_limit_modal) →
Upgrade prompt clicked (surface=usage_limit_modal) →
Subscription started.
Generated-By: PostHog Code
Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Lets us run `posthog.featureFlags.override({ "posthog-code-billing": true })` from the renderer devtools console to test billing UI locally without flipping the flag in PostHog. Gated on `import.meta.env.DEV` so it never ships in prod builds.
Generated-By: PostHog Code
Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
The previous commit (ba2c781) was created while local HEAD was behind the remote tip, which inadvertently reverted the instrumentation changes from b958f25. Re-applies the `Upgrade prompt shown` / `Upgrade prompt clicked` events and their track() call sites. Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Two problems: (1) when VITE_POSTHOG_API_KEY is unset locally, initializePostHog() returns before exposing posthog on window, so the dev override added in ba2c781 never fired; (2) even with the override, flipping a flag in posthog-js without an inited client is unreliable. Switches the five BILLING_FLAG call sites to the established `useFeatureFlag(FLAG) || import.meta.env.DEV` pattern already used for CLOUD_HANDOFF_FLAG and SPEND_ANALYSIS_FLAG. Also moves the window.posthog assignment above the early return so future flag overrides via devtools still work for keys that don't gate on billing. Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
The "(20× Free)" suffix was wrapping the usage bullet onto a second line on narrow widths. Promotes it to a soft accent badge inline with the Pro title and price, where the comparison value sells the plan more directly. Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Reverts the `|| import.meta.env.DEV` checks added to the five BILLING_FLAG call sites and the dev-only `window.posthog` exposure in analytics.ts. Both were added to test the new upgrade copy locally; they should not ship. Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Generated-By: PostHog Code Task-Id: 7ea15f76-06cb-414a-8d45-477e97ed95e7
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/code/src/renderer/features/settings/components/sections/PlanUsageSettings.tsx:376-384
**Duplicate `$1,000` in description and first bullet**
The dialog description already states "Includes $1,000 of Claude and Codex API usage per month", and the first check-list bullet immediately below repeats "$1,000 of Claude & Codex usage / month". A reader sees the same number twice in rapid succession, and the two phrasings also diverge slightly ("API usage" vs "usage"). Removing the first bullet (or rephrasing it to something the description doesn't cover, like "Priority model access") would tighten the dialog and eliminate the inconsistency.
### Issue 2 of 2
apps/code/src/renderer/features/billing/components/UsageLimitModal.tsx:44-47
**Dollar limits hardcoded in three separate places**
`$50`, `$1,000`, and `$200` now appear verbatim in `UsageLimitModal.tsx`, in the Pro plan-card feature list in `PlanUsageSettings.tsx`, and again in the upgrade-dialog description and its first bullet — four string sites across two files. A pricing change requires hunting down every occurrence. The PR description already flags this as a follow-up ("plumb the dollar limit through `usageBucketSchema`"), so this is a reminder to track that work: leaving the values scattered makes the next update error-prone.
Reviews (1): Last reviewed commit: "Drop verbose comments from upgrade promp..." | Re-trigger Greptile |
jonathanlab
approved these changes
May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Sharpen the copy on the three surfaces where we ask free users to upgrade. Today the copy leans on vague phrases ("higher usage limits", "unlimited usage", "limited usage") that hide the actual value prop. After this PR:
Free includes \$50 of Claude and Codex usage per month. Pro includes \$1,000 of usage for \$200/month — 20× more than Free.CTA shortened from "View upgrade options" to "See Pro".\$50 of Claude & Codex usage / month; Pro bullet is\$1,000 of Claude & Codex usage / month (20× Free).Includes \$1,000 of Claude and Codex API usage per month — 5× what you pay.(price is right there, so the ROI frame lands harder than the abundance frame).Framing choice
Two value framings sit alongside each other:
20× more than Free— leads in the modal + plan card. The reader is shopping capacity; a big multiplier on usage is what they want.5× what you pay— leads in the confirm dialog. Price is on screen; ROI math is what justifies the click.Why no A/B test
We only see ~0.4 `Subscription started` events / day project-wide (7 in the last 17 days). A conversion-rate A/B test would need months to reach significance — by which point pricing or product will have moved. Shipping straight; the new copy is concretely better than "higher usage limits". Follow-up below adds instrumentation so we can measure before/after.
Follow-ups (not in this PR)
Test plan