Following the ECJ ruling of October 1, 2019, it is recommended to implement an explicit opt-in for all marketing cookies—or, more broadly, for any cookies not strictly necessary for the website's operation. This means that a user must consent to a marketing cookie before it is deployed (for instance, before tracking via Google Analytics begins). So, how do we implement this explicit opt-in process in Laravel? One streamlined and straightforward option is the Cookie Consent solution from Osano (https://cookieconsent.osano.com/). It allows us to handle everything using just a bit of JavaScript across two layout partials (since the website is bilingual, two language files are also involved—more on that below!).
Our example refers to Google Analytics but is essentially applicable to all other cookies. So, first we add the basic variables, the opt-in and opt-out functions, and the cookie stylesheet to the file.
/resources/views/layouts/partials/header.blade.php
a:
<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" />
In the footer, we then need to include the underlying JavaScript and define the various actions for initialization, status changes, and the withdrawal of consent within the file
/resources/views/layouts/partials/footer.blade.php
with the instructions
<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)
});
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)
});
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>
That's it! Now we just need to populate the respective languages with the variables listed above
/resources/lang/de/main.php
and
/resources/lang/en/main.php
In this case, the definition looks like this, for example:
// 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',
],
And then there's also...
artisan view:clear
artisan cache:clear
and
artisan config:clear
And that's it. Tested at our web agency on a website running Laravel 6.0.4.
