New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offer opt out without iframe / 3rd party cookies #17452
Comments
In theory something like this might work and be user-friendly, right? <div id="opt-out"></div>
<script data-id="opt-out" src="https://matomo.example/optout.js"></script> With optout.js being a file like matomo.js that is able to read the data parameter and then use it as a target of https://developer.matomo.org/guides/tracking-javascript-guide#optional-creating-a-custom-opt-out-form to create an opt-out box that looks like the iFrame. Only issue is maybe localisation as this might bloat the js file quite a bit. |
Generally yes @Findus23 It might not be a fixed JS file though but more of an actual request to take into account for example translations. Unless we can solve translations in JavaScript. The current iframe opt out, also has few other options to customise colors etc:
We would provide the same options for this. For example using data attributes like We also offer options to customise cookie domain, cookie same site, cookie secure, cookie path, cookie name prefix. The rendered content should look and function otherwise the same as before. However, the cookie is set on the site that you're on and not on the Matomo instance. |
I made a very simple JavaScript opt-out to circumvent the iframe on some of my projects: It also takes care of localisation by recognizing the browser-language (in a very hardcoded way). I would be glad to see an "official" non-iframe solution so I can get rid of this some time. |
I'm proposing to implement this in the following way: Change the Privacy Manager -> Users opt-out UI to generate HTML code using a Existing iframe code will still be honored using the existing The generated code would look something like this:
The Finally the script will listen for opt out / opt-in events and use Supported appearance options would be: data-language, data-background-color, data-font-color, data-font-size and data-font-family. The options to customize cookies would perhaps be better set on the tracker code? The data-language attribute could support an option to use the detected browser language instead of a specific language value with an option like The opt-out div could of course be positioned anywhere on the page and have additional styling applied as required. @tsteur, @sgiehl Are you happy with this approach? Thoughts welcome 🙂 |
thanks for this. That's already going in the right direction. I've had a look around how other systems handle it and it's somewhat similar concepts. Sometimes they also directly give you the HTML to embed this like <input type="checkbox" id="foo">You are currently opted out. Check this box to opt-in.
<script>
setupOptOut('foo');
function setupOptOut(id){
// toggle checkbox
// set cookie or paq.push
}</script> Benefits: Lot of flexibility for users to change things and use their language/words etc, no extra requests that may be blocked by tracking blockers Maybe we'd just suggest this as an alternative method for people who want to completely customise it and it's in fact already documented here: https://developer.matomo.org/guides/tracking-javascript-guide#optional-creating-a-custom-opt-out-form . It be great to mention this on the page in the Admin UI "Let users opt-out of tracking" and link to it.
Great 👍 So the approach sounds generally good. Below some thoughts to think about
Note that this may not work if people:
The question be how could we detect if this is the case? And what do we do in such a case? We might need to show an error after a while that opt out is not possible if one of these things are happening and that they need to implement a custom opt out for example. The tracker may be loaded with a delay so we might not be able to detect it right away and only after a while. Also we need to find out if the user is currently opted out or not to show the correct state (and an async tracker needs to be set up). Maybe it would mean we only show the content once we retrieved the current opt out/in status from the tracker? If we generate the JavaScript for OptOut in a controller action (instead of an API), then depending if a user is logged into their Matomo account we could potentially show error messages for these people while for not logged in users we maybe keep the content empty so they don't see these errors. Just a thought. It may not be clear though because developers who integrate this may not be logged into Matomo and wouldn't know what the problem is. Then we'd maybe at least want to show this in the console or also in the UI etc.
Ideally yes. However, it does require that the tracking code is loaded and that an async tracker has been created. I wonder if we need a fallback for when this is not the case or if we just show error messages etc. Of course if this optOut script was to set cookies, then they would need to have the ability to specify cookie path etc and it would need to match the tracker settings which can be tricky to maintain. Otherwise we might set cookies on the wrong domain. So there's clearly a benefit letting the tracker set the cookies. So generally it looks already quite good and just wanted to bring up a few things to further think about. I guess the biggest question is how do we make sure the optOut will actually work for users in case eg |
Thanks @tsteur I had thought about returning dynamic JavaScript, if that's something we're okay doing then it's definitely a cleaner solution with fewer calls 👍 Implementation plan changes: ✔️ Instead of serving fixed JavaScript and using data attributes, we add a new controller action <div id="m-opt-out"></div>
<script src="/index.php?module=CoreAdminHome&action=optOut&language=en&backgroundColor=FFF&div=m-opt-out">
</script> ✔️ On the Privacy Manager -> Users opt-out UI we can add an alternative option for more customization where we provide a self-contained version of the opt-out code that doesn't make any API calls but will need to be customized, eg. it won't be translated. Additionally we show a link the custom opt-out form guide. ✔️ Provide a new opt-out code generation option to skip the introduction text. ✔️ Write a blog post explaining the advantages of the new opt-out approach and showing how to easily migrate existing sites, add a Missing JS tracker fallback: If we want to support opt-out when something has prevented the JS tracker from loading then I think a fallback option where we set the cookie directly could work. So if the JS tracker is loaded elsewhere then it can find the cookie and knows not to track. The current The Does that sound ok? |
Sounds overall good @bx80
Overall it sounds all good. It's bit hard to imagine the user experience so we might just need to tweak to make sure we have a good user experience should there be not a tracker on the same site (for whatever reason). |
Thanks for the feedback @tsteur 👍 ✔️ Only wait 30secs for the JS tracker
Yes, I was thinking we have a URL parameter to enable the fallback to direct cookies, this would allow flexibility for unusual configurations where direct cookie writing isn't desired for some reason. Maybe it defaults to fallback enabled? ✔️ If the JS tracker isn't detected, fallback is enabled and there are no custom cookie settings in the URL params then attempt to load custom cookie settings from the For honoring existing opt outs, maybe we check for an old third party cookie as part of the controller request, if it exists and there is no first party cookie then we use the third party cookie value as an initial opt out state and then immediately write the first party cookie to match it, but when we detect that a first party cookie exists then we just ignore the third party cookie. This would 'migrate' existing third party cookies to first party. Do you think that would work? 🤔 I think I have enough to get started, so I can try to implement the 'migrate' cookies approach if we think it will work and then we can test the user experience to see if anything needs to be tweaked. |
It may work in some browsers. I'm not 100% sure how all the browsers handle third party cookies these days. Ignoring the third party cookie would mean effectively deleting the third party cookie in the controller request I assume. AFAIK at least Safari would block such a deletion but that could be fine (or maybe it would even work :) ). In the worst case a user would stay opted out which could be fine. It's mostly only an issue if a website owner previously opted out via 3rd party cookie and then they want to migrate the opt out and test if it works and then opting in and out again might not work. Maybe it all works nicely though and maybe we could also ignore this edge case. |
Customer’s message: During testing we have identified an issue regarding the opt-out iFrame message- see below. The iFrame message appears as it should do when viewed using a PC but when viewed on an Apple device (safari browser), user see the message in red below. It seems like apple software is automatically set to block cookies unless user opt-in via their devices privacy settings. |
Just a quick thought: The case where people have the matomo.js loading correctly sounds great to me, but I think we should change the other one: If matomo.js is blocked (let's assume the user has an ad-blocker enabled) and one wants to opt out. Even with 30s timeout, people would just assume that Matomo if forcing everyone to do the incredibly user-hostile "wait for this extremely long loading bar to move to opt out" that far too many websites are doing and go away with a bad impression of Matomo (while with the iFrame at the moment they would think that the opt-out is quite easy). And this brings me to another issue: What to do if the |
Some good points there @Findus23 👍
It's definitely not ideal, do you have an alternative approach to waiting 30 seconds to see if matomo.js loads? If we don't wait at all or wait for only a few seconds then the tracker code will be rarely used, at which point it would probably be better to ignore it altogether. For comparison the current iframe JavaScript will wait two minutes for matomo.js to load and then fail silently.
The fallback option would be enabled by default, so the choice to disable it would only be there to provide flexibility for sites that need it. (Maybe matomo.js has been modified and it's not appropriate to set direct cookies? Or some other site config we haven't imagined?)
I suppose we could use an Ajax call instead of a direct <div id="m-opt-out"></div>
<script>
showOptOut('foo');
function showOptOut (id) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
eval(xhr.responseText);
} else {
document.getElementById("m-opt-out").innerHTML = "failed to load tracking opt out";
}
xhr.open('GET', '/index.php?module=CoreAdminHome&action=optOut&language=en&backgroundColor=FFF');
xhr.send();
}
</script>
We could add a placeholder to the generated code with some sort of hard coded loading message. The opt-out generator UI could provide an option for the user to set this message. <div id="m-opt-out">... Tracking opt out is loading ...</div> It seems like the only way to be sure that the opt-out will not be blocked would be to have the generated opt-out code be entirely self-contained, which is already covered by the alternative / custom option specified above. If the self-contained code could be kept compact and fairly simple then I wonder whether it would be a better default option for the out-out generated code since it would be more reliable? The optOutJs version with a <script> tag compatible with the iFrame version could then be an easier upgrade option for existing opt out users (if a little less reliable). @tsteur Do you have any thoughts? |
I don't have any strong thoughts. I've seen some platforms offering self-contained code and they copy/paste the entire code into the page. The problem being that if there's any regression or browser incompatibility or other change then users will likely not know when they should update this self-contained code and it can often be complicated to get it changed. On the other side of course it won't be blocked. For example if anything changes around cookies (which it did in the past) then the optOut might break. Maybe if the OptOut JS is blocked, then users also wouldn't be tracked and it wouldn't be as much of an issue? Or maybe we could also get the path allowed in some privacy filters? Generally I don't have a big preference though either way. I guess in the end we might just give people the option to either self contain the code (see https://developer.matomo.org/guides/tracking-javascript-guide#optional-creating-a-custom-opt-out-form) or use the code that loads a file? |
This issue has been mentioned on Matomo forums. There might be relevant details there: |
3rd party cookies work less and less and eventually won't be available anymore. Kind of related post https://matomo.org/blog/2020/02/new-cookie-behaviour-in-browsers-may-cause-regressions/ For the opt in to work we therefore need a different way and set first party cookies.
Matomo for WordPress already doesn't use the opt out iframe anymore and sets first party cookies. In On-Premise as part of #12767 we already added the support of
postMessages
to set first party cookies when possible. This however currently only works in some cases (eg when the tracking code is embedded on the same page and both opt out and tracking code use the same Matomo domain).In the future ideally we show a message in the opt out iframe when it won't work because eg there's no tracking code on the privacy policy page. We might even want to completely remove the third party cookie part (however we'd still need to detect it when it's set and not track to not break BC and to not suddenly start tracking users that oped out previously). Maybe we could even remove the domain check and opt users out in more cases even if there is a mismatch between the opt out iframe and the tracking domain on the privacy policy page.
Or maybe we would need to offer a new way of embedding the opt out without any iframe. This would likely require loading another JS and some configuration to customise it and for Matomo to know where to place it (unless this is all stored in a JS file and the user can configure multiple different JS opt out files).
The text was updated successfully, but these errors were encountered: