{
  "schemaVersion": "1.0",
  "corpus": "methodology",
  "title": "ConsentMark methodology v7.8",
  "version": "v7.8",
  "canonicalUrl": "https://www.consentmark.com/methodology/v7.8.json",
  "humanUrl": "https://www.consentmark.com/methodology/v7.8",
  "publisher": {
    "name": "Obscurity Ltd",
    "cro": "622475",
    "jurisdiction": "Ireland",
    "url": "https://obscurity.ie"
  },
  "licence": {
    "name": "ConsentMark corpus compilation licence 1.0",
    "summary": "You may quote, cite and redistribute this corpus, in whole or in part, for any purpose, provided you attribute it to Obscurity Ltd and cite the canonical URL and the asOf date. You may not re-characterise it: presenting a value, a grade band, a gate or a consent state as saying something this corpus does not say, or presenting a derived work as the published corpus, is outside these terms.",
    "attributionRequired": true,
    "derivativeReCharacterisation": "not permitted"
  },
  "citeAs": "ConsentMark. (2026, September 6). ConsentMark methodology v7.8. Obscurity Ltd (CRO 622475). https://www.consentmark.com/methodology/v7.8",
  "asOf": "2026-09-06",
  "generatedAt": "2026-09-07T09:38:36.812Z",
  "frozenAtPublication": "Frozen at publication. This corpus is the record as it stood on its asOf date. Corrections are published as new dated versions at their own URL, and nothing here is edited in place.",
  "engineVersion": "7.8",
  "scoring": {
    "dimensions": [
      {
        "key": "consent",
        "name": "Technical Consent Controls",
        "weightFull": 0.4,
        "weightFree": 0.5
      },
      {
        "key": "jurisdiction",
        "name": "Cross-Border Data Transfers",
        "weightFull": 0.2,
        "weightFree": null
      },
      {
        "key": "cookieStorage",
        "name": "Pre-Consent Data Leakage",
        "weightFull": 0.15,
        "weightFree": 0.2
      },
      {
        "key": "tagManagement",
        "name": "Governance Controls",
        "weightFull": 0.15,
        "weightFree": 0.15
      },
      {
        "key": "thirdPartyVolume",
        "name": "Third-Party Exposure",
        "weightFull": 0.1,
        "weightFree": 0.15
      }
    ],
    "weightSets": {
      "full": {
        "consent": 0.4,
        "jurisdiction": 0.2,
        "cookieStorage": 0.15,
        "tagManagement": 0.15,
        "thirdPartyVolume": 0.1
      },
      "free": {
        "consent": 0.5,
        "cookieStorage": 0.2,
        "tagManagement": 0.15,
        "thirdPartyVolume": 0.15
      }
    },
    "gradeBandMidpoints": {
      "A": 95,
      "B": 85,
      "C": 72,
      "D": 52,
      "F": 22,
      "I": 0
    }
  },
  "gates": [
    {
      "code": "F1",
      "band": "F",
      "gradeCeiling": "F",
      "label": "Personal data found in tracking requests"
    },
    {
      "code": "F2",
      "band": "F",
      "gradeCeiling": "F",
      "label": "Tracking active with no consent controls"
    },
    {
      "code": "F3",
      "band": "F",
      "gradeCeiling": "F",
      "label": "Data collection starts before consent"
    },
    {
      "code": "F4",
      "band": "F",
      "gradeCeiling": "F",
      "label": "Tracking fires on a fresh page load after consent was rejected, or cookies persist"
    },
    {
      "code": "F5",
      "band": "F",
      "gradeCeiling": "F",
      "label": "Consent signals are contradicting each other"
    },
    {
      "code": "D1",
      "band": "D",
      "gradeCeiling": "D",
      "label": "Consent platform not blocking all tracking"
    },
    {
      "code": "D2",
      "band": "D",
      "gradeCeiling": "D",
      "label": "Post-reject tracking continues, but Consent Mode v2 downgrades the signal"
    },
    {
      "code": "D3",
      "band": "D",
      "gradeCeiling": "D",
      "label": "Consent banner did not render - visitor had no opportunity to consent"
    },
    {
      "code": "D4",
      "band": "D",
      "gradeCeiling": "D",
      "label": "Tracking was still sent to this vendor after the visit was rejected. The requests carry markers showing they continued an activity already under way before the rejection, rather than new collection started after it. This is recorded as a failure. The vendor was running before any consent decision was made - see the pre-consent finding above."
    },
    {
      "code": "C1",
      "band": "C",
      "gradeCeiling": "C",
      "label": "Rejecting consent is harder than accepting it"
    },
    {
      "code": "C2",
      "band": "C",
      "gradeCeiling": "C",
      "label": "Data sent outside EU/UK/DPF-adequate jurisdictions without safeguards visible to an external scan"
    },
    {
      "code": "C3",
      "band": "C",
      "gradeCeiling": "C",
      "label": "Vendor consent signal contradicts user rejection"
    },
    {
      "code": "B1",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Some tracking before consent, but in restricted mode"
    },
    {
      "code": "B2",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Tag manager fires before consent, but tracking is gated"
    },
    {
      "code": "B3",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Self-managing consent tool active before consent platform"
    },
    {
      "code": "B4",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Non-tracking widgets load pre-consent"
    },
    {
      "code": "B5",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Google-hosted fonts loaded before consent (third-party data transfer)"
    },
    {
      "code": "B6",
      "band": "B",
      "gradeCeiling": "B",
      "label": "Collection call before consent to a first-party endpoint"
    }
  ],
  "crossBorderTransfers": {
    "adequateJurisdictions": [
      "EU",
      "UK"
    ],
    "effectiveSafeRatioWeights": {
      "usDpfAdequacy": 0.7,
      "euHostedProcessorWithContractualSafeguards": 0.9,
      "contractualSafeguardOnly": 0.5,
      "unknownJurisdiction": 0.25
    },
    "note": "Each weight is the fraction of a destination counted as safe when computing the effective safe ratio. A destination in an adequate jurisdiction counts in full; one with no jurisdiction on record counts a quarter, because unknown sits closer to unsafe than to safe."
  },
  "consentStates": [
    {
      "token": "pre",
      "label": "No choice recorded",
      "meaning": "The page loaded and the banner was never touched. No decision has been recorded. This is the state a first-time visitor is in for as long as they read the page.",
      "howReached": "Load the URL and do nothing.",
      "reachability": "Measurable on any surface, including one whose consent platform the harness cannot drive. It is the pre-consent state by construction."
    },
    {
      "token": "none",
      "label": "Consent refused",
      "meaning": "Every optional category rejected through the banner, and the rejection recorded by the consent platform. A recorded rejection is an explicit denial, which is a different state from an untouched banner and often produces different behaviour.",
      "howReached": "Load, then decline all.",
      "reachability": "Only where the consent platform can be driven."
    },
    {
      "token": "all",
      "label": "Consent granted",
      "meaning": "Every category accepted and recorded.",
      "howReached": "Load, then accept all.",
      "reachability": "Only where the consent platform can be driven."
    },
    {
      "token": "performance",
      "label": "Performance granted",
      "meaning": "Performance and analytics accepted, advertising rejected.",
      "howReached": "Granular banner interaction.",
      "reachability": "OneTrust and CookieYes today. Refused elsewhere rather than approximated."
    },
    {
      "token": "targeting",
      "label": "Targeting granted",
      "meaning": "Advertising accepted, performance rejected.",
      "howReached": "Granular banner interaction.",
      "reachability": "OneTrust and CookieYes today. Refused elsewhere rather than approximated."
    }
  ],
  "consentExemption": {
    "rule": "A vendor is exempt from the consent gates only when its own registry record satisfies all three conditions below. Two of three is not an exemption.",
    "conditions": [
      {
        "id": "pre-consent-permissible",
        "predicate": "isPreConsentPermissible",
        "requirement": "The vendor's own registry record affirmatively declares that it may load before consent. An unstated declaration reads as false."
      },
      {
        "id": "eprivacy-strictly-necessary",
        "predicate": "isEprivacyStrictlyNecessary",
        "requirement": "The registry classifies the vendor's storage or access as strictly necessary under ePrivacy Art 5(3). This is deliberately not the GDPR Art 6 basis: a vendor can rely on legitimate interest under Art 6 and still require consent on the device."
      },
      {
        "id": "cited-provenance",
        "predicate": "hasCitedPreConsentProvenance",
        "requirement": "The registry holds both an authority for the assertion and the date it was last verified. An exemption carrying neither, or only one, is withheld rather than granted, and is omitted from the exempt set entirely."
      }
    ],
    "absenceRule": "A vendor the registry has never characterised returns false from every condition. Absence is unknown, and unknown never exempts - a coverage gap must not launder a real pre-consent leak into a clean grade.",
    "notPublishedHere": "The per-vendor exemption grants, with the authority and verification date behind each, are held in the registry and are not published in this corpus."
  },
  "advancedConsentMode": {
    "statement": "Google Consent Mode v2 downgrades a signal; it does not stop a tag. A Google tag type in Google Tag Manager showing a consent setting of notSet means the container applies no ADDITIONAL consent checks - it does not mean the tag is ungated. The Google tag types awud, awct, gaawe, googtag and flc carry built-in consent checks of their own. Reading notSet as ungated produces a false finding of the most serious kind. Gate D2 exists precisely because the downgrade is real: tracking that continues after a recorded rejection while Consent Mode v2 downgrades what is sent is graded D rather than F, because something did enforce - and it is not clean, because the request was still made.",
    "gate": "D2"
  },
  "omits": [
    "Per-vendor consent obligations, exemption grants and detection signatures. The registry holds them; this corpus publishes the rule, not the roll.",
    "The corrections log. A correction is published as its own dated version, so a published methodology stays the record it was on its asOf date.",
    "Any assessment outside EU and EEA law. The methodology reads Art 5(3) of the ePrivacy Directive as transposed, and the GDPR. It says nothing about any other regime."
  ]
}
