Wallogit.com
2017 © Pedro Peláez
October CMS plugin to make websites GDPR and ePrivacy compliant
October CMS plugin to make websites GDPR compliant., (*1)
This plugin is available on the October Marketplace: https://octobercms.com/plugin/offline-gdpr, (*2)
This plugin provides two simple components to make your October installation GDPR compliant., (*3)
, (*4)
php artisan gdpr:import
cookieManager component on a cookies.htm pagecookieBanner component on all of your layouts. Use the configuration listed below.[cookieBanner]
include_css = 1
update_partial = "gdpr"
update_selector = "#gdpr-reload"
cookie_manager_page = "cookies"
==
{% component 'cookieBanner' %}
gdpr.htm partial. Include the partial in your layouts as shown below. Note the #gdpr-reload
wrapper.<div id="gdpr-reload">
{% partial 'gdpr' %}
</div>
gdpr.htm partial you can now conditionally include your dependencies by querying the cookie's code.{% if gdprCookieAllowed('google-analytics') %}
<!-- Include analytics code here -->
{% endif %}
The cookieManager component gives a visitor more control over the cookies your site is using., (*5)
This component can simply be placed on a page and needs no further configuration., (*6)
title = "Cookies"
url = "/cookies"
layout = "default"
is_hidden = 0
[cookieManager]
==
{% component 'cookieManager' %}
It is possible to define your cookie groups and cookies in a yaml file and import them using the gdpr:import console command.
This allows you to define cookies once and re-use them between installations., (*7)
php artisan gdpr:import --path=plugins/offline/gdpr/assets/presets/example_en.yaml --replace
You can find example definitions in the assets/presets directory of this plugin., (*8)
You can optionally use the --replace flag to remove all existing cookie data and replace it with your preset., (*9)
If no path is specified, the plugin will load all presets from the configured presets_path and ask you which preset to import., (*10)
You can change the path where presets are loaded from by changing the offline.gdpr::config.presets_path config entry.
To do this, create the file config/offline/gdpr/config.php and return your custom path:, (*11)
<?php
return [
'presets_path' => '/path/to/your/presets',
];
, (*12)
The cookieBanner component displays a cookie banner on the first page view. There the user has the possibility to
enable and disable cookies that your website uses (defined via October's backend settings)., (*13)
These settings are stored and made available in your partials using the gdprCookieAllowed helper. With this helper
you can check for the user's consent and optionally include your resources., (*14)
cookieBanner component to all your layouts.[cookieBanner]
include_css = 1
update_partial = "gdpr"
update_selector = "#gdpr-reload"
cookie_manager_page = "cookies"
==
{% component 'cookieBanner' %}
You can enable a log via the backend settings so every cookie banner request gets logged. This is useful to get an idea of the number of users that do not accept a cookie request and therefore never end up in your analytics data., (*15)
The log only contains the user's session id and their decision., (*16)
If you don't want to include the default css use include_css = 0 when including your component., (*17)
cookieManager pageSet the property cookie_manager_page to the page that contains the cookieManager component., (*18)
A Advanced Settings link will be placed on the cookieBar that links to this page. This enables the user to
further define what cookies are allowed., (*19)
gdprCookieAllowed($code, $minLevel = 0)Check if a certain cookie is allowed to be included. You can optionally pass a cookie level to check if the user has accepted a specific level of this cookie., (*20)
{% if gdprCookieAllowed('google-analytics') %}
{% endif %}
{% if gdprCookieAllowed('google-analytics', 3) %}
{% endif %}
gdprAllowedCookieLevel($code)Get the max allowed level for a certain cookie. A return value of -1 means the cookie is not allowed at all. A
value of 0 or higher means the cookie is allowed with the returned level value., (*21)
{% if gdprAllowedCookieLevel('google-analytics') >= 3 %}
<!-- Include advanced Level 3 Analytics Code here -->
{% endif %}
gdprIsUndecided()Check if the user has made a decision about the cookies yet. This will return true on the second page view if the
user did not interact with the cookieBanner (silent opt-in)., (*22)
The data retention functionality enables you to delete old plugin data after a specified amount of days., (*23)
You can specify the data retention policy for each plugin via October's backend settings., (*24)
Important: To automatically delete old data make sure you have set up the Task Scheduler correctly., (*25)
To register your plugin you have to listen for the offline.gdpr::cleanup.register event in your Plugin's boot method., (*26)
public function boot()
{
\Event::listen('offline.gdpr::cleanup.register', function () {
return [
'id' => 'your-contact-form-plugin',
'label' => 'Custom Contact Form Plugin',
'models' => [
[
'label' => 'Contact form messages',
'comment' => 'Delete logged contact form messages',
'class' => MessageLog::class,
],
[
'id' => 'vendor-plugin-spam-messages', // The ID is required if you specify a closure. This should be unique to your plugin.
'label' => 'SPAM-Messages',
'comment' => 'Delete blocked SPAM messages',
'closure' => function (Carbon $deadline, int $keepDays) {
// Delete your old data here
},
],
],
];
});
}
You have to specify the following data:, (*27)
| key | information |
|---|---|
| id | A unique identifier of your plugin |
| label | A human readable label for your plugin |
| models | An array of all your data collecting models |
As models you have to specify an array with the following data:, (*28)
| key | information |
|---|---|
| id | A unique string to identify this model. Use only _-a-z0-9. Only required if you specify a closure. (ex. offline-gdpr-spam-messages) |
| label | A human readable label for the backend switch form widget |
| comment | A human readable comment for the backend switch form widget |
| closure | A closure that is called when the cleanup job is run. Make sure to also define an id. |
| class | A model class that defines a gdprCleanup method |
You have to specify either a closure or a class value. If both are specified the closure value will be used., (*29)
You can either specify a closure or a model class that defines a gdprCleanup method. Both have the same
signature:, (*30)
public function gdprCleanup(\Carbon\Carbon $deadline, int $keepDays)
{
self::where('created_at', '<', $deadline)->each(function (self $item) {
$item->delete();
});
// or
// self::where('created_at', '<', $deadline)->delete();
}
This method is called whenever the cleanup job is run. $deadline contains a Carbon instance.
All data older than this date has to be deleted. $keepDays contains the number of days
that $deadline is in the past., (*31)
Make sure to use an each/delete loop if your model makes use of deleting/deleted model events., (*32)
You can trigger the cleanup on demand via, (*33)
php artisan gdpr:cleanup, (*34)