2026-04-18·17 min read·

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 ScopeArt.5 PrinciplesArt.6 Lawful BasesArt.7 Consent Conditions (this guide).


The Four Art.7 Conditions at a Glance

Art.7ConditionCore RequirementMost Common Failure
Art.7(1)Proof burdenController must be able to demonstrate consent was givenNo consent log: no timestamp, no text version, no mechanism ID
Art.7(2)Written consent clarityConsent requests in writing must be clearly distinguishable from other mattersT&C checkbox also covers marketing consent
Art.7(3)Withdrawal mechanicsData subject can withdraw at any time; withdrawal as easy as giving consentWithdrawal requires support ticket; no in-app toggle
Art.7(4)Bundling prohibitionService 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) 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:

  1. Who gave consent (identity linkable to the data subject)
  2. When consent was given (timestamp)
  3. What was consented to (the exact processing purpose and scope as presented at the time)
  4. How consent was given (the mechanism — checkbox, toggle, signed form, API scope acceptance)
  5. Which version of the consent text was shown (if your privacy notice changes, old consents may not cover new processing)

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."

Art.7(1) records must be retained for as long as the processing continues plus the applicable limitation period for potential enforcement. In practice:

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.


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:

  1. 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.
  2. 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:

"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:


Art.7(3) contains three binding requirements:

  1. Right to withdraw: The data subject has the right to withdraw consent at any time
  2. Prior information obligation: The data subject must be informed before giving consent that they have the right to withdraw (Art.13(2)(c))
  3. 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:

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:

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:

What you cannot do after withdrawal:


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:

  1. Misidentified the lawful basis (should be Art.6(1)(b)), or
  2. Expanded the service scope to include processing that is actually optional
Processing TypeBundling Permissible?Correct Basis
Account creation data (name, email)N/A — necessary for contractArt.6(1)(b)
Service delivery data (usage logs for billing)N/A — necessary for contractArt.6(1)(b)
Marketing emailsNo — cannot gate serviceArt.6(1)(a) with separate opt-in
Third-party advertising analyticsNo — cannot gate serviceArt.6(1)(a) with separate opt-in
Product improvement analyticsNo — cannot gate serviceArt.6(1)(a) or Art.6(1)(f) LIA
Crash reporting / core error logsArguable — necessary for service qualityArt.6(1)(b) or Art.6(1)(f)

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).


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.

"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.

When must you re-obtain consent?

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 sets a specific framework for online services offered "directly" to children. Key provisions:

Art.8 ElementRequirement
Age thresholdProcessing lawful for children 16+ with their own consent. Member States may lower to minimum 13.
Parental consentFor 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 collectionAge verification must not collect more data than necessary

Member State Implementations of Art.8

CountryMinimum AgeNotes
Germany16Full Art.8 default
France15Age digitale 2023 law
Netherlands16
Ireland16
UK (post-Brexit)13UK GDPR Art.8 + Age Appropriate Design Code
Spain14
Austria14DSG §4
Poland16UODO guidance

Developer Implications for Art.8

If your service could be used by under-16s (social platform, educational tool, gaming, creative apps):


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:

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:

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.

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.

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:

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:

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.