___TERMS_OF_SERVICE___ By creating or modifying this file you agree to Google Tag Manager's Community Template Gallery Developer Terms of Service available at https://developers.google.com/tag-manager/gallery-tos (or such other URL as Google may provide), as modified from time to time. ___INFO___ { "type": "TAG", "id": "cvt_temp_public_id", "version": 1, "securityGroups": [], "displayName": "Cleancmp Consent Mode Template", "brand": { "id": "brand_dummy", "displayName": "Cleancmp", "thumbnail": "" }, "description": "Sets Google Consent Mode defaults and updates consent from the Cleancmp CMP runtime", "categories": [ "UTILITY", "ADVERTISING", "ANALYTICS" ], "containerContexts": [ "WEB" ] } ___TEMPLATE_PARAMETERS___ [ { "type": "SELECT", "name": "loadRuntime", "displayName": "Load Cleancmp runtime", "simpleValueType": true, "selectItems": [ { "value": "true", "displayValue": "true" }, { "value": "false", "displayValue": "false" } ], "defaultValue": "true", "help": "Use true when GTM should deploy the CMP script. Use false only when the script is hardcoded on the page." }, { "type": "TEXT", "name": "installUrl", "displayName": "Cleancmp install URL", "simpleValueType": true, "valueHint": "https://cmp.cleancmp.com/cmp/install/ck_your-install-key/cleancmp.js", "defaultValue": "", "help": "Site-specific Cleancmp install URL from the Admin How To Install panel." }, { "type": "TEXT", "name": "waitForUpdateMs", "displayName": "wait_for_update milliseconds", "simpleValueType": true, "valueHint": "15000", "defaultValue": "15000" }, { "type": "SELECT", "name": "ad_storage", "displayName": "Default ad_storage", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, { "type": "SELECT", "name": "ad_user_data", "displayName": "Default ad_user_data", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, { "type": "SELECT", "name": "ad_personalization", "displayName": "Default ad_personalization", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, { "type": "SELECT", "name": "analytics_storage", "displayName": "Default analytics_storage", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, { "type": "SELECT", "name": "functionality_storage", "displayName": "Default functionality_storage", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "granted" }, { "type": "SELECT", "name": "personalization_storage", "displayName": "Default personalization_storage", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, { "type": "SELECT", "name": "security_storage", "displayName": "Default security_storage", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "granted" }, { "type": "PARAM_TABLE", "name": "regionalDefaults", "displayName": "Default Consent (GEO targeting)", "paramTableColumns": [ { "param": { "type": "SELECT", "name": "ad_storage", "displayName": "Advertisement cookies [ad_storage]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "ad_user_data", "displayName": "Advertisement User Data [ad_user_data]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "ad_personalization", "displayName": "Advertisement Personalization [ad_personalization]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "analytics_storage", "displayName": "Analytics Cookies [analytics_storage]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "functionality_storage", "displayName": "Functional Cookies [functionality_storage]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "granted" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "personalization_storage", "displayName": "Personalization Cookies [personalization_storage]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "denied" }, "isUnique": false }, { "param": { "type": "SELECT", "name": "security_storage", "displayName": "Security cookies [security_storage]", "simpleValueType": true, "selectItems": [ { "value": "denied", "displayValue": "denied" }, { "value": "granted", "displayValue": "granted" } ], "defaultValue": "granted" }, "isUnique": false }, { "param": { "type": "TEXT", "name": "region", "displayName": "Regions", "simpleValueType": true, "valueHint": "DK, DE, US-CA", "defaultValue": "", "help": "Comma-separated ISO 3166-2 region codes." }, "isUnique": false } ], "newRowButtonText": "Add region", "newRowTitle": "New row", "editRowTitle": "Edit row", "help": "Optional region-specific Consent Mode defaults. Use ISO 3166-2 region codes, comma-separated. Examples: DK, DE, US-CA." }, { "type": "SELECT", "name": "adsDataRedaction", "displayName": "Ads data redaction", "simpleValueType": true, "selectItems": [ { "value": "inherit", "displayValue": "Inherit (do not set)" }, { "value": "true", "displayValue": "Enabled" }, { "value": "false", "displayValue": "Disabled" } ], "defaultValue": "inherit" }, { "type": "SELECT", "name": "urlPassthrough", "displayName": "URL passthrough", "simpleValueType": true, "selectItems": [ { "value": "inherit", "displayValue": "Inherit (do not set)" }, { "value": "true", "displayValue": "Enabled" }, { "value": "false", "displayValue": "Disabled" } ], "defaultValue": "inherit" } ] ___SANDBOXED_JS_FOR_WEB_TEMPLATE___ const setDefaultConsentState = require("setDefaultConsentState"); const updateConsentState = require("updateConsentState"); const setInWindow = require("setInWindow"); const callInWindow = require("callInWindow"); const gtagSet = require("gtagSet"); const makeNumber = require("makeNumber"); const injectScript = require("injectScript"); const getCookieValues = require("getCookieValues"); const decodeUriComponent = require("decodeUriComponent"); const json = require("JSON"); const CONSENT_TYPES = [ "ad_storage", "ad_user_data", "ad_personalization", "analytics_storage", "functionality_storage", "personalization_storage", "security_storage" ]; const STORED_CONSENT_COOKIE = "CleanCmpConsent"; const DEFAULT_DENIED = { ad_storage: "denied", ad_user_data: "denied", ad_personalization: "denied", analytics_storage: "denied", functionality_storage: "granted", personalization_storage: "denied", security_storage: "granted" }; // ─── Helpers ──────────────────────────────────────────────────────────────── const splitInput = (input) => { if (!input) return []; const entries = input.forEach ? input : ("" + input).split(","); const output = []; entries.forEach((entry) => { const value = ("" + entry).trim().toUpperCase(); if (value) output.push(value); }); return output; }; const consentValue = (value, fallback) => { const normalized = ("" + value).trim().toLowerCase(); if (normalized === "granted" || normalized === "true") return "granted"; if (normalized === "denied" || normalized === "false") return "denied"; return fallback; }; const waitMs = () => { return makeNumber(data.waitForUpdateMs) || 15000; }; // ─── Script URL helpers ────────────────────────────────────────────────────── const stableScriptUrl = (input) => { const url = input || ""; const queryIndex = url.indexOf("?"); const hashIndex = url.indexOf("#"); let end = url.length; if (queryIndex !== -1 && queryIndex < end) end = queryIndex; if (hashIndex !== -1 && hashIndex < end) end = hashIndex; return url.substring(0, end); }; const installKeyFromRuntimeUrl = (input) => { const url = stableScriptUrl(input); const marker = "/cmp/install/"; const start = url.indexOf(marker); if (start === -1) return ""; const rest = url.substring(start + marker.length); const end = rest.indexOf("/cleancmp.js"); if (end === -1) return ""; return rest.substring(0, end); }; const configUrlFromRuntimeUrl = (input) => { const url = stableScriptUrl(input); const marker = "/cmp/install/"; const start = url.indexOf(marker); if (start === -1) return ""; const origin = url.substring(0, start); const installKey = installKeyFromRuntimeUrl(url); return installKey ? origin + "/api/public/install/" + installKey + "/production" : ""; }; // ─── Consent update (called by CMP runtime after user interacts) ───────────── const normalizeConsent = (record) => { let source = null; if (record) { source = record.googleConsent; if (!source) { const cleancmp = record.cleancmp; if (cleancmp) source = cleancmp.googleConsent; } if (!source) { const owncmp = record.owncmp; if (owncmp) source = owncmp.googleConsent; } } if (!source) return null; const output = {}; CONSENT_TYPES.forEach((type) => { output[type] = source[type] === "granted" ? "granted" : "denied"; }); return output; }; const parseStoredConsentCookie = () => { const values = getCookieValues(STORED_CONSENT_COOKIE); if (!values || !values.length) return null; let raw = values[0]; if (!raw) return null; const decoded = decodeUriComponent(raw); if (decoded) raw = decoded; raw = ("" + raw).trim(); if (raw.charAt(0) !== "{" || raw.charAt(raw.length - 1) !== "}") return null; if (raw.indexOf("\"googleConsent\"") === -1) return null; const record = json.parse(raw); if (!record || !record.categories) return null; return record; }; const applyStoredConsentCookie = () => { const record = parseStoredConsentCookie(); if (record) applyConsentUpdate(record); }; let lastConsentKey = ""; const consentStateKey = (consent) => { const parts = []; CONSENT_TYPES.forEach((type) => { parts.push(type + ":" + consent[type]); }); return parts.join("|"); }; const applyConsentUpdate = (record) => { const consent = normalizeConsent(record); if (!consent) return; const key = consentStateKey(consent); if (key === lastConsentKey) return; lastConsentKey = key; updateConsentState(consent); }; const registerRuntimeListeners = () => { const registered = callInWindow("OwnCMPAddConsentListener", applyConsentUpdate); if (registered === true) { setInWindow("OwnCMPGtmBridge", null, true); return; } callInWindow("OwnCMP.onReady", applyConsentUpdate); callInWindow("OwnCMP.onChange", applyConsentUpdate); }; // ─── Default consent state (applied before user interacts) ─────────────────── const buildConsentState = (source) => { const state = {}; CONSENT_TYPES.forEach((type) => { state[type] = consentValue(source && source[type], DEFAULT_DENIED[type]); }); return state; }; // data.regionalDefaults is a PARAM_TABLE — each row is a plain object with // consent type keys plus a "region" key (e.g. { ad_storage: "granted", region: "DK" }). const getRegionalRows = () => { if (data.regionalDefaults && data.regionalDefaults.length) return data.regionalDefaults; return []; }; const rowRegions = (row) => { return splitInput(row && (row.region || row.regions || row.Region || row.Regions)); }; const setDefault = (state, regions) => { state.wait_for_update = waitMs(); if (regions && regions.length) state.region = regions; setDefaultConsentState(state); }; const applyDefaultConsentStates = () => { const rows = getRegionalRows(); let index = 0; // Apply region-scoped defaults first (e.g. DK granted, DE denied). // Google Consent Mode matches these against the visitor's detected country. for (index = 0; index < rows.length; index++) { const row = rows[index]; const regions = rowRegions(row); if (!regions.length) continue; setDefault(buildConsentState(row), regions); } // Apply global fallback last — used for any visitor not matched by a regional row. setDefault(buildConsentState(data)); }; // ─── Bootstrap ─────────────────────────────────────────────────────────────── const runtimeUrl = stableScriptUrl(data.installUrl || ""); const siteId = installKeyFromRuntimeUrl(runtimeUrl) || ""; const configUrl = configUrlFromRuntimeUrl(runtimeUrl) || ""; const bootstrapSettings = { siteId: siteId, configUrl: configUrl, dataLayerName: "dataLayer", googleConsent: false, gtmConsentFallback: false }; if (data.adsDataRedaction !== "inherit") { gtagSet("ads_data_redaction", data.adsDataRedaction === "true"); } if (data.urlPassthrough !== "inherit") { gtagSet("url_passthrough", data.urlPassthrough === "true"); } applyDefaultConsentStates(); applyStoredConsentCookie(); setInWindow("OwnCMPGtmBridge", applyConsentUpdate, true); setInWindow("OwnCMPBootstrap", bootstrapSettings, true); if (data.loadRuntime === "false") { registerRuntimeListeners(); data.gtmOnSuccess(); } else if (!runtimeUrl) { data.gtmOnFailure(); } else { injectScript(runtimeUrl, () => { registerRuntimeListeners(); data.gtmOnSuccess(); }, data.gtmOnFailure, "owncmp-runtime-" + siteId); } ___WEB_PERMISSIONS___ [ { "instance": { "key": { "publicId": "access_globals", "versionId": "1" }, "param": [ { "key": "keys", "value": { "type": 2, "listItem": [ { "type": 3, "mapKey": [ { "type": 1, "string": "key" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" }, { "type": 1, "string": "execute" } ], "mapValue": [ { "type": 1, "string": "OwnCMPBootstrap" }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "key" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" }, { "type": 1, "string": "execute" } ], "mapValue": [ { "type": 1, "string": "OwnCMPGtmBridge" }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "key" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" }, { "type": 1, "string": "execute" } ], "mapValue": [ { "type": 1, "string": "OwnCMPAddConsentListener" }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "key" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" }, { "type": 1, "string": "execute" } ], "mapValue": [ { "type": 1, "string": "OwnCMP.onReady" }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "key" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" }, { "type": 1, "string": "execute" } ], "mapValue": [ { "type": 1, "string": "OwnCMP.onChange" }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true }, { "type": 8, "boolean": true } ] } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true }, { "instance": { "key": { "publicId": "access_consent", "versionId": "1" }, "param": [ { "key": "consentTypes", "value": { "type": 2, "listItem": [ { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "ad_storage" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "ad_user_data" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "ad_personalization" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "analytics_storage" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "functionality_storage" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "personalization_storage" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] }, { "type": 3, "mapKey": [ { "type": 1, "string": "consentType" }, { "type": 1, "string": "read" }, { "type": 1, "string": "write" } ], "mapValue": [ { "type": 1, "string": "security_storage" }, { "type": 8, "boolean": false }, { "type": 8, "boolean": true } ] } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true }, { "instance": { "key": { "publicId": "write_data_layer", "versionId": "1" }, "param": [ { "key": "keyPatterns", "value": { "type": 2, "listItem": [ { "type": 1, "string": "url_passthrough" }, { "type": 1, "string": "ads_data_redaction" } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true }, { "instance": { "key": { "publicId": "inject_script", "versionId": "1" }, "param": [ { "key": "urls", "value": { "type": 2, "listItem": [ { "type": 1, "string": "https://cmp.cleancmp.com/cmp/install/*/cleancmp.js" } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true }, { "instance": { "key": { "publicId": "get_cookies", "versionId": "1" }, "param": [ { "key": "cookieAccess", "value": { "type": 1, "string": "specific" } }, { "key": "cookieNames", "value": { "type": 2, "listItem": [ { "type": 1, "string": "CleanCmpConsent" } ] } } ] }, "clientAnnotations": { "isEditedByUser": true }, "isRequired": true } ] ___TESTS___ scenarios: [] ___NOTES___ Built on 2026-05-31T14:43:23.292Z