Umsetzung des Google Consent Mode V2
Voraussetzungen
Für die Umsetzung dieses Tricks wird von Version 4.3+ des REDAXO Consent Manager AddOns ausgegangen. Diese ist zum Zeitpunkt der Erstellung dieses Tricks unter Umständen noch nicht veröffentlicht worden. Wichtigste Neuerung und Teil dieses Tricks ist die Erweiterung der Dienst-Konfiguration um Skripte, die nach Abwahl eines Dienstes geladen werden sollen. Dies wird für die Umsetzung von Opt-Out-Szenarien benötigt und agiert insofern wie eine Art Event Handler.
Integration
Hinzufügen einer JS-Datei
Essenziell ist das Hinzufügen der nachfolgenden JavaScript-Datei im Frontend. Wichtig dabei ist, dass diese zwingend vor der Einbindung des Consent Manager Platzhalters (oder PHP-Codes) eingebunden wird. Um dies sicherzustellen, wird empfohlen, den Code inline direkt im Template auszugeben.
Dazu legt man z.B. die Datei google.consent.mode.v2.js
an unter /redaxo/src/addons/project/assets/js/
an, speichert
den unten stehenden Code darin und gibt deren Inhalt im Template im Bereich <head>
minifiziert
(z.B. über composer require tedivm/jshrink
) aus:
echo Minifier::minify(
"<script>".
rex_file::get(rex_addon::get('project')->getAssetsPath('js/google.consent.mode.v2.js')).
"</script>"
);
// ab hier oder später Code für den Consent Manager
echo consent_manager_frontend::getFragment(false, false, 'consent_manager_box_cssjs.php').PHP_EOL;
Der Inhalt der Datei google.consent.mode.v2.js
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
let GOOGLE_CONSENT_V2_DEFAULT_STATE = 'denied';
let GOOGLE_CONSENT_V2_STORAGE_KEY = 'consentMode';
let GOOGLE_CONSENT_V2_FIELDS = [
'ad_storage', // adwords
'ad_user_data', // adwords
'ad_personalization', // adwords
'analytics_storage', // analytics
'personalization_storage', // necessary
'functionality_storage', // necessary
'security_storage', // necessary
];
// sample for custom event handlers
let GOOGLE_CONSENT_V2_FIELDS_EVENTS = {
'analytics_storage': {
'on_granted': function() {},
'on_denied': function() {}
}
}
// get current settings
let consentStorage= localStorage.getItem(GOOGLE_CONSENT_V2_STORAGE_KEY);
if(consentStorage === null) {
// init of consent settings
let defaultSettings = array_combine(GOOGLE_CONSENT_V2_FIELDS, array_fill(0, GOOGLE_CONSENT_V2_FIELDS.length, GOOGLE_CONSENT_V2_DEFAULT_STATE));
if(defaultSettings !== false) {
gtag('consent', 'default', defaultSettings);
localStorage.setItem(GOOGLE_CONSENT_V2_STORAGE_KEY, JSON.stringify(defaultSettings));
}
} else {
// check if array is consistent (if new entries appear in the future)
let storedSettings = JSON.parse(consentStorage);
if(Object.keys(storedSettings).length !== GOOGLE_CONSENT_V2_FIELDS.length) {
GOOGLE_CONSENT_V2_FIELDS.forEach((field) => {
if (typeof storedSettings[field] == "undefined") {
storedSettings[field] = GOOGLE_CONSENT_V2_DEFAULT_STATE;
}
});
gtag('consent', 'default', storedSettings);
localStorage.setItem(GOOGLE_CONSENT_V2_STORAGE_KEY, JSON.stringify(storedSettings));
}
}
if(localStorage.getItem('userId') != null) {
window.dataLayer.push({'user_id': localStorage.getItem('userId')});
}
function setConsent(consent) {
let consentSettings = JSON.parse(localStorage.getItem(GOOGLE_CONSENT_V2_STORAGE_KEY));
for (const [key, value] of Object.entries(consentSettings)) {
if (typeof consent[key] !== "undefined") {
if(typeof(GOOGLE_CONSENT_V2_FIELDS_EVENTS[key]) != 'undefined') {
if(consent[key] === true && consentSettings[key] === 'denied') {
GOOGLE_CONSENT_V2_FIELDS_EVENTS[key]['on_granted']();
} else if (consent[key] === false && consentSettings[key] === 'granted') {
GOOGLE_CONSENT_V2_FIELDS_EVENTS[key]['on_denied']();
}
}
consentSettings[key] = (consent[key] === true ? 'granted' : 'denied');
}
}
gtag('consent', 'update', consentSettings);
localStorage.setItem(GOOGLE_CONSENT_V2_STORAGE_KEY, JSON.stringify(consentSettings));
}
/**
* helper to bring in PHP's array_combine function
* @param keys
* @param values
*/
function array_combine(keys, values) {
const newArray = {}
let i = 0
if (
typeof keys !== 'object' ||
typeof values !== 'object' ||
typeof keys.length !== 'number' ||
typeof values.length !== 'number' ||
!keys.length ||
!values.length ||
keys.length !== values.length
) {
return false;
}
for (i = 0; i < keys.length; i++) {
newArray[keys[i]] = values[i]
}
return newArray;
}
/**
* helper to bring in PHP's array_fill function
* @param startIndex
* @param num
* @param mixedVal
* @return
*/
function array_fill(startIndex, num, mixedVal) {
let key;
const tmpArr= [];
if (!isNaN(startIndex) && !isNaN(num)) {
for (key = 0; key < num; key++) {
tmpArr[(key + startIndex)] = mixedVal
}
}
return tmpArr;
}
Wer auf Re-Installieren des project-AddOns verzichten möchte, um immer die aktuellen Assets auch verfügbar zu haben,
kann natürlich auch einen eigenen Assets-Ordner oder die Struktur des Theme-AddOns nutzen und den Pfad dann mit
theme_path::assets('frontend/js/google.consent.mode.v2.js')
abrufen.
Dienst anlegen für Google Analytics
Im Backend wird nun die Verwaltung des Consent Managers betreten und ein neuer Dienst angelegt oder ein bereits bestehender Dienst für Google Analytics angepasst. In der nachfolgenden Konfiguration wird der Name für den Schlüssel so gewählt, dass der Multi-Domain-Einsatz berücksichtigt wird. Es schadet nicht, dass immer so zu handhaben, da man nie wissen kann, ob später weitere Domains mit eigenen Consent-Einstellungen hinzukommen.
Konfiguration des Dienstes
Die Inhalte können 1:1 übernommen werden. Lediglich die Stelle GTM-XXXXXXX
muss durch die eigene Google Tag Manager ID ersetzt
werden.
Feld | Wert |
---|---|
Schlüssel [a-z0-9-] | google-analytics-domain-x |
Dienst- / Cookiename | Google Analytics |
Definitionen (YAML) |
|
Anbieter | |
Link Datenschutzerklärung |
leer weil in DSE enthalten |
Skripte, die nach Einverständnis geladen werden |
|
Skripte, die nach Widerrufen des Einverständnisses geladen werden (ab 4.3+) |
|
Anschließend wird nach bekannter Vorgehensweise eine Gruppe angelegt (in diesem Fall namentlich "Statistik"
), der Dienst
und die Domain zugewiesen.
Dienst anlegen für Google AdWords (und weitere Google Ad-Tools)
Die Einstellungen für diesen Dienst ähneln der o.g. Analytics-Konfiguration sehr. Wichtigste Änderung ist hier die Einstellung
für den Local Storage. Statt analytics_storage
wird hier verwendet:
<script> setConsent({
ad_storage: true,
ad_user_data: true,
ad_personalization: true
}); </script>
... bzw. alles aus false
im Bereich "Skripte, die nach Widerrufen des Einverständnisses geladen werden"
der Dienst-
Konfiguration.
Die anderen Consent Mode Flags ...
Eine (automatisch übersetzte) Übersicht über die Flags und deren Bedeutung findet sich hier:
Flag | Beschreibung |
---|---|
ad_storage |
Ermöglicht die Speicherung (z. B. von Cookies) im Zusammenhang mit Werbung. |
ad_user_data |
Legt die Zustimmung zur Übermittlung von Nutzerdaten im Zusammenhang mit Werbung an Google fest. |
ad_personalization |
Legt die Zustimmung für personalisierte Werbung fest. |
analytics_storage |
Ermöglicht die Speicherung (z. B. von Cookies) im Zusammenhang mit der Analyse, z. B. der Besuchsdauer. |
Zusätzlich zu den Parametern für den Zustimmungsmodus gibt es die folgenden Datenschutzparameter:
Flag | Beschreibung |
---|---|
functionality_storage |
Ermöglicht die Speicherung von Daten, die die Funktionalität der Website oder App unterstützen, z. B. Spracheinstellungen. |
personalization_storage |
Ermöglicht die Speicherung im Zusammenhang mit der Personalisierung, z. B. Videoempfehlungen. |
security_storage |
Ermöglicht die Speicherung von sicherheitsrelevanten Daten wie Authentifizierungsfunktionen, Betrugsprävention und sonstigem Benutzerschutz. |
Es wird wohl empfohlen (?), die Zusatz-Flags (2. Tabelle) immer mit true
zu versehen. Man kann nachfolgenden Code
daher entweder an einen Dienst hängen, der mit einer Consent Gruppe im Bereich Notwendig
verknüpft ist (z.B. phpsessid
)
oder ihn direkt nach Einbindung des oben genannten Snippets ins Template ausführen.
<script>setConsent({
functionality_storage: true,
personalization_storage: true,
security_storage: true
});</script>
Im Einsatz
Der Ausgangszustand sollte so aussehen:
Wählt man nur notwendige Dienste aus, werden functionality_storage
, personalization_storage
und security_storage
auf true
gesetzt:
Wählt man die Statistik-Gruppe aus, werden die Flags gesetzt, der Tag Manager eingeladen und (wegen der aktivierten Flags) auch Google Analytics geladen: