To setup targeted advertisement make sure you have all of the prerequisites done before you continue. The setup will require you to change some of the website's code, so please keep that in mind.
First we want to check if we have both the campaign properly setup and if all of our segments work properly. To do that we can use the script below, simply copy and paste the script into the browser's console (Ctrl + Shift + I then click "Console"), add any modifications that you wish (eg. adding the segment ID), and execute the script by pressing the Enter key.
(function(segment) {
let req = new XMLHttpRequest();
// Setup request events
req.addEventListener('load', function() {
if(segment) {
if(segment === this.responseText)
console.log('Segment verified! Everything looks ok.');
else
console.log('Segment mismatch! Actual response: ' + this.responseText);
}
else if(this.responseText && this.responseText !== '')
console.log('Received segment! Everything looks ok.');
else
console.log('No segment received! Something is wrong.');
});
req.addEventListener('error', function() {
console.log('An error occured during sending/receiving request!');
});
// Send request
req.open('GET', 'https://analytics.contentexchange.me/bex/keywords' + (segment ? ('?segment=' + segment) : ''));
req.withCredentials = true;
req.send();
})(); // If you want to target a specific segment, within the () put 'segment_id' with ' included. Example: ('5e610309f2f66476f179b0be')
The universal header code is designed to obtain the "keywords" or segment IDs of the user, that way we can use them later on to target ads. There are 2 types of codes that are different depending on what kind of system you use.
To install the universal code, you have to make sure it is loaded first. That means it has to be above all other scripts, if it is not then unexpected issues can sometimes occur. So copy and paste one of the provided codes below based on your advertisement system.
Note: We provide both the HTML and JS codes for async, unless you have a centralize JS script, we recommend using Sync HTML
<script async src="https://analytics.contentexchange.me/bex/keywords?format=js&ref=https://originating.host"></script>
<script>
(function() {
// Create placeholders
const bextag = window.bextag = window.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
// Setup segment parser
function findSegment(key) {
let keyVal = location.search.substring(1).split('&');
for(let a = 0; a < keyVal.length; a++) {
let parts = keyVal[a].split('=');
for(let b = 0; b < parts.length; b++) {
if(parts[b] === key) {
if((b + 1) < parts.length)
return parts[b + 1];
break;
}
}
}
return null;
}
// Setup request parser
function executeOrder66() {
// Check if loaded already
if(targeting.loaded) return;
// Save data
targeting.segment = this.responseText;
// Run callback
if(targeting.executor)
targeting.executor();
}
// Check if predetermined
let segment = findSegment('segment');
if(segment) return targeting.segment = segment;
// Setup bex request
let segment_request = new XMLHttpRequest();
// Send request
segment_request.addEventListener('load', executeOrder66);
segment_request.open('GET', 'https://analytics.contentexchange.me/bex/keywords?ref=https://originating.host');
segment_request.withCredentials = true;
segment_request.send();
})();
</script>
(function() {
// Create placeholders
const bextag = window.bextag = window.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
// Setup segment parser
function findSegment(key) {
let keyVal = location.search.substring(1).split('&');
for(let a = 0; a < keyVal.length; a++) {
let parts = keyVal[a].split('=');
for(let b = 0; b < parts.length; b++) {
if(parts[b] === key) {
if((b + 1) < parts.length)
return parts[b + 1];
break;
}
}
}
return null;
}
// Setup request parser
function executeOrder66() {
// Check if loaded already
if(targeting.loaded) return;
// Save data
targeting.segment = this.responseText;
// Run callback
if(targeting.executor)
targeting.executor();
}
// Check if predetermined
let segment = findSegment('segment');
if(segment) return targeting.segment = segment;
// Setup bex request
let segment_request = new XMLHttpRequest();
// Send request
segment_request.addEventListener('load', executeOrder66);
segment_request.open('GET', 'https://analytics.contentexchange.me/bex/keywords?ref=https://originating.host');
segment_request.withCredentials = true;
segment_request.send();
})();
Now that we have our universal script on our website, we have to enable the actual targeting. Targeting works in multiple different ways based on which ad system and provider you use. We do have ones that we custom made the support for below, but you also have the "Example" script, that one is a raw template that will let you easily create support for your own system/provider.
To get started simply find a script that will suit your provider/system or modify the example one, once you have the script simply put it after the script tag that loads your provider/system's script but before the master code is initialized.
Warning: Google's tag manager and IProm are an exception to this! Replace the load functions on both the providers with the selected script! (Google is "googletag.enableServices();", IProm is "_ipromNS('load')"
Note: The iframe scripts are designed to be modified with some of your information. Please change anything in the script with <> wrapped around the word except <script>
<script>
(function () {
// Create placeholders
const bextag = window.bextag = window.bextag ||
{};
const targeting = bextag.targeting = bextag.targeting ||
{};
//targeting timeout - for fallback to ads without targeting if the keyword call is too late
const timeout = 300
//const LOAD_ADS = function(segment) => user defined function to load ads with/wihtout targeting
//targeting.executor - called below or in TOP PART when keywords finish loading
targeting.executor = function ()
{
if (targeting.loaded) return
targeting.loaded = true
if (!LOAD_ADS) return
// targeting.segment provides the segment ID(s) of the user
if (targeting.segment)
{
// With targeting
LOAD_ADS(targeting.segment)
}
else
{
// Without targeting
LOAD_ADS()
}
}
// Check if targeting data is already available
if (targeting.segment && targeting.segment !== '')
{
//load ads immediately
targeting.executor()
}
else
{
// Create timeout to trigger ads without targeting
setTimeout(targeting.executor, timeout);
}
})();
</script>
<script>
(function() {
// Create placeholders
const bextag = window.bextag = window.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
// Setup timeout
setTimeout(function() {
if(!targeting.loaded) {
targeting.loaded = true;
googletag.enableServices();
}
}, 300);
// Passtrough builder setup
function buildPassthrough(keywords) {
// Get all segments
let segments = keywords.split(',');
// Load google tag targeting
if(segments)
googletag.pubads().setTargeting('Targeting', segments);
}
// Run google ad manager
if(targeting.segment && targeting.segment !== '') {
buildPassthrough(targeting.segment);
googletag.enableServices();
targeting.loaded = true;
} else {
targeting.executor = function() {
buildPassthrough(targeting.segment);
googletag.enableServices();
targeting.loaded = true;
}
}
})();
</script>
<script>
(function() {
// Create placeholders
const bextag = window.bextag = window.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
const orgAdOcean = ado.master;
// Passtrough builder setup
function buildPassthrough(keywords) {
return keywords.split(',');
}
// Invoker
ado.master = function(data) {
if(!orgAdOcean) return;
if(data.keys)
data.keys.concat(buildPassthrough(targeting.segment));
else
data.keys = buildPassthrough(targeting.segment);
orgAdOcean.apply(this, arguments);
}
})();
</script>
<script>
(function() {
// Create placeholders
const bextag = window.bextag = window.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
// Create listener to load the tags
window.addEventListener('DOMContentLoaded', function(ev) {
if(!targeting.segment) return;
// Find all revive tags and split keywords
let reviveTags = document.querySelectorAll('ins[data-revive-id]');
// Add keywords to revive tags
for(let i = 0; i < reviveTags.length; i++)
reviveTags[i].setAttribute('data-revive-keywords', targeting.segment);
});
})();
</script>
<script>
(function() {
let mainWindow = window;
let mainDocument = document;
if(window.top != window) {
while(mainWindow != window.top) {
try {
let topDoc = window.parent.document;
mainWindow = window.parent;
mainDocument = topDoc;
} catch(ex) {
break;
}
}
}
// Create placeholders
const bextag = mainWindow.bextag = mainWindow.bextag || {};
const targeting = bextag.targeting = bextag.targeting || {};
// Change all of the revive tags
let loaded = false;
function buildTargeting() {
if(loaded) return;
loaded = true;
// Set the targeting
if(targeting.segment) {
let reviveTags = mainDocument.querySelectorAll('ins[data-revive-id]');
for(let i = 0; i < reviveTags.length; i++)
reviveTags[i].setAttribute('data-revive-keywords', targeting.segment);
}
// Place the script
let reviveScript = document.createElement('script');
reviveScript.async = true;
reviveScript.src = '<Revive Script URL>';
document.head.appendChild(reviveScript);
}
// Setup timeout
setTimeout(buildTargeting, 30);
// Check if there is a segment, if there is none request it
if(targeting.hasOwnProperty('segment')) buildTargeting();
else {
let segment_request = new XMLHttpRequest();
segment_request.addEventListener('load', function() {
targeting.segment = this.responseText;
buildTargeting();
});
segment_request.open('GET', 'https://analytics.contentexchange.me/bex/keywords');
segment_request.withCredentials = true;
segment_request.send();
}
})();
</script>