A CTA labeled 'Start free trial' with no stated duration, post-trial price, or auto-conversion notice is textbook negative option marketing under FTC Negative Option Rule (2025) — the consumer is not making an informed decision to authorize future recurring charges. California ARL Section 17601 requires that all three facts (trial length, conversion trigger, post-trial price) appear at the point of enrollment. When a user discovers an unexpected $29 charge weeks after forgetting a trial, the result is a chargeback, not a cancellation — and Stripe's dispute rate threshold is 0.75%.
High because withholding post-trial price and auto-conversion terms at the enrollment point constitutes the specific negative option pattern the FTC's 2025 rule targets for civil penalty enforcement.
Display all three required trial disclosures — duration, auto-conversion, and post-trial price — at the trial entry point, not only at the Stripe checkout screen. In components/TrialCTA.tsx:
import { addDays, format } from 'date-fns'
const trialEndDate = format(addDays(new Date(), 14), 'MMMM d, yyyy')
<p className="trial-terms text-sm mt-2">
Free for 14 days (until {trialEndDate}), then $29/month.
Cancel before your trial ends and you won't be charged.
</p>
When credit card is collected at trial signup, make the conversion notice even more prominent: 'Your card will not be charged until [date]. Cancel before then to avoid the $29/month charge.' Ensure trial_period_days in stripe.subscriptions.create matches the number displayed.
ID: subscription-compliance.pre-purchase.free-trial-terms-explicit
Severity: high
What to look for: If the application offers a free trial, find every location where the free trial is advertised or initiated. For each location, check whether the following three facts are visible without requiring additional user interaction: (1) the exact trial duration (e.g., "14-day free trial," not just "free trial"), (2) what happens when the trial ends — specifically, that the subscription converts to paid automatically and the user will be charged unless they cancel, and (3) the price and billing period that will apply after the trial. Check the trial CTA button text: "Start free trial" alone is insufficient if the trial duration is not stated nearby. Check stripe.checkout.sessions.create or stripe.subscriptions.create for trial_period_days and verify this value matches what is displayed in the UI. Check whether the trial end date (calculated from today) is shown, not just the duration — showing the actual calendar date helps users remember to cancel if needed. Before evaluating, extract and quote the exact text shown to the consumer at the trial enrollment point — the trial duration, what happens after, and the price after conversion. Count all instances found and enumerate each.
Pass criteria: Every trial entry point displays: the exact trial length, the fact that it converts to paid automatically at trial end, and the post-trial price and billing frequency. The information is visible before the user clicks through to checkout. At least 1 implementation must be confirmed.
Fail criteria: Trial duration is advertised (e.g., "Try free") with no stated length. Post-trial price is not shown before trial signup. The trial conversion to paid is not explicitly stated — users could reasonably believe the trial just ends without a charge.
Skip (N/A) when: The application offers no free trial, freemium tier, or time-limited free access.
Cross-reference: The price-per-period check in Pre-Purchase verifies the pricing disclosure that consumers see before the trial conversion.
Detail on fail: Specify what is missing. Example: "Hero section says 'Start free trial' with no mention of trial duration or post-trial charge. Post-trial pricing only appears in /pricing page FAQ." or "Trial duration shown (14 days) but post-trial price and auto-conversion not disclosed until Stripe Checkout screen.".
Remediation: Include all three trial facts at every trial entry point:
// components/TrialCTA.tsx
import { addDays, format } from 'date-fns'
const TRIAL_DAYS = 14
const POST_TRIAL_PRICE = '$29'
const BILLING_PERIOD = 'month'
export function TrialCTA() {
const trialEndDate = format(addDays(new Date(), TRIAL_DAYS), 'MMMM d, yyyy')
return (
<div className="trial-cta">
<button type="button" onClick={handleStartTrial}>
Start your {TRIAL_DAYS}-day free trial
</button>
{/* All three required disclosures in one clear statement */}
<p className="trial-terms">
Free for {TRIAL_DAYS} days (until {trialEndDate}), then {POST_TRIAL_PRICE}/{BILLING_PERIOD}.
Cancel before your trial ends and you won't be charged.
No credit card required until trial ends.
</p>
</div>
)
}
If credit card is collected upfront (common in Stripe trials), adjust the disclosure accordingly and make it even more prominent: "Your card will not be charged until [date]. Cancel before then to avoid the $29/month charge."