Skip to main content

Migration of the CMP implementation

Since version 32.0.0 of the CMP, the implementation in your website has been simplified. In the page, we will see how to migrate step by step from old implementation to the new one.


New implementation

The code to be implemented in your website is provided under each notice in the configuration interface and can be easily copied using the "Copy" button. All that remains is to paste the code into the <head> section of your website.

Event listener

The event listener has been integrated directly into the notice, so it is no longer necessary to add it on all the pages of your website. You can therefore remove the following script from your website.

To delete
<!-- ADD EVENTLISTENER -->
<script type="text/javascript">
(adsbygoogle=window.adsbygoogle||[]).pauseAdRequests=1,window.dataLayer=window.dataLayer||[],__tcfapi("addEventListener",2,function(e,n){if(n&&e.gdprApplies&&("tcloaded"===e.eventStatus||"useractioncomplete"===e.eventStatus)){if((adsbygoogle=window.adsbygoogle||[]).pauseAdRequests=0,e.purpose.consents)
for(var s in window.dataLayer.push({AppConsent_IAB_PURPOSES:e.purpose.consents}),e.purpose.consents)e.purpose.consents[s]&&window.dataLayer.push({event:"appconsent_ctrl_"+s});var o,a;e.acExtraPurposes&&(o={},e.acExtraPurposes.forEach(function(e){o[e]=!0}),window.dataLayer.push({AppConsent_EXTRA_PURPOSES:o})),e.acExtraVendors&&(a={},e.acExtraVendors.forEach(function(e){a[e]=!0}),window.dataLayer.push({AppConsent_EXTRA_VENDORS:a})),e.purpose.consents&&e.vendor.consents&&("object"==typeof sfbxguardian&&e.purpose.consents[1]&&window.sfbxguardian.unblock(),"function"==typeof gtag&&(e.purpose.consents[1]&&e.vendor.consents[755]?gtag("consent","update",{analytics_storage:e.purpose.consents[7]||e.purpose.consents[9]?"granted":"denied",ad_storage:e.purpose.consents[3]?"granted":"denied "}):gtag("consent","update",{analytics_storage:"denied",ad_storage:"denied"})))}window.dataLayer.push({event:"appconsent_loaded"})});
</script>
<!-- END EVENTLISTENER -->

The init and show commands

From now on, the init and show commands are automatically executed at the initialization of the notice and this implies changes in the implementation of the notice.

The init command

Previously, it was necessary to implement the following script in the <body> section of HTML pages.

To delete
<script type="text/javascript">
__tcfapi('init', 2, console.log, {
appKey: 'YOUR_APP_KEY',
url: 'https://collector.appconsent.io',
// targetCountries: ['FR', 'UK', 'US'],
// forceGDPRApplies: true,
})
</script>

Callback of the init command

If you have defined a callback in the init command, you must now add it to the configSFBXAppConsent configuration variable in the callbacks parameter.

As a reminder, the callback will be executed at the end of the initialization of the notice. And takes as input parameters error and state.

info

In the documentation for the old implementation, we suggested putting console.log as a callback to the command. If you are in this case, it is no longer necessary to set it as callback.

Example of init callback configuration :

<script type="text/javascript">
const configSFBXAppConsent = {
appKey: 'YOUR_APP_KEY',
callbacks: {
init: ( error, state ) => {},
}
}
</script>

The show command

Same as the init command, the show command no longer needs to be implemented like this :

To delete
<script type="text/javascript">
__tcfapi('show', 2, console.log, {
lazy: true,
})
</script>

Callback of show command

If you defined a callback in the show command, you must now add it to the configSFBXAppConsent configuration variable in callbacks parameter.

As a reminder, this callback will be executed at the end of the command execution. And takes as input parameter error.

info

In the example code of the old implementation, we proposed in the documentation to put console.log in the callback of the command If you are in this case, it is no longer necessary to put it in callback.

Example of callback configuration :

<script type="text/javascript">
const configSFBXAppConsent = {
appKey: 'YOUR_APP_KEY',
callbacks: {
show: ( error ) => {}
}
}
</script>

Change in the configuration of the cmp

Option url

The url option has now the following default value : https://collector.appconsent.io. It is not necessary to have this option in your cmp configuration, if you use this url.

old implementation
<script type="text/javascript">
__tcfapi('init', 2, console.log, {
appKey: 'YOUR_APP_KEY',
url: 'https://collector.appconsent.io',
})
</script>

New implementation

<script type="text/javascript">
const configSFBXAppConsent = {
appKey: 'YOUR_APP_KEY'
}
</script>

Option lazy

The lazy option is now enabled by default, if you had enabled the lazy option, it is no longer required to have it in the configuration.

old implementation
<script type="text/javascript">
__tcfapi('show', 2, console.log, {
lazy: true,
})
</script>

New implementation

<script type="text/javascript">
const configSFBXAppConsent = {
appKey: 'YOUR_APP_KEY'
}
</script>

Guardian

If you haven't implemented guardian, you can skip this chapter.

The guardian configuration has been changed. Previously, it was necessary to add a <script> tag in which you defined the urls you wanted to blacklist or whitelist.

Old implementation
<script>
window.SFBX_GUARDIAN_BLACKLIST = [
/facebook/, /youtube/,
]
// Or a whitelist
window.SFBX_GUARDIAN_WHITELIST = [
/appconsent/,
]
</script>

Now this configuration must be put in the configuration variable configSFBXAppConsent with the parameter dynamicallyLoadedScripts with two subparts blacklist and whitelist.

<script type="text/javascript">
const configSFBXAppConsent = {
appKey: 'YOUR_APP_KEY',
dynamicallyLoadedScripts: {
blacklist: [
/facebook/, /youtube/,
],
whitelist: [
/appconsent/,
]
},
}
</script>

The Guardian script has been changed to accommodate this new way of configuring Guardian. So you have to replace the old <script> tag containing the Guardian code with this one:

To change
<script>
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).sfbxguardian={})}(this,function(t){"use strict";function o(e,t){return e&&(!t||t!==c)&&(!s.blacklist||s.blacklist.some(function(t){return t.test(e)}))&&(!s.whitelist||s.whitelist.every(function(t){return!t.test(e)}))}function l(t){var e=t.getAttribute("src");return s.blacklist&&s.blacklist.every(function(t){return!t.test(e)})||s.whitelist&&s.whitelist.some(function(t){return t.test(e)})}if(typeof configSFBXAppConsent === 'undefined'){console.error('SFBX Guardian has not been executed! The configuration (configSFBXAppConsent) must be placed before calling the script '); return}if(!configSFBXAppConsent.dynamicallyLoadedScripts||(!configSFBXAppConsent.dynamicallyLoadedScripts.blacklist&&!configSFBXAppConsent.dynamicallyLoadedScripts.whitelist)){console.warn('SFBX Guardian: No whitelist or blacklist has been defined'); return;}var c="javascript/blocked",s={blacklist:configSFBXAppConsent.dynamicallyLoadedScripts.blacklist,whitelist:configSFBXAppConsent.dynamicallyLoadedScripts.whitelist},u={blacklisted:[]},f=new MutationObserver(function(t){for(var e=0;e<t.length;e++)for(var i=t[e].addedNodes,r=function(t){var r=i[t];if(1===r.nodeType&&"SCRIPT"===r.tagName){var e=r.src,n=r.type;if(o(e,n)){u.blacklisted.push([r,r.type]),r.type=c;r.addEventListener("beforescriptexecute",function t(e){r.getAttribute("type")===c&&e.preventDefault(),r.removeEventListener("beforescriptexecute",t)}),r.parentElement&&r.parentElement.removeChild(r)}}},n=0;n<i.length;n++)r(n)});f.observe(document.documentElement,{childList:!0,subtree:!0});var i=document.createElement,a={src:Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src"),type:Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"type")};function p(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(t)))return;var r=[],n=!0,i=!1,o=void 0;try{for(var c,a=t[Symbol.iterator]();!(n=(c=a.next()).done)&&(r.push(c.value),!e||r.length!==e);n=!0);}catch(t){i=!0,o=t}finally{try{n||null==a.return||a.return()}finally{if(i)throw o}}return r}(t,e)||r(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t))return Array.from(t)}(t)||r(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function r(t,e){if(t){if("string"==typeof t)return n(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?n(t,e):void 0}}function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}document.createElement=function(){for(var t=arguments.length,e=new Array(t),r=0;r<t;r++)e[r]=arguments[r];if("script"!==e[0].toLowerCase())return i.bind(document).apply(void 0,e);var n=i.bind(document).apply(void 0,e);try{Object.defineProperties(n,{src:{get:function(){return a.src.get.call(this)},set:function(t){o(t,n.type)&&a.type.set.call(this,c),a.src.set.call(this,t)}},type:{set:function(t){var e=o(n.src,n.type)?c:t;a.type.set.call(this,e)}}}),n.setAttribute=function(t,e){"type"===t||"src"===t?n[t]=e:HTMLScriptElement.prototype.setAttribute.call(n,t,e)}}catch(t){console.warn("sfbxguardian: unable to prevent script execution for script src ",n.src,".\n",'A likely cause would be because you are using a third-party browser extension that monkey patches the "document.createElement" function.')}return n};var y=new RegExp("[|\{}()[\\]^$+*?.]","g");t.unblock=function(){for(var t=arguments.length,r=new Array(t),e=0;e<t;e++)r[e]=arguments[e];r.length<1?(s.blacklist=[],s.whitelist=[]):(s.blacklist&&(s.blacklist=s.blacklist.filter(function(e){return r.every(function(t){return"string"==typeof t?!e.test(t):t instanceof RegExp?e.toString()!==t.toString():void 0})})),s.whitelist&&(s.whitelist=[].concat(d(s.whitelist),d(r.map(function(e){if("string"==typeof e){var r=".*"+e.replace(y,"\\$&")+".*";if(s.whitelist.every(function(t){return t.toString()!==r.toString()}))return new RegExp(r)}else if(e instanceof RegExp&&s.whitelist.every(function(t){return t.toString()!==e.toString()}))return e;return null}).filter(Boolean)))));for(var n=document.querySelectorAll('script[type="'.concat(c,'"]')),i=0;i<n.length;i++){var o=n[i];l(o)&&(u.blacklisted.push([o,"application/javascript"]),o.parentElement.removeChild(o))}var a=0;d(u.blacklisted).forEach(function(t,e){var r=p(t,2),n=r[0],i=r[1];if(l(n)){var o=document.createElement("script");for(var c in"undefined"!==n.src&&o.setAttribute("src",n.src),o.setAttribute("type",i||"application/javascript"),n)c.startsWith("on")&&(o[c]=n[c]);document.head.appendChild(o),u.blacklisted.splice(e-a,1),a++}}),s.blacklist&&s.blacklist.length<1&&f.disconnect()},Object.defineProperty(t,"__esModule",{value:!0})});
</script>

Please go tho this page to get last instructions to use Google Consent Mode v2 with our CMP.

How to implement GCM

Implementing our CMP using Google Tag Manager

The third solution proposed was to use your tag manager to trigger Google Analytics tags based on the purpose_events sent to the dataLayer. Depending on what you have implemented in your pages, you can remove it to migrate to the new implementation.

For more information, see page : Installer Appconsent avec Google Tag Manager