GDPR Art.7: Conditions for Consent — Proof Burden, Withdrawal Mechanics & Bundling Prohibition (2026)
Post #439 in the sota.io EU Cyber Compliance Series
Art.7 is the operational layer beneath Art.6(1)(a). Where Art.6 says consent can be a lawful basis, Art.7 defines exactly how that consent must be obtained, recorded, and revoked to be legally effective. Failing Art.7 does not just mean the consent is invalid — it means there is no lawful basis at all, making all processing under that consent unlawful under Art.5(1)(a). Supervisory authorities regularly challenge consent validity not at the Art.6(1)(a) level (where developers focus) but at the Art.7 level: missing proof logs, bundled checkboxes, or withdrawal mechanisms buried behind a support ticket flow.
This guide is part of the GDPR Chapter I series: Art.1-4 Scope → Art.5 Principles → Art.6 Lawful Bases → Art.7 Consent Conditions (this guide).
The Four Art.7 Conditions at a Glance
| Art.7 | Condition | Core Requirement | Most Common Failure |
|---|---|---|---|
| Art.7(1) | Proof burden | Controller must be able to demonstrate consent was given | No consent log: no timestamp, no text version, no mechanism ID |
| Art.7(2) | Written consent clarity | Consent requests in writing must be clearly distinguishable from other matters | T&C checkbox also covers marketing consent |
| Art.7(3) | Withdrawal mechanics | Data subject can withdraw at any time; withdrawal as easy as giving consent | Withdrawal requires support ticket; no in-app toggle |
| Art.7(4) | Bundling prohibition | Service access cannot be conditioned on consent to non-necessary processing | "Accept analytics to use app" = presumption of involuntary consent |
Each condition applies cumulatively. Meeting three out of four is not sufficient — any Art.7 failure invalidates the consent entirely.
Art.7(1) — Proof Burden: Controller Must Demonstrate Consent
The Legal Standard
Art.7(1) places the burden of proof on the controller: when processing is based on consent, the controller must be able to demonstrate that the data subject has given consent to the processing operation. This is an ongoing obligation — not a one-time record. If the consent record is lost, corrupted, or insufficiently detailed to demonstrate that valid consent was given, the processing becomes unlawful.
"Demonstrate" is a higher standard than "record." The EDPB Guidelines 05/2020 on Consent clarify that the controller must be able to produce evidence showing:
- Who gave consent (identity linkable to the data subject)
- When consent was given (timestamp)
- What was consented to (the exact processing purpose and scope as presented at the time)
- How consent was given (the mechanism — checkbox, toggle, signed form, API scope acceptance)
- Which version of the consent text was shown (if your privacy notice changes, old consents may not cover new processing)
Minimum Consent Log Requirements
For a SaaS product, the Art.7(1) proof log should contain at minimum:
{
"user_id": "uuid",
"timestamp_utc": "2026-04-18T14:00:00Z",
"ip_address": "203.0.113.42",
"consent_type": "marketing_emails",
"consent_text_version": "v2.3",
"consent_text_hash": "sha256:abc123...",
"mechanism": "checkbox_opt_in",
"withdrawal_timestamp_utc": null,
"withdrawal_mechanism": null
}
Key principle: You need the consent text hash or version ID because the validity of the consent is tied to what was shown to the user at that moment. A consent given under a text that said "we may send product updates" does not cover later adding "we may share your data with advertising partners."
Retention of Consent Records
Art.7(1) records must be retained for as long as the processing continues plus the applicable limitation period for potential enforcement. In practice:
- Retain consent logs for the duration of the processing relationship plus at least 3 years (to cover supervisory authority investigation windows in most Member States)
- When a user withdraws consent, retain the withdrawal record — do not delete the entire consent history
- Include consent records in your ROPA (Art.30) as evidence of the lawful basis
Supervisory Authority Enforcement on Proof Burden
The ICO (UK, pre-Brexit) and multiple DPAs have fined controllers for consent processing where records were incomplete. The French CNIL's cookie enforcement actions systematically checked whether consent logs included all five elements above. Missing the consent text version — so the controller could not prove what the user saw — has been treated as equivalent to no consent record at all.
Art.7(2) — Written Consent: Clarity and Separation Requirements
The Legal Standard
When consent is requested in writing "in the context of" other matters (contracts, terms, other declarations), the request for consent must be presented in a "manner which is clearly distinguishable from the other matters, in an intelligible and easily accessible form, using clear and plain language."
Art.7(2) second sentence adds: "Any part of such a declaration which constitutes an infringement of this Regulation shall not be binding."
This has two practical consequences:
- If a T&C acceptance checkbox also covers a consent request for marketing analytics, the marketing analytics consent is invalid — but the T&C acceptance may remain valid if it is severable.
- The clarity obligation means pre-formatted consent text buried in footnote 47 of a 32-page privacy policy does not satisfy Art.7(2).
The Distinguishability Requirement in Practice
Invalid:
☐ I accept the Terms of Service, Privacy Policy, and agree to receive
marketing communications and to have my usage data processed for
product improvement analytics.
Valid:
☐ I accept the Terms of Service and Privacy Policy [required to use service]
[Optional — you can use the service without these:]
☐ I would like to receive product news and offers by email
☐ I agree to usage analytics to help improve the product
The distinguishability requirement means:
- Separate checkboxes for each purpose (Art.6 granularity requirement reinforced)
- Consent requests visually and structurally separated from mandatory T&C acceptance
- Pre-ticked boxes are invalid (Recital 32, Planet49 C-673/17)
- The consent checkbox must be unchecked by default
"Intelligible and Easily Accessible" — Plain Language Obligation
Art.7(2) uses the same "intelligible" standard as Art.13-14 (transparency). The EDPB Guidelines 05/2020 require:
- Plain language: No legal or technical jargon. "We will send you emails about offers" not "We will conduct direct marketing operations for commercial purposes."
- Easily accessible: Not buried in a linked page that requires five clicks to find
- Named purposes: Generic language like "we may use your data" is insufficient — state specifically what the data will be used for
- Named partners: If consent covers data sharing with third parties, name them or at least describe the category and number
Art.7(3) — Withdrawal: Same Ease as Giving Consent
The Legal Standard
Art.7(3) contains three binding requirements:
- Right to withdraw: The data subject has the right to withdraw consent at any time
- Prior information obligation: The data subject must be informed before giving consent that they have the right to withdraw (Art.13(2)(c))
- Equivalence principle: Withdrawing consent must be as easy as giving it
Recital 42 adds: "Consent should not be regarded as freely given if the data subject has no genuine choice or is unable to refuse or withdraw consent without detriment."
The Equivalence Principle in Practice
This is where most SaaS products fail. The equivalence test is symmetrical: if consent was given by ticking a checkbox on a signup form, withdrawal must be achievable by ticking (or unticking) an equivalent checkbox in an account settings page — not by:
- Sending an email to a support address
- Filling out a web form that requires you to describe the processing
- Waiting for a 30-day manual review
- Deleting your account (which may be the only available option)
The EDPB 05/2020 test for equivalence:
"If the data subject is required to send a letter or an e-mail in order to withdraw consent, while the consent itself was given by the click of a button, the ease requirements of Art.7(3) are not fulfilled."
Implementing Withdrawal Mechanics
Minimum implementation for a SaaS product with consent-based processing:
class ConsentWithdrawalFlow:
"""
Art.7(3)-compliant withdrawal must match the mechanism used for consent.
"""
WITHDRAWAL_PATHS = {
"checkbox_signup": "account_settings_toggle", # Checkbox → toggle in settings
"oauth_scope": "oauth_revoke_endpoint", # OAuth grant → token revocation
"signed_form": "settings_toggle_or_written_request", # Signed form → toggle or email OK
"api_key_scope": "api_settings_scope_update", # API consent → API settings
}
def validate_withdrawal_mechanism(
self, consent_mechanism: str, withdrawal_mechanism: str
) -> bool:
required = self.WITHDRAWAL_PATHS.get(consent_mechanism)
if required is None:
raise ValueError(f"Unknown consent mechanism: {consent_mechanism}")
return withdrawal_mechanism == required
Key implementation points:
- Account settings must have a clearly labeled section for consent-based processing
- The toggle or withdrawal link must be findable in under 3 clicks from the product dashboard
- After withdrawal, processing based on that consent must stop — but processing already performed before withdrawal remains lawful (Art.7(3) sentence 2)
- Send a withdrawal confirmation to the user
Effect of Withdrawal
Art.7(3) sentence 2: "The withdrawal of consent shall not affect the lawfulness of processing based on consent before its withdrawal."
This means:
- Past processing under valid consent remains lawful even after withdrawal
- Future processing from the withdrawal moment onward is unlawful
- If you relied on consent for both collection and ongoing use, you must stop both
- If you have derived data or trained models on the data, the EDPB position is that you may not continue using outputs derived from unlawfully processed data after withdrawal
What you cannot do after withdrawal:
- Continue sending marketing emails
- Continue tracking page views for analytics
- Continue sharing data with partners
- Retain data beyond the withdrawal date (unless another lawful basis applies — e.g., Art.6(1)(c) for billing records)
Art.7(4) — Bundling Prohibition: Consent as Service Gating
The Legal Standard
Art.7(4): "When assessing whether consent is freely given, utmost account shall be taken of whether, inter alia, the performance of a contract, including the provision of a service, is conditional on consent to the processing of personal data that is not necessary for the performance of that contract."
The EDPB clarifies in Guidelines 05/2020 that this creates a rebuttable presumption: if consent is a condition of service access, the consent is presumed to not have been freely given. The controller bears the burden of rebutting this presumption, which is extremely difficult in practice.
The Necessity Test
The critical question is whether the processing is "necessary for the performance of that contract." This is the same necessity test as Art.6(1)(b) — and if processing is truly necessary for the contract, Art.6(1)(b) is the correct basis, not consent.
Practical consequence: If you find yourself using consent for processing that you believe is necessary to provide your service, you have likely either:
- Misidentified the lawful basis (should be Art.6(1)(b)), or
- Expanded the service scope to include processing that is actually optional
| Processing Type | Bundling Permissible? | Correct Basis |
|---|---|---|
| Account creation data (name, email) | N/A — necessary for contract | Art.6(1)(b) |
| Service delivery data (usage logs for billing) | N/A — necessary for contract | Art.6(1)(b) |
| Marketing emails | No — cannot gate service | Art.6(1)(a) with separate opt-in |
| Third-party advertising analytics | No — cannot gate service | Art.6(1)(a) with separate opt-in |
| Product improvement analytics | No — cannot gate service | Art.6(1)(a) or Art.6(1)(f) LIA |
| Crash reporting / core error logs | Arguable — necessary for service quality | Art.6(1)(b) or Art.6(1)(f) |
Cookie Walls and Consent Walls
The EDPB's July 2023 Guidelines 05/2023 on the use of consent in the context of cookie banners (re-affirming earlier positions) state clearly that "cookie walls" — making website access conditional on consent to analytics or advertising cookies — are generally invalid under Art.7(4).
The relevant test: if the user cannot access your product or service at all without accepting processing that is not strictly necessary, the consent is presumed involuntary. A "pay or consent" model (paywall alternative to analytics consent) may be permissible in limited circumstances but must meet a strict proportionality test (Meta EU DPA taskforce 2023 decision).
EDPB Guidelines 05/2020 on Consent — Key Developer Takeaways
The EDPB Guidelines 05/2020 on Consent (updated 2020-05-04, adopted 2020-05-04, replacing WP259) are the authoritative interpretation. The most operationally important points for developers:
Granularity Requirement
"As a rule, a single consent request covering multiple purposes will not satisfy the requirement of being specific."
One checkbox per processing purpose. If you have four types of optional processing (marketing, analytics, third-party sharing, profiling), you need four separate consent requests, each independently withdrawable.
Dynamic Consent for Evolving Processing
"Consent is not always 'given once for all'. This means that in cases where further processing has changed significantly from what the data subject originally consented to, new consent will be required."
Practically: if you add a new analytics partner, a new marketing channel, or a new purpose that the original consent text did not specifically cover, you must obtain fresh consent. A "we may update how we use your data" clause does not satisfy this requirement.
Re-Consent Requirements
When must you re-obtain consent?
- The controller's identity changes (acquisition, merger)
- Processing purposes change or expand
- The categories of data processed change
- The third parties data is shared with change materially
- The consent text version changes significantly
Consent Fatigue and Compliance
The EDPB acknowledges that requiring separate consent for many purposes can lead to "consent fatigue" and form abandonment. Their guidance: prefer Art.6(1)(f) Legitimate Interests with a LIA (Legitimate Interests Assessment) for analytics that users would reasonably expect, and reserve consent for processing that would genuinely surprise users or that requires their active choice.
Art.8 — Children's Consent
Art.8 sets a specific framework for online services offered "directly" to children. Key provisions:
| Art.8 Element | Requirement |
|---|---|
| Age threshold | Processing lawful for children 16+ with their own consent. Member States may lower to minimum 13. |
| Parental consent | For under-16 (or lower threshold), consent of parent/guardian required |
| Age verification | "Reasonable efforts" to verify parental authorisation — not a nominal declaration |
| No excessive data collection | Age verification must not collect more data than necessary |
Member State Implementations of Art.8
| Country | Minimum Age | Notes |
|---|---|---|
| Germany | 16 | Full Art.8 default |
| France | 15 | Age digitale 2023 law |
| Netherlands | 16 | — |
| Ireland | 16 | — |
| UK (post-Brexit) | 13 | UK GDPR Art.8 + Age Appropriate Design Code |
| Spain | 14 | — |
| Austria | 14 | DSG §4 |
| Poland | 16 | UODO guidance |
Developer Implications for Art.8
If your service could be used by under-16s (social platform, educational tool, gaming, creative apps):
- Implement age gate at signup
- For users below the Member State threshold: require parental email + confirmation flow
- Document your age verification mechanism in your DPIA (Art.35)
- Store age verification evidence with the same Art.7(1) proof standard as consent records
- The UK Age Appropriate Design Code (Children's Code) adds 15 standards for services "likely to be accessed" by children — relevant for any consumer-facing service
Key CJEU Case Law on Art.7 Conditions
Planet49 (C-673/17, 2019) — Pre-Ticked Boxes Invalid
Facts: Planet49 ran a promotional lottery where participation required ticking two checkboxes. The first (unticked by default) covered prize partner data sharing. The second was pre-ticked and covered statistical cookies and access by advertising partners.
Ruling: Pre-ticked checkboxes do not constitute valid consent under GDPR/ePrivacy Directive. The court held that:
- The silence resulting from a pre-ticked box cannot constitute an "unambiguous indication" (Art.4(11))
- The controller could not demonstrate consent under Art.7(1) — no affirmative act by the user
- The bundling of lottery participation with cookie consent raised Art.7(4) concerns
Art.7 relevance: Planet49 is the definitive ruling on Art.7(1) proof burden — you cannot satisfy the demonstration requirement with silence or inaction.
Orange România (C-61/19, 2020) — Burden Shifts to Controller
Facts: Orange România's mobile contracts included a pre-ticked box consenting to copying customers' identity documents. The Romanian DPA fined Orange for invalid consent.
Ruling:
- A pre-ticked box does not meet the "unambiguous indication" standard
- When processing is alleged to be based on consent, the controller must prove the data subject gave consent — the burden does not lie with the data subject to prove they did not
- The requirement under Art.7(1) to "demonstrate" consent means the controller must provide positive evidence
Art.7 relevance: Directly establishes the Art.7(1) proof burden as controller-side. In any enforcement proceeding, the DPA will ask: show us the consent record. If you cannot, the basis fails.
Fashion ID (C-40/17, 2019) — Joint Controllership and Consent at Collection Point
Facts: Fashion ID embedded a Facebook "Like" button that transmitted visitor data to Facebook before any interaction. A consumer protection association challenged this.
Ruling: Fashion ID was a joint controller with Facebook for the collection and transmission phase. For joint controllers, consent must be obtained for the joint processing — each joint controller bears responsibilities under Art.7.
Art.7 relevance: If you embed third-party trackers (analytics, social widgets, advertising pixels), you may be a joint controller and must ensure consent is obtained before the first data transmission — not after page load.
Schrems II (C-311/18, 2020) — Consent Cannot Legitimise Structural Surveillance
Facts: Data Transfer from EU to US via Standard Contractual Clauses challenged after US CLOUD Act/FISA 702 surveillance programs.
Ruling: Standard Contractual Clauses remain valid but cannot substitute for adequate protection where US intelligence access creates systemic risk. Explicit consent under Art.49(1)(a) as a derogation for transfers is possible but must be "explicit, specific, and informed" — Art.7 conditions apply.
Art.7 relevance: For international transfers relying on Art.49(1)(a) consent as derogation, the Art.7 conditions apply with full force: users must be specifically informed of the surveillance risk, consent must be explicit, and it cannot be obtained as a standard click-through.
Python ConsentValidator — Full Implementation
import hashlib
import json
from datetime import datetime, timezone
from dataclasses import dataclass, field
from typing import Optional
from enum import Enum
class ConsentMechanism(Enum):
CHECKBOX_OPT_IN = "checkbox_opt_in"
OAUTH_SCOPE = "oauth_scope"
API_KEY_ACCEPTANCE = "api_key_acceptance"
SIGNED_FORM = "signed_form"
VERBAL_RECORDED = "verbal_recorded"
class ConsentPurpose(Enum):
MARKETING_EMAIL = "marketing_email"
ANALYTICS = "analytics"
THIRD_PARTY_SHARING = "third_party_sharing"
PROFILING = "profiling"
CHILDREN_PARENTAL = "children_parental"
@dataclass
class ConsentRecord:
user_id: str
purpose: ConsentPurpose
mechanism: ConsentMechanism
consent_text: str
timestamp_utc: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
ip_address: Optional[str] = None
user_agent: Optional[str] = None
withdrawal_timestamp_utc: Optional[datetime] = None
withdrawal_mechanism: Optional[str] = None
@property
def consent_text_hash(self) -> str:
return hashlib.sha256(self.consent_text.encode()).hexdigest()[:16]
@property
def is_active(self) -> bool:
return self.withdrawal_timestamp_utc is None
class ConsentValidator:
"""
Validates consent records against GDPR Art.7 four conditions.
EDPB Guidelines 05/2020 compliance.
"""
# Art.7(3): Withdrawal must match consent mechanism
EQUIVALENT_WITHDRAWAL = {
ConsentMechanism.CHECKBOX_OPT_IN: "account_settings_toggle",
ConsentMechanism.OAUTH_SCOPE: "oauth_token_revocation",
ConsentMechanism.API_KEY_ACCEPTANCE: "api_settings_scope_update",
ConsentMechanism.SIGNED_FORM: "settings_toggle_or_written_withdrawal",
ConsentMechanism.VERBAL_RECORDED: "written_withdrawal_acceptable",
}
def validate_art7_1_proof_burden(self, record: ConsentRecord) -> dict:
"""Art.7(1): Controller must demonstrate consent."""
issues = []
if not record.user_id:
issues.append("Missing user_id: cannot link consent to data subject")
if not record.timestamp_utc:
issues.append("Missing timestamp: cannot prove when consent was given")
if not record.consent_text:
issues.append("Missing consent_text: cannot prove what was consented to")
if not record.mechanism:
issues.append("Missing mechanism: cannot prove how consent was given")
if not record.ip_address:
issues.append("WARNING: Missing ip_address — reduces proof strength")
return {
"condition": "Art.7(1) Proof Burden",
"valid": len([i for i in issues if not i.startswith("WARNING")]) == 0,
"issues": issues,
"consent_text_hash": record.consent_text_hash,
}
def validate_art7_2_written_clarity(
self, consent_text: str, bundled_with_tos: bool = False
) -> dict:
"""Art.7(2): Written consent must be clearly distinguishable."""
issues = []
if bundled_with_tos:
issues.append(
"Consent bundled with T&C acceptance — must be clearly distinguishable "
"(Art.7(2)). Use separate checkbox."
)
# Check for vague language markers
vague_phrases = [
"we may use your data",
"your information may be processed",
"data processing activities",
"various purposes",
]
for phrase in vague_phrases:
if phrase.lower() in consent_text.lower():
issues.append(
f"Vague language detected: '{phrase}' — specify exact purpose "
"per EDPB 05/2020 plain language requirement"
)
# Minimum length check (trivially short text likely non-specific)
if len(consent_text) < 30:
issues.append(
"Consent text too brief — must be specific enough to satisfy "
"Art.4(11) 'informed' requirement"
)
return {
"condition": "Art.7(2) Written Clarity",
"valid": len(issues) == 0,
"issues": issues,
}
def validate_art7_3_withdrawal(
self,
consent_mechanism: ConsentMechanism,
withdrawal_mechanism_available: str,
) -> dict:
"""Art.7(3): Withdrawal must be as easy as giving consent."""
required = self.EQUIVALENT_WITHDRAWAL.get(consent_mechanism)
issues = []
INVALID_WITHDRAWAL_MECHANISMS = [
"support_ticket",
"email_to_support",
"postal_letter",
"account_deletion_only",
"30_day_review_queue",
]
if withdrawal_mechanism_available in INVALID_WITHDRAWAL_MECHANISMS:
issues.append(
f"Withdrawal mechanism '{withdrawal_mechanism_available}' is harder "
f"than consent mechanism '{consent_mechanism.value}'. "
"Art.7(3) requires equivalent ease. EDPB 05/2020: email withdrawal "
"not equivalent to checkbox consent."
)
if required and withdrawal_mechanism_available != required:
issues.append(
f"Preferred equivalent withdrawal for '{consent_mechanism.value}' "
f"is '{required}'. Current: '{withdrawal_mechanism_available}'."
)
return {
"condition": "Art.7(3) Withdrawal Equivalence",
"valid": len(issues) == 0,
"required_withdrawal": required,
"issues": issues,
}
def validate_art7_4_bundling(
self,
processing_necessary_for_contract: bool,
consent_gates_service_access: bool,
) -> dict:
"""Art.7(4): Consent cannot gate access to processing not necessary for contract."""
issues = []
if consent_gates_service_access and not processing_necessary_for_contract:
issues.append(
"Consent gates service access for processing not necessary for the contract "
"(Art.7(4)). Presumption of non-free consent. Use Art.6(1)(b) if truly "
"necessary, or make the processing optional."
)
if not processing_necessary_for_contract and not consent_gates_service_access:
# This is the correct pattern: optional processing with optional consent
pass
return {
"condition": "Art.7(4) Bundling Prohibition",
"valid": len(issues) == 0,
"issues": issues,
}
def full_validation(
self,
record: ConsentRecord,
bundled_with_tos: bool = False,
withdrawal_mechanism: str = "account_settings_toggle",
processing_necessary: bool = False,
consent_gates_service: bool = False,
) -> dict:
"""Run all four Art.7 condition checks."""
results = [
self.validate_art7_1_proof_burden(record),
self.validate_art7_2_written_clarity(record.consent_text, bundled_with_tos),
self.validate_art7_3_withdrawal(record.mechanism, withdrawal_mechanism),
self.validate_art7_4_bundling(processing_necessary, consent_gates_service),
]
all_valid = all(r["valid"] for r in results)
total_issues = sum(len(r["issues"]) for r in results)
return {
"overall_valid": all_valid,
"total_issues": total_issues,
"conditions": results,
}
# Usage examples
if __name__ == "__main__":
validator = ConsentValidator()
# Example 1: Valid SaaS marketing consent
valid_record = ConsentRecord(
user_id="usr_abc123",
purpose=ConsentPurpose.MARKETING_EMAIL,
mechanism=ConsentMechanism.CHECKBOX_OPT_IN,
consent_text=(
"I would like to receive product updates, offers, and news from sota.io "
"by email. I can withdraw this consent at any time in my account settings."
),
ip_address="203.0.113.42",
)
result = validator.full_validation(
record=valid_record,
bundled_with_tos=False,
withdrawal_mechanism="account_settings_toggle",
processing_necessary=False,
consent_gates_service=False,
)
print("Example 1 (valid marketing consent):")
print(f" Valid: {result['overall_valid']}, Issues: {result['total_issues']}")
# Example 2: Cookie wall — invalid bundling
analytics_record = ConsentRecord(
user_id="usr_def456",
purpose=ConsentPurpose.ANALYTICS,
mechanism=ConsentMechanism.CHECKBOX_OPT_IN,
consent_text="Accept analytics to use the dashboard.",
ip_address="203.0.113.43",
)
result2 = validator.full_validation(
record=analytics_record,
bundled_with_tos=False,
withdrawal_mechanism="support_ticket", # Art.7(3) violation
processing_necessary=False,
consent_gates_service=True, # Art.7(4) violation
)
print("\nExample 2 (cookie wall + support ticket withdrawal):")
print(f" Valid: {result2['overall_valid']}, Issues: {result2['total_issues']}")
for condition in result2["conditions"]:
if condition["issues"]:
print(f" {condition['condition']}: {condition['issues']}")
# Example 3: Pre-ticked checkbox (Planet49 pattern)
# Note: This is detected at the UI layer — consent record would never be created
# because no affirmative action occurred. Document the non-creation.
print("\nExample 3 (Planet49 pre-ticked — no record created):")
print(" Pre-ticked consent does not create a valid record. Art.7(1): cannot")
print(" demonstrate 'unambiguous indication' from pre-ticked state (Recital 32).")
Art.7 and International Data Transfers
When using Art.49(1)(a) explicit consent as the derogation mechanism for transfers to third countries lacking adequacy decisions (Art.45) or appropriate safeguards (Art.46), the Art.7 conditions apply in their strictest form:
- Consent must be explicit (not just unambiguous — a higher standard requiring a clear affirmative statement for the specific transfer risk)
- The data subject must be specifically informed of the risks of the transfer — including that the destination country may lack equivalent protection
- Consent under Art.49(1)(a) cannot be obtained as a standard checkbox at signup — it must be obtained at the time of the specific transfer decision
- Art.49(1)(a) consent is explicitly described in Recital 113 as an occasional mechanism, not a structural solution for regular systematic transfers
Practical implication: For SaaS companies hosting in the EU and serving EU users, avoid relying on Art.49(1)(a) consent for routine US-EU data flows. Use SCCs (Art.46) or adequacy decisions instead. If EU data must flow to a US service, the CLOUD Act risk assessment is required regardless of the transfer mechanism (Schrems II).
Art.7 Compliance Checklist for Developers
Art.7(1) — Proof Burden
☐ Consent log records: user_id, timestamp, consent_text, mechanism, IP
☐ Consent text version/hash stored with each record
☐ Retention policy: processing period + 3 years
☐ Withdrawal records retained (not deleted)
☐ Proof records included in ROPA (Art.30) documentation
Art.7(2) — Written Clarity
☐ Consent separate from T&C checkbox (visually and structurally)
☐ One checkbox per purpose (granularity)
☐ Plain language — no legal jargon
☐ No pre-ticked boxes
☐ Specific purpose named (not "data processing activities")
Art.7(3) — Withdrawal
☐ Withdrawal toggle/button available in account settings
☐ Withdrawal mechanism ≤ 3 clicks from product dashboard
☐ No support ticket required for withdrawal
☐ Withdrawal confirmation sent to user
☐ Processing stops immediately on withdrawal
☐ Withdrawal right communicated at consent-time (Art.13(2)(c))
Art.7(4) — No Bundling
☐ Marketing/analytics consent NOT required to access core service
☐ No cookie wall gating content access on consent
☐ Optional processing clearly labeled as optional
☐ Service fully functional without optional consents
☐ If processing is necessary → use Art.6(1)(b) not consent
Art.8 — Children (if applicable)
☐ Age gate at signup for services likely used by under-16s
☐ Parental consent flow for below-threshold users
☐ Age verification mechanism documented in DPIA
☐ Member State threshold checked (13–16 depending on country)
☐ UK Age Appropriate Design Code standards reviewed (if UK users)
Records and Documentation
☐ Consent database schema reviewed against Art.7(1) five elements
☐ Consent text versioning system in place
☐ Re-consent workflow built for when purposes change
☐ DPIA includes consent mechanism assessment (if high-risk, Art.35)
What Comes Next in the GDPR Series
Art.7 defines how consent is obtained and managed. The downstream articles build on this foundation:
- Art.8 — Children's consent (already covered in this guide as it directly modifies Art.7)
- Art.12-14 Transparency — The information that must be provided before consent is obtained
- Art.17 — Right to erasure: what happens to data when consent is withdrawn and no other basis applies
- Art.21 — Right to object: the analogue for Legitimate Interests processing
The GDPR Chapter I series continues with the data subject rights chapters. See the full series index at gdpr-compliance-developer-guide-sota-io.
Art.7 is where consent either works or collapses. The conditions are not suggestions — they are the mechanism by which GDPR transforms "we asked" into "we have lawful processing." Missing any single condition means the entire consent basis fails. Host with sota.io to keep all data processing within EU jurisdiction under a single lawful basis from day one.