Authenticated subscribe CTA. Checks for an existing subscription to prevent double-subscribing, then routes to checkout in redirect, event-only, or embedded-flow mode.
A single CTA button with state-aware copy. On mount, the widget:
Exchanges the bridge token for an in-memory session JWT.
Calls a server-side BFF endpoint to check whether this customer already has an active subscription to the offering.
If not subscribed: shows "Subscribe" (or your ctaText). Clicking initiates checkout.
If already subscribed: shows a disabled "Already subscribed" affordance with a link to the subscription manager.
INFO
The anti-double-subscribe check is UX, not security. Aforo also enforces uniqueness at the database layer — even if the check is bypassed, a duplicate subscription create will be rejected. The button just gives the customer a clearer signal.
Standard hosted checkout. On click, the widget calls Aforo's checkout-initiate endpoint to create a cart, then redirects the browser to the gateway-hosted checkout page (or your own checkout if you've configured it). The customer lands back at returnUrl after completion.
event-only
For parent pages that own the checkout rendering. The widget emits aforo.subscribe.checkout_requested with the full payload and does not redirect. Your parent page handles the rest (open your own modal, navigate to your own route, etc.). The widget waits for an inbound aforo:checkout-completed postMessage to flip into the "subscribed" state.
Renders an inline AforoCheckoutFlow in place of the button after the customer clicks. No redirect, no popup — the entire checkout flow lives on your page.
One offering per button. If you want a customer to choose between multiple plans, use (which renders one CTA per offering) plus per-offering URL overrides.
Coupon codes are Phase 1. The V49 coupon engine is shipped server- side; the customer-facing input UI lands in a future minor.
Trial mode display is v2. The button doesn't currently surface "14-day free trial" copy automatically based on the offering's trial config. Use ctaText as a manual workaround.