klaro-js icon indicating copy to clipboard operation
klaro-js copied to clipboard

Callback function after saving preferences

Open comede opened this issue 5 years ago • 19 comments

Would it be possible to habe a callback-function after saving the preferences. e.g. to reload the page after preferences has been saved?

comede avatar Dec 12 '18 08:12 comede

I think this is already implemented (at least kind of).

When the user accepts, rejects or manually toggles apps a callback is ran per app if defined: https://github.com/KIProtect/klaro/blob/15660ffc035ace5c1a38d0bb78205e3315f6429d/src/consent-manager.js#L139-L140

You can specify a callback for those apps that require reloading the page to achieve the same result:

var klaroConfig = {
  privacyPolicy: '/privacy.html',
  // [...]
  apps: [
    // [...]
    {
      name: 'custom-app',
      default: true,
      title: 'My custom app',
      callback: function(consent, app) {
        window.location.reload();
      }
    }
  ]
}

Note these callbacks are only executed when consent status has changed for that particular app: https://github.com/KIProtect/klaro/blob/15660ffc035ace5c1a38d0bb78205e3315f6429d/src/consent-manager.js#L135-L136

josemmo avatar Jan 01 '19 23:01 josemmo

I don't think that would work for 2 reasons.

  1. The callbacks are also called when klaro initializes. I can see the console.log outputs. So this solution would end in an endless reload-loop, wouldn't it?
  2. Even if not, it would only work, if there is only one app that needs the reload. If there are more than one, the reaload would start even though the user has not set all settings.

What i suggested is a callback funktion on the Close/Save-Button of the Consent Manager where i would prefer to put the page-reload in.

comede avatar Jan 18 '19 12:01 comede

Think I need this too. The normal callback => reload end in a LOD

But I need a reload cause I need to implement this scripts lazy and with the current solution it's not possible.

davidhellmann avatar Nov 08 '19 08:11 davidhellmann

What does the abbreviation LOD mean? What do you refer to as lazy loading? The <script>'s defer or async tags or inserting a script tag with JavaScript?

Does someone have an overview of what all the acceptance criteria are?

jaller94 avatar Nov 08 '19 09:11 jaller94

@jaller94 sorry :) => loop of dead

I use lazysizes. it works also with data-src and class="lazyload"

But I think it would be not a Problem when there is a possibility to have a global callback.

davidhellmann avatar Nov 08 '19 11:11 davidhellmann

ok lazyloading works when it do it this way:

{% set klaro = getCookie('klaro') | json_decode %}
    <div type="opt-in" data-name="youtube"></div>

    {% if klaro and klaro.youtube %}
      <iframe width="560"
              height="315"
              class="lazyload"
              data-src="https://www.youtube.com/embed/u8SEv6WVsuE"
              frameborder="0"
              allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
              allowfullscreen></iframe>
    {% endif %}

But, when I change the settings I have to reload the page. but when I add it to the callback here it reloads in a loop:

{
                name: 'googleAnalytics',
                default: true,
                title: 'Google Analytics',
                purposes: ['statistics'],
                cookies: [
                    ['_ga', '/', cookieDomain],
                    ['_gat', '/', cookieDomain],
                    ['_gid', '/', cookieDomain],
                ],
                callback: function (consent, app) {
                    console.log("User consent for app " + app.name + ": consent=" + consent);
                    location.reload();
                },
            },

davidhellmann avatar Nov 08 '19 11:11 davidhellmann

One use-case for this in addition to the OPs requirement is for consent logging. When a user saves their preferences a callback could be made to an endpoint which logs the pertinent information. This would probably be better served as a global callback rather than having to implement something for every single application.

How about adding a callback on save?

https://github.com/KIProtect/klaro/blob/master/src/consent-manager.js#L125

    saveConsents(){
        if (this.consents === null)
            deleteCookie(this.cookieName)
        const v = JSON.stringify(this.consents)
        setCookie(this.cookieName, v, this.config.cookieExpiresAfterDays || 120)
        this.confirmed = true
        this.changed = false
+        if(!!this.config.saveCallback){
+            this.config.saveCallback(this.consents);
+        }
    }

sPooKee avatar Nov 27 '19 15:11 sPooKee

@sPooKee Might be better to just check if the callback is a function

if(typeof this.config.saveCallback === 'function'){
    this.config.saveCallback(this.consents);
}

But that does look like a good place for the callback to come in

I was looking for exactly the same thing: A reload after a consent was revoked to throw out lazy loaded scripts. This would be hugely beneficial for the consistence of the user flow (e.g. an integrated customer chat popup does not work anymore if I let klaro delete it's session cookies but not remove the chat itself from the page).

I would propose a declarative configuration style, meaning that there should be a new key-value pair in the configuration of any app just like required: boolean, optOut: boolean or onlyOnce: boolean. Something like: reloadPageAfterRevoke: boolean. The library should then trigger one reload if at least one of the registered apps that were just revoked by the user have that flag set to true.

This would be very easy to use and also be possible to note down in yaml syntax that's used by some frameworks to do package configuration without touching programming logic. This makes it very neat to integrate in CMS systems like Neos.

klfman avatar Jan 09 '20 09:01 klfman

Adding to my previous comment: If I create a placeholder for something, lets say a video (like for example discussed here: https://github.com/KIProtect/klaro/issues/157) and want to embed it if the user consents, it would be neat to have this function, too. reloadPageAfterConsent: boolean would be a nice counterpart to reloadPageAfterRevoke: boolean on the configuration level of a single app which would do the reload only once for all apps together upon saving the new preferences. What do you think?

I think the cost/benefit ratio of this feature is good :)

I don't have the skills to create a pull request for this project right now. But I will gladly test this and open issues in case I see any problems.

Would be cool to see this integrated!

klfman avatar Feb 25 '20 10:02 klfman

Sounds like a great idea indeed, we'll implement this!

adewes avatar Feb 25 '20 15:02 adewes

Thanks @adewes, very much appreciated! ❤️ Are you planning to implement that soonish?

klfman avatar Feb 27 '20 15:02 klfman

Hello, has this been pushed to the latest build yet? If not, is there a workaround I can use in the meantime?

RFreiwang avatar Jun 10 '20 11:06 RFreiwang

We also need this for consent logging and callbacks for GTM. It would be great to have that I've seen https://github.com/KIProtect/klaro/pull/195 but that also introduces a snapdragon dependency?! Would be great to have that in a next build soon. And thnx for that great library so far!

soey avatar Jun 10 '20 20:06 soey

https://github.com/kiprotect/klaro/pull/195 Why was this PR closed even though the changes made doesn't exists in this repo?

EDIT : just have found the new saveConsents notify event in master, will it be in next build ?

Striffly avatar Aug 26 '20 13:08 Striffly

Did someone ever find a solution to this problem? We need to refresh the page after consent is saved/updated. Got no clue on how to fix this issue. Plz help?

studiovlijmscherp avatar Oct 09 '20 15:10 studiovlijmscherp

Hi @studiovlijmscherp, we have a callback now that you can use for this purposes, like this:

let manager = klaro.getManager() // get the consent manager
manager.watch({
  update: function(manager, eventType, data){
     // your logic here...
  }
}) //

The consent manager will emit a saveConsents call with a dict as data that contains changes (changed consent choices), consents (consent choices for all services) and type (either save, accept or decline).

Does that fulfill your requirements? We haven't documented this publicly yet as we might change the interface a bit.

adewes avatar Oct 09 '20 17:10 adewes

Btw @Striffly we closed this PR since we merged it with another change by the same author, if I remember correctly.

adewes avatar Oct 09 '20 17:10 adewes