-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PUC update to include Native Phase 2 spec: #106
Changes from 3 commits
9b3901e
1e220d4
4f11052
b8d8f22
6cacfc5
a4d5f58
5d953f3
f436d1e
319ac69
413e443
6f1ca64
1af6176
d0184e2
4ee7db1
9ddae29
73fa612
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
* values in native creative templates. | ||
*/ | ||
|
||
import { sendRequest } from './utils'; | ||
import { sendRequest, loadScript } from './utils'; | ||
|
||
/* | ||
* Native asset->key mapping from Prebid.js/src/constants.json | ||
|
@@ -27,6 +27,7 @@ const NATIVE_KEYS = { | |
phone: 'hb_native_phone', | ||
price: 'hb_native_price', | ||
salePrice: 'hb_native_saleprice', | ||
rendererUrl: 'hb_renderer_url', | ||
}; | ||
|
||
// Asset type mapping as per Native IAB spec 1.2 | ||
|
@@ -160,14 +161,26 @@ export function newNativeAssetManager(win) { | |
/* | ||
* Entry point to search for placeholderes and set up postmessage roundtrip | ||
* to retrieve native assets. Looks for placeholders for the given adId and | ||
* fires a callback after the native html is updated. | ||
* fires a callback after the native html is updated. If no placeholders found | ||
* and requestAllAssets flag is set in the tag, postmessage roundtrip | ||
* to retrieve native assets that have a value on the corresponding bid | ||
*/ | ||
function loadAssets(adId, cb) { | ||
const placeholders = scanForPlaceholders(adId); | ||
const placeholders = scanForPlaceholders(adId), flag = (typeof win.pbNativeData !== 'undefined'); | ||
|
||
if (flag && win.pbNativeData.hasOwnProperty('assetsToReplace')) { | ||
win.pbNativeData.assetsToReplace.forEach((asset) => { | ||
const key = (asset.match(/hb_native_/i)) ? asset : NATIVE_KEYS[asset]; | ||
if (key) {placeholders.push(key);} | ||
}); | ||
} | ||
|
||
if (placeholders.length > 0) { | ||
callback = cb; | ||
requestAssets(adId, placeholders); | ||
}else if (flag && win.pbNativeData.hasOwnProperty('requestAllAssets') && win.pbNativeData.requestAllAssets) { | ||
callback = cb; | ||
requestAllAssets(adId); | ||
} | ||
} | ||
|
||
|
@@ -176,10 +189,11 @@ export function newNativeAssetManager(win) { | |
*/ | ||
function scanForPlaceholders(adId) { | ||
let placeholders = []; | ||
const flag = (typeof win.pbNativeData !== 'undefined'); | ||
|
||
Object.keys(NATIVE_KEYS).forEach(key => { | ||
const placeholderKey = NATIVE_KEYS[key]; | ||
const placeholder = (adId) ? `${placeholderKey}:${adId}` : `${placeholderKey}`; | ||
const placeholder = (adId && !flag) ? `${placeholderKey}:${adId}` : `${placeholderKey}`; | ||
const placeholderIndex = win.document.body.innerHTML.indexOf(placeholder); | ||
|
||
if (~placeholderIndex) { | ||
|
@@ -190,6 +204,19 @@ export function newNativeAssetManager(win) { | |
return placeholders; | ||
} | ||
|
||
/* | ||
* Searches the DOM for existence passed string | ||
*/ | ||
function scanForString(str) { | ||
const strIndex = win.document.body.innerHTML.indexOf(str); | ||
|
||
if (~strIndex) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could just do return win.document.body.innerHTML.indexOf(str) !== -1 Not sure this function is even being used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont remember this function but cant find a use for it so removing |
||
|
||
/* | ||
* Sends postmessage to Prebid for asset placeholders found in the native | ||
* creative template, and setups up a listener for when Prebid responds. | ||
|
@@ -204,6 +231,23 @@ export function newNativeAssetManager(win) { | |
assets, | ||
}; | ||
|
||
|
||
win.parent.postMessage(JSON.stringify(message), '*'); | ||
} | ||
|
||
/* | ||
* Sends postmessage to Prebid for asset placeholders found in the native | ||
* creative template, and setups up a listener for when Prebid responds. | ||
*/ | ||
function requestAllAssets(adId) { | ||
win.addEventListener('message', replaceAssets, false); | ||
|
||
const message = { | ||
message: 'Prebid Native', | ||
action: 'allAssetRequest', | ||
adId, | ||
}; | ||
|
||
win.parent.postMessage(JSON.stringify(message), '*'); | ||
} | ||
|
||
|
@@ -227,12 +271,43 @@ export function newNativeAssetManager(win) { | |
} | ||
|
||
if (data.message === 'assetResponse') { | ||
const body = win.document.body.innerHTML; | ||
const newHtml = replace(body, data); | ||
const body = win.document.body.innerHTML,flag = (typeof win.pbNativeData !== 'undefined'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you split this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
win.document.body.innerHTML = newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
if ((data.hasOwnProperty('rendererUrl') && data.rendererUrl) || (flag && win.pbNativeData.hasOwnProperty('rendererUrl'))) { | ||
if (win.renderAd) { | ||
const newHtml = (win.renderAd && win.renderAd(data.assets)) || ''; | ||
win.document.body.innerHTML = body + newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
} else if (document.getElementById('pb-native-renderer')) { | ||
document.getElementById('pb-native-renderer').addEventListener('load', function() { | ||
const newHtml = (win.renderAd && win.renderAd(data.assets)) || ''; | ||
win.document.body.innerHTML = body + newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
}); | ||
} else { | ||
loadScript(win, ((flag && win.pbNativeData.hasOwnProperty('rendererUrl') && win.pbNativeData.rendererUrl) || data.rendererUrl), function() { | ||
const newHtml = (win.renderAd && win.renderAd(data.assets)) || ''; | ||
win.document.body.innerHTML = body + newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
}) | ||
} | ||
} else if ((data.hasOwnProperty('adTemplate') && data.adTemplate)||(flag && win.pbNativeData.hasOwnProperty('adTemplate'))) { | ||
const template = (flag && win.pbNativeData.hasOwnProperty('adTemplate') && win.pbNativeData.adTemplate) || data.adTemplate; | ||
const newHtml = replace(template, data); | ||
|
||
win.document.body.innerHTML = body + newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
} else { | ||
const newHtml = replace(body, data); | ||
|
||
win.document.body.innerHTML = newHtml; | ||
callback && callback(); | ||
win.removeEventListener('message', replaceAssets); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -244,7 +319,8 @@ export function newNativeAssetManager(win) { | |
let html = document; | ||
|
||
(assets || []).forEach(asset => { | ||
const searchString = (adId) ? `${NATIVE_KEYS[asset.key]}:${adId}` : `${NATIVE_KEYS[asset.key]}`; | ||
const flag = (typeof win.pbNativeData !== 'undefined'); | ||
const searchString = (adId && !flag) ? `${NATIVE_KEYS[asset.key]}:${adId}` : ((flag) ? '##'+`${NATIVE_KEYS[asset.key]}`+'##' : `${NATIVE_KEYS[asset.key]}`); | ||
const searchStringRegex = new RegExp(searchString, 'g'); | ||
html = html.replace(searchStringRegex, asset.value); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Script to handle firing impression and click trackers from native teamplates | ||
*/ | ||
import { parseUrl, triggerPixel, transformAuctionTargetingData } from './utils'; | ||
import { newNativeAssetManager } from './nativeAssetManager'; | ||
|
||
const AD_ANCHOR_CLASS_NAME = 'pb-click'; | ||
const AD_DATA_ADID_ATTRIBUTE = 'pbAdId'; | ||
|
||
export function newNativeRenderManager(win) { | ||
let publisherDomain; | ||
|
||
|
||
function findAdElements(className) { | ||
let adElements = win.document.getElementsByClassName(className); | ||
return adElements || []; | ||
} | ||
|
||
function loadClickTrackers(event, adId) { | ||
fireTracker(adId, 'click'); | ||
} | ||
|
||
function fireTracker(adId, action) { | ||
if (adId === '') { | ||
console.warn('Prebid tracking event was missing \'adId\'. Was adId macro set in the HTML attribute ' + AD_DATA_ADID_ATTRIBUTE + 'on the ad\'s anchor element'); | ||
} else { | ||
let message = { message: 'Prebid Native', adId: adId }; | ||
|
||
// fires click trackers when called via link | ||
if (action === 'click') { | ||
message.action = 'click'; | ||
} | ||
|
||
win.parent.postMessage(JSON.stringify(message), publisherDomain); | ||
} | ||
} | ||
|
||
function fireNativeImpTracker(adId) { | ||
fireTracker(adId, 'impression'); | ||
} | ||
|
||
function fireNativeCallback() { | ||
const adElements = findAdElements(AD_ANCHOR_CLASS_NAME); | ||
for (let i = 0; i < adElements.length; i++) { | ||
adElements[i].addEventListener('click', function(event) { | ||
loadClickTrackers(event, window.pbNativeData.adId); | ||
}, true); | ||
} | ||
} | ||
|
||
// START OF MAIN CODE | ||
let renderNativeAd = function(nativeTag) { | ||
window.pbNativeData = nativeTag; | ||
const targetingData = transformAuctionTargetingData(nativeTag); | ||
const nativeAssetManager = newNativeAssetManager(window); | ||
|
||
if (nativeTag.hasOwnProperty('adId')) { | ||
let parsedUrl = parseUrl(window.pbNativeData.pubUrl); | ||
publisherDomain = parsedUrl.protocol + '://' + parsedUrl.host; | ||
|
||
if (nativeTag.hasOwnProperty('rendererUrl') && !nativeTag.rendererUrl.match(/##.*##/i)) { | ||
const scr = document.createElement('SCRIPT'); | ||
scr.src = nativeTag.rendererUrl, | ||
scr.id = 'pb-native-renderer'; | ||
document.body.appendChild(scr); | ||
} | ||
nativeAssetManager.loadAssets(nativeTag.adId,fireNativeCallback); | ||
fireNativeCallback(); | ||
fireNativeImpTracker(nativeTag.adId); | ||
}else{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. some more lint issues There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have a space after closing bracket befor else and after } else { There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe just run enable eslint in your editor and see what else there is? |
||
console.warn('Prebid Native Tag object was missing \'adId\'.'); | ||
} | ||
} | ||
|
||
return { | ||
renderNativeAd | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
import { newNativeTrackerManager } from './nativeTrackerManager'; | ||
import { newNativeRenderManager } from './nativeRenderManager'; | ||
|
||
window.pbNativeTag = (window.pbNativeTag || {}); | ||
const nativeTrackerManager = newNativeTrackerManager(window); | ||
const nativeRenderManager = newNativeRenderManager(window); | ||
|
||
window.pbNativeTag.startTrackers = nativeTrackerManager.startTrackers; | ||
window.pbNativeTag.renderNativeAd = nativeRenderManager.renderNativeAd; | ||
|
||
window.pbNativeTag.startTrackers = nativeTrackerManager.startTrackers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after closing brackets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed these. Not sure how they didnt update last time around