-
-
Save andydavies/8847bb8b984f26348c19152b0adaf7a8 to your computer and use it in GitHub Desktop.
TCF2.0 Compliant approach to loading Google Ad Manager, Prebid and Amazon APS tags that prevents TCV2.1a errors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
</head> | |
<body> | |
<!-- Quantcast CMP, pasted un-modified from Quantcast interface --> | |
<script type="text/javascript" async=true> | |
(function() { | |
var host = window.location.hostname; | |
var element = document.createElement('script'); | |
var firstScript = document.getElementsByTagName('script')[0]; | |
var url = 'https://quantcast.mgr.consensu.org' | |
.concat('/choice/', '<<your quantcast id>>', '/', host, '/choice.js') | |
var uspTries = 0; | |
var uspTriesLimit = 3; | |
element.async = true; | |
element.type = 'text/javascript'; | |
element.src = url; | |
firstScript.parentNode.insertBefore(element, firstScript); | |
function makeStub() { | |
var TCF_LOCATOR_NAME = '__tcfapiLocator'; | |
var queue = []; | |
var win = window; | |
var cmpFrame; | |
function addFrame() { | |
var doc = win.document; | |
var otherCMP = !!(win.frames[TCF_LOCATOR_NAME]); | |
if (!otherCMP) { | |
if (doc.body) { | |
var iframe = doc.createElement('iframe'); | |
iframe.style.cssText = 'display:none'; | |
iframe.name = TCF_LOCATOR_NAME; | |
doc.body.appendChild(iframe); | |
} else { | |
setTimeout(addFrame, 5); | |
} | |
} | |
return !otherCMP; | |
} | |
function tcfAPIHandler() { | |
var gdprApplies; | |
var args = arguments; | |
if (!args.length) { | |
return queue; | |
} else if (args[0] === 'setGdprApplies') { | |
if ( | |
args.length > 3 && | |
args[2] === 2 && | |
typeof args[3] === 'boolean' | |
) { | |
gdprApplies = args[3]; | |
if (typeof args[2] === 'function') { | |
args[2]('set', true); | |
} | |
} | |
} else if (args[0] === 'ping') { | |
var retr = { | |
gdprApplies: gdprApplies, | |
cmpLoaded: false, | |
cmpStatus: 'stub' | |
}; | |
if (typeof args[2] === 'function') { | |
args[2](retr); | |
} | |
} else { | |
queue.push(args); | |
} | |
} | |
function postMessageEventHandler(event) { | |
var msgIsString = typeof event.data === 'string'; | |
var json = {}; | |
try { | |
if (msgIsString) { | |
json = JSON.parse(event.data); | |
} else { | |
json = event.data; | |
} | |
} catch (ignore) {} | |
var payload = json.__tcfapiCall; | |
if (payload) { | |
window.__tcfapi( | |
payload.command, | |
payload.version, | |
function(retValue, success) { | |
var returnMsg = { | |
__tcfapiReturn: { | |
returnValue: retValue, | |
success: success, | |
callId: payload.callId | |
} | |
}; | |
if (msgIsString) { | |
returnMsg = JSON.stringify(returnMsg); | |
} | |
event.source.postMessage(returnMsg, '*'); | |
}, | |
payload.parameter | |
); | |
} | |
} | |
while (win) { | |
try { | |
if (win.frames[TCF_LOCATOR_NAME]) { | |
cmpFrame = win; | |
break; | |
} | |
} catch (ignore) {} | |
if (win === window.top) { | |
break; | |
} | |
win = win.parent; | |
} | |
if (!cmpFrame) { | |
addFrame(); | |
win.__tcfapi = tcfAPIHandler; | |
win.addEventListener('message', postMessageEventHandler, false); | |
} | |
}; | |
makeStub(); | |
var uspStubFunction = function() { | |
var arg = arguments; | |
if (typeof window.__uspapi !== uspStubFunction) { | |
setTimeout(function() { | |
if (typeof window.__uspapi !== 'undefined') { | |
window.__uspapi.apply(window.__uspapi, arg); | |
} | |
}, 500); | |
} | |
}; | |
var checkIfUspIsReady = function() { | |
uspTries++; | |
if (window.__uspapi === uspStubFunction && uspTries < uspTriesLimit) { | |
console.warn('USP is not accessible'); | |
} else { | |
clearInterval(uspInterval); | |
} | |
}; | |
if (typeof window.__uspapi === 'undefined') { | |
window.__uspapi = uspStubFunction; | |
var uspInterval = setInterval(checkIfUspIsReady, 6000); | |
} | |
})(); | |
</script> | |
<!-- Our Prebid.js build, all bidders are IAB registered and the build | |
includes Consent Management and GDPR Enforcement --> | |
<script async src="/prebid.js"></script> | |
<!-- Amazon APS --> | |
<script> | |
!function(a9,a,p,s,t,A,g){if(a[a9])return;function q(c,r){a[a9]._Q.push([c,r])}a[a9]={init:function(){q("i",arguments)},fetchBids:function(){q("f",arguments)},setDisplayBids:function(){},targetingKeys:function(){return[]},_Q:[]};A=p.createElement(s);A.async=!0;A.src=t;g=p.getElementsByTagName(s)[0];g.parentNode.insertBefore(A,g)}("apstag",window,document,"script","//c.amazon-adsystem.com/aax2/apstag.js"); | |
</script> | |
<!-- Our bespoke ad code --> | |
<script> | |
window.googletag=window.googletag||{}; | |
window.googletag.cmd=window.googletag.cmd||[]; | |
window.pbjs=window.pbjs||{}; | |
window.pbjs.que=window.pbjs.que||[]; | |
(function() { | |
// Initiate the whole ad stack, including | |
// Prebid, amazon and GAM | |
function initAdStack() { | |
// a whole load of code in here to initiate your ad stack | |
// e.g. | |
// * request bids through pre bid | |
// * request bids through amazon | |
// * define & display ad units via googletag | |
} | |
// Wait for the signal before touching GAM/Amazon/Prebid | |
window.__tcfapi('addEventListener', 2, function(tcData, listenerSuccess) { | |
if (listenerSuccess) { | |
// Don't initiate ads until after the result from the CMP | |
// 'useractioncomplete' >> Fired when the user clicks accept/reject | |
// 'tcloaded' >> Fired when the CMP loads, the user may or may not have made a decision yet | |
if( tcData.eventStatus === 'useractioncomplete' || tcData.eventStatus === 'tcloaded' ) { | |
// Don't bother initiating any ad systems unless you have concent for Purpose 1. | |
if( tcData.purpose.consents[1] ) { | |
if( !window.adInit ) { | |
// Make sure we only call this once per page load just in case the user | |
// changing preferences triggers a 2nd event. | |
window.adInit = true; | |
// Iniaite you're ad stack | |
initAdStack(); | |
} | |
} | |
} | |
} | |
}); | |
})(); | |
</script> | |
<!-- Register GAM script after Quantcast but I don't think it matters if its before | |
or after as it only sets cookies once you interact with it via `googletag` --> | |
<script async src="//www.googletagservices.com/tag/js/gpt.js"></script> | |
<!-- ... rest of page ... --> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment