-
Posts
89 -
Joined
-
Last visited
-
Days Won
8
Everything posted by joshua
-
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Thanks for your feedback - I'm glad you like it! Haven't thought about a way for donation yet, but PayPal should work fine. Thanks a lot ? -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Thank you for the PR and the idea! Of course it's a good think to have the render function hookable. I also like the idea of @horst with an hookable output file. I would definitely like to spend some time soon to refactor / optimize PrivacyWire. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Good question! I don't know a native "processwirish" procedure for this yet. Your solution like a good start. Does anyone else knows a processwirish way of doing this? -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Thank you for all your input! I've been quite busy the last weeks, sorry for my delay in answering your requests. During the last couple of days I refactored some code and implemented an suggested feature by @horst (to call a custom js function after saving the consent). As this version might not be as stable as the current version, you'll find it currently in a separate branch. The following updates are also only in this branch at the moment. I agree on that and just added this category to PrivacyWire (in the V2-Branch). In the new branch I switched to save the consent information in LocalStorage instead of Cookies. Now the lifetime in all browsers should be 365 days. About the details about cookies / categories: I also agree that there should be an option to display more details. The idea of a Textformatter for this purpose sounds good. Haven't got the time though to implement it right away. I'm open for PullRequests with improvements, if you want ? The styling is currently applied directly within the js file. To add the option to disable loading the stylesheet, I could exclude this from the js file and add an option to the module config. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
That's an interesting point. As I understood the GDPR (but I'm not a lawyer, so not sure about that) a listing of the single cookies is not mandatory right now - but the upcoming ePrivacy could change that. When you want/need to implement this solution, KLARO could be a better choice at the moment. Currently this feature isn't included in PrivacyWire and I'm not sure if or when I could implement it. Or you could fork PrivacyWire and add the feature with a PR? ? Best, Joshua -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Hi Montero, thank you for your feedback. I just looked into this and fixed the bug in the new release. Best, Joshua -
Thank you! ? Yes, sure, I can give some examples. The workflow is getting refactored right now, so I can't show any specific details, but I'll describe the process. A quite simple example for a tiny helper class is this Headline Class for rendering headlines without risking to use more than one <h1> tag per page call: I like to use this on content heavy pages (e.g. within RepeaterMatrix Elements) where I want to be sure to not have more than one <h1>. By default only the first call of this helper method returns the <h1> tag, all the others an <h2> (unless otherwise specified with $sizeTag). To output a headline with this, simply use <?php echo Headline::render($page->headline); ?> I also have some helpers for rendering responsive (lazy loading) images or buttons and in this project most of the business logic of the "magic link" login is within one of these helper functions. Currently I require these classes manuelly within the ready.php include_once($_SERVER['DOCUMENT_ROOT'] . "/site/templates/helpers/Headline.php"); include_once($_SERVER['DOCUMENT_ROOT'] . "/site/templates/helpers/Image.php"); include_once($_SERVER['DOCUMENT_ROOT'] . "/site/templates/helpers/Link.php"); include_once($_SERVER['DOCUMENT_ROOT'] . "/site/templates/helpers/FrontendUserManagement.php"); include_once($_SERVER['DOCUMENT_ROOT'] . "/site/templates/helpers/CopeCartHandler.php"); But I definitely want to dig deeper into autoloading them. I want to refactor especially my Link and Image helper soon, perhaps I'll explain them afterwards further... As example for the custom Page Class here is an extract from my SpeakerPage: My Workflow Local <-> Stage <-> Live Our webserver uses Plesk Onyx as the hosting control panel. For each web project we create a separate "subscription" where the stage and live domain will live. For the dev / stage domain we use the plesk integrated git repo as dev branch. The live domain gets connected to the master branch of the same repo. As we exclude a lot of files in git (e.g. the whole /wire/ directory or the assets and module directories) we had to find a solution to copy them between stages. I'll come to that point later again. In my local environment I'm using MAMP Pro for the server environment. After pulling everything from the dev branch, we need also pull the database and exluded files / directories. To do so, the python script connects itself via SSH to the server and dumps the database, creates the same database locally and imports its contents. The files / directories will be pulled as zip files and extracted locally. Our first try here was to use rsync, but with asset-heavy pages this can take quite a while to copy... During development we usually do all the database-related stuff in the staging environment and just pull the database with our Python CLI script. When we need to pull also modules or the wire dir, our CLI script can handle that as well. Our content-editors mostly work in the staging environment ( on new web projects) or directly in the live environment (on existing projects). I'll definitely write an in-depth article about this, as soon as we have refactored it completely! Then I can also show some code snippets or even publish it, we'll see.
-
We recently launched the website “Resilienz-Kongress”, which is kind of an online summit / online conference about resilience (only in German language). The users can register as a participant and will receive daily emails during the conference timeframe with a conference room link for each day. Within this virtual conference room the participants can watch several interviews with experts and exchange ideas via comments. This concept is especially during the COVID-19 lockdown an interesting possibility for idea exchanges. Some technical details: • ProcessWire 3.0.155+ • ProCache • ProFields (RepeaterMatrix) • PrivacyWire • Seo Maestro • WireMail SendGrid • CodyFrame UI Framework • CopeCart (as the E-Commerce API) • Git, Node, Yarn, Gulp, PostCSS, Autoprefixer for a modern workflow combined with our individual local <-> stage <-> live environment and sync helper build with Python We heavily used the ability to specify custom Page classes (introduced in PW 3.0.152) and a lot of custom helper classes for cleaner code. Every frontend user registration with double opt-in is linked with the SendGrid API. The login process for frontend users is quite individual as we wanted to integrate a password-free login method similar to “Magic Links”. To achieve this we developed a “FrontendUserManagement” Class, which takes care of all the magic in the background. I’ll write another article about this topic as soon as I find the time, as I like the idea to implement this solution also as an open-source ProcessWire module. For the after-selling area we used CopeCart as our cart system with their IPN. With this combination we don’t have to handle the billing process at all. Also a clean cross-device affiliate tracking system between CopeCart, ProcessWire and SendGrid is integrated even though we’re currently not using the affiliate system at all. As frontend framework we used CodyFrame with an intense usage of CSS Custom Properties (for modern browsers with a classic fallback CSS for old browsers). https://www.resilienz-kongress.de/
-
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
I've updated the module today to add the W3C validation. Starting now the type can be "text/plain" instead of "optin", the js will detect the elements via the data-category attribute. I will update the documentation. That's a good point. Right now there isn't a detection for this but I'll think about a way to implement this. When you add a button to change cookie preferences in your privacy policy, the selected options are pre-selected, so one could say it's "documented". I'm not sure if this is sufficient for your case? That will not work, as the loading works via javascript. When javascript is disabled (and the <noscript> tag comes into play), PrivacyWire isn't loaded as well so it cannot load the <noscript> tag. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
That's right, currently the W3C does not validate. @gebeer also mentioned this with the possible solution to use "text/plain" instead of "optin". I'm planning to implement this solution, but as an optional addition to keep backwards compatibility for the users who already use the "optin" variant. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Thanks again for your feedback. I tested the privacy & imprint URLs and there really was a small bug about the multi language URLs. When you update the module the multi language URLs should work now. Example of external media: <!-- This is the output container --> <div id="player"></div> <script type="optin" data-type="text/javascript" data-category="external_media"> // 2. This code loads the IFrame Player API code asynchronously. var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); // 3. This function creates an <iframe> (and YouTube player) // after the API code downloads. var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '360', width: '640', videoId: 'M7lc1UVf-VE', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); } // 4. The API will call this function when the video player is ready. function onPlayerReady(event) { event.target.playVideo(); } // 5. The API calls this function when the player's state changes. // The function indicates that when playing a video (state=1), // the player should play for six seconds and then stop. var done = false; function onPlayerStateChange(event) { if (event.data == YT.PlayerState.PLAYING && !done) { setTimeout(stopVideo, 6000); done = true; } } function stopVideo() { player.stopVideo(); } </script> See this for more info about the YouTube API. The code above is from their example. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Thanks for your feedback! I'll look into bug about the privacy URL in different languages later today. For embedding videos I'll also write an example and update the main post later with this. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Hi Sergio, thank you! ? Glad you like the module. I actually never thought about the "opt out" approach as our customers or their "Data protection officer" requested the opt-in version. Do you mean this approach for "pre-selecting" the checkboxes within the choose-window? That would be not to hard to implement, I could add an option for this to the module config. More difficult would it be to automatically load all scripts on page load and only stop specific categories, when the user choose to opt-out. About the Google Tag Manager: I have no experience in this kind of granular control within the GTM. Maybe this article could help? -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Update - Version 0.0.6 Minor CSS-Debugging (hiding the choose button when no cookie group is selected) Added ProCache support for the script tag, when ProCache is installed -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
I today integrated the multi-language support for all the config fields. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
You can simply write your own CSS. In the module included are only some basic styles (less than 500 byte) which are directly included via JS. I tried to keep the module as slim as possible, the javascript has only 3.05 kb (gzipped) with all the functionality. You can see an example of styling at our website or this website. I usually only style the div.privacywire and the buttons to match the website styles. -
module PrivacyWire - Cookie Management & async external asset loading
joshua replied to joshua's topic in Modules/Plugins
Right now only the default values can be overwritten via language translation files. But good hint - I'll add multi-language support for the config fields as well. -
--- Module Directory: https://modules.processwire.com/modules/privacy-wire/ Github: https://github.com/blaueQuelle/privacywire/ Packagist:https://packagist.org/packages/blauequelle/privacywire Module Class Name: PrivacyWire Changelog: https://github.com/blaueQuelle/privacywire/blob/master/Changelog.md --- This module is (yet another) way for implementing a cookie management solution. Of course there are several other possibilities: - https://processwire.com/talk/topic/22920-klaro-cookie-consent-manager/ - https://github.com/webmanufaktur/CookieManagementBanner - https://github.com/johannesdachsel/cookiemonster - https://www.oiljs.org/ - ... and so on ... In this module you can configure which kind of cookie categories you want to manage: You can also enable the support for respecting the Do-Not-Track (DNT) header to don't annoy users, who already decided for all their browsing experience. Currently there are four possible cookie groups: - Necessary (always enabled) - Functional - Statistics - Marketing - External Media All groups can be renamed, so feel free to use other cookie group names. I just haven't found a way to implement a "repeater like" field as configurable module field ... When you want to load specific scripts ( like Google Analytics, Google Maps, ...) only after the user's content to this specific category of cookies, just use the following script syntax: <script type="text/plain" data-type="text/javascript" data-category="statistics" data-src="/path/to/your/statistic/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing" data-src="/path/to/your/mareketing/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="external_media" data-src="/path/to/your/external-media/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing">console.log("Inline scripts are also working!");</script> The data-attributes (data-type and data-category) are required to get recognized by PrivacyWire. the data-attributes are giving hints, how the script shall be loaded, if the data-category is within the cookie consents of the user. These scripts are loaded asynchronously after the user made the decision. If you want to give the users the possibility to change their consent, you can use the following Textformatter: [[privacywire-choose-cookies]] It's planned to add also other Textformatters to opt-out of specific cookie groups or delete the whole consent cookie. You can also add a custom link to output the banner again with a link / button with following class: <a href="#" class="privacywire-show-options">Show Cookie Options</a> <button class="privacywire-show-options">Show Cookie Options</button> I would love to hear your feedback ? CHANGELOG You can find the always up-to-date changelog file here.
- 222 replies
-
- 29
-
Yes, the legal situation in Germany / Europe is getting harder. I'm also still struggling with a good solution. Our wordpress developer uses https://borlabs.io/ which is a quite complete solution for cookie management (and external scripts / media blocker). Thanks for the links to klaro & oil.js - both are looking really promising. I'll definetely take a deeper look. I'm still behind my updates of the fork but was thinking about extending the features (as our german customers are asking for features as choosing the cookie groups, blocking external scripts, if not opted in ...). Maybe it'll also be a complete rewrite, as the intended use changes. Edit: My current draft work of a rewrite you'll find here: https://github.com/blaueQuelle/privacywire/tree/dev
-
You're right, this isn't included yet. I definetely need to update the code later ?
-
It's a pleasure ? Yes, DNT should also be a selectable option. I'll add an suggestion for this feature later. That's true. To add this as a non-breaking feature we could also add the type of accepted cookies as a separate storage option "allowedCookieType" => "all" // "necessary". In this case no existing setup should break.
-
I agree that there should be a different value for necessary cookies... Maybe the pwcmbAllowCookies in localStorage could have values like "all", "necessary" and "no" instead of just "y" and "n"? I also thought about respecting the "DoNotTrack" choice of the user in the browser. I'm currently working on this, but this simple snippet at the start of the init function should do it: /* if the user activated the "DoNotTrack" function in their browser, respect that choice and do not show the banner */ if (navigator.doNotTrack) { cookieMonster.cfg.allowCookies = "n"; cookieMonster.cfg.selectionMade = "y"; cookieMonster.cfg.storedVersion = cookieMonster.cfg.version; cookieMonster.sendActionBeacon(); cookieMonster.updateStatus(); cookieMonster.sendTrackingBeacon(); return; }
-
As some of our customers do have the same request (checkbox for only necessary cookies), I implemented this option in this fork. Till now I only added the option in the vanilla js solution as we don't use jQuery at all. If desired I could add also this option to the jQuery part and open a PR. Technically the button for "only necessary" cookies is the same as the option to not consent at all, just a different position of the button and naming. This is an example of the module frontend.
-
First of all, many thanks to @thomasaull for this awesome module. I'm starting to develop an server-side-rendered Webapp with Sapper at the frontend and ProcessWire as the backend. For learning the behavior of pages and fields accessed via the REST API, I started a tiny example repo here. It allows to loop through all pages and if questioned for one specific page it outputs all (no validation, if a field should be readable to the frontend users) fields of the page (with some opinionated default values). Right now it only covers "basic" text-based fields, images and Repeaters. I was wondering if there is an easy way to check for field settings like access control, conditional visibility etc. I'm thinking about a most practical solution, which is also abstractable for further projects with totally different fields. Maybe extending the Fieldtype Classes could be a solution?
-
Hi @horst, that's right, but the script looks, if there is already a webp-version of the image and if deliver this directly. So there is no big processing during normal frontend activities through website users, if the conversion was already done. Though you are definetely right, it's an extra PHP call (but cacheable)