OneTrust
This document provides the required information for integrating OneTrust's Cookie Consent and contentpass. Please complete the following general steps first
General Tasks
Here, all general tasks are listed. contentpass does not directly obtain or store any user consent, or any other personal data for that matter. We have integrations with several Consent Management Providers though. Everything CMP-specific is described in the according sub-pages.
Steps:
- Make sure no third party resources are loaded without consent
- Sign up for a contentpass account
- Configure CNAME Record for contentpass Session Management
- Mention contentpass in Privacy Policy
- Integrate contentpass with your CMP
- Further improvements
0. Load third party resources after consent
OneTrust provides solutions on how to load third party resources after consent. You can view the information in their documentation (requires a MyOneTrust account).
The OneTrust Javascript API provides you with "helper" methods for programmatically loading resources after consent. For example, you can insert script tags via OneTrust.InsertScript(args)
, and for inserting HTML they provide OneTrust.InsertHTML(args)
.
You can find more information in their documentation.
Alternatively OneTrust provides a method to prevent loading third parties via script tags by replacing the type
attribute.
We have included an example of how to block third party resources loaded via scripts on your page, using the methods and examples provided by your CMP.
The OneTrust CMP uses a category "class system" for updating the script tag depending on consent. You can read more about their class groups in their documentation here. The examples below use the "C0002" class group (Onetrust's category for "Performance Cookies") as an example.
External Resource example:
<!-- Before Modification -->
<script type="text/javascript" src="https://third-party-resource.net/en_US/script.js"></script>
<!-- After Modification -->
<script
type="text/plain"
src="https://third-party-resource.net/en_US/script.js"
class="optanon-category-C0002"
></script>
Inline Resource example:
<!-- Before Modification -->
<script type="text/javascript">
// some code that loads a third party
</script>
<!-- After Modification -->
<script type="text/plain" class="optanon-category-C0002">
// some code that loads a third party
</script>
Iframe/Embed Blocking
<!-- Before Modification -->
<iframe src="https://www.youtube.com/embed/o-YBDTqX_ZU"></iframe>
<!-- After Modification -->
<!-- to not automatically load Googles Adtech stack, the URL must also be rewritten to youtube-nocookie -->
<iframe
data-src="https://www.youtube-nocookie.com/embed/o-YBDTqX_ZU"
class="optanon-category-C0005"
>
</iframe>
You can find your Cookie IDs as explained in this article.
Visit our docs on Third Party Resources for more information on how to block third parties and the technical details on why this is important.
1. Sign up for contentpass
Go to publisher.contentpass.net and create your publisher account. The wizard will guide you through the steps of creating a publisher profile as well as the first property. The property's status page will present the required steps for a successful contentpass integration. This document contains further details that should help you with the process.
2. Configure CNAME Record for contentpass Session Management
Since 3rd-party cookies don't work reliably anymore in most browsers, contentpass subscribers must be identified using a 1st-party session.
To simplify handling of these 1st-party sessions, contentpass provides an endpoint that must be configured behind a CNAME subdomain of the publisher's first-party domain.
In the following example we assume that the publisher's website is: https://www.example.com
and the propertyId
is 1234abcd
. You can find your propertyId
in the settings of your property. Can't find it? Get in touch with us to obtain your propertyId
.
A CNAME must be set up as follows:
cp.example.com. 300 IN CNAME 1234abcd.with.contentpass.net.
Once the CNAME has been set up, contentpass will automatically provision the required SSL certificates.
3. Mention contentpass in Privacy Policy
While we do not process any data of non-subscribers, we receive the IP addresses of your visitors for technical reasons. Please inform your visitors about this data processing and link to our privacy policy by including the following snippet on your privacy policy page:
- plain text
- html
contentpass
Auf unserer Website bieten wir Ihnen einen Service zum werbe- und tracking-freien surfen mit contentpass an. Dieser Service ist ein Angebot der Content Pass GmbH, Wolfswerder 58, 14532 Kleinmachnow, Deutschland. Beim Abschluss des Service wird contentpass Ihr Vertragspartner.
Um Ihnen diesen Service auf unserer Webseite anzuzeigen und damit anbieten zu können, verarbeitet contentpass, in unserem Auftrag, zu Beginn Ihres Webseitenaufrufs Ihre IP-Adresse. Für die Registrierung sowie die Vertragsabwicklung des contentpass und die damit einhergehende Datenverarbeitung ist contentpass Verantwortlicher im Sinne der DS-GVO. Wir sind ausschließlich Verantwortlicher für die Verarbeitung Ihrer IP-Adresse. Für weitere Informationen bezüglich der Datenverarbeitung bei contentpass, lesen Sie bitte die dortigen Hinweise zum Datenschutz.
Grundlage für die Datenverarbeitung der IP-Adresse, im Rahmen unserer Auftragsverarbeitung mit contentpass, ist unser berechtigtes Interesse Ihnen die Möglichkeit zu bieten, unsere Webseite werbe- und tracking-frei aufrufen zu können und Ihr Interesse an der Nutzung unserer Webseite praktisch ohne Werbung und Tracking [Art. 6 Abs. 1 S. 1 lit. f) DS-GVO]. Zudem erfüllen wir hiermit die rechtliche Verpflichtung, eine rechtskonforme Zustimmung in einwilligungsbedürftige Datenverarbeitungen einzuholen [Art. 6 Abs. 1 lit. c) DS-GVO].
Sie können sich hier in Ihren contentpass Account einloggen, und sich hier für contentpass anmelden.
<h3>contentpass</h3>
<p>Auf unserer Website bieten wir Ihnen einen Service zum <a href="https://www.contentpass.net/register/" onclick="cp('signup'); return false;" target="_self" >werbe- und tracking-freien surfen mit contentpass</a> an. Dieser Service ist ein Angebot der Content Pass GmbH, Wolfswerder 58, 14532 Kleinmachnow, Deutschland. Beim Abschluss des Service wird contentpass Ihr Vertragspartner.</p>
<p>Um Ihnen diesen Service auf unserer Webseite anzuzeigen und damit anbieten zu können, verarbeitet contentpass, in unserem Auftrag, zu Beginn Ihres Webseitenaufrufs Ihre IP-Adresse. Für die Registrierung sowie die Vertragsabwicklung des contentpass und die damit einhergehende Datenverarbeitung ist contentpass Verantwortlicher im Sinne der DS-GVO. Wir sind ausschließlich Verantwortlicher für die Verarbeitung Ihrer IP-Adresse. Für weitere Informationen bezüglich der Datenverarbeitung bei contentpass, lesen Sie bitte die dortigen <a href="https://www.contentpass.net/privacy">Hinweise zum Datenschutz</a>.</p>
<p>Grundlage für die Datenverarbeitung der IP-Adresse, im Rahmen unserer Auftragsverarbeitung mit contentpass, ist unser berechtigtes Interesse Ihnen die Möglichkeit zu bieten, unsere Webseite werbe- und tracking-frei aufrufen zu können und Ihr Interesse an der Nutzung unserer Webseite praktisch ohne Werbung und Tracking [Art. 6 Abs. 1 S. 1 lit. f) DS-GVO]. Zudem erfüllen wir hiermit die rechtliche Verpflichtung, eine rechtskonforme Zustimmung in einwilligungsbedürftige Datenverarbeitungen einzuholen [Art. 6 Abs. 1 lit. c) DS-GVO].</p>
<p>Sie können sich hier in Ihren contentpass Account einloggen, und sich hier für contentpass anmelden.</p>
Note:
Link target for login:
javascript: cp('login');
Link target for signup:
javascript: cp('signup');
Since these are not quite ordinary links, it may happen that your CMS does not support them. In that case, you can simply link to https://www.contentpass.net/login and https://www.contentpass.net/signup instead.
4. Onetrust Contentpass integration
Set up OneTrust
We assume a valid TCFv2 configuration including TCFv2 Geolocation Rule, Vendorlist, etc. Based on this setup, the following changes need to be done to have the best contentpass experience.
Configure privacy center buttons
First, open the privacy center tab of your TCF2-based template:

Open “Content” on the left and click on the edit icon next to “Button Set”. Configure the settings according to the screenshot below. The most important ones are:
- Show Allow All button
- Show Reject All button
- Show Close Button
- Show Close Button (X)

Make sure to apply these changes to all languages supported in your template.
Disable banner from being shown automatically
When publishing your changes, make sure you enable the “Prevent Fetching Banner” toggle.

Add contentpass snippet
Please add the following script below the OneTrust script. Make sure to check/update the OneTrust parameter scriptId
and the contentpass variables cpBaseUrl
and cpPropertyId
.
- Minified
- Plain Javascript
<script src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js"
type="text/javascript"
charset="UTF-8"
data-domain-script="{{scriptId}}" >
</script>
<script type="text/javascript" charset="UTF-8">
!function() {
var cpBaseUrl = 'https://cp.example.com';
var cpPropertyId = '1234abcd';
!function(C,o,n,t,P,a,s){C.CPObject=n,C[n]||(C[n]=function(){
for(var e=arguments.length,i=new Array(e),c=0;c<e;c++)i[c]=arguments[c];const[r,u,l]=i;if(C[n].q||(C[n].q=[]),
t=Array.prototype.slice.call(arguments,0),!C[n].patched&&("fatal"===r&&u&&(C[n].le=u,
Array.prototype.forEach.call(C[n].q,(function(e){"error"===e[0]&&"function"==typeof e[1]&&e[1](u)}))),
"error"===r&&"function"==typeof u&&C[n].le&&u(C[n].le),"extension"===r&&u&&l&&"function"==typeof l.init&&(l.init(),
l.initialized=!0),"authenticate"===r&&u)){try{
P=-1===(o.cookie||"").indexOf("_cpauthhint=")&&!(C.localStorage||{})._cpuser&&-1===C.location.href.toLowerCase().indexOf("cpauthenticated")
}catch(e){P=!1}P&&(a={isLoggedIn:function(){return!1},hasValidSubscription:function(){return!1}},
"function"==typeof u&&u(null,a),t=["authenticate",null])}C[n].q.push(t)});try{
((s=(o.cookie.split("_cpauthhint=")[1]||"").split(";")[0])?Number(s[1]):NaN)>0&&(o.body?o.body.classList.add("cpauthenticated"):o.addEventListener("DOMContentLoaded",(function(){
o.body.classList.add("cpauthenticated")})))}catch(e){}C[n].l=+new Date,C[n].sv=5}(window,document,"cp");
cp("extension","onetrust",{version:1,init:function(){function e(){
const e=document.getElementById("onetrust-consent-sdk");if(!e)return
;const r=Array.prototype.find.call(e.children,(function(e){return e.classList.contains("onetrust-pc-dark-filter")}))
;r&&(r.classList.remove("ot-hide"),r.removeAttribute("style"),r.style.zIndex="2147483644")}function r(){!function(){
const r=document.getElementById("onetrust-banner-sdk");if(r){const c=r.getAttribute("style")
;r.classList.contains("ot-hide")||c||(r.style.zIndex="2147483645",e())}else{
if("function"!=typeof window.MutationObserver)return;new MutationObserver((function(r,c){
Array.prototype.forEach.call(r,(function(r){
"childList"===r.type&&r.target&&"onetrust-consent-sdk"===r.target.id&&Array.prototype.forEach.call(r.addedNodes,(function(r){
if("onetrust-banner-sdk"===r.id){const i=r.getAttribute("style")
;r.classList.contains("ot-hide")||i||(r.style.zIndex="2147483645",e()),c.disconnect()}}))}))
})).observe(document.documentElement,{childList:!0,subtree:!0})}}(),function(){
const e=document.getElementById("__cp_ot_hide_banner");e&&e.parentElement&&e.parentElement.removeChild(e)}()}
return function(){let e=document.getElementById("__cp_ot_hide_banner");e||(e=document.createElement("style"),
e.id="__cp_ot_hide_banner",e.appendChild(document.createTextNode("#onetrust-banner-sdk { display: none !important; }")),
document.head?document.head.appendChild(e):document.body&&document.body.appendChild(e))}(),function(){
if("function"==typeof window.MutationObserver)new MutationObserver((function(e,r){
Array.prototype.forEach.call(e,(function(e){
"childList"===e.type&&e.target&&"onetrust-consent-sdk"===e.target.id&&Array.prototype.forEach.call(e.addedNodes,(function(e){
e.classList.contains("onetrust-pc-dark-filter")&&(e.classList.add("ot-hide"),r.disconnect())}))}))
})).observe(document.documentElement,{childList:!0,subtree:!0});else{const e=setInterval((function(){
const r=document.getElementById("onetrust-consent-sdk");if(!r)return;const c=r.querySelector(".onetrust-pc-dark-filter")
;c&&(c.classList.add("ot-hide"),clearInterval(e))}),50)}}(),cp("error",(function(){r()}))}});
// Will activate Contentpass and initialize basic interfaces for
// communicating with Contentpass
cp('create', cpPropertyId, {
baseUrl: cpBaseUrl
});
// Will render the layer provided by contentpass.
// If user gives full consent, the onFullConsent callback is fired.
// If user is logged into contentpass and has a valid subscription for the
// current website, no layer is displayed.
// Use the cp('authenticate') function below to react on further details
// regarding contentpass users.
cp('render', {
onFullConsent: function() {
console.log('[CP] onFullConsent');
// load advertising
}
});
// Will evaluate the user's login state regarding contentpass and whether
// user has a valid subscription.
// This call is optional as "cp('render')" above is also checking for the
// contentpass subscription state.
// Use this function for example to update your layout for contentpass users.
// We also provide CSS-based and cookie-based options for this case.
cp('authenticate', function (error, user) {
if (error) {
// Error handling depending on use case
return;
}
if (user.isLoggedIn() && user.hasValidSubscription()) {
// User has valid subscription
} else {
// User has no valid subscription
}
});
}()
</script>
<script src="https://cp.example.com/now.js" async fetchPriority="high" onerror="cp('fatal', arguments)"></script>
<script src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js"
type="text/javascript"
charset="UTF-8"
data-domain-script="{{scriptId}}" >
</script>
<script type="text/javascript" charset="UTF-8">
!function() {
var cpBaseUrl = 'https://cp.example.com';
var cpPropertyId = '1234abcd';
function(C, o, n, t, P, a, s) {
C.CPObject = n;
if (!C[n]) {
C[n] = function() {
for (var _len = arguments.length, cpFnArgs = new Array(_len), _key = 0; _key < _len; _key++) {
cpFnArgs[_key] = arguments[_key];
}
const [operation, operationArg1, operationArg2] = cpFnArgs;
if (!C[n].q) {
C[n].q = [];
}
t = Array.prototype.slice.call(arguments, 0);
if (!C[n].patched) {
if (operation === "fatal" && operationArg1) {
C[n].le = operationArg1;
Array.prototype.forEach.call(C[n].q, (function(args) {
if (args[0] === "error" && typeof args[1] === "function") {
args[1](operationArg1);
}
}));
}
if (operation === "error" && typeof operationArg1 === "function") {
if (C[n].le) {
operationArg1(C[n].le);
}
}
if (operation === "extension" && operationArg1) {
if (operationArg2 && typeof operationArg2.init === "function") {
operationArg2.init();
operationArg2.initialized = true;
}
}
if (operation === "authenticate" && operationArg1) {
try {
P = (o.cookie || "").indexOf("_cpauthhint=") === -1 && !(C.localStorage || {})._cpuser && C.location.href.toLowerCase().indexOf("cpauthenticated") === -1;
} catch (e) {
P = false;
}
if (P) {
a = {
isLoggedIn: function() {
return false;
},
hasValidSubscription: function() {
return false;
}
};
if (typeof operationArg1 === "function") {
operationArg1(null, a);
}
t = [ "authenticate", null ];
}
}
}
C[n].q.push(t);
};
}
try {
s = (o.cookie.split("_cpauthhint=")[1] || "").split(";")[0];
if ((s ? Number(s[1]) : NaN) > 0) {
if (o.body) {
o.body.classList.add("cpauthenticated");
} else {
o.addEventListener("DOMContentLoaded", (function() {
o.body.classList.add("cpauthenticated");
}));
}
}
} catch (e) {}
C[n].l = +new Date;
C[n].sv = 5;
}(window, document, "cp");
cp("extension", "onetrust", {
version: 1,
init: function() {
function hideDarkFilter() {
if (typeof window.MutationObserver === "function") {
new MutationObserver((function(mutationsList, observer) {
Array.prototype.forEach.call(mutationsList, (function(mutation) {
if (mutation.type === "childList" && mutation.target && mutation.target.id === "onetrust-consent-sdk") {
Array.prototype.forEach.call(mutation.addedNodes, (function(node) {
if (node.classList.contains("onetrust-pc-dark-filter")) {
node.classList.add("ot-hide");
observer.disconnect();
}
}));
}
}));
})).observe(document.documentElement, {
childList: true,
subtree: true
});
} else {
const intervalHdl = setInterval((function() {
const oneTrustContainer = document.getElementById("onetrust-consent-sdk");
if (!oneTrustContainer) {
return;
}
const darkFilter = oneTrustContainer.querySelector(".onetrust-pc-dark-filter");
if (darkFilter) {
darkFilter.classList.add("ot-hide");
clearInterval(intervalHdl);
}
}), 50);
}
}
function hideFirstLayer() {
let element = document.getElementById("__cp_ot_hide_banner");
if (element) {
return;
}
element = document.createElement("style");
element.id = "__cp_ot_hide_banner";
element.appendChild(document.createTextNode("#onetrust-banner-sdk { display: none !important; }"));
if (document.head) {
document.head.appendChild(element);
} else if (document.body) {
document.body.appendChild(element);
} else {}
}
function hideOneTrustElements() {
hideFirstLayer();
hideDarkFilter();
}
function unhideFirstLayer() {
const style = document.getElementById("__cp_ot_hide_banner");
if (style && style.parentElement) {
style.parentElement.removeChild(style);
}
}
function unhideDarkFilterImpl() {
const container = document.getElementById("onetrust-consent-sdk");
if (!container) {
return;
}
const darkFilter = Array.prototype.find.call(container.children, (function(v) {
return v.classList.contains("onetrust-pc-dark-filter");
}));
if (darkFilter) {
darkFilter.classList.remove("ot-hide");
darkFilter.removeAttribute("style");
darkFilter.style.zIndex = "2147483644";
}
}
function unhideDarkFilter() {
const banner = document.getElementById("onetrust-banner-sdk");
if (banner) {
const attr = banner.getAttribute("style");
if (!banner.classList.contains("ot-hide") && !attr) {
banner.style.zIndex = "2147483645";
unhideDarkFilterImpl();
}
} else {
if (typeof window.MutationObserver !== "function") {
return;
}
new MutationObserver((function(mutationsList, observer) {
Array.prototype.forEach.call(mutationsList, (function(mutation) {
if (mutation.type === "childList" && mutation.target && mutation.target.id === "onetrust-consent-sdk") {
Array.prototype.forEach.call(mutation.addedNodes, (function(node) {
if (node.id === "onetrust-banner-sdk") {
const attr = node.getAttribute("style");
if (!node.classList.contains("ot-hide") && !attr) {
node.style.zIndex = "2147483645";
unhideDarkFilterImpl();
}
observer.disconnect();
}
}));
}
}));
})).observe(document.documentElement, {
childList: true,
subtree: true
});
}
}
function unhideOneTrustElements() {
unhideDarkFilter();
unhideFirstLayer();
}
hideOneTrustElements();
return cp("error", (function() {
unhideOneTrustElements();
}));
}
});
// Will activate Contentpass and initialize basic interfaces for
// communicating with Contentpass
cp('create', cpPropertyId, {
baseUrl: cpBaseUrl
});
// Will render the layer provided by contentpass.
// If user gives full consent, the onFullConsent callback is fired.
// If user is logged into contentpass and has a valid subscription for the
// current website, no layer is displayed.
// Use the cp('authenticate') function below to react on further details
// regarding contentpass users.
cp('render', {
onFullConsent: function() {
console.log('[CP] onFullConsent');
// load advertising
}
});
// Will evaluate the user's login state regarding contentpass and whether
// user has a valid subscription.
// This call is optional as "cp('render')" above is also checking for the
// contentpass subscription state.
// Use this function for example to update your layout for contentpass users.
// We also provide CSS-based and cookie-based options for this case.
cp('authenticate', function (error, user) {
if (error) {
// Error handling depending on use case
return;
}
if (user.isLoggedIn() && user.hasValidSubscription()) {
// User has valid subscription
} else {
// User has no valid subscription
}
});
}()
</script>
<script src="https://cp.example.com/now.js" async fetchPriority="high" onerror="cp('fatal', arguments)"></script>
Keeping contentpass code snippet up to date
We’re always aiming to improve the contentpass code snippet to ensure optimal performance, compatibility, and functionality. Sometimes also updates of our CMP partners require an update of our integration, and thus your code that initializes the CMP and contentpass.
To save effort on your end, we want to keep the amount of updates low, but on the other hand those updates should never be breaking changes. But of course it's always beneficial to use the latest version.
How to know when an update is needed
We check your integration with our daily property reviews. The property status page in your publisher dashboard will either show a green, yellow or red status. For yellow, we strongly recommend to update, but it's not urgent. In case you landed here because the code snippet check turned red, or you got the corresponding mail notification, please immediately update the contentpass code snippet.
How to update the contentpass code snippet
Simply replace the outdated snippet with the latest version. You’ll always find the latest version in the above section: Add contentpass snippet.
Allow the user to open the CMP settings
To open the CMP settings layer, OneTrust provides a simple SDK function: OneTrust.ToggleInfoDisplay()
You can easily trigger this function by adding a link to your footer with an onclick
handler like this:
<a href="#" onclick="OneTrust.ToggleInfoDisplay();return false;">Open Consent Settings</a>
5. Further Improvements
5.1 Performance Optimizations (optional)
Providing a reliable and high-performant service is one of our highest concerns. One such way is by ensuring our now.js bundle is as small as possible (~30 KB) and also having our components loaded asynchronously, so chunks are fetched only as needed.
Speed up connection to our servers
One way in which you can improve the initial loading time of your page is by adding a preconnect link element to the head of your website. This will tell the browser to initiate a connection to our servers as early as possible so it is ready when our actual SDK is requested.
The following snippet contains a placeholder value that you need to replace with the correct value for your property
The href placeholder
https://cp.example.com
should use the CNAME created for your property. You can find the correct values for the property on the publisher dashboard.
You can find the correct values for your property on the Publisher Dashboard
Please replace the href placeholder and add the following tag to the head of your page, as high up in the HTML as possible.
<link rel="preconnect" href="https://cp.example.com" />
You can also initiate a preconnect via the Link HTTP header
Additionally, incorporating the fetchPriority attribute in our SDK script tag, setting its value to "high", and placing it high up inside the element of the HTML can significantly enhance the page's response time. This is because the browser can immediately fetch the resources it needs to render the first layer.
Faster Loading
In some rare situations you may want to load third-parties without basing it on TCF-Consent, but not load them for contentpass users. There is a way to accomplish this without relying on our backend, thus without additional request. Please consult our Loading third-parties for non-subscribers only section in the third-party docs for details.
5.2 Improving UX for contentpass users
We offer a few methods for you to recognize if the current visitor is a contentpass subscriber, so you can improve the user experience for them. This can be achieved on both the client and server side.
Client-Side Javascript
To check if a contentpass subscriber is authenticated on the front-end we recommend using our SDK method: cp('authenticate')
, see our web-sdk docs for more details.
The callback argument will return an object that contains all the up-to-date information you need to determine a user with a valid contentpass session.
cp('authenticate', function (error, user) {
if (error) {
// Error handling depending on use case
return;
}
if (user.isLoggedIn() && user.hasValidSubscription()) {
// User has valid subscription
} else {
// User has no valid subscription
}
});
The .cpauthenticated
CSS class
To avoid having lots of empty ad-slots for contentpass users, we provide a way to recognize contentpass users on the client-side via CSS.
We provide a special css selector cpauthenticated
which allows you to easily change the page styling depending on the user's authentication status.
When an authenticated user is logged-in the class name cpauthenticated
is added to the class list of the body
tag.
This provides you with the means to easily customise any child elements without having to check the subscription status yourself.
Please ensure that this CSS rule is applied as early as possible on your page to avoid layout shifts of the page content! Adding it to the first CSS file that is loaded on your page is recommended, or as high up as possible in the <head>
of your page.
Examples
Basic example: hiding all containers with a specific class for authenticated users
This basic css can be added to your stylesheet to hide all containers with the class ad-container
as soon as the user is logged in with contentpass
body.cpauthenticated .ad-container {
display: none;
}
Advanced example: hiding containers which have anchor tags with a specific href
This example shows how to hide all containers with the classads
which contain an anchor tag with an href starts with http
and that does not contain example.com/
. This is useful to e.g. hide all external ads that are not from your own domain while e.g. still showing internal sponsored articles.<html lang="en">
<head>
<style>
body.cpauthenticated
.ads:has(a[href^="http"]:not([href*="example.com/"])) {
display: none;
}
</style>
</head>
<body class="cpauthenticated">
<div class="ads">
<p>adserver.com</p>
<a href="https://adserver.com/?redirect=123">
<img src="..." />
</a>
</div>
<div class="ads">
<p>example.com</p>
<a href="https://example.com/mysponsoredarticle.html">
<img src="..." />
</a>
</div>
</body>
</html>
Conclusion
The cpauthenticated class provides developers with a convenient way to manage user authentication states and dynamically adjust the display of elements within their web applications. By leveraging the cpauthenticated class, developers can create a more personalized and seamless user experience for their audience.
We do not recommend relying on this as a robust method for recognizing contentpass users for business logic. CSS classes can be easily manipulated by the user or any other javascript running on the page. Additionally there is no guarantee that the CSS styles are applied before your javascript runs.
Server-Side Cookie
For recognizing contentpass users on the backend we provide a _cpauthhint
cookie that we set on the user's browser. If the user is a logged-in contentpass user the cookie will have a value of 1
and 0
if they are logged out.
The following is a simplified-code example of how one might check for the cookie on a node.js server, in order to serve content without anti-adblocking messages for contentpass users and only for regular users.
// Middleware to check the "_cpauthhint" cookie
function checkUserType(req, res, next) {
const cpAuthHintCookie = req.cookies._cpauthhint;
// Check if the cookie exists and has the value for a logged in CP user
req.isLoggedInCpUser = cpAuthHintCookie === '1';
next();
}
// Route that uses the authentication middleware
app.get('/dashboard', checkUserType, function (req, res) {
// Render different views for ContentPass users and regular users
if (req.isCpUser) {
res.render('dashboard', { user: 'ContentPassUser', showAdblockCommunication: false });
} else {
res.render('dashboard', { user: 'RegularUser', showAdblockCommunication: true });
}
});