oillogo

Version: 1.2.1-RELEASE

Introduction

About oil.js

The OIL project aims for a stable cross-company solution for the challenges the GDPR and new EU ePrivacy Regulation will pose to our business.

  • Data privacy opt-in overlay for all users of services offered by various Axel Springer brands and/or units

  • Local opt-in (called "Site Opt-In", SOI) as well as group-based cross-company opt-in (called "Power Opt-In", POI)

  • Integration and hosting on Tealium with the option to run it standalone.

The Opt-In Layer (OIL) is an offical Consent Management Provider (CMP) after the IAB Europe "Transparency & Consent Framework".

Technical Quality Goals

  • OIL will be held compatible with the latest official browser releases, going back to the latest version as listed below and tested on broad range of browsers using Browserstack.com:

    • Chrome 14 - Latest

    • IE 9 - Latest

    • Firefox 9 - Latest

    • Safari 6 - Latest

    • Opera 12

    • Apple iOS 5.1 - Latest

    • Android 4.4.4 - Latest

  • Continously integrated and delivered

  • Modular and maintainable solution

Features

  • Customisable UI and text with audit-proof versioning

  • Fully configurable (cookie categories, timeouts, …​)

  • Easy AB-Testing with extensive events for each user interaction

  • AB-Tested in different brand specific designs with 250k unique users

  • Supports IAB Europe Standard and additionally custom calls

  • Supports Group-Opt-In

  • Works with 99,9% of all browsers (in Germany) & Works with all devices and all resolutions

  • Optimised for high performance and low latency (build to be loaded first)

  • OpenSource

  • Tested in the cloud on all possible devices

  • Tealium integration and additional features via Tealium like reporting

  • Redirect-Fallback for some older browsers and even for disabled 3rd party cookies in Safari

  • High quality code with high test coverage and static code analysis

  • Loads with low latency and asynchronously for different parts

  • Happy path loads only ~20k (subject to change and further optimization) of gzipped JavaScript

  • Easy to implement with open documentation and examples, including dev kit

  • With SaaS: Domain White Listing against unauthorized usage

Team & Stakeholders

Role/Name Contact

Business Owner

Johannes Fenner, CDP

Legal Affairs

Susanne Stollhoff, Dr. Olaf Koglin

Product Owner

Antonino Tumminelli, AS Ideas Engineering

UX

Özden Gelgec, AS Ideas Engineering

UX

Andreas Wagner, AS Ideas Engineering

Developer

Sebastian Waschnick, AS Ideas Engineering

Developer

Marcel Bankmann, AS Ideas Engineering

Developer

Alexander Glintschert, AS Ideas Engineering

Developer

Dmitri Awerkov-Schäfer, AS Ideas Engineering

Tealium Consulting

Michael Sievers, CDP

Solution Strategy

According the proposal of the Commission, the European Parliament, and the Council of Ministers, a website is required to prompt users with a menu of privacy options when they are visiting for the first time.[1]

The Opt-In Layer (OIL) is our solution for these requirements consisting of three parts:

  • A subscriber part, which adds the opt-in Layer to the host pages DOM and asks the user to opt-in.

  • A hub part, which acts as a registry site for POI on a domain hosted by the content provider/publishder. This is optional and only needed for POI functionality.

Opt-In Information is stored in a first party cookie in the user’s browser and communicated in a general way to the host site and Tealium. For Power Opt-In there is also a 3rd party cookie stored on a second domain to share information between sites.

Why is there no native app support?

Native mobile apps are very customized concerning technology stack and implementation of tracking and advertising. Therefore, the OIL project won’t offer a generic solution for this purpose. Each unit has to review their app how tracking and advertising is implemented and find a solution to get the consent from the user by a dialog. Consents both on desktop or mobile browsers given by the user are not able to be used in the mobile app because: * mobile browsers and in app web views use different ressources to store their cookies * desktop browsers and mobile apps have no physical connections

Quickstart

Minimal setup

<script id="oil-configuration" type="application/configuration">
  {
    "publicPath": "//my.server",
    "locale_url": "//my.server/myLocale.json"
  }
</script>
  • Add OIL and the CMP-stub to your website, with a tag manager like tealium or directly as a tag, i.e.:

<script>
/*! 1.2.1-RELEASE */!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="//oil.axelspringer.com/release/1.2.1/",n(n.s=115)}({115:function(e,t,n){"use strict";!function(e,t){e.__cmp||(e.__cmp=function(){function n(){return!(!e.AS_OIL||!e.AS_OIL.commandCollectionExecutor)}(e.attachEvent||e.addEventListener)("message",function(t){e.__cmp.receiveMessage(t)},!1),function e(){if(!(t.getElementsByName("__cmpLocator").length>0))if(t.body){var n=t.createElement("iframe");n.style.display="none",n.name="__cmpLocator",t.body.appendChild(n)}else setTimeout(e,5)}();var r=[],o=function(o,a,c){if("ping"===o)!function(e){if(e){var r=!0,o=t.querySelector('script[type="application/configuration"]#oil-configuration');if(null!==o&&o.text)try{var a=JSON.parse(o.text);a&&a.hasOwnProperty("gdpr_applies_globally")&&(r=a.gdpr_applies_globally)}catch(e){}e({gdprAppliesGlobally:r,cmpLoaded:n()},!0)}}(c);else{var l={command:o,parameter:a,callback:c};r.push(l),n()&&e.AS_OIL.commandCollectionExecutor(l)}};return o.commandCollection=r,o.receiveMessage=function(e){var t=e&&e.data&&e.data.__cmpCall;t&&r.push({callId:t.callId,command:t.command,parameter:t.parameter,event:e})},o}())}(window,document)}});
</script>
<script type="text/javascript" src="https://oil.axelspringer.com/release/1.2.1/oil.1.2.1-RELEASE.min.js"></script>

OIL SDK

This is a like a drop-in to add a small sdk to any site, which has oil included.

dev kit 01
dev kit 02

Add this to your favorites and open the link on the website you want it to be included:

javascript:(function () {let d = document, s = d.createElement('script');s.id = 'oil-dev-kit-js';s.src = '//oil.axelspringer.com/latest/oildevkit.min.js';(d.head || d.body).appendChild(s)}());

How to implement OIL on your site

Setting up OIL on your page consists of the following steps:

  • Add the oil.js javascript snippet to your page

  • Add a configuration block to your pages DOM

OIL creates a standard for the Opt-In but can’t automatically stop your site from tracking your users. So to actually make your page respond to opt-ins you also need to do the following.

  • Make sure your page doesn’t track the user in its default state.

  • Use Tealium for all tracking activities and use the loading rules we provide

  • Listen to OIL events for loading non-Tealium tags, after the user opted in.

Axel Springer Tealium needs to configure your site to inherit the predefined lib-dip-optin library profile. Once this is in place you publish those changes in the following way:

  • Open your Tealium profile and go to "extensions"

  • Find the entry for "AS Opt-in Overlay", you’ll be noticed of a change to this extension

  • Publish / deploy your profile to activate the changes to Oil.js

Tealium Client Profile

This needs to be repeated for every new version of OIL. The library profile can’t push new code to your website without your action.

Adding oil.js to your site via direct integration

If Tealium can’t be used on your site you also can add OIL directly from our CDN.

Example (replace with the latest version):

<script>
/*! 1.2.1-RELEASE */!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="//oil.axelspringer.com/release/1.2.1/",n(n.s=115)}({115:function(e,t,n){"use strict";!function(e,t){e.__cmp||(e.__cmp=function(){function n(){return!(!e.AS_OIL||!e.AS_OIL.commandCollectionExecutor)}(e.attachEvent||e.addEventListener)("message",function(t){e.__cmp.receiveMessage(t)},!1),function e(){if(!(t.getElementsByName("__cmpLocator").length>0))if(t.body){var n=t.createElement("iframe");n.style.display="none",n.name="__cmpLocator",t.body.appendChild(n)}else setTimeout(e,5)}();var r=[],o=function(o,a,c){if("ping"===o)!function(e){if(e){var r=!0,o=t.querySelector('script[type="application/configuration"]#oil-configuration');if(null!==o&&o.text)try{var a=JSON.parse(o.text);a&&a.hasOwnProperty("gdpr_applies_globally")&&(r=a.gdpr_applies_globally)}catch(e){}e({gdprAppliesGlobally:r,cmpLoaded:n()},!0)}}(c);else{var l={command:o,parameter:a,callback:c};r.push(l),n()&&e.AS_OIL.commandCollectionExecutor(l)}};return o.commandCollection=r,o.receiveMessage=function(e){var t=e&&e.data&&e.data.__cmpCall;t&&r.push({callId:t.callId,command:t.command,parameter:t.parameter,event:e})},o}())}(window,document)}});
</script>
<script type="text/javascript" src="https://oil.axelspringer.com/release/1.2.1/oil.1.2.1-RELEASE.min.js"></script>

Updated versions of the script will be deployed using a different filename hence we’ll never alter an existing version.

Please make sure you’re working with the latest version available.

Please check https://oil.axelspringer.com/release for further updates. Choose the latest version or the version fitting to this documentation. Normalley there will be multiple files:

  • oil.1.0.34-RELEASE.min.js - This is the file you will need to reference in your website

  • hub.1.0.34-RELEASE.min.js

  • Chunks, beginning with numbers - they will ne loaded asynchronously and you don’t need to do anything with them.

    • 0.1.0.34-RELEASE.chunk.js

    • X.1.0.34-RELEASE.chunk.js

Configuring OIL

OIL is configured using a simple JSON configuration block that you put in the upper part of your html.

The Configuration Block

Minimum configuration requires the parameters publicPath and locale or locale_url, so a minimal configuration block would look like this:

<script id="oil-configuration" type="application/configuration">
  {
    "publicPath": "my.server",
    "locale_url": "my.server/myLocale.json"
  }
</script>

locale_url or locale?

There are two ways to pass locale configuration to your OIL instance. One is the configuration parameter locale which is expected to be an object, the other is locale_url signaling OIL to load that same configuration object from the given URL. You can use whichever is better suited for you but make sure that one of the parameters is part of your configuration.

See the functional configuration parameters section for information on publicPath, locale_url, locale and all the other configuration parameters.

Power Opt-In (POI) or Site Opt-In (SOI)?

Before integrating OIL, decide on whether to use Power Opt-In or Site Opt-In. If you want to implement oil.js on a single site you only need the Site Opt-In aka SOI and the above example is enough to make OIL work on your site.

What if you want to share consent across websites? That’s when you need Power Opt-In aka POI.

POI – Power Opt-In

To instantiate oil.js with POI activated, make up a name for your company group (in the example below MyGroupName is used), then follow these steps:

  • Setup a server where the consent cookie is stored. For example any.domain.com.

  • Upload hub.html from the ./release folder, resulting in https://any.domain.com/hub.html

  • Create a MyGroupName.json and upload it in a subfolder named poi-lists to your server, resulting in https://any.domain.com/poi-lists/MyGroupName.json. Note the file name must be the same as the value passed in poi_group_name. For an example see POI-List section.

  • Make sure the MyGroupName.json is served with the right CORS-headers so that your websites are allowed to read it.

  • Add the required parameters to each website configuration that should share the consent cookie:

  "poi_activate_poi": true,
  "poi_hub_origin": "//any.domain.com",
  "poi_hub_path": "/hub.html",
  "poi_group_name": "MyGroupName"

A single consent cookie will now be shared across sites that use the same poi_hub_origin and poi_group_name values. You can have multiple groups on the same domain.

Remember you are legally obliged to list all websites/companies belonging to one group.

Example minimal POI configuration:

<script id="oil-configuration" type="application/configuration">
  {
    "poi_activate_poi": true,
    "poi_hub_origin": "//any.domain.com",
    "poi_hub_path": "/hub.html",
    "poi_subscriber_set_cookie": true,
    "poi_group_name": "MyGroupName",
    "locale_url": "my.server/myLocale.json"
  }
</script>

POI-List

A POI-List file must be a json containing an object with a single property companyList. CompanyList must be an array of company names.

{
"companyList":
  [
    "Foo Comp",
    "Bar Inc."
  ]
}

Functional Configuration Parameters

This is a full list of configurable options.

Config Parameter Description Default Setting

publicPath

The server path from which all chunks and ressources will be loaded. You should upload all released files there and configure it.

None, required

locale

Object including locale version, id and labels. You can define the standard labels for all legal texts and buttons and set a version for it. See here for details

None

locale_url

As an alternative to passing a locale object, set this to a JSON file with the locale configuration. See See here for an example file

None

preview_mode

The preview mode is useful when testing OIL in a production or live environment. As a dev you can trigger the overlay by setting a cookie named "oil_preview" with the value "true". This will show the OIL layer on your client.

false

theme

The theme for the layer. By default there are two themes and size modifier themes, dark and light as well as small dark and small light. Themes currently work only as an additional css class. To change the style or theme, look into the styling guide.

light

poi_activate_poi

Activates or disactivates Power Opt-In.

false

poi_hub_origin

The origin of the hub.js installation, if any.

None

poi_hub_path

The path to the hub.html installation on the origin, if any.

/hub.html

poi_group_name

POI group name. POI only affects those sites with the same group name (mandatory if POI is activated).

none

poi_subscriber_set_cookie

Whether to set the SOI cookie on POI opt-ins or not.

true

cookie_expires_in_days

Value in days until the domain cookie used to save the users decision in days

31

timeout

Value in seconds until the opt-in layer will be automatically hidden. 0 or lower deactivates auto-hide.

60

advanced_settings

Replaces the No Button with a advanced settings button, which enables the user to select between different settings of privacy. The results of this selection is stored in the oil cookie (both SOI and POI) as well.

false

cpc_type

Specifies the type (the layout) of the Cookie Preference Center. Currently, two types are supported: 'standard' and 'tabs'. Depending on this parameter additional label configuration may be necessary. See section Full Label Configuration for details.

standard

persist_min_tracking

If minimum tracking should result in removing all OIL cookies from the users browser and close the layer and store this selection in the oil cookie.

true

iabVendorListUrl

Vendorlist to use

https://vendorlist.consensu.org/vendorlist.json

iabVendorWhitelist

Array of vendor IDs to include in consent. If it is set, values in iabVendorBlacklist are ignored. Details here

none

iabVendorBlacklist

Array of vendor IDs to exclude from consent. Details here

None

customPurposes

Array of custom purposes defined by publisher. IDs for custom purposes may range from 25-88.

none

default_to_optin

Signal opt-in to vendors while still displaying the Opt-In layer to the end user

false

advanced_settings_purposes_default

All purposes in the advanced settings layer should be activated by default

false

gdpr_applies_globally

Flag to indicate that publisher is from the EU, thus showing the OIL layer to every user. The flag is passed to vendors.

true

Texts & Locale Object

The locale object must contain at least "localeId" and "version" along with the localized texts in the texts property. LocaleId and version will be stored with the consent cookie so we can keep track of which explicit text version consent was granted for. There are three options to pass a locale configuration into your application:

  • Store your locale object as 'locale' in the oil.js configuration (lowest priority)

<script id="oil-configuration" type="application/configuration">
{
  "locale": {
    "localeId": "enEN_01",
    "version": 1,
    "texts": {
      "label_intro_heading": "Insider, Inc."
    }
  }
}
</script>
  • Write your locale object directly to AS_OIL.CONFIG.LOCALE (middle priority)

<script>
(function () {
    if (!window.AS_OIL) {
      window.AS_OIL = {};
      window.AS_OIL.CONFIG = {}
    }
    window.AS_OIL.CONFIG.locale = {
      "localeId": "enEN_01",
      "version": 1,
      "texts": {
        "label_intro_heading": "Insider, Inc."
      }
    };
  }()
)
</script>
  • Return a JSON object from your server through locale_url configuration parameter (highest priority)

<script id="oil-configuration" type="application/configuration">
{
  "timeout": -1,
  "locale_url": "//www.yoursite.com/locale.json"
}
</script>

The recommended way is to keep the standard locale definitions.

Language label configuration

Language configuration goes in the texts object of the locale config parameter. These texts define the standard labels for all legal texts and buttons. For configurations with advanced_settings=false most of these labels are not needed.

Example for complete texts object

{
  "label_intro_heading": "We use cookies and other technologies",
  "label_intro": "The website uses cookies, web beacons, JavaScript and similar technologies. I agree that <a href=\"javascript:void(0)\" class=\"as-oil__intro-txt--link as-js-companyList\">companies belonging to Axel Springer SE</a> and <a href=\"javascript:void(0)\" class=\"as-oil__intro-txt--link as-js-thirdPartyList\">trusted partners</a> generate pseudonymous user profiles for adapting the website to the user, for market research and for advertising. The generated data can also be shared with third parties while the user profiles cannot be combined with personal data. Detailed information, also on the right to withdraw consent, can be found in the website's privacy policy.",
  "label_button_yes": "OK",
  "label_button_back": "Back",
  "label_button_advanced_settings": "More information",
  "label_cpc_heading": "Please select a privacy setting:",
  "label_cpc_text": "cpc_text",
  "label_cpc_activate_all": "Activate all",
  "label_cpc_deactivate_all": "Deactivate all",
  "label_cpc_purpose_desc": "Purposes",
  "label_cpc_purpose_01_text": "Accessing a Device",
  "label_cpc_purpose_01_desc": "Allow storing or accessing information on a user’s device.",
  "label_cpc_purpose_02_text": "Advertising Personalisation",
  "label_cpc_purpose_02_desc": "Allow processing of a user’s data to provide and inform personalised advertising (including delivery, measurement, and reporting) based on a user’s preferences or interests known or inferred from data collected across multiple sites, apps, or devices; and/or accessing or storing information on devices for that purpose.",
  "label_cpc_purpose_03_text": "Analytics",
  "label_cpc_purpose_03_desc": "Allow processing of a user’s data to deliver content or advertisements and measure the delivery of such content or advertisements, extract insights and generate reports to understand service usage; and/or accessing or storing information on devices for that purpose.",
  "label_cpc_purpose_04_text": "Content Personalisation",
  "label_cpc_purpose_04_desc": "Allow processing of a user’s data to provide and inform personalised content (including delivery, measurement, and reporting) based on a user’s preferences or interests known or inferred from data collected across multiple sites, apps, or devices; and/or accessing or storing information on devices for that purpose.",
  "label_cpc_purpose_05_text": "Matching Data to Offline Sources",
  "label_cpc_purpose_05_desc": "Combining data from offline sources that were initially collected in other contexts",
  "label_cpc_purpose_06_text": "Linking Devices",
  "label_cpc_purpose_06_desc": "Allow processing of a user’s data to connect such user across multiple devices.",
  "label_cpc_purpose_07_text": "Precise Geographic Location data",
  "label_cpc_purpose_07_desc": "Allow processing of a user’s precise geographic location data in support of a purpose for which that certain third party has consent",
  "label_poi_group_list_heading": "Your consent for companies of the group",
  "label_poi_group_list_text": "Here is a list of companies of the group:",
  "label_third_party": "Third Parties",
  "label_thirdparty_list_heading": "Your consent for third party software",
  "label_thirdparty_list_text": "",
  "label_nocookie_head": "In order to be able to provide our services in the best possible way, cookies must be activated in your browser.",
  "label_nocookie_text": "Please activate Cookies in the properties of your Browsers. So you can do it in <a href=\"https://support.google.com/chrome/answer/95647?co=GENIE.Platform%3DDesktop&hl=en-GB\" class=\"as-oil__intro-txt--link\" target=\"_blank\">Google Chrome</a> or <a href=\"https://support.mozilla.org/en-US/kb/cookies-information-websites-store-on-your-computer\" class=\"as-oil__intro-txt--link\" target=\"_blank\">Firefox</a>."
}

Labels starting with label_cpc_purpose_N are automatically derived from the vendor list if missing from your locale object.

Example Screenshot:

oil labels intro

Special CSS classes within labels

There are multiple special CSS classes, which will get click handlers attached. If any element has these classes, they will work as links to the different pages of the layer. Currently there are these special css classes:

  • as-js-optin: Will trigger an opt-in with SOI/POI depending on the current configuration.

  • as-js-optin-poi: Will trigger an opt-in as POI.

  • as-js-companyList: Will trigger the layer to show the company list.

  • as-js-thirdPartyList: Will trigger the layer to show the 3rd party list.

  • as-js-advanced-settings: Will trigger the layer to show the CPC (cookie preference center / advanced settings).

  • as-js-oilback: Will trigger the layer to go back to the first view.

For example adding the class as-js-companyList will add a click handler, which will show the company list (group list):

"label_intro": "I agree that <a href=\"javascript:void(0)\" class=\"as-oil__intro-txt--link as-js-companyList\">companies belonging to Group X</a> ...",

preview_mode

The preview mode is useful when testing OIL in a production or live environment. When in preview_mode, the consent layer remains hidden until you set a cookie named "oil_preview" with the value "true".

This will show the OIL layer on your client:

document.cookie = "oil_preview=true";

To delete the cookie, do:

document.cookie = "oil_preview=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"

When preview_mode is not set in configuration and no consent cookie is found, the layer will show for the visitor.

Blacklisting and Whitelisting

With iabVendorWhitelist and iabVendorBlacklist you can exclude specific vendors from the consent (blacklist) or include only the ones you want (whitelist). You can only use one method at the time - either whitelist or blacklist.

As an example, the vendorlist may contain vendors with vendor IDs 1 to 10. In the example the user accepts everything, he just pressed "OK". The consent-string would normally contain (by getVendorConsents) this data:

Default result from getVendorConsents without whitelist/blacklist
{
  "metadata": "consent-string",
  "purposeConsents": {
    "1": 1,
    "2": 1,
    "3": 1,
    "4": 1,
    "5": 1
  },
  "vendorConsents": {
    "1": true,
    "2": true,
    "3": true,
    "4": true,
    "5": true,
    "6": true,
    "7": true,
    "8": true,
    "9": true,
    "10": true
  }
}

Whitelist: The whitelist contains IDs 3, 4, 5 in form of the configuration with "iabVendorWhitelist": [3, 4, 5]. If the user has given his consent by clicking on "OK" only vendors on the whitelist will be true.

Result from getVendorConsents with whitelisting vendor IDs 3, 4, 5
{
  "metadata": "consent-string",
  "purposeConsents": {
    "1": 1,
    "2": 1,
    "3": 1,
    "4": 1,
    "5": 1
  },
  "vendorConsents": {
    "1": false,
    "2": false,
    "3": true,
    "4": true,
    "5": true,
    "6": false,
    "7": false,
    "8": false,
    "9": false,
    "10": false
  }
}

Blacklist: The blacklist contains IDs 6, 7, 8 in form of the configuration with "iabVendorBlacklist": [6, 7, 8]. If the user has given his consent by clicking on "OK" only vendors NOT on the blacklist will be true.

Result from getVendorConsents with blacklisting vendor IDs 6, 7, 8
{
  "metadata": "consent-string",
  "purposeConsents": {
    "1": 1,
    "2": 1,
    "3": 1,
    "4": 1,
    "5": 1
  },
  "vendorConsents": {
    "1": true,
    "2": true,
    "3": true,
    "4": true,
    "5": true,
    "6": false,
    "7": false,
    "8": false,
    "9": true,
    "10": true
  }
}

Auto-Hiding the layer (timeout)

If you do not interact with the Opt-In Layer, it will autohide after a fixed time. If you want to disable the feature, you need to edit the configuration and the set the value to 0 or -1. If you click on any navigation link in the Opt-In Layer the timeout will be canceled. The default timeout is:

const defaultTimeoutInSeconds = 60;

The IAB specification explains how a vendor should communicate with a CMP to gather consent information before running any data processing. That API is a set of JavaScript functions. You can find more at the official website http://advertisingconsent.eu/

The consent string is the central part of the IAB framework: it encodes all the consent information for the user, by purpose and by vendor.

JS-API

This API has to support the following functionality. All methods are strings and can be called over the window.__cmp function.

<script type="text/javascript">
__cmp('getVendorConsents', null, (result) => console.info(result));
</script>

getVendorConsents

Parameter: vendorIds (Uint16Array)

Callback signature: Callback( VendorConsents object, success: boolean)

The vendorIds array contains the vendor ids (as identified in the Global Vendor List) for which consent is being requested. If vendorIds is null or empty, the operation will return consent status for all vendors in the vendor list. The callback function will be called with a VendorConsents object as the parameter. If vendorIds is provided and not empty, then VendorConsents.vendorConsents will only included IDs from vendorIds, The callback is called only after consent is obtained from the UI or existing cookies. The consent will be returned false ("No Consent") for any invalid vendorId. The boolean success parameter passed to the callback indicates whether the call to getVendorConsents() was successful.

getConsentData

Parameter: consentStringVersion (string)

Callback signature: Callback(VendorConsentData object, success: boolean)

If consentStringVersion is provided, then fetch that version if available (else returns null). If consentStringVersion is null, then the latest supported version of the consent string is returned. The callback is called only after consent is obtained from the UI or existing cookies. The boolean success parameter passed to the callback indicates whether the call to getConsentData() was successful.

ping

Callback signature: Callback(PingReturn object, success: boolean)

The "ping" command invokes the callback immediately with information about whether the main CMP script has loaded yet and if GDPR has been configured for all users or just EU users. (This requires this command’s implementation and this configuration to be in the stub).

Optional call: getPublisherConsents

Parameter: purposeIds: Uint16Array

Callback signature: Callback( PublisherConsents object, success: boolean)

The purposeIds lists the purpose ids the publisher is requesting consent for. If this array is null or empty, it will default to all configured purposes. PurposeId’s 1-24 indicate standard purposes, while 25-88 indicate custom (publisher-configured) purposes. The callback function will be called with a PublisherConsents object as the parameter. The purpose ids would be set by the publisher using a CMP-defined initialization function. The callback is called only after consent is obtained from the UI or existing cookies. The boolean success parameter passed to the callback indicates whether the call to getPublisherConsents() was successful.

Optional call: getVendorList

Parameter: vendorListVersion (scalar)

Callback signature: Callback(GlobalVendorList object, success:boolean)

The callback function will be called with the GlobalVendorList parameter being the vendor list object of the requested version. If the vendorListVersion is null, the vendor list for the VendorListVersion in the current consent string is returned. If no consent string value is currently set, the latest version of the vendor list is returned. If the vendorListVersion value is ?LATEST?, the latest version available is returned. If the vendorListVersion is invalid, the callback function will be called with 'null' as the first argument and false as the success argument. The boolean success parameter passed to the callback indicates whether the call to getVendorList() was successful.

OIL API

In addition to the configuration the host site can communicate with the OIL layer using its API. OIL, in its default state, never emits console errors. To get a full log and all errors you can enable the verbose mode. For test deployments and A/B testing OIL supports a preview mode.

Test Deployment and Preview Mode

The preview mode is useful for testing OIL in a live environment without making it available to your end-users.

The preview mode is turned off by default, meaning OIL will be available to all your users. If you turn the preview mode on (please see configuration section), OIL won’t be shown at first, but can be enabled for your current session on the browser’s console:

window.AS_OIL.previewModeOn();
window.AS_OIL.previewModeOff();

When preview mode is turned on some debug information will be seen on the browser console. See also "Verbose Logging" below for more detailed logging.

OIL Verbose Logging

OIL will show no logs, except in preview mode or verbose mode.

Run the following commands on the console of your browser to switch verbose logging on and off:

window.AS_OIL.verboseModeOn();
window.AS_OIL.verboseModeOff();

Debug mode can be turned on at any time, whereas the similar preview mode can only be enabled in the configuration, please see above.

Please note that verbose logging can only be activated for your own browser, all other users won’t see those logs.

OIL JS-Calls

API Call Description

window.AS_OIL.triggerOptIn();

The user will opted in. It’s the same behaviour as when the user is clicking Accept on the layer.

window.AS_OIL.triggerOptOut();

OIL will remove all cookies if triggered and therefore opt-out the user of everything, even POI.

window.AS_OIL.reload();

OIL will reload the configuration from the host’s website.

window.AS_OIL.showPreferenceCenter();

OIL will inject the Cookie Preference Center into your website. Please see "OIL CPC API" section.

window.AS_OIL.applyGDPR();

Sets gdprApplies variable to true and displays the layer if user hasn’t opted-in. Useful in case you need to show the layer to a user from inside the EU and you’re not a EU publisher.

OIL Events

#2. Register an event handler with a callback to be executed when OIL fires the opt-in event or the user has opted in on an earlier occasion and revisits the page.

  <script type="text/javascript">
    // Cross browser event handler definition
    var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
    var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';
    var eventer = window[eventMethod];

    // Callback to be executed when event is fired
    function receiveMessage(event) {
      function eventDataContains(str) {
        return JSON.stringify(event.data).indexOf(str) !== -1;
      }
      if (event && event.data && (eventDataContains('oil_optin_done') || eventDataContains('oil_has_optedin'))) {
        // Do something when event is fired...
        console.log("Do something when event is fired...");
      }
    }

    // Register event handler
    eventer(messageEvent, receiveMessage, false);
  </script>

OIL is currently emitting the following events:

Event name Description

oil_optin_done

When a users selects opt-in.

oil_as_cpc_privacy_selected

When a user used the cpc and clicked opt-in.

oil_click_advanced_settings

When a users clicks the advanced settings button/link.

oil_click_back_to_main

When a user clicks the back link from the advanced settings page.

oil_no_cookies_allowed

When a users has no cookies allowed and the no cookies layer is displayed

oil_has_optedin

On every page reload, when the user has opted_in previously (OIL should be hidden)

oil_shown

When oil is shown

oil_hide_layer

When oil gets automatically hidden

oil_click_thirdparty_list

When a user clicks the third party list link

oil_click_company_list

When a user clicks the company list link

OIL CPC API

You can add an integrated version of the OIL Cookie Preference Center to your page to give the user the chance to reverse his initial selection (or even Opt-Out).

For this include a div with the id below in your page:

<div id="oil-preference-center"></div>

To insert the OIL CPC in the prepared div, which you included in your page, execute this javascript snippet:

window.AS_OIL.showPreferenceCenter();

For the action element to save the current setting there is an API endpoint:

window.oilTriggerOptin();

The inserted CPC will show the users current setting when inserted. Make sure OIL is part of the page first to make this work.

CPC API definition:

Function Name Description

window.AS_OIL.showPreferenceCenter()

inserts the CPC into the predefined div with the id #oil-preference-center into the host site

window.AS_OIL.triggerOptIn()

will trigger the generic opt-in (can also result in an opt-out)

Soft Blocking of DOM Elements

With OIL you can manage third-party scripts to ensure that they only run if the user has given consent to their use. For example, this is useful for scripts provided by vendors that do not implement the IAB JavaScript API yet. Furthermore, OIL can manage other elements with a src or an href attribute the same way.

Managing <script> Elements

To manage <script> tags you have to add a data-managed attribute with the value as-oil. To avoid automatic execution of the <script> tag as long as it should be deactivated change the type attribute to opt-in and add a data-type attribute with the original type. In case of tag activation OIL replaces the type attribute with this original type. With an additional data-purposes attribute you can specify a comma-separated list of purpose ids the user has to consent with to activate the tag. If data-purposes attribute is omitted all defined purposes are necessary for tag activation.

Here is an example for a managed <script> tag:

<script data-managed="as-oil"
        data-type="text/javascript"
        data-purposes="1,2,4"
        type="as-oil"
        id="managedScriptTag">
  document.getElementById("demoText").innerHTML = "This text will be shown with given consent!";
</script>

OIL can manage <script> tags that load a script from an URL as well. Simply replace the src attribute with data-src as shown below:

<script data-managed="as-oil"
        data-type="text/javascript"
        data-src="oilDemoScript.js"
        data-purposes="1,2,4"
        type="as-oil"
        id="managedScriptTag">
</script>

Attributes class, id, defer, async and charset and further data- attributes can be used. They are not changed by OIL.

Managing Other Elements

To manage elements with a src or href attribute add a data-managed attribute with the value as-oil and replace the src attribute with data-src or the href attribute with data-href. With the optional data-title attribute a title can be defined - use it instead of title attribute. With a data-purposes attribute you can specify a comma-separated list of purpose ids the user has to consent with to activate the tag. If data-purposes attribute is omitted all defined purposes are necessary for tag activation. All other attributes are not changed by OIL - with one exception. To ensure that managed elements are not visible as long as they should be deactivated OIL sets the CSS display property to none. To provide a value for this property that is used when the tag is activated add a corresponding data-display attribute. OIL sets its value into the CSS display property when it activates the tag. Other CSS properties can be specified by a style attribute or in a CSS section or file.

Here is an example for a managed <img> tag:

<img data-managed="as-oil"
         data-src="simpleImage.png"
         data-title="Simple Image"
         data-display="block"
         data-purposes="1,2,4"
         alt="A simple image"
         height="50"
         width="50"
         id="imgId"
         class="imgClass"
         style="border: 1px solid #ddd; border-radius: 20px;">

Tracking and Google Analytics Events

If you want to use Google Analytics with OIL you can use OIL Events (see above) and proxy them to your specific GA installation.

This is an example script to subscribe to the event 'oil_optin_done' and forward it to Google Analytics. You might need to tweak it to your environment and needs.

// Multibrowser Support
var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';
var eventer = window[eventMethod];

function receiveOptInMessage(event) {
  function eventDataContains(str) {
    return JSON.stringify(event.data).indexOf(str) !== -1;
  }
  if (window.ga && window.ga.loaded && event && event.data && eventDataContains('oil_optin_done')) { // event name
    var nonInteraction = true; // should be set to false for non-click events
    window.ga('send', 'event', 'OIL', 'oil_optin_done', {'nonInteraction': nonInteraction});
  }
}

eventer(messageEvent, receiveOptInMessage, false);

You can also use the global event queue to process events that have been fired before you declared the event listeners. Therefore all events are stored in the global window.AS_OIL.eventCollection array. Every entry is an object including the event name and the timestamp when it has been fired.

if (window.AS_OIL.eventCollection && window.AS_OIL.eventCollection.length) {
    window.AS_OIL.eventCollection.forEach(function(item){
        // console.log(item.name);
        // console.log(item.timestamp);
        // use your tracking code to process every event that has been fired so far
        // example: Adobe tag manager
        _satellite.track(item.name)
    });
}

// event listener code, see above

Customisation

Supported A/B Testing with us

If you want to optimize and test your OIL installation with our Kameleoon A/B testing, you also need to include the right kameleoon script into your website, which will alter the optics and behaviour of OIL according to the test and your specific environment.

An example link would look like:

<script type="text/javascript" src="//static-bp.kameleoon.com/css/customers/xxxxxxxxxxx/0/kameleoon.js"></script>

Instead of xxxxxxxxxxx the right hash needs to be present, so Kameleoon knows which website it deals with. When we setup OIL A/B testing on your page this hash needs to be generated within Kameleoon.

Your own A/B Testing

For setting up A/B testing in your own environment, the following information could come handy.

Enabling OIL for a specific variant only

For testing you can also use the preview mode to disable OIL by default and enable it in certain variants.

Add the following standard configuration to your website, which will disable OIL by default:

<script id="oil-configuration" type="application/configuration">
  {
    "preview_mode": true,
  }
</script>

For enabling it in a variant you need to replace the configuration and trigger OIL to reload it. As part of your variant insert a customized version of this script:

<script type="text/javascript">
    (function () {
        var config = {
            "preview_mode": false,
            "label_intro_heading": "Please confirm!",
            "label_button_yes": "Of course"
        };
        var oldScript = document.getElementById('oil-configuration');
        if (oldScript) {
            oldScript.parentNode.removeChild(oldScript);
        }

        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');

        script.id = 'oil-configuration';
        script.type = 'application/configuration';
        script.text = JSON.stringify(config);

        head.appendChild(script);
        window.AS_OIL.reload();
    }());
</script>

Full Label Configuration

Even though OIL is supposed to come with legal texts that shouldnt be altered, except the main heading, for testing purposes all labels can be overwritten, even the default ones, in the OIL configuration block (see chapter "OIL configuration") as follows:

Config Parameter Example Value

label_intro_heading

We use cookies and other technologies

label_intro

We’re using cookies, please confirm!

label_button_yes

Yes

label_button_back

Back

label_button_advanced_settings

More information

label_advanced_settings_heading

Cookie Preference Center

label_advanced_settings_text

Please select a setting:

label_advanced_settings_essential_text

Essentials

label_advanced_settings_essential_verbose

Only essential cookies

label_advanced_settings_functional_text

Social

label_advanced_settings_functional_verbose

Additional social cookies

label_advanced_settings_advertising_text

Ads

label_advanced_settings_advertising_verbose

Additional ads cookies

label_nocookie_head

No Cookies allowed.

label_nocookie_text

Please enable cookies!

label_poi_group_list_heading

Company units

label_poi_group_list_text

Here is a list of company units

label_thirdparty_list_heading

Third Parties

label_thirdparty_list_text

Here is a list of third parties

Important
If you want to reference the company or third party list from your custom text you need to add the links inline and set the right css classes.
<a href="javascript:void(0)" class="as-oil__intro-txt--link as-js-companyList">CompanyListLink</a>
<a href="javascript:void(0)" class="as-oil__intro-txt--link as-js-thirdPartyList">ThirdPartys</a>

Styling guide

There are 5 different view you can style: * The default layer * No-cookies banner * Group list * 3rd party list * Cookie Preference Center

You can style the layer with additional CSS. All OIL styles use the css classes directly, this means the lowest possible css specificity. Here are two examples. The first one is for changing the font and the color. The second is for changing the background color and the shadow.

div.as-oil {
  font-family: Arial;
  color: #bada55;
}
div.as-oil-content-overlay {
  background-color: #ff00ff;
  box-shadow: 0 -8px 20px 0 rgba(0, 0, 0, 0.2);
}

Here are the current raw html snippets used for the opt-in layer. You can use these as reference for which classes were used.

Opt-In layer

Default View
<div class="as-oil light" data-qa="oil-Layer">
  <div class="as-oil-content-overlay" data-qa="oil-full">
    <div class="as-oil-l-wrapper-layout-max-width">
      <div class="as-oil__heading">label_intro_heading</div>
      <p class="as-oil__intro-txt">label_intro</p>
      <div class="as-oil-l-row as-oil-l-buttons">
        <div class="as-oil-l-item">
          <button class="as-oil__btn-optin as-js-optin" data-context="YES" data-qa="oil-YesButton">label_button_yes
          </button>
        </div>
        <div class="as-oil-l-item as-oil-l-item--stretch"></div>
      </div>
    </div>
  </div>
</div>
No Cookies
<div class="as-oil light" data-qa="oil-Layer">
  <div class="as-oil-content-overlay oil-nocookies" data-qa="oil-nocookies">
    <div class="as-oil-l-wrapper-layout-max-width">
      <div class="as-oil__heading">
        label_nocookie_head
      </div>
      <p class="as-oil__intro-txt">
        label_nocookie_text
      </p>
    </div>
  </div>
</div>

POI group list

Group list
<div class="as-oil-fixed">
  <div class="as-oil-content-overlay as-oil-poi-group-list-wrapper" data-qa="oil-poi-list">
    <div class="as-oil-l-wrapper-layout-max-width">
      <div class="as-oil__heading">
        label_poi_group_list_heading
      </div>
      <p class="as-oil__intro-txt">
        label_poi_group_list_text
      </p>
      <div class="as-oil-poi-group-list">
        <div class="as-oil-poi-group-list-element">a</div>
        <div class="as-oil-poi-group-list-element">b</div>
      </div>
      <button class="as-oil-back-button as-js-oilback" data-context="BACK" data-qa="oil-back-button">
        <span class="as-oil-back-button__text">label_button_back</span>
        <svg class="as-oil-back-button__icon" width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
          <g fill="none" fill-rule="evenodd">
            <circle fill="#757575" cx="11" cy="11" r="11" />
            <path d="M15.592 14.217a.334.334 0 0 1 .098.245c0 .098-.033.18-.098.246l-.928.908a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098L11 12.4l-3.2 3.216a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098l-.928-.908a.334.334 0 0 1-.098-.246c0-.098.033-.18.098-.245L9.632 11 6.408 7.808c-.163-.164-.163-.327 0-.491l.904-.933a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098L11 9.576l3.2-3.192a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098l.904.933c.163.164.163.32 0 .466l-3.224 3.192 3.224 3.242z"
                  fill="#FFF" opacity=".88" />
          </g>
        </svg>
      </button>
    </div>
    <div class="as-oil-l-row as-oil-l-buttons-light">
      <div class="as-oil-l-item">
        <button class="as-oil__btn-optin as-js-optin" data-context="YES" data-qa="oil-YesButton">
          label_button_yes
        </button>
      </div>
    </div>
  </div>
</div>

Third party list

Third party list
<div class="as-oil light" data-qa="oil-Layer">
  <div class="as-oil-fixed">
    <div class="as-oil-content-overlay as-oil-poi-group-list-wrapper" data-qa="oil-poi-list">
      <div class="as-oil-l-wrapper-layout-max-width">
        <div class="as-oil__heading">
          Your consent for third party software
        </div>
        <p class="as-oil__intro-txt">
          label_thirdparty_list_text
        </p>
        <div class="as-oil-poi-group-list">
          <div class="as-oil-third-party-list-element">
                <span onclick="AS_OIL._toggleViewElements(this)">
                    <svg class="as-oil-icon-plus" width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
                      <path d="M5.675 4.328H10v1.344H5.675V10h-1.35V5.672H0V4.328h4.325V0h1.35z" fill="#0068FF" fill-rule="evenodd" fill-opacity=".88"></path>
                    </svg>
                    <svg class="as-oil-icon-minus" style="display: none;" width="10" height="5" viewBox="0 0 10 5" xmlns="http://www.w3.org/2000/svg">
                      <path d="M0 0h10v1.5H0z" fill="#3B7BE2" fill-rule="evenodd" opacity=".88"></path>
                    </svg>
                    <span class="as-oil-third-party-name">Exponential Interactive, Inc</span>
                </span>
            <div class="as-oil-third-party-toggle-part" style="display: none;">
              <p class="as-oil-third-party-description">undefined</p>
              <div class="as-oil-third-party-link">undefined</div>
            </div>
          </div>
        </div>
        <button class="as-oil-back-button as-js-oilback" data-context="BACK" data-qa="oil-back-button">
          <span class="as-oil-back-button__text">Back</span>
          <svg class="as-oil-back-button__icon" width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
            <g fill="none" fill-rule="evenodd">
              <circle fill="#757575" cx="11" cy="11" r="11"></circle>
              <path d="M15.592 14.217a.334.334 0 0 1 .098.245c0 .098-.033.18-.098.246l-.928.908a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098L11 12.4l-3.2 3.216a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098l-.928-.908a.334.334 0 0 1-.098-.246c0-.098.033-.18.098-.245L9.632 11 6.408 7.808c-.163-.164-.163-.327 0-.491l.904-.933a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098L11 9.576l3.2-3.192a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098l.904.933c.163.164.163.32 0 .466l-3.224 3.192 3.224 3.242z" fill="#FFF" opacity=".88"></path>
            </g>
          </svg>
        </button>
      </div>
      <div class="as-oil-l-row as-oil-l-buttons-light">
        <div class="as-oil-l-item">
          <button class="as-oil__btn-optin as-js-optin" data-context="YES" data-qa="oil-YesButton">
            OK
          </button>
        </div>
      </div>
    </div>
  </div>
</div>
CPC
<div class="as-oil light" data-qa="oil-Layer">
  <div id="as-oil-cpc" class="as-oil-content-overlay" data-qa="oil-cpc-overlay">
    <div class="as-oil-l-wrapper-layout-max-width as-oil-cpc-wrapper">
      <div class="as-oil__heading">
        label_cpc_heading
      </div>
      <p class="as-oil__intro-txt">
        label_cpc_text
      </p>
      <div class="as-oil-cpc__row-btn-all">
        <span class="as-js-btn-deactivate-all as-oil__btn-grey">label_cpc_deactivate_all</span>
        <span class="as-js-btn-activate-all as-oil__btn-blue">label_cpc_activate_all</span>
      </div>
      <button class="as-oil-back-button as-js-oilback" data-context="BACK" data-qa="oil-back-button">
        <span class="as-oil-back-button__text">
                  label_button_back
                </span>
        <svg class="as-oil-back-button__icon" width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg">
          <g fill="none" fill-rule="evenodd">
            <circle fill="#757575" cx="11" cy="11" r="11"></circle>
            <path d="M15.592 14.217a.334.334 0 0 1 .098.245c0 .098-.033.18-.098.246l-.928.908a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098L11 12.4l-3.2 3.216a.303.303 0 0 1-.22.098.33.33 0 0 1-.244-.098l-.928-.908a.334.334 0 0 1-.098-.246c0-.098.033-.18.098-.245L9.632 11 6.408 7.808c-.163-.164-.163-.327 0-.491l.904-.933a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098L11 9.576l3.2-3.192a.473.473 0 0 1 .244-.098.33.33 0 0 1 .244.098l.904.933c.163.164.163.32 0 .466l-3.224 3.192 3.224 3.242z"
                  fill="#FFF" opacity=".88"></path>
          </g>
        </svg>
      </button>
      <div data-qa="cpc-snippet" class="as-oil-l-row as-oil-cpc__content">
        <div class="as-oil-cpc__left">
          <a href="#as-oil-cpc-purposes" onclick="AS_OIL._switchLeftMenuClass(this)" class="as-oil-cpc__category-link as-oil-cpc__category-link--active">
            label_cpc_purpose_desc
          </a>
          <a href="#as-oil-cpc-third-parties" onclick="AS_OIL._switchLeftMenuClass(this)" class="as-oil-cpc__category-link">
            label_third_party
          </a>
        </div>
        <div class="as-oil-cpc__middle as-js-purposes">
          <div class="as-oil-cpc__row-title" id="as-oil-cpc-purposes">
            label_cpc_purpose_desc
          </div>
          <div class="as-oil-cpc__purpose">
            <div class="as-oil-cpc__purpose-container">
              <div class="as-oil-cpc__purpose-header">Purpose 1</div>
              <div class="as-oil-cpc__purpose-text">label_cpc_purpose_01_desc</div>
              <label class="as-oil-cpc__switch">
                <input data-id="1" id="as-js-purpose-slider-1" class="as-js-purpose-slider" type="checkbox" name="oil-cpc-purpose-1" value="false">
                <span class="as-oil-cpc__status"></span>
                <span class="as-oil-cpc__slider"></span>
              </label>
            </div>
          </div>
          <div class="as-oil-cpc__purpose">
            <div class="as-oil-cpc__purpose-container">
              <div class="as-oil-cpc__purpose-header">Purpose 2</div>
              <div class="as-oil-cpc__purpose-text">label_cpc_purpose_02_desc</div>
              <label class="as-oil-cpc__switch">
                <input data-id="2" id="as-js-purpose-slider-2" class="as-js-purpose-slider" type="checkbox" name="oil-cpc-purpose-2" value="false">
                <span class="as-oil-cpc__status"></span>
                <span class="as-oil-cpc__slider"></span>
              </label>
            </div>
          </div>
          <div class="as-oil-cpc__purpose">
            <div class="as-oil-cpc__purpose-container">
              <div class="as-oil-cpc__purpose-header">Purpose 3</div>
              <div class="as-oil-cpc__purpose-text">label_cpc_purpose_03_desc</div>
              <label class="as-oil-cpc__switch">
                <input data-id="3" id="as-js-purpose-slider-3" class="as-js-purpose-slider" type="checkbox" name="oil-cpc-purpose-3" value="false">
                <span class="as-oil-cpc__status"></span>
                <span class="as-oil-cpc__slider"></span>
              </label>
            </div>
          </div>
          <div class="as-oil-cpc__purpose">
            <div class="as-oil-cpc__purpose-container">
              <div class="as-oil-cpc__purpose-header">Purpose 4</div>
              <div class="as-oil-cpc__purpose-text">label_cpc_purpose_04_desc</div>
              <label class="as-oil-cpc__switch">
                <input data-id="4" id="as-js-purpose-slider-4" class="as-js-purpose-slider" type="checkbox" name="oil-cpc-purpose-4" value="false">
                <span class="as-oil-cpc__status"></span>
                <span class="as-oil-cpc__slider"></span>
              </label>
            </div>
          </div>
          <div class="as-oil-cpc__purpose">
            <div class="as-oil-cpc__purpose-container">
              <div class="as-oil-cpc__purpose-header">Purpose 5</div>
              <div class="as-oil-cpc__purpose-text">label_cpc_purpose_05_desc</div>
              <label class="as-oil-cpc__switch">
                <input data-id="5" id="as-js-purpose-slider-5" class="as-js-purpose-slider" type="checkbox" name="oil-cpc-purpose-5" value="false">
                <span class="as-oil-cpc__status"></span>
                <span class="as-oil-cpc__slider"></span>
              </label>
            </div>
          </div>
          <div class="as-oil-cpc__row-title" id="as-oil-cpc-third-parties">
            label_third_party
          </div>
          <div id="as-js-third-parties-list">
            <div class="as-oil-poi-group-list">
              <div class="as-oil-third-party-list-element">
                <span onclick="AS_OIL._toggleViewElements(this)">
                        <svg class="as-oil-icon-plus" width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
                          <path d="M5.675 4.328H10v1.344H5.675V10h-1.35V5.672H0V4.328h4.325V0h1.35z" fill="#0068FF" fill-rule="evenodd" fill-opacity=".88"></path>
                        </svg>
                        <svg class="as-oil-icon-minus" style="display: none;" width="10" height="5" viewBox="0 0 10 5" xmlns="http://www.w3.org/2000/svg">
                          <path d="M0 0h10v1.5H0z" fill="#3B7BE2" fill-rule="evenodd" opacity=".88"></path>
                        </svg>
                        <span class="as-oil-third-party-name">Emerse Sverige AB</span>
                </span>
                <div class="as-oil-third-party-toggle-part" style="display: none;">
                  <a class="as-oil-third-party-link" href="https://www.emerse.com/privacy-policy/">https://www.emerse.com/privacy-policy/</a>
                </div>
              </div>
              <div class="as-oil-third-party-list-element">
                <span onclick="AS_OIL._toggleViewElements(this)">
                        <svg class="as-oil-icon-plus" width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
                          <path d="M5.675 4.328H10v1.344H5.675V10h-1.35V5.672H0V4.328h4.325V0h1.35z" fill="#0068FF" fill-rule="evenodd" fill-opacity=".88"></path>
                        </svg>
                        <svg class="as-oil-icon-minus" style="display: none;" width="10" height="5" viewBox="0 0 10 5" xmlns="http://www.w3.org/2000/svg">
                          <path d="M0 0h10v1.5H0z" fill="#3B7BE2" fill-rule="evenodd" opacity=".88"></path>
                        </svg>
                        <span class="as-oil-third-party-name">BeeswaxIO Corporation</span>
                </span>
                <div class="as-oil-third-party-toggle-part" style="display: none;">
                  <a class="as-oil-third-party-link" href="https://www.beeswax.com/privacy.html">https://www.beeswax.com/privacy.html</a>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="as-oil-cpc__right">
          <div class="as-oil-l-row as-oil-l-buttons-light">
            <div class="as-oil-l-item">
              <button class="as-oil__btn-optin as-js-optin" data-context="YES" data-qa="oil-YesButton">
                label_button_yes
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

"Thank you" Screen

If you are performing A/B tests on the OIL Layer while not having the tracking disabled technically, we recommend to additionally insert this customized "Thank you"-Layer javascript code your website.

This code will listen to OIL events to show another window after the user finished the conversion process explaining the nature of the test.

(function () {

    // Cross browser event handler definition
    var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
    var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message';
    var eventer = window[eventMethod];

    // Callback to be executed when event is fired
    function receiveMessage(event) {
        function eventDataContains(str) {
            return JSON.stringify(event.data).indexOf(str) !== -1;
        }

        if (event && event.data && (eventDataContains('oil_opt'))) {
            var htmlCode = '<div class="as-oil-content-overlay">'
                + '<div class="as-oil-l-wrapper-layout-max-width">'
                + '<div class="as-oil__heading">'
                + 'Thank you for your feedback!'
                + '</div>'
                + '<p class="as-oil__intro-txt">'
                + 'We as a company take your privacy very seriously. In order to learn your expectations we '
                + 'currently conduct this survey. Thank you for your understanding!'
                + '</p>'
                + '<div class="as-oil-l-row as-oil-l-buttons">'
                + '<div class="as-oil-l-item">'
                + '<button class="as-oil__btn-soi as-js-optin as-close-ty-button" onclick="closeOil()">'
                + 'Close'
                + '</button>'
                + '</div>'
                + '</div>'
                + '</div>'
                + '</div>';

            var thankYouNode = document.createElement('div');
            thankYouNode.id = "as-oil-thank-you";
            thankYouNode.innerHTML = htmlCode;
            thankYouNode.setAttribute('class', 'as-oil');
            document.body.appendChild(thankYouNode);
        }
    }

    // Register event handler
    eventer(messageEvent, receiveMessage, false);
}());

Adding Scripts programmatically

Adding oil.js configuration

var oldScript = document.getElementById('oil-configuration');
if (oldScript) {
  oldScript.parentNode.removeChild(oldScript);
}

var config = {
  preview_mode: true
};
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');

script.id = 'oil-configuration';
script.type = 'application/configuration';
script.text = JSON.stringify(config);

head.appendChild(script);

Appendix

Glossary

Term Explanation

OIL

Stands for opt-in Layer and besides the fact that it stand for the name of the product it is often used to refer to the UI layer shown on the page.

Site Opt-In (SOI)

The Site Opt-In stores a user’s opt-in permit for the current site only. Also known as domain opt-in.

Power Opt-In (POI)

The Power Opt-In functionality stores the opt-in permit for multiple Axel Springer websites. This allows users to only give their opt-in permit for many websites at once. POI is implemented via an iframe solution, see also Hub . Also known as group opt-in.

Hub

POI is implemented via an iframe solution that points to a hub site that acts as a third party cookie storage. Technically, the hub consists of an html and js.

Subscriber

A site that subscribes to a POI hub