Skip to content

Give Ultra subscribers a discount on third-party plugins - #546

Draft
simonhamp wants to merge 1 commit into
mainfrom
ultra-plugin-discount
Draft

simonhamp wants to merge 1 commit into
mainfrom
ultra-plugin-discount

Conversation

@simonhamp

Copy link
Copy Markdown
Member

What this does

Third-party plugins get a cheaper price for Ultra subscribers: $70 for Gold, $35 for Silver and $20 for Bronze. That's about 70% of the regular price. On those sales we take no platform fee, so the seller keeps everything the buyer pays.

Everyone else sees a card on third-party plugin pages: "Get this plugin for $70 with Ultra". It links to the Ultra page. Ultra subscribers see the regular price struck through and the Ultra price in the purchase box instead.

It also changes how payouts are worked out when a promotion code or coupon is used. Sellers are now paid their share of what the buyer actually paid, not of the listed price. That applies to every plugin and bundle sale, Ultra or not.

How it works

  • There is a new ultra price tier. Ultra prices are rows in plugin_prices, created from the plugin's pricing tier the same way the regular price is. A migration adds them for existing third-party plugins that have a tier.
  • Official plugins are included with Ultra, so they never get an Ultra price and ignore one if an admin adds it.
  • A buyer gets the Ultra price if hasActiveUltraSubscription() is true. Team members without their own subscription pay the regular price, which matches how team pricing already works.
  • The license records which tier was charged in a new plugin_licenses.price_tier column. A sale at the Ultra tier gets a 0% platform fee whatever the developer's payout_percentage is. payouts:backfill follows the same rule.
  • If the Ultra price isn't lower than the regular price, the regular price wins and the normal fee applies.
  • HandleInvoicePaidJob works out what was paid from the discount Stripe reports on each invoice line. It finds the line by name, so checkout now names plugin and bundle lines with CartItem::getItemName(). If it can't find the line (the webhook only carries the first 10) it shares the invoice discount in proportion and rounds down, so payouts for one invoice can't add up to more than the charge.
  • price_paid on a plugin license is now the amount after discounts.

Other changes

  • The cart labels Ultra-priced plugins.
  • The tier picker on the developer's plugin page shows what Ultra subscribers pay for each tier, and the onboarding FAQ explains the Ultra payout.
  • "Around 30% off third-party plugins" is added to the benefits on /ultra and the Ultra dashboard page.
  • In the admin, the pricing tables know about the Ultra tier and Third-Party Sales marks sales made at the Ultra price.

Things to check

  • We pay Stripe's fee on Ultra sales and take nothing. Agreed, since the subscription covers it.
  • A seller on a better split than 70% earns less on an Ultra sale than on a regular one. Also agreed.
  • A seller's payout now drops when the buyer uses a promotion code. Before, they were paid on the list price.
  • hasActiveUltraSubscription() doesn't recognise the old Max price ID that is hard-coded in Subscription::fromStripePriceId(), though hasUltraAccess() does. Anyone still on that price won't get the Ultra price.
  • Plugins with no tier (custom prices) get no Ultra price unless one is added in the admin.
  • The developer terms still describe a flat 30% fee. This pays sellers more than that on Ultra sales, so I left them alone.
  • Queue workers need restarting with the deploy. A worker on the old code would record an Ultra sale without its tier and take the normal fee.
  • This touches HandleInvoicePaidJob, which the course checkout fix also changes.

Tests

New tests cover who gets the Ultra price, the prices each tier creates, the cart and checkout, the payout split, promotion codes on Ultra, regular and bundle sales, the backfill command, the migration, the plugin page card and the admin screens. Full suite: 2055 passed, 1 skipped.

I also checked the pages in a browser as a guest and as an Ultra subscriber, and confirmed how Stripe reports per-line discounts with a read-only invoice preview in test mode.

🤖 Generated with Claude Code

Third-party plugins get an Ultra price (Gold $70, Silver $35, Bronze $20)
for buyers with an active Ultra subscription. The seller keeps all of
what the buyer pays on those sales. Everyone else sees the Ultra price
advertised on third-party plugin pages.

Payouts on every plugin and bundle sale are now worked out from what the
buyer actually paid after promotion codes and coupons, instead of the
listed price.

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

This branch has not been deployed

No deployments
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.

1 participant