okkur / syna

Highly customizable open source theme for Hugo based static websites
https://syna.okkur.org/demo/
Apache License 2.0
250 stars 133 forks source link

a Fragment Cookie for GDPR ? #836

Open JOduMonT opened 3 years ago

JOduMonT commented 3 years ago

As it is proposed in the Contributing Guide I open this issue to talk about having a Cookie-GDPR fragment in Syna.

While the base of theme doesn't need it because it doesn't store any data from the user, the website which use Syna might store data via the fragments: Contact, Member and Stripe but also using 3rd parties such as Google Analytic and/or Matamo/Piwik.

A what able to dump cut a past a Cookie Pop-up to make my website GDPR compliant. I would like to understand how to make it a fragment and to propose it as a PR

HTML

<div class="cookie-popup js-cookie-popup cookie-popup--uses-badge"><h2>This website uses cookies</h2><p>Select which cookies to opt-in to via the checkboxes below; our website uses cookies to examine site traffic and user activity while on our site, for marketing, and to provide social media functionality. <a href="#not-specified">More details...</a></p><form><input id="gdpr-necessary" name="gdpr-necessary" checked="checked" disabled="disabled" type="checkbox"> <label for="gdpr-necessary">Required</label> <input id="gdpr-functions" name="gdpr-functions" type="checkbox"> <label for="gdpr-functions">Functionality</label> <input id="gdpr-analytics" name="gdpr-analytics" type="checkbox"> <label for="gdpr-analytics">Analytical</label> <input id="gdpr-marketing" name="gdpr-marketing" type="checkbox"> <label for="gdpr-marketing">Marketing</label><p class="cookie-popup__save-wrapper"><button type="submit" class="cookie-popup__save">Save</button></p></form><span class="cookie-popup-label">Cookie Policy</span></div>
<script>(function() {
                function addScript (src, inline) {
                    var newScript = document.createElement('script');

                    if (src) {
                        newScript.setAttribute('src', src);
                    }

                    if (inline) {
                        newScript.text = inline;
                    }

                    document.body.appendChild(newScript);
                }

                var popup = document.querySelector('.js-cookie-popup');
                var checkboxes = popup.querySelectorAll('input[type="checkbox"]');
                var save = popup.querySelector('button');
                var currentConfig = localStorage.getItem('gdpr-allowed-cookies');
                var blockedScripts = document.querySelectorAll('script[type^="gdpr-blocker/"]');

                popup.addEventListener('click', function() {
                    if (!popup.classList.contains('cookie-popup--is-sticky')) {
                        popup.classList.add('cookie-popup--is-sticky');
                    }
                });

                save.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    popup.classList.remove('cookie-popup--is-sticky');
                    var allowedGroups = [];

                    for (var i = 0; i < checkboxes.length; i++) {
                        if (checkboxes[i].checked) {
                            var groupName = checkboxes[i].getAttribute('name').replace('gdpr-', '');
                            var scripts = document.querySelectorAll('script[type="gdpr-blocker/' + groupName + '"]');

                            for (var j = 0; j < scripts.length; j++) {
                                addScript(scripts[j].src, scripts[j].text);
                            }

                            allowedGroups.push(groupName);
                        }
                    }

                    localStorage.setItem('gdpr-allowed-cookies', allowedGroups.join(','));
                    popup.classList.remove('cookie-popup--is-sticky');

                    setTimeout(function () {
                        if (currentConfig !== null) {
                            window.location.reload();
                        }
                    }, 250);
                });

                if (currentConfig === null) {
                    popup.classList.add('cookie-popup--is-sticky');
                } else {
                    if (currentConfig !== '') {
                        var allowedGroups = currentConfig.split(',');

                        for (var i = 0; i < allowedGroups.length; i++) {
                            var scripts = document.querySelectorAll('script[type="gdpr-blocker/' + allowedGroups[i] + '"]');
                            var checkbox = popup.querySelector('input[type="checkbox"][name="gdpr-' + allowedGroups[i] + '"]');

                            if (checkbox) {
                                checkbox.checked = true;
                            }

                            for (var j = 0; j < scripts.length; j++) {
                                addScript(scripts[j].src, scripts[j].text);
                            }
                        }
                    }
                }
            })();</script>

CSS

.cookie-popup{background:#fff;border-radius:2px;bottom:1rem;-webkit-box-shadow:0 0 12px rgba(0,0,0,.15);box-shadow:0 0 12px rgba(0,0,0,.15);font-size:15px;left:16px;right:16px;max-width:600px;padding:2rem;position:fixed;-webkit-transform:translateY(100%);-ms-transform:translateY(100%);transform:translateY(100%);-webkit-transition:-webkit-transform .8s ease 0s;transition:-webkit-transform .8s ease 0s;-o-transition:transform .8s ease 0s;transition:transform .8s ease 0s;transition:transform .8s ease 0s,-webkit-transform .8s ease 0s;will-change:transform;z-index:1000}.cookie-popup--uses-badge{background:#24a931;border-radius:6px 6px 0 0;bottom:.6rem;height:2rem;padding:0;-webkit-transition:all .24s ease-out;transition:all .24s ease-out;width:6.4rem}.cookie-popup.cookie-popup--uses-badge.cookie-popup--uses-link:hover,.cookie-popup.cookie-popup--uses-badge:hover{bottom:2rem}.cookie-popup.cookie-popup--uses-badge.cookie-popup--uses-link.cookie-popup--is-sticky{bottom:.6rem}.cookie-popup--uses-badge>form,.cookie-popup--uses-badge>h2,.cookie-popup--uses-badge>p{display:none}.cookie-popup--is-sticky{border-radius:2px;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);-webkit-transition:transform .8s ease 0s;transition:transform .8s ease 0s}.cookie-popup--uses-badge.cookie-popup--is-sticky{background:#fff;bottom:1rem;height:auto;padding:2rem;width:100%}@media (max-width:600px){.cookie-popup--uses-badge.cookie-popup--is-sticky{bottom:0!important;left:0;right:0}}@media (min-width:600px){.cookie-popup--uses-badge.cookie-popup--is-sticky:hover{bottom:1rem}}.cookie-popup--uses-badge.cookie-popup--is-sticky>form,.cookie-popup--uses-badge.cookie-popup--is-sticky>h2,.cookie-popup--uses-badge.cookie-popup--is-sticky>p{display:block}.cookie-popup.cookie-popup--uses-link{background:#fff;bottom:0}.cookie-popup.cookie-popup--uses-badge.cookie-popup--uses-link{background:#24a931;bottom:.6rem}.cookie-popup.cookie-popup--uses-badge.cookie-popup--uses-link.cookie-popup--is-sticky{background:#fff}.cookie-popup--is-sticky.cookie-popup--uses-link{-webkit-transform:translateY(-1rem);-ms-transform:translateY(-1rem);transform:translateY(-1rem)}.cookie-popup>h2{font-size:20px;margin:0}.cookie-popup>p{margin:1rem 0 0}.cookie-popup input[type=checkbox]+label{margin-right:.53333rem;white-space:nowrap}.cookie-popup input[type=checkbox]+label::before{height:20px;line-height:20px;width:20px;margin-right:.26667rem}.cookie-popup input[type=checkbox]:disabled+label:before{content:"";background-color:#f6f6f6;background-image:url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 8'%3e%3cpolygon points='9.53 0 4.4 5.09 1.47 2.18 0 3.64 2.93 6.54 4.4 8 5.87 6.54 11 1.46 9.53 0' fill='%23999999'/%3e%3c/svg%3e")}.cookie-popup__save{background:#24a931;border:none!important;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#fff!important;font-size:13px;padding:.666rem 1.2rem}.cookie-popup>form,.cookie-popup__save-wrapper{margin-top:1.06667rem}.cookie-popup__save:active,.cookie-popup__save:hover{opacity:.85}.cookie-popup-label{color:#fff;cursor:pointer;left:50%;position:absolute;top:50%;-webkit-transform:translateX(-50%) translateY(-50%);-ms-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);white-space:nowrap}.cookie-popup--is-sticky .cookie-popup-label{display:none}
stp-ip commented 3 years ago

Related issue #385 We didn't come around to it yet, but would be happy for a PR. It should be configurable as a simple fragment, mostly configured globally aka in _global, but might also be used only on sub pages I guess.

The simplest iteration is just a cookie banner without selection possibilities.

The next iteration could add selection, which is a bit harder as this would need support from the analytics and other fragments I guess.

Happy for ideas etc.