CUTCODEDOWN
Minimalist Semantic Markup

Welcome Guest
Please Login or Register

If you have registered but not recieved your activation e-mail in a reasonable amount of time, or have issues with using the registration form, please use our Contact Form for assistance. Include both your username and the e-mail you tried to register with.

Author Topic: Cookie consent message in an accesible way  (Read 1940 times)

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Cookie consent message in an accesible way
« on: 25 Jun 2020, 08:48:10 am »
This my approach to implement the odious "cookie consent" message in a website. Although it works, it's non-optimal since this non-relevant content should be at the bottom of the HTML code and the code that sets display:none is at the end causing some flickering.

I'm using elementalsjs for cookie management. I use googleon and googleoff tags to indicate Google the content should be ignored.

This code goes after <body>:
Code: [Select]
<!--googleoff: index-->
<div id="cookies">                                                     
  Blah, blah, blah <a href="privacy-policy/">Privacy policy</a>. <span class="accept"><a href="'.$actual_link.'" onclick="_.Cookies.set(\'consent\',\'yes\',false,\'/\')">Accept</a></span>
</div><!-- #cookies -->                                                 
<!--googleon: index-->       
           
This code goes just before </body>:
Code: [Select]
<script src="theme/elementals.min.js"></script>                                               
<script>                                                               
  var consent = _.Cookies.get("consent");                               
  if (consent)                                                         
    document.getElementById("cookies").style.display = "none";         
</script> 

Any feedback or ideas to improve the code are most welcomed.
« Last Edit: 25 Jun 2020, 08:57:39 am by fgm »

coothead

  • Sr. Member
  • ****
  • Posts: 390
  • Karma: +89/-0
  • I smile benignly
    • coothead's stuff ~ an eclectic collection
Re: Cookie consent message in an accesible way
« Reply #1 on: 25 Jun 2020, 09:03:17 am »
Hi there fgm,

I have found that the "I don't care about cookies" add-on/extension
does the job very well in Firefox, chrome and Vivaldi.

Information site:-

https://www.i-dont-care-about-cookies.eu/

coothead
~ the original bald headed old fart ~

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #2 on: 25 Jun 2020, 12:54:21 pm »
@coothead, he's trying to IMPLEMENT one, not block all of them. Since it's a legal requirement in many places (thankfully not the US yet) this isn't too uncommon.

@fgm, your first mistake is slopping scripting into the markup with onclick, and to be frank if it only works scripting on, you shouldn't be having the ack anchor in the markup in the first place!

Again, 'onevent' attributes in the markup are junk. Don't do it.

Your second mistake is putting scripting-only anchors into the markup. If it only works scripting on, it doesn't go there in the first place.

I would double-wrap the DIV and make it a modal IF scripting is present. Otherwise as you said, leave it at the bottom of the page.

Code: [Select]
<div id="cookies">
<div>
Blah, blah, blah <a href="privacy-policy/">Privacy policy</a>.
</div>
<!-- #cookies --></div>

Gets you your scripting off and/or JS off code. Place it before </body> and your external scripts.

Code: [Select]
(function(d, w) {

var
cookieDiv = d.getElementById('cookies');

cookieDiv.id = 'cookiesModal';
_.Class.add(cookieDiv, 'modal');

w.location.hash = '#cookiesModal';

_.make('ul', {
content : [
[ 'li', [
[ 'a@google.com~Cancel' ]
] ],
[ 'li', [
[ 'a@#~Accept', {
onclick : function(e) {
_.Cookie.set('cookies_accepted', Date.now());
}
} ]
] ]
],
last : cookieDiv.firstElementChild
});

})(document, window);

Elementals _.make routine adds a menu with both a "get me out of here" link, and an "accept". Otherwise it behaves as a normal hash triggered modal.

See my page about that here:
https://cutcodedown.com/tutorial/modalDialogs

The CSS being something like:

Code: [Select]
.modalFix,
.modal {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
overflow:auto;
}

.modal {
overflow:auto;
display:flex;
padding:1em;
left:-100%;
background:rgba(224,224,224,0.9);
box-shadow:
inset 0 0 128px 128px rgba(0,0,0,0.1);
opacity:0;
transition:left 0s 0.5s, opacity 0.5s;
}

.modal:target {
left:0;
opacity:1;
transition:opacity 0.5s;
}

.modal section {
overflow:hidden;
position:relative;
top:-50vh;
margin:auto;
background:#FFF;
border:1px solid #777;
border-radius:0.25em;
box-shadow:
0 0.25em 0.75em rgba(0,0,0,0.2);
transition:top 0.5s;
}

.modal:target section {
top:0;
}

Just don't forget to put <div class="modalFix"> around all of your content, that way you can overlap the scrollbars.

Code untested, I may be mixing and matching Elementals 3 and 4 syntax, but later on I'll do a proper demo if I have the time.

Documenting elementals 4 right now. API docs are complete, but I have to rewrite all the demo's to use it and/or drag them into the light.

-- edit -- I'm assuming you're using a cookie so that server side if the cookie is set, you don't send that DIV?
« Last Edit: 25 Jun 2020, 01:42:34 pm by Jason Knight »
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #3 on: 25 Jun 2020, 01:40:45 pm »
Had a spare moment after downing lunch, so I threw this together:

https://cutcodedown.com/for_others/fgm/cookieModal/

Should be about what you're trying to do.

Again, since you're using a cookie I assume you'd be checking that server side to not send this section you want to show/hide if they've already accepted it. The script is written to detect if the cookie is set and not apply itself, though it too should probably have it's <script> tag omitted if the cookie is set.
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Re: Cookie consent message in an accesible way
« Reply #4 on: 25 Jun 2020, 02:46:05 pm »
Thanks a lot for the tips and the code :) my javascript knowledge is near zero and it's not easy to  find good examples, so this help is much appreciated.

Since my site is fully static (no PHP server side) I don't know any other way to check for the installed cookies, so I've added these two lines just after if (!cookieDiv) return; in your code to show the modal just once and not in every page load:
Code: [Select]
if (_.Cookies.get('cookies_accepted')) {
    document.getElementById('cookies').style.display = 'none';
    return;
}

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #5 on: 25 Jun 2020, 03:11:43 pm »
Rather than setting it to display:none, I'd probably just remove it from the DOM entirely.

likewise if it's only going to be used client-side, I'd consider using localStorage instead of cookies. That way you're not adding unnecessary overhead to each and every request.

But I'd not expect you to know that, since as you said you're a JS rookie. No shame on the ignorance there there, we can fix that.

Something like:

Code: [Select]
(function(d, w) {

var cookieDiv = d.getElementById('cookies');

if (!cookieDiv) return;

if (localStorage.getItem('cookies_accepted')) {
_.Node.remove(cookieDiv); // remove it ENTIRELY
return;
}

cookieDiv.id = 'cookiesModal';
_.Class.add(cookieDiv, 'modal');

w.location.hash = '#cookiesModal';

_.make('ul.actionMenu', {
content : [
[ 'li', [
[ 'a@https://google.com~Cancel' ]
] ],
[ 'li', [
[ 'a@#~Accept', {
onclick : function(e) {
localStorage.setItem('cookies_accepted', Date.now());
}
} ]
] ]
],
last : cookieDiv.firstElementChild
});

})(document, window);

Localstorage doesn't communicate server-side, so unlike cookies it doesn't get applied to each and every file request. They often also don't have expirations and are rarely flushed, meaning it will often be more persistent than a "forever" cookie.

Sometimes that's a plus, sometimes it'a a minus, depends on the task at hand.  Also beware localStorage doesn't exist in IE 7/earlier if you care. I stopped caring about that two years ago.

That said, this REALLY should have the server side involved. This is why static websites are a relic of the past.
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Re: Cookie consent message in an accesible way
« Reply #6 on: 25 Jun 2020, 03:42:36 pm »
That makes sense, thanks again. I didn't know about localStorage, it seems the right choice for this task. Why is server side cookie management so important in this application?

I've added some lorem ipsum paragraphs to the example inside .modalFix div but the scroll bars are still showed.

Could be possible to load Google Adsense scripts only after the modal is accepted?. This should be the correct behaviour to comply with the law, but I'm not sure if this is viable.

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #7 on: 25 Jun 2020, 04:19:05 pm »
First off I just want to say: "Excellent questions all-around". I wish more people weren't afraid to simply ask questions. It's what smart people do.

I didn't know about localStorage
NOT too surprising. Even though it's about a decade old now, it's still considered a "new' technology.

Why is server side cookie management so important in this application?
So you aren't wasting bandwidth sending things client-side -- like the agreement and its associated scripting -- once it's already accepted on each and every sub-page. It could even be implemented as a stage based load (two separate pages) for scripting off behavior.

Not everyone browses with JavaScript enabled, or from UA's where JavaScript is even relevant. See my "bad days" where I'm increasingly reliant on my braille reader.

I've added some lorem ipsum paragraphs to the example inside .modalFix div but the scroll bars are still showed.

They should be overlaid, but that could also be an issue with the modal scripting handling. Modals are ... fragile.

If the modals were moved after the .modalFix they will guaranteed behave when modals, but since the agreement could also be static content it can go bits-up face-down scripting off. It's often hard to balance the two.

Position:fixed on .modal may alleviate that woe. I'd have to play with it. What I gave you was a quick drive-by recode, not my best work.

Could be possible to load Google Adsense scripts only after the modal is accepted?. This should be the correct behaviour to comply with the law, but I'm not sure if this is viable.
Absolutely, I do it on cutcodedown. Elementals even has a _.Load.script function for this very purpose.

The trick? Remove the script that looks something like this from your markup:

Code: [Select]
<script data-ad-client="ca-pub-yourNumberHere" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

Make sure your <ins> tag where you want the advert has data-ad-client on it.

Code: [Select]
<ins class="adsbygoogle" data-ad-client="ca-pub-yourNumberHere" data-ad-slot="slotNumberHere" data-ad-format="auto" style="display:block;"></ins>

Where we localStorage.setItem in the scripting? Add this:

Code: [Select]
_.Load.script('//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', { async : true} );
For those not using elementals.js, vanilla scripting for this would go something like:

Code: [Select]
var adsByGoogle = document.createElement('script');
adsByGoogle.src = '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
adsByGoogle.async = true;
document.body.appendChild(adsByGoogle);

I actually like to put that in my onload chain, so it doesn't even try to load their scripting until after everything else of mine is done and a "meaningful paint" has been completed.

Late loading non-essential scripts can really help with speed rankings, and with Google now treating speed rankings on mobile as part of your search weight, every bit helps.
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Re: Cookie consent message in an accesible way
« Reply #8 on: 25 Jun 2020, 05:15:57 pm »
That makes sense, thank you.

Using position:fixed in .modal worked fine in my browser and now the scroll bars are gone! :)

Wow, that's fantastic. So after replacing the original <script> with <ins>, for this code that _.Load function should be inside the conditional so it's loaded only after the cookies are accepted, isn't it?
Code: [Select]
if (localStorage.getItem('cookies_accepted')) {
  _.Node.remove(cookieDiv); // remove it ENTIRELY
  _.Load.script('//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', { async : true} );
  return;
 }

I'm applying for adsense so I can't test right now, but I think I got the idea.

- edit - I forgot to ask about <section> in your example code, is there any reason to use it instead of <div>?

I'd like the Accept button to link to the actual page instead of # for the modal to work in all the pages. Would passing the value from PHP as a parameter be the way to go, or it's some kind of helper in elementalsjs? if so, how could I do that? I actually have $actual_url variable in my application.

If it were PHP I'd do something like:
Code: [Select]
[ 'a@'.$actual_url.'#~Accept', {   
« Last Edit: 25 Jun 2020, 06:28:56 pm by fgm »

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #9 on: 25 Jun 2020, 07:23:32 pm »
Wow, that's fantastic. So after replacing the original <script> with <ins>, for this code that _.Load function should be inside the conditional so it's loaded only after the cookies are accepted, isn't it?
Yeah, it should be there too. Have it in both spots.

Code: [Select]
if (localStorage.getItem('cookies_accepted')) {
  _.Node.remove(cookieDiv); // remove it ENTIRELY
  _.Load.script('//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', { async : true} );
  return;
 }

- edit - I forgot to ask about <section> in your example code, is there any reason to use it instead of <div>?
Some of my more complex modals it saves me a class. Other than that, no. People EXPECT HTML 5 markup even though it's pointless crap, so... I do it even if I hate it.

I'd like the Accept button to link to the actual page instead of # for the modal to work in all the pages.
href="#" will work on all the pages, it's not "/#", it's just "#". All the modals will work that way. Just plain href="#" is the current page, always. Hence you don't need to play any extra games.

There is no reason to play with it. Regardless of what page you're on, it will access the current page not redirect you.

Just to explain my aggravatingly and pointlessly cryptic DOM-JON, the type of crap I usually take others to task for... with a DSS:

a@#~Accept

Is the same thing as:

<a href="#">Accept</a>

with no leading slash or URI, that href points at the currently loaded page. So no extra games needed across multiple pages.
« Last Edit: 25 Jun 2020, 07:25:13 pm by Jason Knight »
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Re: Cookie consent message in an accesible way
« Reply #10 on: 25 Jun 2020, 08:17:38 pm »
href="#" will work on all the pages, it's not "/#", it's just "#". All the modals will work that way. Just plain href="#" is the current page, always. Hence you don't need to play any extra games.

There is no reason to play with it. Regardless of what page you're on, it will access the current page not redirect you.
When browsing in a subdirectory it redirects me to / only if I use base href:
Code: [Select]
<base href="https://www.mysite.com/">
or even:
Code: [Select]
<base href="https://www.mysite.com">

I've tested in Firefox 77.0.1 and Chromium 83.0.4103.106. When I remove this code, the Accept button works fine leaving me in the same page.

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #11 on: 26 Jun 2020, 05:23:25 pm »
only if I use base href:
Well there's your problem.

A few years ago I would have advocated using BASE, but when using techniques like this it's become impractical. Generally if your directory structure is worth a flying purple fish you shouldn't have issues that require BASE to fix anyways, if you just use a rooted path.

Aka instead of "template/screen.css" just use "/template/screen.css" or whathaveyou. The only "real" reason to use base is if your .html isn't in the root and to avoid rooting in the URI, but since the only places where that would/should matter should be relative to the http root anyways, why bother?

Using BASE is a practice I've back-tracked on the use of as more and more features that let me pitch JavaScript in the trash have started to conflict with it.

Also part of why I prefer the "one index.php to rule them all" approach to dev... but even when not doing that I put all user-callable HTML in the root, it's all the sub-files that belong in subdirectories, not the user calls.
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

fgm

  • Jr. Member
  • **
  • Posts: 60
  • Karma: +5/-0
Re: Cookie consent message in an accesible way
« Reply #12 on: 26 Jun 2020, 06:19:18 pm »
That's definitely a good reason to ditch base href. Thank you again, your help is much appreciated.

Jason Knight

  • Administrator
  • Hero Member
  • *****
  • Posts: 1049
  • Karma: +188/-1
    • CutCodeDown -- Minimalist Semantic Markup
Re: Cookie consent message in an accesible way
« Reply #13 on: 27 Jun 2020, 01:47:45 am »
That's definitely a good reason to ditch base href
... and that's the thing, there's a reason.

A decade ago I used it religiously because I had been told a decade before that how great it was... when suddenly people started saying it wasn't but -- like so many things -- refused to give me a legitimate reason WHY! Just like frameworks, just like arrow functions, just like the new structural tags... you'll get a vague parroting of the propaganda but not a legitimate explanation of WHY!

If someone had simply told me "It jacks up using hash links" I'd have stopped using it a lot sooner.

Instead 8 to 10 years ago when I was trying to find out WHY the only answers I got were "it's just bad" or "So and so big name in the industry said so."... and like so many other wild unfounded claims, typically those blindly repeating them can't even link to where they heard it.

To me those are never reasons to do or believe anything. Apparently that makes me "defective" in a lot of people's eyes.
« Last Edit: 27 Jun 2020, 01:50:09 am by Jason Knight »
We are all, we are all, we are all FRIENDS! For today we're all brothers, tonight we're all friends. Our moment of peace in a war that never ends.

GrumpyYoungMan

  • Hero Member
  • *****
  • Posts: 787
  • Karma: +8/-0
    • Grumpy Young Man
Re: Cookie consent message in an accesible way
« Reply #14 on: 27 Jun 2020, 02:32:23 am »
Only tracking cookies need consent?

I thought all functional ones were exempt?

Trying to learn a new trick to prove old dogs can learn new ones...

Total Novice have-a go Amateur Programmer - not sure that is the right thing to say... but trying to learn...

 

SMF spam blocked by CleanTalk

Advertisement