Consent is a decision the user makes about themselves, so the interface owes them the facts before the choice, not after it. The failure is rarely a missing checkbox. It is a screen that asks for something the user cannot evaluate, at a moment when saying no is expensive, in words written to be agreed with rather than understood.
This doc covers asking for permission, writing consent copy, and handling data the user would not want on a screen. The wider copy voice lives in microcopy.md, form mechanics in forms.md, and the manipulation patterns this doc rules out in anti-patterns.md.
Ask at the Moment the Reason Is Visible
- Tie the request to the action that needs it. Ask for the camera when the user taps to take a photo, not on the first launch. A request that arrives with its reason on screen is answered on the merits. A request that arrives cold is answered by reflex, and the reflex is no.
- Explain before the system prompt, not after. An operating system permission dialog can be shown once and its refusal is expensive to reverse. Put your own screen first, saying plainly what you will do with the access, and let the user reach the real prompt from it. If they decline your screen, do not raise the system one.
- Ask for one thing at a time. A screen requesting contacts, location and notifications together is answered as a single yes or a single no, and the user learns nothing about any of them.
- Accept no as an answer. Store the refusal, keep the feature reachable in a degraded form where possible, and do not re-ask on the next launch. If the feature genuinely cannot work, say so at the point of use, with a route to change the setting.
Write the Consent, Do Not Perform It
- Say what you collect, who sees it, and what you do with it. Three facts, in the user's words. "We use your email to send the receipt and nothing else" is consent copy. "We value your privacy" is not.
- Name the third party. If data leaves for someone else, the reader is consenting to that too, and a generic "our partners" hides the only detail that matters.
- Make the checkbox statement true when ticked. A checkbox reading "I do not want to opt out of updates" is a puzzle, and a puzzle is not consent. Write the affirmative: "Email me product updates."
- Never pre-tick a consent box. A default yes is not a choice, and in several jurisdictions it is not consent at all.
- Keep decline as legible as accept. Same size, same weight, same distance from the thumb. A greyed-out no beside a filled yes is a dark pattern with extra steps (see
anti-patterns.md— Confirmshaming). - Separate the required from the optional. Terms you must accept to use the product are one control. Marketing email is another. Bundling them turns a legal acceptance into a mailing list.
Cookie and Tracking Banners
- Offer reject as directly as accept. Both on the first screen, both one tap. A reject that costs three taps through a preferences panel is a refusal the interface is trying to prevent.
- Do not block the page for a choice that is not urgent. A banner that covers the content the visitor came for gets dismissed, not read, and a dismissal is not a decision.
- Default every optional category to off. Analytics, personalisation and advertising start unticked. Only what the product cannot run without is on.
- Let the choice be changed later, from somewhere findable. A settings entry named for what it controls, not a link buried in the footer policy.
Sensitive Content on Screen
- Mask by default what a shoulder can read. Account numbers, health details, salary, and anything a user would not want visible in an open-plan office. Show the last few characters and let the user reveal the rest deliberately.
- Give reveal a clear affordance and an accessible name. A reveal control announces itself as "Show account number", and its pressed state announces the change, so the reader is never guessing what is visible (see
ui/accessibility.md— Accessible names). - Keep sensitive values out of URLs, logs and error messages. An error that echoes the value it failed to process copies it into places nobody consented to.
- Warn before a screen share or an export, not after. If a view holds sensitive fields, say so at the point the user is about to make it visible to someone else.
- Do not let a placeholder or an empty state hold real data. Sample content that looks like a real record teaches the user to distrust what they see.
Deletion and Withdrawal
- Make withdrawing consent as easy as giving it. If one tap turned tracking on, one tap turns it off. A withdrawal that requires an email to support is a refusal.
- Say what withdrawal does and does not undo. Stopping collection and deleting what was already collected are different promises. Name which one you are making.
- Confirm destructive privacy actions with the consequence, not with a generic warning. "Delete your account and its 42 projects, permanently" tells the user what they are about to lose (see
dialogs.md— Destructive confirmation). - Show the state, not the switch alone. A privacy settings screen should say what is currently happening in plain words, above the controls that change it.
Do Not
- Do not treat continued use as consent. "By browsing this site you agree" is a claim, not an agreement.
- Do not ask again immediately after a no. The second prompt tells the user their answer was not recorded, which is worse than the refusal.
- Do not use urgency, guilt or a loaded decline label. "No thanks, I do not want to save money" is a documented manipulation and it reads as one.
- Do not hide the scope in a linked policy. A link to twelve pages is not disclosure. The one sentence that matters belongs on the screen.
Checklist
- Every permission is requested at the moment its reason is on screen, one at a time
- Your own explanation precedes any operating system prompt, and a decline stops there
- Consent statements name what is collected, who sees it, and what it is used for
- No consent box is pre-ticked, and required acceptance is separate from optional
- Decline is the same size, weight and reach as accept
- Optional cookie categories default to off, and reject is one tap on the first screen
- Sensitive values are masked by default, with a named reveal control
- Sensitive values never appear in URLs, logs or error messages
- Withdrawing consent takes the same effort as giving it, and says what it undoes