Confirm shaming — labeling the 'decline' button with language designed to make the user feel guilty, inadequate, or foolish ('No thanks, I prefer to stay limited') — is identified in the FTC's Dark Patterns Report as a manipulative interface design that undermines informed consumer choice. The FTC Act §5 unfairness prong covers practices that cause substantial consumer injury not outweighed by benefits. While individual instances seem minor, confirm shaming at scale across millions of upgrade prompts constitutes a systematic manipulation of consumer decision-making that the FTC treats as an unfair practice.
Low because confirm shaming harms consumers through psychological manipulation rather than direct financial loss, and a single instance rarely triggers enforcement — but the pattern is identified by the FTC and signals a design culture that tolerates dark patterns elsewhere.
Replace all guilt-language decline options with neutral alternatives and grep the codebase to find all instances before shipping.
// WRONG — confirm shaming
// <button>No thanks, I prefer to stay limited</button>
// <button>I'll miss out on the savings</button>
// RIGHT — neutral decline language
function UpgradeModal({ onAccept, onDecline }: ModalProps) {
return (
<dialog>
<h2>Upgrade to Pro</h2>
<p>Unlimited projects, priority support, advanced analytics.</p>
<div className="flex gap-3">
<button onClick={onAccept}>Upgrade now</button>
<button onClick={onDecline} variant="ghost">
No thanks {/* or: Maybe later / Not right now / Decline */}
</button>
</div>
</dialog>
)
}
Find all instances with:
grep -r "I don't want\|I prefer to stay\|I'll miss out\|I'll take my chances\|No thanks, I" src/
Acceptable decline labels: 'No thanks', 'Maybe later', 'Not right now', 'Decline', 'Skip', 'Dismiss', 'Cancel', 'Close'.
ID: ftc-consumer-protection.dark-patterns.no-confirm-shaming
Severity: low
What to look for: Count all relevant instances and enumerate each. Search marketing copy, modal text, and dialog button labels for "confirm shaming" — also called "nagging" or "guilt-tripping." This pattern labels the "decline" option in a way designed to make the user feel bad about declining. Examples: "No thanks, I don't want to save money" as the reject button label for an upsell; "I prefer to stay average" as the dismiss option for a premium upgrade prompt; "No thanks, I'll figure it out myself" as the reject for a training offer. Search component text for: modals with asymmetric button labels, upgrade prompts with condescending decline options, email unsubscribe pages that use guilt language ("You'll miss out on..."). Look specifically in: upgrade modal components, trial expiration modals, exit-intent popups, email preference pages, and upsell banners.
Pass criteria: Decline options on offers, upsells, and prompts use neutral language: "No thanks," "Maybe later," "Decline," "Not now," or equivalent. At least 1 implementation must be verified. No modal or prompt uses language designed to make the user feel guilty, inadequate, or foolish for declining.
Fail criteria: Any modal, prompt, banner, or dialog uses guilt-tripping language on the decline option. The decline button implies the user is making a mistake or is inferior for not accepting.
Skip (N/A) when: The application has no modals, offers, upsell prompts, or dismissible banners of any kind.
Detail on fail: Example: "Upgrade modal decline button reads 'No thanks, I prefer to stay limited.' This is confirm shaming." or "Exit-intent popup dismiss button reads 'No, I don't want more leads.' This is confirm shaming." or "Trial expiration modal labels the dismiss option 'I'll take my chances without backup.'"
Remediation: Audit all modal and prompt button labels and replace shaming language with neutral alternatives:
// BEFORE — confirm shaming
// <button>No thanks, I prefer losing money</button>
// AFTER — neutral decline language
function UpgradeModal({ onAccept, onDecline }: ModalProps) {
return (
<dialog>
<h2>Upgrade to Pro</h2>
<p>Get unlimited projects, priority support, and advanced analytics.</p>
<div className="flex gap-3">
<button onClick={onAccept}>Upgrade now</button>
{/* Neutral decline language */}
<button onClick={onDecline} variant="ghost">
No thanks
</button>
</div>
</dialog>
)
}
// Acceptable decline labels:
// "No thanks"
// "Maybe later"
// "Not right now"
// "Decline"
// "Skip"
// "Dismiss"
// "Cancel"
// "Close"
Search the codebase with grep -r "I don't want\|I prefer to stay\|I'll miss out\|I'll take my chances\|No thanks, I" to find instances. None of these patterns are acceptable.