SDK docs ›

Debug console (cmpconsole)

DE EN

The debug console is an on-demand diagnostics panel built into cmp.js. On your own page it shows what the CMP is doing right now: which regime was detected, which consent is stored, which scripts, iframes and pixels were blocked or released after consent, which third-party domains are not yet mapped to any vendor, and every event since the page started loading (TCF events, banner, clicks, consent storage, network).

It is meant for site owners, agencies and developers to verify an integration, get tag blocking right and resolve support cases. Visitors never see it unless it is explicitly opened.

Debug console, Elements tab: blocked scripts and iframe before consent
“Elements” tab before consent: consent banner on top, console docked at the bottom, all marked elements are blocked. (The console follows the page language – German here.)

Opening the console

MethodExampleEffect
URL parameterhttps://your-site.com/article?cmpconsole
…?foo=1&cmpconsole
Opens the console and remembers it in this browser (see flag).
Hashhttps://your-site.com/article#cmpconsoleSame as the parameter – handy because a hash does not cause a new request or a different cache key.
Persistent flaglocalStorage.adcmp_console = "1"The console opens on every page of this domain until you close it. Set automatically by the two methods above.
JavaScript APIcmp.console()Opens the console immediately and also sets the flag. Available as soon as cmp.js has loaded – even if the configuration failed to load. Before that, via the queue: cmp.q.push(["console"]).

The parameter also accepts a value, e.g. ?cmpconsole=1. The console is a separate script (/cmp/v1/cmp-console.js) that is only fetched when opened – cmp.js itself barely grows.

Tip: open the console in a private window to see the state before consent. Recording starts the moment cmp.js runs, so events that happened before you opened the console are included.

Closing and disabling

  • ✕ (top right) closes the console and removes the adcmp_console flag – it is gone on the next page view.
  • cmp.console(false) (or cmp.console("close")) – the same from JavaScript.
  • ?cmpconsole=0 or #cmpconsole=off – does not open it and clears the flag (useful in a link for colleagues).
  • localStorage.removeItem("adcmp_console") – manually.
  • — minimises the console to a small pill with counters (stays active), ⬆/⬇ docks it at the top or bottom. Drag the top edge to resize; height and position are remembered.

Layout

Header: cmp.js and console versions, count badges (click to filter the element list), Copy JSON, dock, minimise, close. Below: five tabs and a search box that filters every tab (domain, URL, vendor, log text …). While open, the console reserves space at the bottom (or top) so the consent banner and the “privacy settings” button stay usable. On phones, tables are shown as cards.

BadgeMeaning
blockedHeld back by the CMP (no consent for the vendor/purpose).
activatedWas blocked and has been released after consent (with timestamp).
allowedMapped to a vendor that already had consent – loaded immediately.
leaksMapped to a vendor without consent but loaded anyway (e.g. included before the CMP, or an <img> pixel). Should be 0.
unknownThird-party element whose domain matches no vendor – not blocked.

“Status” tab

  • CMP: SDK version, CMP ID, CMP version, whether __tcfapi, the __tcfapiLocator frame and __gpp exist, cmpStatus/displayStatus from ping, TCF policy and GVL version, whether the CMP is ready and whether the banner is visible.
  • Property / configuration: property key, API base, config version and publish time, page, publisher country, number of GVL vendors / custom vendors / purposes.
  • Regime & region: detected regime (tcf_eu GDPR, tcf_uk, ch, gpp_us US opt-out, notice_only, none), detected country, enabled regimes, language, gdprApplies and whether the browser sends GPC (Global Privacy Control).
  • Timings (ms since navigation start): DOMContentLoaded, cmp.js loaded, config.json loaded, CMP ready, banner shown, consent saved, load event.
  • Blocker: whether the auto-block hooks are active, counters and any dropped old entries (buffer: 500 events / 600 elements).
  • Google Consent Mode v2: every signal (ad_storage, ad_user_data, ad_personalization, analytics_storage …) with its default and latest update value from the dataLayer, plus the call order.
  • Decision: none yet / accepted all / partial / declined, timestamp, consent ID (for records and support) and maximum validity.
  • Purposes (IAB TCF 1–11) with consent and legitimate interest, special features (precise geolocation, device scanning), GVL vendors with consent, legitimate interest and purposes, custom vendors with domains, purposes and opt-in.
  • TC string raw and decoded (version, created/updated, CMP ID, consent screen, language, GVL/policy version, publisher country, consented purposes and vendors) – directly comparable with tools such as the IAB TC string decoder.
  • GPP string (US regime only).

“Elements” tab

Every third-party script, iframe, image and stylesheet the CMP has seen. Filter chips (All / Blocked / Activated / Allowed / Leaks / Unknown) and the search box narrow the list.

ColumnMeaning
TimeWhen the CMP first saw the element (ms since navigation start).
Typescript, iframe, img, link.
DomainHost of the source; inline for inline scripts without src.
SourceFull URL (src, data-cmp-src or href).
VendorMatched vendor: IAB vendor with name and GVL ID (from data-cmp-vendor or domain mapping) or custom vendor (from data-cmp-custom or its domains).
PurposesFrom data-cmp-purposes, if set.
Method manual (markup) – marked by the site owner: type="text/plain" with data-cmp-vendor/data-cmp-custom/data-cmp-purposes, or <iframe data-cmp-src>. The most reliable method.
auto-block (hook) – inserted dynamically via JavaScript (appendChild/insertBefore) and intercepted automatically by domain, without markup changes.
observer (bypassed hook) – inserted via innerHTML/the parser and only seen by the MutationObserver after insertion; for scripts the request may already have started.
in DOM before CMP – present in the HTML before cmp.js or already loaded when the CMP started; cannot be stopped any more.
Stateblocked, activated @ 4265 ms (release time), allowed, not blocked or unknown. Below it the reason, e.g. vendor:755, custom:youtube, purposes:8, host:hotjar. Warning “not configured in property – stays blocked”: see troubleshooting.
Debug console after accept all: all elements activated with timestamp
After “accept all”: the marked elements are activated (with release time). Hotjar stays blocked because the vendor is not configured in the property; three scripts/pixels inserted by a tag manager are unknown.

“Domains” tab

Aggregates elements and all resources actually loaded (Resource Timing – including requests that scripts fire themselves via fetch/XHR/pixels) per domain. Your own domain and the CMP domain are hidden.

  • Unmatched domains (top): third-party domains that match no vendor and are therefore not blocked. Copy list gives you all hosts, one per line.
  • Mapped domains: with vendor, consent state, number of elements and requests, time of first request and initiator (script, img, iframe, fetch …). The note “requested before/without consent” flags vendors whose domain was requested without consent or before consent was given.
Debug console, Domains tab with unmatched domains
“Domains” tab: unmatched hosts are listed first and can be copied as a list.

Adding an unknown domain as a custom vendor

  1. In the admin, open Custom Vendors → New (“Neu”).
  2. Enter a key (e.g. hotjar), name and privacy policy URL, paste the copied hosts into Domains (one per line; example.com also covers subdomains such as cdn.example.com), add cookie names/patterns and purposes (functional, statistics, marketing or IAB IDs), choose the legal basis and click Anlegen (create).
  3. In the property under Settings → “Custom Vendors dieser Property” (custom vendors of this property), tick the vendor and save.
  4. Reload the page with ?cmpconsole in a private window (the public config is cached for up to 2 minutes): the elements now show as blocked with method auto-block (hook), and the vendor is listed in the banner.

IAB vendors don't need a custom vendor: mark the tag with data-cmp-vendor="GVL-ID" and add the vendor to the property's vendor selection.

“Log” tab

Chronological log from the moment cmp.js loaded, with relative time (ms) and clock time. Filter categories with the chips; details (JSON) are shown below each message.

CategoryExamples
bootcmp.js loaded (with document.readyState)
consoleconsole is being loaded
netconfig.json GET, config.json → 200 (313 ms), regime tcf_eu, lang de, v1, consent log POST → 201 (85 ms)
meteringthe page view is counted server-side when config.json is loaded (basis for billing; bots/prefetch excluded)
gcmGoogle Consent Mode consent default / consent update with all signals
tcfTC string update with eventStatus: tcloaded, cmpuishown, useractioncomplete
tcfapicalls from other scripts to __tcfapi (e.g. addEventListener, getTCData, ping) – shows which ad tags query the CMP
gpp__gpp installed, GPC detected, US opt-out set/cleared
consentbanner required: no stored consent (or new config version, expired …), stored consent valid → no banner, consent saved: 11 purposes, 5 vendors, 2 custom
readyCMP ready
uibanner shown (layer 1/2) / hidden, clicks on accept, reject, settings, save selection
actionAPI calls cmp.consentAll(), cmp.declineAll(), cmp.show()
block / unblock / elementelement blocked / activated after consent / allowed, unknown or not blocked
cookiescookies of declined vendors deleted (patterns)
errorconfig errors, missing property key, failed consent log, console could not load
Debug console, Log tab
“Log” tab with category filters.

Copy JSON

Copy JSON puts a complete snapshot on the clipboard: page, SDK version, property, regime, country, language, consent state including TC and GPP strings, counters, all elements and all events with absolute timestamps. Ideal for support requests – just send it to support. __adcmpConsole.snapshot() in the browser console returns the same snapshot.

Troubleshooting

A script loads before consent

  • State not blocked with method in DOM before CMP: the tag sits in the HTML before cmp.js. Include stub.js/cmp.js first in <head>, or mark the tag manually (type="text/plain" + data-cmp-vendor/data-cmp-custom).
  • Method observer (bypassed hook): the tag was inserted via innerHTML or document.write. Switch to manual markup.
  • Type img: pixel requests start as soon as src is assigned. Create the pixel from a blocked <script type="text/plain" data-cmp-vendor="…">.
  • State unknown: the domain is not mapped to any vendor – see next section.
  • “requested before/without consent” in the Domains tab but no element in the list: the request was fired by another (allowed or unknown) script itself, e.g. via fetch. Block the originating script (the Initiator column gives a hint).

A script stays blocked despite consent

  • Warning “not configured in property – stays blocked”: the domain is on the built-in tracker list (e.g. Hotjar, YouTube, Google Maps) but the vendor is not part of your property, so visitors cannot consent to it. Create it as a custom vendor or tick it in the property settings (how to) – it then appears in the banner and is released after consent.
  • Reason purposes:…: consent is missing for at least one purpose listed in data-cmp-purposes.
  • Check the Consent tab to see whether the vendor really has consent (e.g. only partially accepted).

A domain shows as unknown

  • It matches neither a custom vendor of the property nor the built-in tracker list. Create a custom vendor (how to) or mark the tag with data-cmp-vendor.
  • Non-critical domains (your own CDN, fonts you consider strictly necessary) may stay unknown – they are not blocked.
  • Still unknown after adding it? Is the vendor ticked in the property settings? Wait up to 2 minutes for the cache, use a private window, check the domain spelling (no https://, no path).

The console does not appear

  • Is cmp.js loaded? No cmp.js, no console. Look for cmp-console.js in the browser devtools network tab.
  • A Content Security Policy must allow scripts from the CMP domain (as for cmp.js).
  • Some sites strip query parameters with a redirect – use #cmpconsole or cmp.console() instead.

No banner / status “not initialised yet”

Look for error and config.json → … in the log: 404 = wrong property key or no published configuration; regime none = no banner configured for this country.

Technical notes & privacy

  • cmp.js only keeps a small in-memory ring buffer (max. 500 events, 600 elements). Nothing is sent or persisted; only the adcmp_console flag (plus the console's height/dock position) is stored in localStorage when you open the console.
  • The console is fetched from the CMP domain only when opened (/cmp/v1/cmp-console.js, versioned), renders inside a shadow DOM (no style conflicts with your page) and displays all page content as plain text.
  • It never changes consent or blocks anything – it only observes. Its own API queries do not appear in the log.
  • Globals: window.__adcmpDebug (buffer), window.__adcmpConsole (open(), close(), refresh(), snapshot()).