The FTC Negative Option Rule (2025) and California ARL both require subscription terms to be 'clear and conspicuous' before the consumer acts — not discoverable only after clicking through to Stripe. When billing frequency, price, and auto-renewal notice are absent from the pre-checkout screen, users reasonably believe they are making a one-time purchase. The resulting chargebacks and regulatory complaints are not recoverable by updating your Terms of Service retroactively; the disclosure must exist at the moment of decision. Under EU Consumer Rights Directive 2011/83/EU, failure to disclose recurring payment terms before order placement can make the contract voidable.
Critical because absent pre-purchase disclosure is the primary trigger for FTC enforcement actions and class-action suits under state ARL statutes, with civil penalties up to $50,120 per violation.
Add billing frequency, auto-renewal notice, and price to every pricing card and upgrade entry point before the checkout action. In components/PricingCard.tsx, render a visible disclosure paragraph immediately below the CTA:
<p className="billing-notice text-sm text-gray-700 mt-2">
Billed monthly. Renews automatically. Cancel anytime from account settings.
</p>
If routing through Stripe Checkout (hosted), populate subscription_data.description so Stripe's own confirmation screen reflects the terms:
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
subscription_data: {
description: 'Monthly subscription — renews automatically at $29/month. Cancel anytime.',
},
})
ID: subscription-compliance.pre-purchase.terms-clear-before-checkout
Severity: critical
What to look for: Locate the pricing page, upgrade modal, or any entry point to subscription enrollment. Before the user clicks any "Subscribe," "Start Trial," or "Get Started" button, examine what subscription information is visible in the UI without any additional user interaction (no hover, no click, no "Learn more" expansion required). Specifically check: is the billing frequency (monthly vs. annual) clearly labeled? Is the price per period displayed as a number, not just a marketing tagline? Is the auto-renewal nature of the subscription stated — i.e., does the page make clear that this is a recurring charge, not a one-time payment? Search for phrases like "billed monthly," "billed annually," "renews automatically," or "recurring" in pricing page components. If the only disclosure is in a small-font Terms of Service link, that is insufficient. Check Stripe Checkout session parameters for payment_method_collection and whether subscription_data is populated with meaningful descriptions. Count all instances found and enumerate each.
Pass criteria: Before initiating checkout, the user can see: (1) the billing frequency explicitly labeled (e.g., "billed monthly" or "per month"), (2) a statement that the subscription auto-renews (e.g., "renews automatically," "cancel anytime," or equivalent), and (3) the recurring nature of the charge is unmistakable from the pricing UI — not dependent on reading fine print or following links. At least 1 implementation must be confirmed.
Fail criteria: Subscription terms are absent from the pre-checkout UI. The price is shown but billing frequency is not labeled. Auto-renewal is disclosed only in a linked Terms of Service or a footnote visible only after scrolling. The checkout page is the first place subscription terms appear.
Skip (N/A) when: The application has no subscription or recurring billing of any kind.
Detail on fail: Specify what is missing. Example: "Pricing page shows '$29' with no billing frequency label and no mention of auto-renewal. Terms are only in footer ToS link." or "Subscribe button initiates checkout without displaying billing period or recurring charge notice on the pre-checkout screen.".
Remediation: Add explicit subscription term disclosures to every pricing and upgrade entry point:
// components/PricingCard.tsx
export function PricingCard({ plan }: { plan: Plan }) {
return (
<div className="pricing-card">
<h2>{plan.name}</h2>
{/* Price with explicit billing period */}
<div className="price">
<span className="amount">${plan.priceMonthly}</span>
<span className="period">/ month</span>
</div>
{/* Auto-renewal disclosure — must be visible without interaction */}
<p className="billing-notice">
Billed monthly. Renews automatically. Cancel anytime.
</p>
{plan.trialDays > 0 && (
<p className="trial-notice">
{plan.trialDays}-day free trial, then ${plan.priceMonthly}/month.
No charge until {formatTrialEndDate(plan.trialDays)}.
</p>
)}
<button type="button" onClick={handleSubscribe}>
{plan.trialDays > 0 ? `Start ${plan.trialDays}-day free trial` : 'Subscribe'}
</button>
</div>
)
}
If using Stripe Checkout (hosted), populate subscription_data.description with the billing terms so they appear in Stripe's own UI:
// app/api/checkout/route.ts
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
subscription_data: {
description: 'Monthly subscription — renews automatically at $29/month. Cancel anytime.',
trial_period_days: 14,
},
// ...
})