Nach dem EUGH-Urteil vom 01. Oktober 2019 wird empfohlen, ein explizites Opt-In für alle Marketing-Cookies / für alle nicht zwingend für den Betrieb einer Website erforderlichen Cookies zu implementieren. Das heißt: Bevor überhaupt ein Marketing-Cookie ausgespielt wird, z.B. ein User durch Google Analytics getrackt wird, muss er diesem Cookie zustimmen. Wie setzen wir dieses explizite Opt-In-Verfahren nun in Laravel um? Eine schlanke und unkomplizierte Möglichkeit ist hier die Cookie Consent-Lösung von Osano (https://cookieconsent.osano.com/). Mit dieser können wir im Grunde mit ein wenig Javascript in 2 Layout-Partials alles erledigen (da Website zweisprachig, kommen hier noch 2 Sprachdateien dazu, dazu weiter unten mehr!).

 

Unser Beispiel bezieht sich auf Google Analytics, ist aber im Grunde auf alle anderen Cookies übertragbar. Zuerst fügen also wir die Grundvariablen und die Opt-In und Opt-Out-Funktionen, sowie das Cookie-Stylesheet in die Datei

 

/resources/views/layouts/partials/header.blade.php

 

ein:

 

<script>

var gaProperty = 'UA-XXXXXXXXX-X',

disableStr = 'ga-disable-' + gaProperty;

if (document.cookie.indexOf(disableStr + '=true') > -1) {

                window[disableStr] = true;

}

function gaOptout()

{

                document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';

                window[disableStr] = true;

}

function gaOptin()

{

                window[disableStr] = false;

                document.cookie = disableStr + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';

}                             

</script>

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />

 

Im Footer dann müssen wir das zugrunde liegende Javascript einbinden und die verschiedenen Aktionen bei Initialisierung, Statusänderung und Widerruf des Einverständnisses definieren in der Datei

 

 /resources/views/layouts/partials/footer.blade.php

 

mit den Anweisungen

 

<script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>

<script>

window.cookieconsent.initialise({

                "palette": {

                               "popup": {

                                               "background": "#000"

                               },

                               "button": {

                                               "background": "#f5f5f5"

                               }

                },

                "type": "opt-in",

                "content": {

                "message": "@lang('main.osano-cookies.message')",

                "allow": "@lang('main.osano-cookies.allow')",

                "link": "@lang('main.osano-cookies.link')",

                "deny": "@lang('main.osano-cookies.deny')",

                "policy": "@lang('main.osano-cookies.policy')",              

                },

                onInitialise: function (status) {

                               var type = this.options.type;

                               var didConsent = this.hasConsented();

                               if (type == 'opt-in' && didConsent) {

                                               @if(app('env') !== 'local')

                                                               (function (i, s, o, g, r, a, m)

                                                               {

                                                                              i['GoogleAnalyticsObject'] = r;

                                                                              i[r] = i[r] || function ()

                                                                              {

                                                                                              (i[r].q = i[r].q || []).push(arguments)

                                                                              }, i[r].l = 1 * new Date();

                                                                              a = s.createElement(o),

                                                                                              m = s.getElementsByTagName(o)[0];

                                                                              a.async = 1;

                                                                              a.src = g;

                                                                              m.parentNode.insertBefore(a, m)

                                                               })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');

                                                               ga('create', gaProperty, 'auto', {

                                                                              anonymizeIp: true

                                                               });

                                                               ga('set', 'anonymizeIp', true);

                                                               ga('send', 'pageview');

                                                               gaOptin();

                                               @endif

                               }

                },

                onStatusChange: function(status, chosenBefore) {

                               var type = this.options.type;

                               var didConsent = this.hasConsented();

                               if (type == 'opt-in' && didConsent) {

                                               @if(app('env') !== 'local')

                                                               (function (i, s, o, g, r, a, m)

                                                               {

                                                                              i['GoogleAnalyticsObject'] = r;

                                                                              i[r] = i[r] || function ()

                                                                              {

                                                                                              (i[r].q = i[r].q || []).push(arguments)

                                                                              }, i[r].l = 1 * new Date();

                                                                              a = s.createElement(o),

                                                                                              m = s.getElementsByTagName(o)[0];

                                                                              a.async = 1;

                                                                              a.src = g;

                                                                              m.parentNode.insertBefore(a, m)

                                                               })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');

                                                               ga('create', gaProperty, 'auto', {

                                                                              anonymizeIp: true

                                                               });

                                                               ga('set', 'anonymizeIp', true);

                                                               ga('send', 'pageview');

                                                               gaOptin();

                                               @endif

                               }

                               if (type == 'opt-in' && !didConsent) {

                                               gaOptout();

                               }

                },

                onRevokeChoice: function() {

                               var type = this.options.type;

                               if (type == 'opt-in') {

                                               gaOptout();

                               }

                }

});

</script>

 

Das war's! Nun müssen wir nur noch die jeweiligen Sprachen befüllen mit den oben aufgeführten Variablen in

 

/resources/lang/de/main.php

 

und

 

/resources/lang/en/main.php

 

Hierbei sieht die Definition z.B. so aus:

 

// Cookie Consent by Osano

'osano-cookies'  => [

                'message'       => 'Um die Webseite optimal gestalten und fortlaufend verbessern zu können, verwendet SECO SIGN Cookies. Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu.',

                'link'                                      => '<a style=\'color:#fff; text-decoration:underline\' href=\'/de/datenschutzerklaerung#ga\'>Mehr Info</a>',

                'allow'                                  => 'Cookies erlauben',

                'deny'                                   => 'Ablehnen',

                'policy'                                 => 'Cookie Verwaltung',

],

 

Dann noch 

 

artisan view:clear

 

artisan cache:clear

 

und

 

artisan config:clear

 

und fertig. Getestet in unserer Internetagentur auf einer Website mit Laravel 6.0.4.