E-commerce dark patterns
Most dark-pattern guides are about taste. This one is about the subset that is
against the law in the markets a store actually sells into — and about the
honest mechanic that replaces each one without losing the sale. A shop that
ships a pre-ticked add-on has not made a design mistake; it has made a
refundable one.
Every finding carries three things: the pattern, the text it breaks, the
replacement.
Do this first
Run the audit before reading anything else. It finds the patterns that can be
inferred from source, each with a file, a line, the law and the fix.
node skills/ecommerce-dark-patterns/scripts/audit-dark-patterns.mjs ./src
Zero dependencies, reads only, writes nothing. Handles React, Vue, Svelte,
Liquid, HTML, Astro, PHP. --json for machine output, --strict to fail a CI
job when anything at severity illegal is found.
Then read references/patterns.md for the catalogue: twelve patterns, and
for each one the jurisdiction where it is illegal, the text, and the honest
version.
If you take one rule from this file
Every honest mechanic sells at least as well as its dark twin, because the
dark twin is measured on the first visit and refunded on the second.
A countdown seeded from page load converts on the first page view. The buyer
who returns sees the same 4:59 and never trusts the shop again. A real
end-of-offer date, printed, converts almost as well and is true the second
time. The audit's job is not to remove urgency; it is to replace false urgency
with a true one.
When to use this skill
- Any compliance, legal, consumer-law, Omnibus, DMCC, FTC, or "is this
allowed" question about a store, cart, checkout or subscription.
- Before shipping a discount, a struck-through price, a countdown, a stock
claim, a review block, an add-on, a "free" claim, or a recurring charge.
- When an agent is asked to "add urgency", "add scarcity", "add social proof"
or "add a protect-my-order option" — the request is usually for the dark
version, and this skill supplies the honest one.
- Reviewing a theme, an upsell app's output, or a generated storefront.
The reference files
| File |
Read it when |
references/patterns.md |
Always. The twelve patterns, the law each breaks, the honest replacement |
references/law.md |
You need the primary texts by jurisdiction, with links and the dates they took effect |
references/replacements.md |
You are rebuilding a page and want the honest mechanic written out as a component spec |
The twelve patterns, in one table
| # |
Dark pattern |
Where it is illegal |
The honest twin |
| 1 |
Pre-ticked add-on, insurance, "protect my order" |
EU (CRD art. 22, refundable), UK (CCR reg. 40), US (FTC "sneaking") |
unchecked box, one sentence of reason |
| 2 |
Struck-through price never charged |
EU (98/6/EC art. 6a, 30-day lowest), UK (DMCC), US (16 CFR 233) |
compare-at = real prior price, or no strike-through |
| 3 |
Countdown seeded from page load |
EU (UCPD Annex I §7), UK (DMCC sched. 20), US (FTC act §5) |
a printed end date, or no timer |
| 4 |
"Only 3 left" not read from stock |
EU (UCPD Annex I §7), UK, US |
a stock figure read from inventory, or nothing |
| 5 |
"12 people are viewing" / fake activity |
EU (UCPD art. 6), UK, US |
nothing — there is no honest version of an invented number |
| 6 |
Fabricated reviews, ratings, review counts |
EU (UCPD Annex I §23b–c), UK (DMCC sched. 20), US (16 CFR 465, penalties) |
the real block, or the slot left empty |
| 7 |
Drip pricing — fee appears at the last step |
UK (DMCC, in force 6 Apr 2025), US (California SB 478; FTC 16 CFR 464 for tickets/lodging), EU (CRD art. 6(1)(e)) |
the all-in price on the first screen |
| 8 |
"Free" that moves the basket total |
EU (UCPD Annex I §20, unfair in all circumstances) |
a gift that costs zero, or the word "included" |
| 9 |
Confirmshaming decline ("No, I hate saving money") |
US (FTC report), EU (UCPD art. 8–9 aggressive practice), UK |
"No thanks", same size, same row |
| 10 |
Subscription harder to cancel than to start |
US (ROSCA; California ARL from 1 Jul 2025), EU (CRD art. 6, 8, 9) |
cancel by the same medium, in the same number of steps |
| 11 |
Pay button that does not say it charges ("Yes!", "Continue") |
EU (CRD art. 8(2), not binding on the consumer) |
"Pay 48,00 €" / "Add to my order — 9,00 €" |
| 12 |
Basket sneaking — an item added without an act |
EU (CRD art. 22), UK, US (FTC "sneaking") |
every line in the basket came from a click |
What the audit finds, and what it cannot
From source it finds: pre-ticked inputs near a price, Date.now() feeding a
countdown, hard-coded viewer counts, stock claims not bound to a variable,
literal review counts and star averages, compare-at figures not derived from a
unit price, confirmshaming strings, "free" next to a price, pay buttons with
no amount, and fee lines that only appear in the last step's template.
It cannot see a live price history, so it flags every struck-through price for
a human to check against the 30-day rule. It cannot read a cancellation flow
that lives in a third-party billing portal; it names the path it could not
follow.
What this skill does not do
It is not legal advice. It is a builder's summary of public texts, each one
linked so the claim can be checked, written so that an agent refuses the
pattern instead of building it and adding a comment. When a shop is close to a
line, the shop's own counsel decides.
It does not remove selling mechanics. The sibling skills
store-design and
checkout-upsell
build the honest versions; this one makes sure what shipped is the honest
version.
Why this exists
Asked to "add urgency" to a product page, a coding agent produces a countdown
that resets on refresh, because that is the median of what it read. Asked
whether a pre-ticked "shipping protection" box is allowed, it cannot cite the
article. There is no citable, code-level catalogue of the storefront patterns
that are illegal rather than merely disliked. This is that catalogue, with the
script that finds them.
Built by uxgen. MIT.
1---2name: ecommerce-dark-patterns3description: Audit a storefront, cart, checkout or subscription flow for the dark patterns that are illegal — not merely distasteful — in the EU, the UK and the US, and replace each with the honest selling mechanic that still sells. Finds the pre-ticked add-on (refundable under Article 22 of 2011/83/EU), the struck-through price that was never charged (Omnibus, 30-day rule), the countdown seeded from page load, the fabricated review count or "12 people are viewing", the hidden fee added at the last step (drip pricing, banned in the UK from April 2025 and in California), the confirmshaming decline, the subscription that is harder to cancel than to start (ROSCA, California ARL) — each with the text of law it breaks, a file and a line, and the replacement. Use for any compliance review, legal audit, consumer-law check, dark pattern audit, deceptive design review, Omnibus or DMCC or FTC question about a store, before shipping any discount, urgency, scarcity, add-on, "free" claim or subscription, and whenever an agent is asked4license: MIT5---67# E-commerce dark patterns89Most dark-pattern guides are about taste. This one is about the subset that is10**against the law** in the markets a store actually sells into — and about the11honest mechanic that replaces each one without losing the sale. A shop that12ships a pre-ticked add-on has not made a design mistake; it has made a13refundable one.1415Every finding carries three things: the pattern, the text it breaks, the16replacement.1718---1920## Do this first2122Run the audit before reading anything else. It finds the patterns that can be23inferred from source, each with a file, a line, the law and the fix.2425```bash26node skills/ecommerce-dark-patterns/scripts/audit-dark-patterns.mjs ./src27```2829Zero dependencies, reads only, writes nothing. Handles React, Vue, Svelte,30Liquid, HTML, Astro, PHP. `--json` for machine output, `--strict` to fail a CI31job when anything at severity `illegal` is found.3233Then read **`references/patterns.md`** for the catalogue: twelve patterns, and34for each one the jurisdiction where it is illegal, the text, and the honest35version.3637## If you take one rule from this file3839**Every honest mechanic sells at least as well as its dark twin, because the40dark twin is measured on the first visit and refunded on the second.**4142A countdown seeded from page load converts on the first page view. The buyer43who returns sees the same 4:59 and never trusts the shop again. A real44end-of-offer date, printed, converts almost as well and is true the second45time. The audit's job is not to remove urgency; it is to replace false urgency46with a true one.4748## When to use this skill4950- Any compliance, legal, consumer-law, Omnibus, DMCC, FTC, or "is this51 allowed" question about a store, cart, checkout or subscription.52- Before shipping a discount, a struck-through price, a countdown, a stock53 claim, a review block, an add-on, a "free" claim, or a recurring charge.54- When an agent is asked to "add urgency", "add scarcity", "add social proof"55 or "add a protect-my-order option" — the request is usually for the dark56 version, and this skill supplies the honest one.57- Reviewing a theme, an upsell app's output, or a generated storefront.5859## The reference files6061| File | Read it when |62|---|---|63| `references/patterns.md` | **Always.** The twelve patterns, the law each breaks, the honest replacement |64| `references/law.md` | You need the primary texts by jurisdiction, with links and the dates they took effect |65| `references/replacements.md` | You are rebuilding a page and want the honest mechanic written out as a component spec |6667## The twelve patterns, in one table6869| # | Dark pattern | Where it is illegal | The honest twin |70|---|---|---|---|71| 1 | Pre-ticked add-on, insurance, "protect my order" | EU (CRD art. 22, refundable), UK (CCR reg. 40), US (FTC "sneaking") | unchecked box, one sentence of reason |72| 2 | Struck-through price never charged | EU (98/6/EC art. 6a, 30-day lowest), UK (DMCC), US (16 CFR 233) | compare-at = real prior price, or no strike-through |73| 3 | Countdown seeded from page load | EU (UCPD Annex I §7), UK (DMCC sched. 20), US (FTC act §5) | a printed end date, or no timer |74| 4 | "Only 3 left" not read from stock | EU (UCPD Annex I §7), UK, US | a stock figure read from inventory, or nothing |75| 5 | "12 people are viewing" / fake activity | EU (UCPD art. 6), UK, US | nothing — there is no honest version of an invented number |76| 6 | Fabricated reviews, ratings, review counts | EU (UCPD Annex I §23b–c), UK (DMCC sched. 20), US (16 CFR 465, penalties) | the real block, or the slot left empty |77| 7 | Drip pricing — fee appears at the last step | UK (DMCC, in force 6 Apr 2025), US (California SB 478; FTC 16 CFR 464 for tickets/lodging), EU (CRD art. 6(1)(e)) | the all-in price on the first screen |78| 8 | "Free" that moves the basket total | EU (UCPD Annex I §20, unfair in all circumstances) | a gift that costs zero, or the word "included" |79| 9 | Confirmshaming decline ("No, I hate saving money") | US (FTC report), EU (UCPD art. 8–9 aggressive practice), UK | "No thanks", same size, same row |80| 10 | Subscription harder to cancel than to start | US (ROSCA; California ARL from 1 Jul 2025), EU (CRD art. 6, 8, 9) | cancel by the same medium, in the same number of steps |81| 11 | Pay button that does not say it charges ("Yes!", "Continue") | EU (CRD art. 8(2), not binding on the consumer) | "Pay 48,00 €" / "Add to my order — 9,00 €" |82| 12 | Basket sneaking — an item added without an act | EU (CRD art. 22), UK, US (FTC "sneaking") | every line in the basket came from a click |8384## What the audit finds, and what it cannot8586From source it finds: pre-ticked inputs near a price, `Date.now()` feeding a87countdown, hard-coded viewer counts, stock claims not bound to a variable,88literal review counts and star averages, compare-at figures not derived from a89unit price, confirmshaming strings, "free" next to a price, pay buttons with90no amount, and fee lines that only appear in the last step's template.9192It cannot see a live price history, so it flags every struck-through price for93a human to check against the 30-day rule. It cannot read a cancellation flow94that lives in a third-party billing portal; it names the path it could not95follow.9697## What this skill does not do9899It is not legal advice. It is a builder's summary of public texts, each one100linked so the claim can be checked, written so that an agent refuses the101pattern instead of building it and adding a comment. When a shop is close to a102line, the shop's own counsel decides.103104It does not remove selling mechanics. The sibling skills105[`store-design`](https://github.com/kinerette/claude-code-store-design) and106[`checkout-upsell`](https://github.com/kinerette/claude-code-checkout-upsell)107build the honest versions; this one makes sure what shipped is the honest108version.109110## Why this exists111112Asked to "add urgency" to a product page, a coding agent produces a countdown113that resets on refresh, because that is the median of what it read. Asked114whether a pre-ticked "shipping protection" box is allowed, it cannot cite the115article. There is no citable, code-level catalogue of the storefront patterns116that are illegal rather than merely disliked. This is that catalogue, with the117script that finds them.118119Built by [uxgen](https://www.uxgen.ai). MIT.