In addition to recording GDPR consent for your forms, our Consent Database also allows you to save consent preferences collected with the Privacy Controls and Cookie Solution. Below we’ll explain how to save proof of consent to cookies with the combination of both solutions.
If you need to track consent preferences across different devices, jump to the advanced integration method.
Once you’ve activated the Consent Database, copy the snippet you find on Dashboard > [Your website] > Consent Database > Embed and paste it in the HEAD of your pages:
<!-- Consent Database -->
<script type="text/javascript">
var _iub = _iub || {};
_iub.cons_instructions = _iub.cons_instructions || [];
_iub.cons_instructions.push(["init", {
api_key: "YOUR_PUBLIC_API_KEY" //use your API key
}]);
</script>
<script type="text/javascript" src="https://cdn.iubenda.com/cons/iubenda_cons.js" async></script>
The API key (displayed as “YOUR_PUBLIC_API_KEY” in the example above) is a unique code generated by us during the Consent Database activation and is specific to the particular site.
The Consent Database code will be followed by the Privacy Controls and Cookie Solution script. Once configured and saved your cookie banner, the Privacy Controls and Cookie Solution snippet will be similar to this:
<!-- Privacy Controls and Cookie Solution -->
<script type="text/javascript">
var _iub = _iub || [];
_iub.csConfiguration = {
"lang": "en",
"siteId": XXXXXX, //use your siteId
"cookiePolicyId": YYYYYY, //use your cookiePolicyId
"banner": {
"position": "float-top-center",
"acceptButtonDisplay": true,
"customizeButtonDisplay": true
}
};
</script>
<script type="text/javascript" src="//cdn.iubenda.com/cs/iubenda_cs.js" charset="UTF-8" async></script>
In order to pass consent preferences to the Consent Database we’ll have to define a bannerHTML
variable (via which we’ll save the banner HTML to use it as a proof) and a couple of callbacks:
<!-- Privacy Controls and Cookie Solution -->
<script type="text/javascript">
var _iub = _iub || [];
var bannerHTML; //bannerHTML variable
_iub.csConfiguration = {
"lang": "en",
"siteId": 896537, //use your siteId
"cookiePolicyId": 8207462, //use your cookiePolicyId
"banner": {
"position": "float-top-center",
"acceptButtonDisplay": true,
"customizeButtonDisplay": true
},
"callback": {
"onReady": function() {
var banner = document.getElementById('iubenda-cs-banner');
if (banner) {
bannerHTML = banner.innerHTML;
}
},
"onPreferenceFirstExpressed": function(event) {
_iub.cons_instructions.push(["submit",
{
consent: {
subject: {},
preferences: event,
legal_notices: [{
identifier: "cookie_policy"
}],
proofs: [{
content: JSON.stringify(event),
form: bannerHTML
}]
}
}
]);
}
}
};
</script>
<script type="text/javascript" src="//cdn.iubenda.com/cs/iubenda_cs.js" charset="UTF-8" async></script>
Once implemented, your Consent Database dashboard will store all the cookie consent preferences collected through the cookie banner:
You can also store any additional parameters you’d like to add to your cookie consent proofs, such as consent method (e.g. consentOnScroll , consentOnLinkAndButton), purposes etc.
If you need to track preferences of a user across different devices (e.g. website and mobile app), you’ll have to call the Consent Database at every pageview to keep the preferences constantly in sync among multiple Privacy Controls and Cookie Solution installations.
Let’s see how to do it.
As before, once you’ve activated the Consent Database, copy the snippet you find on Dashboard > [Your website] > Consent Database > Embed and paste it in the HEAD of your pages:
<!-- Consent Database -->
<script type="text/javascript">
var _iub = _iub || {};
_iub.cons_instructions = _iub.cons_instructions || [];
_iub.cons_instructions.push(["init", {
api_key: "YOUR_PUBLIC_API_KEY" //use your API key
}]);
</script>
<script type="text/javascript" src="https://cdn.iubenda.com/cons/iubenda_cons.js" async></script>
The API key (displayed as “YOUR_PUBLIC_API_KEY” in the example above) is a unique code generated by us during the Consent Database activation and is specific to the particular site.
Again, the Consent Database code will be followed by the Privacy Controls and Cookie Solution script. Once configured and saved your cookie banner, the Privacy Controls and Cookie Solution snippet will be similar to this:
<!-- Privacy Controls and Cookie Solution -->
<script type="text/javascript">
var _iub = _iub || [];
_iub.csConfiguration = {
"lang": "en",
"siteId": XXXXXX, //use your siteId
"cookiePolicyId": YYYYYY, //use your cookiePolicyId
"banner": {
"position": "float-top-center",
"acceptButtonDisplay": true,
"customizeButtonDisplay": true
}
};
</script>
<script type="text/javascript" src="//cdn.iubenda.com/cs/iubenda_cs.js" charset="UTF-8" async></script>
In order to pass consent preferences to the Consent Database, we’ll have to define two callbacks that are fired by the Privacy Controls and Cookie Solution to address all cases where a synchronization is needed:
<script type="text/javascript">
var _iub = _iub || [];
_iub.csConfiguration = {
"lang": "en",
"siteId": XXXXXX, //use your siteId
"cookiePolicyId": YYYYYY, //use your cookiePolicyId
"banner": {
"position": "float-top-center",
"acceptButtonDisplay": true,
"customizeButtonDisplay": true
},
"callback": {
"onReady": function() {
consSyncronizer();
},
"onPreferenceFirstExpressed": function(preferences) {
consSyncronizer();
}
}
};
</script>
Now we’ll need two functions to address three steps:
consPreflight
.onReady
callback) and checks whether the device consent and the Consent Database consent are in sync. We’ll call it consSyncronizer
.consSyncronizer
will fire also when the preferences for the Privacy Controls and Cookie Solution are reopened and changed. We’ll have to repeat these three steps at each pageview. Let’s see them in a little more detail.
In order to avoid the banner to show up if a remote consent is present for a given user, this function queries the Consent Database for a subject_id
(which is used to uniquely identify a user) and tries to retrieve his cookie preferences:
subject_id
is not found and the local cookie that stores the consent is not found either, the Privacy Controls and Cookie Solution is activated and the banner is shown. This is most likely the first visit of the user. subject_id
is not found but the local cookie is present, it is pushed to the Consent Database and the returned subject_id
is stored. The Privacy Controls and Cookie Solution is then activated, but the banner is not shown. This is the case for a user that gave consent before this logic has been implemented. subject_id
is found and the local cookie is not present, the remote preferences are used to create a local consent cookie. The Privacy Controls and Cookie Solution is activated and the banner is not shown. This is the case for users that expressed a preference on one instance of the Privacy Controls and Cookie Solution (e.g. web), and then visited a second instance (e.g. mobile). subject_id
and the local cookie are found, nothing is done at this stage and the Privacy Controls and Cookie Solution is activated. This is the most common case for users that keep navigating the site.function consPreflight() {
// Check if the subject id is available
var subject_id = localStorage.getItem('subject_id');
if (subject_id) {
// Subject id available, check if we need to pull from the Consent Database before activating the Privacy Controls and Cookie Solution
// Try to the fetch the Privacy Controls and Cookie Solution local cookie
var cookiePolicyId = _iub.csConfiguration.cookiePolicyId;
var cookieName = '_iub_cs-' + cookiePolicyId;
var cookieLocal = getCookie(cookieName);
if (cookieLocal === null) {
// No local consent (cookie) found, but a remote consent (Consent Database) likely exists
// Fetch the remote consent and create a local consent from it
// Perform a request for the given subject_id to the Consent Database
// WARNING: This uses the private key and should be done in the backend
$.ajax({
url: "https://consent.iubenda.com/subjects/" + subject_id,
type: "GET",
headers: { "ApiKey": "vs3hcMXwsqrrauIfmW14pFHcUIm9CVvp" }
})
.done(function(data, textStatus, jqXHR) {
var consPreferences = data.preferences;
// Create the local consent with the remote consent info
var cookieContent = {timestamp: consPreferences.cookieTimestamp.value, version: consPreferences.cookieVersion.value, purposes: consPreferences.cookiePurposes.value, id: cookiePolicyId};
setCookie(cookieName, escape(JSON.stringify(cookieContent)), 365);
if (_iub.csConfiguration.enableTCF) {
// If the Privacy Controls and Cookie Solution uses the TCF...
if (consPreferences.cookieTCFv2) {
// ...create a cookie for the TCF...
var cookieTcfName = 'iubeuconsent-v2';
var cookieTcfContent = consPreferences.cookieTCFv2.value;
setCookie(cookieTcfName, cookieTcfContent, 365);
}
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
// If the request fails, a few retries should be performed before activating the Privacy Controls and Cookie Solution
activateCookieSolution();
})
.always(function() {
// Once the request and the syncronization is finished, activate the Privacy Controls and Cookie Solution
activateCookieSolution();
});
} else {
// Local consent (cookie) found, we don't need to do any pre-configuration
activateCookieSolution();
}
} else {
// No subject_id available, so we have nothing to syncronize from
activateCookieSolution();
}
}
For demonstration purpose only, we store the subject_id
in the localStorage. A production application should bind a user and a subject_id
at database level or anyway in a more reliable way than the browser localStorage.
Also, the GET requests to the Consent Database are possible only using the private key (since the public key is write only). This key should not be disclosed publicly in the frontend of the application. The GET requests should therefore be performed in the backend and the results passed to the Privacy Controls and Cookie Solution.
This function fires when the Privacy Controls and Cookie Solution activates (onReady
callback) and checks whether the device consent and the Consent Database consent (if present, or if created in one of the previous cases) are in sync.
This is done by comparing the timestamp of the cookie with the Consent Database preferences:
function consSyncronizer() {
// Check if the subject id is available
var subject_id = localStorage.getItem('subject_id');
// Gather all the local consent info
var cookiePurposes = _iub.cs.consent.purposes;
var cookieTimestamp = _iub.cs.consent.timestamp;
var cookieVersion = _iub.cs.consent.version;
var cookiePolicyId = _iub.cs.consent.id;
if (subject_id === null) {
// No subject_id found...
if (cookieTimestamp == undefined) {
// ...and also no local consent. This is most likely a first time visit
return;
} else {
// ...but local consent found. It has probably never been sent to the ConS, so do it now
var cookiePreferences = {cookiePurposes: cookiePurposes, cookieTimestamp: cookieTimestamp, cookieVersion: cookieVersion, cookiePolicyId: cookiePolicyId};
tcfAddPreferences(cookiePreferences, function() {
consPreferencesPost({}, cookiePreferences);
});
return;
}
}
// Both a subject_id and a local consent found, check if they need to be synced
// Query the ConS and retrieve the remote consent for the given subject
$.ajax({
url: "https://consent.iubenda.com/subjects/" + subject_id,
type: "GET",
headers: { "ApiKey": "vs3hcMXwsqrrauIfmW14pFHcUIm9CVvp" }
})
.done(function(data, textStatus, jqXHR) {
var consPreferences = data.preferences;
// Convert local and remote timestamps into Unix time for easier comparison
var consTimestamp = consPreferences.cookieTimestamp.value;
var cookieUnixTime = new Date(cookieTimestamp).getTime();
var consUnixTime = new Date(consTimestamp).getTime();
if (cookieUnixTime == consUnixTime) {
// Timestamps are equal: the local and remote consents are in sync, do nothing
return;
} else if (cookieUnixTime > consUnixTime) {
// Local timestamp is newer than remote consent: something was changed locally, push the updated consent to ConS
var cookiePreferences = {cookiePurposes: cookiePurposes, cookieTimestamp: cookieTimestamp, cookieVersion: cookieVersion, cookiePolicyId: cookiePolicyId};
tcfAddPreferences(cookiePreferences, function() {
consPreferencesPost({id: subject_id}, cookiePreferences);
});
} else {
// Remote timestamp is newer than local consent: something was changed in another Privacy Controls and Cookie Solution instance and the local consent is now old, get the updated consent from Consent Database
_iub.cs.api.storeConsent({purposes: consPreferences.cookiePurposes.value});
if (_iub.cs.options.enableTCF) {
// If the Privacy Controls and Cookie Solution uses the TCF...
if (consPreferences.cookieTCFv2) {
// ...update the cookie for the TCF...
var cookieTcfName = 'iubeuconsent-v2';
var cookieTcfContent = consPreferences.cookieTCFv2.value;
setCookie(cookieTcfName, cookieTcfContent, 365);
}
}
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log("[consSyncronizer] Consent Database call failed");
});
}
The consSyncronizer
function will fire also when the preferences for the Privacy Controls and Cookie Solution are reopened and changed. This happens when using (for example) a button with the iubenda-cs-preferences-link
class that opens the preferences window.
In this case, since both step 1 and step 2 have already been performed, we can safely assume that the local consent and the remote consent are in sync and that the preference change needs to be pushed to the Consent Database.
Once you’ve implemented these steps along with other additional functions (see our CodePen demo), your Consent Database dashboard will store all the cookie consent preferences collected through the cookie banner across different devices.