Creating a Custom Consent UI
We provide an open source reference UI package that can be extended however you see fit. This package provides a strong foundation with full regime-specific UI integration, compatibility with our auto-prompt functionality, and translations for 54 languages.
https://github.com/transcend-io/consent-manager-ui
See this doc to learn more about customizing the stylesheet (CSS) for our out-of-the-box UIs rather than building an entirely custom UI.
To prevent our default UI module from loading, add a data-ui="off"
attribute to your airgap.js script tag.
If your own UI is available as a discrete external JavaScript file, you can optionally replace our UI module and airgap.js will asynchronously auto-load your module instead by specifying a URL in the data-ui
script attribute.
If your UI setup code runs before airgap.js core is initialized, you will need to use airgap.ready()
as demonstrated below:
// Stub airgap.js ready queue if (!self?.airgap?.ready) { self.airgap = { readyQueue: [], ready(callback) { this.readyQueue.push(callback); }, ...self?.airgap, }; } // Wait for airgap.js core to load self.airgap.ready((airgap) => { // Init your UI DOM here });
Every airgap.js API that can mutate consent state requires a genuine user gesture (event.isTrusted == true
) which can be either any UIEvent
(e.g. click
) or a form submit
event.
Script load
events that fired prior to airgap.js initialization can also be used as valid consent authorization.
<script data-cfasync="false" src="https://transcend-cdn.com/cm/443312ef-12f9-494d-85f5-969894260cc7/airgap.js" onload="setAirgapAuth(event);" ></script>
You should pass the load event value to your own trusted code for safekeeping in setAirgapAuth(event)
.
That event can later be used when authorization is required, like for airgap.getConsent()
(see below)
airgap.setConsent(getAirgapAuth(), consent);
airgap.getConsent()
returns an TrackingConsentDetails
descriptor. This descriptor has a purposes
field which returns an object keyed by all consentable tracking purpose types. The descriptor also has an ISO 8601 timestamp accessible via the timestamp
field.
getConsent() Example
await airgap.sync(); const consent = airgap.getConsent().purposes; console.log(JSON.stringify(consent, null, 2));
airgap.getConsent().purposes
output:
{ "Functional": false, "Analytics": false, "Advertising": false }
airgap.setConsent()
sets user consent for individual tracking purposes. A trusted interaction Event (or the script load event for the airgap.js script) is required by this API.
Example
saveConsentButton.addEventListener('click', (interaction) => { airgap.setConsent(interaction, serializeConsent()); });
ℹ️ The first argument to
airgap.setConsent
must be a nativeclick
orsubmit
Event. If you're using React, your event may be a SyntheticEvent. In this case, you will need to passinteraction.nativeEvent
.
await airgap.sync(); const hasPrivacyRights = airgap.getRegimePurposes().size !== 0; // Is user fully opted-in to core unessential tracking purposes: // Functional, Analytics, and Advertising const isOptedIn = airgap.isOptedIn(); // a similar utility is available for detecting full opt-out // of these purposes: // const isOptedOut = airgap.isOptedOut(); const consentForm = document.getElementById('...'); const consentCheckbox = document.getElementById('...'); consentCheckbox.checked = isOptedIn; if (hasPrivacyRights) { consentCheckbox.addEventListener('change', (interaction) => { if (interaction.target.checked) { // Consent to all user-configurable tracking purposes airgap.optIn({ interaction }); } else { // Opt-out of all user-configurable tracking purposes airgap.optOut({ interaction }); } }); } else { consentForm.style.display = 'none'; consentCheckbox.disabled = true; }
Consent can be set on a per-purpose level using airgap.getConsent()
, airgap.setConsent()
, and airgap.getPurposesTypes()
.
airgap.getPurposesTypes()
returns airgap's current TrackingPurposesTypes
config. This config data can be used in conjunction with airgap.getConsent()
to inform the content of a custom consent UI.
const purposes = airgap.getPurposesTypes(); console.log(JSON.stringify(purposes, null, 2));
airgap.getPurposesTypes()
example output:
{ "Functional": { "name": "Functionality", "description": "Personalization, autofilled forms, etc.", "defaultConsent": false, "showInConsentManager": true, "configurable": true, "essential": false }, "Analytics": { "name": "Analytics + Performance", "description": "Help us learn how our site is used and how it performs.", "defaultConsent": false, "showInConsentManager": true, "configurable": true, "essential": false }, "Advertising": { "name": "Targeting / Advertising", "description": "Helps us and others serve ads relevant to you.", "defaultConsent": false, "showInConsentManager": true, "configurable": true, "essential": false }, "Essential": { "name": "Essential", "description": "", "defaultConsent": true, "showInConsentManager": false, "configurable": false, "essential": true }, "Unknown": { "name": "Unknown", "description": "", "defaultConsent": false, "showInConsentManager": false, "configurable": false, "essential": false } }