Add new "Consent Banner" plugin, and update Google Analytics plugin to use it

optimising-macrocalls
jeremy@jermolene.com 2020-06-22 11:31:54 +01:00
rodzic 3de6c95fd6
commit 4a84ed0018
14 zmienionych plików z 366 dodań i 13 usunięć

Wyświetl plik

@ -0,0 +1,28 @@
title: $:/plugins/tiddlywiki/consent-banner/banner
tags: $:/tags/PageTemplate
\whitespace trim
<$reveal state="$:/state/consent-banner/accepted" type="match" text="" tag="div">
<div class="tc-consent-backdrop">
</div>
<div class="tc-consent-banner tc-consent-banner-left">
<$transclude tiddler="$:/config/plugins/tiddlywiki/consent-banner/greeting-message" mode="block"/>
<div class="tc-consent-buttons">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ConsentBanner/Button]]">
<$transclude tiddler=<<currentTiddler>> mode="inline"/>
</$list>
</div>
</div>
</$reveal>

Wyświetl plik

@ -0,0 +1,6 @@
title: $:/plugins/tiddlywiki/consent-banner/buttons/accept
tags: $:/tags/ConsentBanner/Button
<$button message="tm-consent-accept" class="tc-consent-button tc-consent-button-default tc-btn-invisible" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/caption}}
</$button>

Wyświetl plik

@ -0,0 +1,6 @@
title: $:/plugins/tiddlywiki/consent-banner/buttons/decline
tags: $:/tags/ConsentBanner/Button
<$button message="tm-consent-decline" class="tc-consent-button tc-btn-invisible" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/caption}}
</$button>

Wyświetl plik

@ -0,0 +1,42 @@
title: $:/plugins/tiddlywiki/consent-banner/config
! [[Greeting Message|$:/config/plugins/tiddlywiki/consent-banner/greeting-message]]
<div style="">
<div style="display:inline-block;vertical-align:top;width:45%;">
<$edit-text tiddler="$:/config/plugins/tiddlywiki/consent-banner/greeting-message" tag="textarea" class="tc-edit-texteditor"/>
</div>
<div style="display:inline-block;vertical-align:top;width:45%;margin:0.5em;border:1px solid black;padding:0.5em;" class="tc-consent-banner">
<$transclude tiddler="$:/config/plugins/tiddlywiki/consent-banner/greeting-message" mode="block"/>
</div>
</div>
! Buttons
|[[Accept caption|$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/caption]] |<$edit-text tiddler="$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/caption" tag="input"/> |
|[[Accept hint|$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/hint]] |<$edit-text tiddler="$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/hint" tag="input"/> |
|[[Decline caption|$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/caption]] |<$edit-text tiddler="$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/caption" tag="input"/> |
|[[Decline hint|$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/hint]] |<$edit-text tiddler="$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/hint" tag="input"/> |
! [[Consent Accepted Status|$:/state/consent-banner/accepted]]
Current status: {{$:/state/consent-banner/accepted}} (blank indicates that consent has not yet been granted or declined)
<$button message="tm-consent-accept" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/accept/caption}}
</$button>
<$button message="tm-consent-decline" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/decline/caption}}
</$button>
<$button message="tm-consent-clear" tooltip={{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/hint}}>
{{$:/config/plugins/tiddlywiki/consent-banner/buttons/clear/caption}}
</$button>

Wyświetl plik

@ -0,0 +1,8 @@
title: $:/config/plugins/tiddlywiki/consent-banner/buttons/
accept/caption: Accept
accept/hint: Accept cookies
clear/caption: Clear
clear/hint: Clear cookies
decline/caption: Decline
decline/hint: Decline cookies

Wyświetl plik

@ -0,0 +1,2 @@
title: $:/config/cookie-consent-required
text: yes

Wyświetl plik

@ -0,0 +1,19 @@
title: $:/config/plugins/tiddlywiki/consent-banner/greeting-message
! Our use of cookies
We use necessary cookies to make our site work. Wed also like to set optional analytics to help us improve it. We wont set optional cookies unless you enable them. Using this tool will set a cookie on your device to remember your preferences.
---
!! Necessary cookies
Necessary cookies enable core functionality such as security, network management, and accessibility. You may disable these by changing your browser settings, but this may affect how the website functions.
---
!! Analytics cookies
Wed like to set non-essential cookies, such as Google Analytics, to help us to improve our website by collecting and reporting information on how you use it. The cookies collect information in a way that does not directly identify anyone.
---

Wyświetl plik

@ -0,0 +1,6 @@
{
"title": "$:/plugins/tiddlywiki/consent-banner",
"name": "Consent Banner",
"description": "Consent banner for GDPR etc",
"list": "readme youtube config"
}

Wyświetl plik

@ -0,0 +1,44 @@
title: $:/plugins/tiddlywiki/consent-banner/readme
! Introduction
The ''consent-banner'' plugin helps make websites that are compliant with "cookie legislation" such as the [[EU General Data Protection Regulation|https://gdpr.eu/cookies/]].
! Overview
This plugin presents a banner inviting the user to accept or reject cookies, keeping track of their consent in local storage so that the banner can be hidden on subsequent visits. Consent status is also available via a configuration tiddler so that it is possible to construct content that behaves differently depending upon whether consent has been granted. As an example, a macro is provided for embedding ~YouTube videos that automatically uses the youtube-nocookie.com variant of video URLs unless the user has accepted cookies.
If the same wiki is opened in multiple tabs then once the warning has been accepted or declined in one tab then the other tabs will autonatically follow suit.
Consent is automatically granted if the user logged in (ie the tiddler [[$:/status/IsLoggedIn]] is set to `yes`).
Please note that using this plugin does not guarantee compliance with any particular legislation. You will need to understand the technical issues specific to your situation, and if necessary seek legal advice.
! ~YouTube macro
A simple macro for embedding ~YouTube videos is provided to show how to adapt content according to whether consent has been granted. It works by checking the tiddler [[$:/state/consent-banner/accepted]] for the following values:
* ''empty or missing'' - the user has yet to accept or decline to give their consent
* `yes` - the user has granted consent
* `no` - the user has declined consent
! Customising banner buttons
The [["accept"|$:/plugins/tiddlywiki/consent-banner/buttons/accept]] and [["decline"|$:/plugins/tiddlywiki/consent-banner/buttons/decline]] buttons in the banner are individual tiddlers with the tag [[$:/tags/ConsentBanner/Button]], allowing them to be customised and extended.
A common use case is to add a "login" button allowing users to login directly to bypass the banner. This could be implemented as a tiddler tagged [[$:/tags/ConsentBanner/Button]] with the following text:
```
<$button message="tm-login" class="tc-consent-button tc-btn-invisible">
Login
</$button>
```
! Integration with other plugins
Third party plugins that set cookies can configure themselves to defer setting cookies until the user grants consent. There are several parts to this mechanism:
* The consent-banner plugin includes a shadow tiddler [[$:/config/cookie-consent-required]] with the text `yes`. The third-party plugin should inspect this tiddler at startup; if it is not set to "yes" then it can proceed to set tiddlers immediately
* Otherwise, the third-party plugin should listen for changes to the tiddler [[$:/state/consent-banner/accepted]] and only start setting cookies when and if the value changes to "yes"
The [[Google Analytics plugin|https://github.com/Jermolene/TiddlyWiki5/tree/master/plugins/tiddlywiki/googleanalytics]] shows an example of how this mechanism can be implemented.

Wyświetl plik

@ -0,0 +1,68 @@
/*\
title: $:/plugins/tiddlywiki/consent-banner/startup.js
type: application/javascript
module-type: startup
Startup initialisation
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "consent-banner";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
var CHECK_CONSENT_INTERVAL = 1000, // Milliseconds between checking local storage
IS_LOGGED_IN_TITLE = "$:/status/IsLoggedIn",
CONSENT_KEY = "COOKIE_CONSENT", // Local storage keyname
CONSENT_TITLE = "$:/state/consent-banner/accepted"; // "": undeclared, "yes": accepted, "no": declined
exports.startup = function() {
var self = this,
consentState = "",
setConsentStatus = function(state) {
if(consentState !== state) {
consentState = state;
// Write to local storage
window.localStorage.setItem(CONSENT_KEY,state);
// Write to a state tiddler
$tw.wiki.addTiddler(new $tw.Tiddler({
title: CONSENT_TITLE,
text: state
}));
}
},
calculateConsentStatus = function() {
// Consent is implied for logged in users, otherwise we check local storage
return ($tw.wiki.getTiddlerText(IS_LOGGED_IN_TITLE) === "yes" && "yes") || window.localStorage.getItem(CONSENT_KEY) || "";
},
checkConsentStatus = function() {
setConsentStatus(calculateConsentStatus());
if(consentState === "") {
pollConsentStatus();
}
},
pollConsentStatus = function() {
setTimeout(checkConsentStatus,CHECK_CONSENT_INTERVAL);
};
// Set the current constant status
checkConsentStatus();
// Listen for tm-clear-browser-storage messages
$tw.rootWidget.addEventListener("tm-consent-accept",function(event) {
setConsentStatus("yes");
});
$tw.rootWidget.addEventListener("tm-consent-decline",function(event) {
setConsentStatus("no");
});
$tw.rootWidget.addEventListener("tm-consent-clear",function(event) {
setConsentStatus("");
});
};
})();

Wyświetl plik

@ -0,0 +1,79 @@
title: $:/plugins/tiddlywiki/consent-banner/styles
tags: $:/tags/Stylesheet
.tc-consent-backdrop {
z-index: 1999;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.2);
}
.tc-consent-banner-left {
z-index: 2000;
position: fixed;
left: 0;
top: 0;
bottom: 0;
max-width: 500px;
overflow-y: auto;
}
.tc-consent-banner {
padding: 1em;
background: #009677;
color: #fff;
box-shadow: 0 0 20px rgba(0,0,0,.2);
}
.tc-consent-banner a.tc-tiddlylink-external {
text-decoration: underline;
color: #fff;
background-color: inherit;
}
.tc-consent-banner a.tc-tiddlylink-external:visited {
color: #fff;
background-color: inherit;
}
.tc-consent-banner hr {
clear: both;
padding: 0;
width: 100%;
overflow: hidden;
text-align: left;
border: 0 none;
margin: 24px 0;
height: 1px;
max-height: 1px;
background: rgba(255,255,255,.25);
}
.tc-consent-buttons {
}
.tc-consent-button {
border: 1px solid #fff;
margin-right: 1em;
margin-top: 1em;
padding: 0.75em 1.5em;
color: #fff;
background: transparent;
font-weight: bold;
}
.tc-consent-button:hover {
color: #009577;
border-color: #fff;
background: #fff;
opacity: .6;
}
.tc-consent-button-default {
color: #009677;
background: #fff;
}

Wyświetl plik

@ -0,0 +1,19 @@
title: $:/plugins/tiddlywiki/consent-banner/youtube
tags: $:/tags/Macro
\define embed-video-with-consent(code)
<$reveal state="$:/state/consent-banner/accepted" type="match" text="yes" tag="div">
<iframe width="560" height="315" src="https://www.youtube.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</$reveal>
<$reveal state="$:/state/consent-banner/accepted" type="nomatch" text="yes" tag="div">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/$code$" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</$reveal>
\end
! Macro source
<$codeblock code={{$:/plugins/tiddlywiki/consent-banner/youtube}}/>
! Example
<<embed-video-with-consent KtCUr83XgyE>>

Wyświetl plik

@ -17,20 +17,44 @@ exports.name = "google-analytics";
exports.platforms = ["browser"];
exports.synchronous = true;
var CONFIG_CONSENT_REQUIRED_TITLE = "$:/config/cookie-consent-required",
CONSENT_TITLE = "$:/state/consent-banner/accepted"; // "": undeclared, "yes": accepted, "no": declined
exports.startup = function() {
// getting parameters
var GA_ACCOUNT = $tw.wiki.getTiddlerText("$:/GoogleAnalyticsAccount","").replace(/\n/g,""),
GA_DOMAIN = $tw.wiki.getTiddlerText("$:/GoogleAnalyticsDomain","").replace(/\n/g,"");
if (GA_DOMAIN == "" || GA_DOMAIN == undefined) GA_DOMAIN = "auto";
// using ga "isogram" function
(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', GA_ACCOUNT, GA_DOMAIN);
ga('send', 'pageview');
var hasInitialised = false,
initialiseGoogleAnalytics = function() {
console.log("Initialising Google Analytics");
hasInitialised = true;
var gaAccount = $tw.wiki.getTiddlerText("$:/GoogleAnalyticsAccount","").replace(/\n/g,""),
gaDomain = $tw.wiki.getTiddlerText("$:/GoogleAnalyticsDomain","auto").replace(/\n/g,"");
// Using ga "isogram" function
(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',gaAccount,gaDomain);
ga('send','pageview');
};
// Initialise now if consent isn't required
if($tw.wiki.getTiddlerText(CONFIG_CONSENT_REQUIRED_TITLE) !== "yes") {
initialiseGoogleAnalytics();
} else {
// Or has been granted already
if($tw.wiki.getTiddlerText(CONSENT_TITLE) === "yes") {
initialiseGoogleAnalytics();
} else {
// Or when our config tiddler changes
$tw.wiki.addEventListener("change",function(changes) {
if(changes[CONSENT_TITLE]) {
if(!hasInitialised && $tw.wiki.getTiddlerText(CONSENT_TITLE) === "yes") {
initialiseGoogleAnalytics();
}
}
});
}
}
};
})();

Wyświetl plik

@ -2,4 +2,6 @@ title: $:/plugins/tiddlywiki/googleanalytics/readme
This plugin enables you to use Google Analytics to track access to your online TiddlyWiki document. Based upon the [[official Google code|https://developers.google.com/analytics/devguides/collection/analyticsjs]].
By default, the user is not asked for permission before initialising Google Analytics. This plugin also optionally integrates with the "Consent Banner" plugin (also found in the official plugin library) so that Google Analytics is not initialised until the user grants explicit permission.
[[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/googleanalytics]]