prebid-universal-creative 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +3 -3
- package/.github/workflows/issue_tracker.yml +89 -0
- package/README.md +1 -1
- package/browsers.json +17 -33
- package/dist/creative.js +3 -3
- package/dist/creative.max.js +516 -420
- package/dist/native-render.js +3 -3
- package/dist/native-trk.js +3 -3
- package/dist/prebid-mobile-rewarded-vast.xml +22 -0
- package/dist/uid.js +2 -2
- package/gulpfile.js +9 -4
- package/package.json +12 -7
- package/src/messaging.js +43 -0
- package/src/nativeAssetManager.js +185 -77
- package/src/nativeORTBTrackerManager.js +32 -0
- package/src/nativeRenderManager.js +10 -12
- package/src/nativeTrackerManager.js +18 -7
- package/src/renderingManager.js +58 -38
- package/src/utils.js +3 -0
- package/static/prebid-mobile-rewarded-vast.xml +22 -0
- package/test/helpers/mocks.js +7 -3
- package/test/spec/messaging_spec.js +64 -0
- package/test/spec/nativeAssetManager_spec.js +493 -347
- package/test/spec/nativeORTBTrackerManager_spec.js +76 -0
- package/test/spec/nativeRenderManager_spec.js +18 -1
- package/test/spec/renderingManager_spec.js +163 -73
@@ -3,8 +3,12 @@
|
|
3
3
|
* values in native creative templates.
|
4
4
|
*/
|
5
5
|
|
6
|
+
import { addNativeClickTrackers, fireNativeImpressionTrackers } from './nativeORTBTrackerManager';
|
6
7
|
import { sendRequest, loadScript } from './utils';
|
8
|
+
import {prebidMessenger} from './messaging.js';
|
9
|
+
import { newEnvironment } from './environment.js';
|
7
10
|
|
11
|
+
const envionment = newEnvironment(window);
|
8
12
|
/*
|
9
13
|
* Native asset->key mapping from Prebid.js/src/constants.json
|
10
14
|
* https://github.com/prebid/Prebid.js/blob/8635c91942de9df4ec236672c39b19448545a812/src/constants.json#L67
|
@@ -56,17 +60,26 @@ const assetTypeMapping = {
|
|
56
60
|
const DEFAULT_CACHE_HOST = 'prebid.adnxs.com';
|
57
61
|
const DEFAULT_CACHE_PATH = '/pbc/v1/cache';
|
58
62
|
|
59
|
-
export function newNativeAssetManager(win) {
|
63
|
+
export function newNativeAssetManager(win, pubUrl) {
|
64
|
+
const sendMessage = prebidMessenger(pubUrl, win);
|
60
65
|
let callback;
|
61
66
|
let errorCountEscapeHatch = 0;
|
67
|
+
let cancelMessageListener;
|
68
|
+
|
69
|
+
function stopListening() {
|
70
|
+
if (cancelMessageListener != null) {
|
71
|
+
cancelMessageListener();
|
72
|
+
cancelMessageListener = null;
|
73
|
+
}
|
74
|
+
}
|
62
75
|
|
63
76
|
function getCacheEndpoint(cacheHost, cachePath) {
|
64
77
|
let host = (typeof cacheHost === 'undefined' || cacheHost === "") ? DEFAULT_CACHE_HOST : cacheHost;
|
65
78
|
let path = (typeof cachePath === 'undefined' || cachePath === "") ? DEFAULT_CACHE_PATH : cachePath;
|
66
|
-
|
79
|
+
|
67
80
|
return `https://${host}${path}`;
|
68
81
|
}
|
69
|
-
|
82
|
+
|
70
83
|
function parseResponse(response) {
|
71
84
|
let bidObject;
|
72
85
|
try {
|
@@ -76,7 +89,7 @@ export function newNativeAssetManager(win) {
|
|
76
89
|
}
|
77
90
|
return bidObject;
|
78
91
|
}
|
79
|
-
|
92
|
+
|
80
93
|
function transformToPrebidKeys(adMarkup) {
|
81
94
|
let assets = [];
|
82
95
|
let clicktrackers;
|
@@ -105,7 +118,7 @@ export function newNativeAssetManager(win) {
|
|
105
118
|
'key' : 'title',
|
106
119
|
'value' : asset.title.text
|
107
120
|
})
|
108
|
-
}
|
121
|
+
}
|
109
122
|
})
|
110
123
|
|
111
124
|
if (adMarkup.link) {
|
@@ -121,7 +134,8 @@ export function newNativeAssetManager(win) {
|
|
121
134
|
return {
|
122
135
|
assets,
|
123
136
|
clicktrackers,
|
124
|
-
'imptrackers' : adMarkup.imptrackers
|
137
|
+
'imptrackers' : adMarkup.imptrackers,
|
138
|
+
'eventtrackers': adMarkup.eventtrackers
|
125
139
|
}
|
126
140
|
}
|
127
141
|
|
@@ -137,8 +151,9 @@ export function newNativeAssetManager(win) {
|
|
137
151
|
win.document.body.innerHTML = newHtml;
|
138
152
|
|
139
153
|
callback && callback({
|
140
|
-
clickTrackers: data.clicktrackers,
|
141
|
-
impTrackers: data.imptrackers
|
154
|
+
clickTrackers: data.clicktrackers,
|
155
|
+
impTrackers: data.imptrackers,
|
156
|
+
eventtrackers: data.eventtrackers
|
142
157
|
});
|
143
158
|
} else {
|
144
159
|
// TODO Shall we just write the markup in the page
|
@@ -151,13 +166,17 @@ export function newNativeAssetManager(win) {
|
|
151
166
|
}
|
152
167
|
|
153
168
|
function loadMobileAssets(tagData, cb) {
|
154
|
-
const placeholders =
|
169
|
+
const placeholders = scanDOMForPlaceHolders();
|
155
170
|
if (placeholders.length > 0) {
|
156
171
|
callback = cb;
|
157
172
|
requestAssetsFromCache(tagData);
|
158
173
|
}
|
159
174
|
}
|
160
175
|
|
176
|
+
function hasPbNativeData() {
|
177
|
+
return typeof win.pbNativeData !== 'undefined'
|
178
|
+
}
|
179
|
+
|
161
180
|
/*
|
162
181
|
* Entry point to search for placeholderes and set up postmessage roundtrip
|
163
182
|
* to retrieve native assets. Looks for placeholders for the given adId and
|
@@ -166,43 +185,47 @@ export function newNativeAssetManager(win) {
|
|
166
185
|
* to retrieve native assets that have a value on the corresponding bid
|
167
186
|
*/
|
168
187
|
function loadAssets(adId, cb) {
|
169
|
-
const placeholders =
|
188
|
+
const placeholders = scanDOMForPlaceHolders(adId);
|
170
189
|
|
171
|
-
if (
|
190
|
+
if (hasPbNativeData() && win.pbNativeData.hasOwnProperty('assetsToReplace')) {
|
172
191
|
win.pbNativeData.assetsToReplace.forEach((asset) => {
|
173
192
|
const key = (asset.match(/hb_native_/i)) ? asset : NATIVE_KEYS[asset];
|
174
193
|
if (key) {placeholders.push(key);}
|
175
194
|
});
|
176
195
|
}
|
177
196
|
|
178
|
-
if (
|
197
|
+
if (hasPbNativeData() && win.pbNativeData.hasOwnProperty('requestAllAssets') && win.pbNativeData.requestAllAssets) {
|
179
198
|
callback = cb;
|
180
|
-
requestAllAssets(adId);
|
199
|
+
cancelMessageListener = requestAllAssets(adId);
|
181
200
|
} else if (placeholders.length > 0) {
|
182
201
|
callback = cb;
|
183
|
-
requestAssets(adId, placeholders);
|
184
|
-
}
|
202
|
+
cancelMessageListener = requestAssets(adId, placeholders);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
function placeholderFor(key, adId) {
|
207
|
+
return (adId && !hasPbNativeData()) ? `${key}:${adId}` : ((hasPbNativeData()) ? `##${key}##` : key)
|
208
|
+
}
|
209
|
+
|
210
|
+
function scanForPlaceHolders(adId, ...markupFragments) {
|
211
|
+
return Object.values(NATIVE_KEYS)
|
212
|
+
.reduce((found, key) => {
|
213
|
+
const placeholder = placeholderFor(key, adId);
|
214
|
+
for (const mkup of markupFragments.filter(Boolean)) {
|
215
|
+
if (mkup.indexOf(placeholder) >= 0) {
|
216
|
+
found.push(key);
|
217
|
+
break;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
return found;
|
221
|
+
}, []);
|
185
222
|
}
|
186
223
|
|
187
224
|
/*
|
188
|
-
* Searches the DOM for placeholder values sent in by Prebid Native
|
225
|
+
* Searches the DOM for legacy placeholder values sent in by Prebid Native
|
189
226
|
*/
|
190
|
-
function
|
191
|
-
|
192
|
-
const doc = win.document;
|
193
|
-
const flag = (typeof win.pbNativeData !== 'undefined');
|
194
|
-
|
195
|
-
Object.keys(NATIVE_KEYS).forEach(key => {
|
196
|
-
const placeholderKey = NATIVE_KEYS[key];
|
197
|
-
const placeholder = (adId && !flag) ? `${placeholderKey}:${adId}` : `${placeholderKey}`;
|
198
|
-
const placeholderIndex = (~doc.body.innerHTML.indexOf(placeholder)) ? doc.body.innerHTML.indexOf(placeholder) : (doc.head.innerHTML && doc.head.innerHTML.indexOf(placeholder));
|
199
|
-
|
200
|
-
if (~placeholderIndex) {
|
201
|
-
placeholders.push(placeholderKey);
|
202
|
-
}
|
203
|
-
});
|
204
|
-
|
205
|
-
return placeholders;
|
227
|
+
function scanDOMForPlaceHolders(adId) {
|
228
|
+
return scanForPlaceHolders(adId, win.document.body.innerHTML, win.document.head.innerHTML);
|
206
229
|
}
|
207
230
|
|
208
231
|
/*
|
@@ -210,8 +233,6 @@ export function newNativeAssetManager(win) {
|
|
210
233
|
* creative template, and setups up a listener for when Prebid responds.
|
211
234
|
*/
|
212
235
|
function requestAssets(adId, assets) {
|
213
|
-
win.addEventListener('message', replaceAssets, false);
|
214
|
-
|
215
236
|
const message = {
|
216
237
|
message: 'Prebid Native',
|
217
238
|
action: 'assetRequest',
|
@@ -219,8 +240,7 @@ export function newNativeAssetManager(win) {
|
|
219
240
|
assets,
|
220
241
|
};
|
221
242
|
|
222
|
-
|
223
|
-
win.parent.postMessage(JSON.stringify(message), '*');
|
243
|
+
return sendMessage(message, replaceAssets);
|
224
244
|
}
|
225
245
|
|
226
246
|
/*
|
@@ -228,29 +248,26 @@ export function newNativeAssetManager(win) {
|
|
228
248
|
* creative template, and setups up a listener for when Prebid responds.
|
229
249
|
*/
|
230
250
|
function requestAllAssets(adId) {
|
231
|
-
win.addEventListener('message', replaceAssets, false);
|
232
|
-
|
233
251
|
const message = {
|
234
252
|
message: 'Prebid Native',
|
235
253
|
action: 'allAssetRequest',
|
236
254
|
adId,
|
237
255
|
};
|
238
|
-
|
239
|
-
win.parent.postMessage(JSON.stringify(message), '*');
|
256
|
+
return sendMessage(message, replaceAssets);
|
240
257
|
}
|
241
258
|
|
242
259
|
/*
|
243
260
|
* Sends postmessage to Prebid for native resize
|
244
261
|
*/
|
245
|
-
function requestHeightResize(adId, height) {
|
262
|
+
function requestHeightResize(adId, height, width) {
|
246
263
|
const message = {
|
247
264
|
message: 'Prebid Native',
|
248
265
|
action: 'resizeNativeHeight',
|
249
266
|
adId,
|
250
267
|
height,
|
268
|
+
width
|
251
269
|
};
|
252
|
-
|
253
|
-
win.parent.postMessage(JSON.stringify(message), '*');
|
270
|
+
sendMessage(message);
|
254
271
|
}
|
255
272
|
|
256
273
|
/*
|
@@ -267,7 +284,7 @@ export function newNativeAssetManager(win) {
|
|
267
284
|
* if for some reason Prebid never responds with the native assets,
|
268
285
|
* get rid of this listener because other messages won't stop coming
|
269
286
|
*/
|
270
|
-
|
287
|
+
stopListening();
|
271
288
|
}
|
272
289
|
return;
|
273
290
|
}
|
@@ -275,69 +292,160 @@ export function newNativeAssetManager(win) {
|
|
275
292
|
if (data.message === 'assetResponse') {
|
276
293
|
const body = win.document.body.innerHTML;
|
277
294
|
const head = win.document.head.innerHTML;
|
278
|
-
const flag = (typeof win.pbNativeData !== 'undefined');
|
279
295
|
|
280
|
-
if (
|
296
|
+
if (hasPbNativeData() && data.adId !== win.pbNativeData.adId) return;
|
281
297
|
|
282
298
|
if (head) win.document.head.innerHTML = replace(head, data);
|
283
299
|
|
284
|
-
|
300
|
+
data.assets = data.assets || [];
|
301
|
+
let renderPayload = data.assets;
|
302
|
+
if (data.ortb) {
|
303
|
+
renderPayload.ortb = data.ortb;
|
304
|
+
callback = () => {
|
305
|
+
fireNativeImpressionTrackers(data.adId, sendMessage);
|
306
|
+
addNativeClickTrackers(data.adId, data.ortb, sendMessage);
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
if ((data.hasOwnProperty('rendererUrl') && data.rendererUrl) || (hasPbNativeData() && win.pbNativeData.hasOwnProperty('rendererUrl'))) {
|
285
311
|
if (win.renderAd) {
|
286
|
-
const newHtml = (win.renderAd && win.renderAd(
|
312
|
+
const newHtml = (win.renderAd && win.renderAd(renderPayload)) || '';
|
287
313
|
|
288
|
-
|
289
|
-
callback && callback();
|
290
|
-
win.removeEventListener('message', replaceAssets);
|
291
|
-
requestHeightResize(data.adId, (document.body.clientHeight || document.body.offsetHeight));
|
314
|
+
renderAd(newHtml, data);
|
292
315
|
} else if (document.getElementById('pb-native-renderer')) {
|
293
316
|
document.getElementById('pb-native-renderer').addEventListener('load', function() {
|
294
|
-
const newHtml = (win.renderAd && win.renderAd(
|
317
|
+
const newHtml = (win.renderAd && win.renderAd(renderPayload)) || '';
|
295
318
|
|
296
|
-
|
297
|
-
callback && callback();
|
298
|
-
win.removeEventListener('message', replaceAssets);
|
299
|
-
requestHeightResize(data.adId, (document.body.clientHeight || document.body.offsetHeight));
|
319
|
+
renderAd(newHtml, data);
|
300
320
|
});
|
301
321
|
} else {
|
302
|
-
loadScript(win, ((
|
303
|
-
const newHtml = (win.renderAd && win.renderAd(
|
322
|
+
loadScript(win, ((hasPbNativeData() && win.pbNativeData.hasOwnProperty('rendererUrl') && win.pbNativeData.rendererUrl) || data.rendererUrl), function() {
|
323
|
+
const newHtml = (win.renderAd && win.renderAd(renderPayload)) || '';
|
304
324
|
|
305
|
-
|
306
|
-
callback && callback();
|
307
|
-
win.removeEventListener('message', replaceAssets);
|
308
|
-
requestHeightResize(data.adId, (document.body.clientHeight || document.body.offsetHeight));
|
325
|
+
renderAd(newHtml, data);
|
309
326
|
})
|
310
327
|
}
|
311
|
-
} else if ((data.hasOwnProperty('adTemplate') && data.adTemplate)||(
|
312
|
-
const template = (
|
328
|
+
} else if ((data.hasOwnProperty('adTemplate') && data.adTemplate)||(hasPbNativeData() && win.pbNativeData.hasOwnProperty('adTemplate'))) {
|
329
|
+
const template = (hasPbNativeData() && win.pbNativeData.hasOwnProperty('adTemplate') && win.pbNativeData.adTemplate) || data.adTemplate;
|
313
330
|
const newHtml = replace(template, data);
|
314
|
-
|
315
|
-
|
316
|
-
win.removeEventListener('message', replaceAssets);
|
317
|
-
requestHeightResize(data.adId, (document.body.clientHeight || document.body.offsetHeight));
|
331
|
+
|
332
|
+
renderAd(newHtml, data);
|
318
333
|
} else {
|
319
334
|
const newHtml = replace(body, data);
|
320
335
|
|
321
336
|
win.document.body.innerHTML = newHtml;
|
322
337
|
callback && callback();
|
323
|
-
|
338
|
+
stopListening();
|
324
339
|
}
|
325
340
|
}
|
326
341
|
}
|
327
342
|
|
343
|
+
/** This function returns the element that contains the current iframe. */
|
344
|
+
function getCurrentFrameContainer(win) {
|
345
|
+
let currentWindow = win;
|
346
|
+
let currentParentWindow;
|
347
|
+
|
348
|
+
while (currentWindow !== win.top) {
|
349
|
+
currentParentWindow = currentWindow.parent;
|
350
|
+
if (!currentParentWindow.frames || !currentParentWindow.frames.length) return null;
|
351
|
+
for (let idx = 0; idx < currentParentWindow.frames.length; idx++)
|
352
|
+
if (currentParentWindow.frames[idx] === currentWindow) {
|
353
|
+
if (!currentParentWindow.document) return null;
|
354
|
+
for (let frameElement of currentParentWindow.document.getElementsByTagName('iframe')) {
|
355
|
+
if (!frameElement.contentWindow) return null;
|
356
|
+
if (frameElement.contentWindow === currentWindow) {
|
357
|
+
return frameElement.parentElement;
|
358
|
+
}
|
359
|
+
}
|
360
|
+
}
|
361
|
+
}
|
362
|
+
}
|
363
|
+
|
364
|
+
function renderAd(html, bid) {
|
365
|
+
// if the current iframe is not a safeframe, try to set the
|
366
|
+
// current iframe width to the width of the container. This
|
367
|
+
// is to handle the case where the native ad is rendered inside
|
368
|
+
// a GAM display ad.
|
369
|
+
if (!envionment.isSafeFrame()) {
|
370
|
+
let iframeContainer = getCurrentFrameContainer(win);
|
371
|
+
if (iframeContainer && iframeContainer.children && iframeContainer.children[0]) {
|
372
|
+
const iframe = iframeContainer.children[0];
|
373
|
+
if (iframe.width === '1' && iframe.height === '1') {
|
374
|
+
let width = iframeContainer.getBoundingClientRect().width;
|
375
|
+
win.document.body.style.width = `${width}px`;
|
376
|
+
}
|
377
|
+
}
|
378
|
+
} else {
|
379
|
+
document.body.style.width = Math.ceil(win.$sf.ext.geom().self.b) + 'px';
|
380
|
+
}
|
381
|
+
win.document.body.innerHTML += html;
|
382
|
+
callback && callback();
|
383
|
+
win.removeEventListener('message', replaceAssets);
|
384
|
+
stopListening();
|
385
|
+
requestHeightResize(bid.adId, (document.body.clientHeight || document.body.offsetHeight), document.body.clientWidth);
|
386
|
+
|
387
|
+
if (typeof window.postRenderAd === 'function') {
|
388
|
+
window.postRenderAd(bid);
|
389
|
+
}
|
390
|
+
}
|
391
|
+
|
392
|
+
function replaceORTBAssetsAndLinks(html, ortb) {
|
393
|
+
|
394
|
+
const getAssetValue = (asset) => {
|
395
|
+
if (asset.img) {
|
396
|
+
return asset.img.url;
|
397
|
+
}
|
398
|
+
if (asset.data) {
|
399
|
+
return asset.data.value;
|
400
|
+
}
|
401
|
+
if (asset.title) {
|
402
|
+
return asset.title.text;
|
403
|
+
}
|
404
|
+
if (asset.video) {
|
405
|
+
return asset.video.vasttag;
|
406
|
+
}
|
407
|
+
return ''
|
408
|
+
}
|
409
|
+
|
410
|
+
ortb.assets.forEach(asset => {
|
411
|
+
html = html.replace(`##hb_native_asset_id_${asset.id}##`, getAssetValue(asset));
|
412
|
+
if (asset.link && asset.link.url) {
|
413
|
+
html = html.replace(`##hb_native_asset_link_id_${asset.id}##`, asset.link.url);
|
414
|
+
}
|
415
|
+
});
|
416
|
+
|
417
|
+
html = html.replaceAll(/##hb_native_asset_id_\d+##/gm, '');
|
418
|
+
|
419
|
+
if (ortb.privacy) {
|
420
|
+
html = html.replace("##hb_native_privacy##", ortb.privacy);
|
421
|
+
}
|
422
|
+
|
423
|
+
if (ortb.link) {
|
424
|
+
html = html.replaceAll("##hb_native_linkurl##", ortb.link.url);
|
425
|
+
}
|
426
|
+
|
427
|
+
return html;
|
428
|
+
}
|
429
|
+
|
328
430
|
/**
|
329
431
|
* Replaces occurrences of native placeholder values with their actual values
|
330
432
|
* in the given document.
|
433
|
+
* If there's no actual value, the placeholder gets replaced by an empty string.
|
331
434
|
*/
|
332
|
-
function replace(
|
333
|
-
|
435
|
+
function replace(html, { assets, ortb, adId }) {
|
436
|
+
if (ortb) {
|
437
|
+
html = replaceORTBAssetsAndLinks(html, ortb);
|
438
|
+
} else if (!Array.isArray(assets)) {
|
439
|
+
return html;
|
440
|
+
}
|
441
|
+
assets = assets || [];
|
334
442
|
|
335
|
-
(
|
336
|
-
const
|
337
|
-
const searchString = (adId && !flag) ? `${NATIVE_KEYS[asset.key]}:${adId}` : ((flag) ? '##'+`${NATIVE_KEYS[asset.key]}`+'##' : `${NATIVE_KEYS[asset.key]}`);
|
443
|
+
scanForPlaceHolders(adId, html).forEach(placeholder => {
|
444
|
+
const searchString = placeholderFor(placeholder, adId);
|
338
445
|
const searchStringRegex = new RegExp(searchString, 'g');
|
339
|
-
|
340
|
-
|
446
|
+
const fittingAsset = assets.find(asset => placeholder === NATIVE_KEYS[asset.key]);
|
447
|
+
html = html.replace(searchStringRegex, fittingAsset ? fittingAsset.value : '');
|
448
|
+
})
|
341
449
|
|
342
450
|
return html;
|
343
451
|
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { loadScript, triggerPixel } from "./utils";
|
2
|
+
|
3
|
+
const AD_ANCHOR_CLASS_NAME = 'pb-click';
|
4
|
+
const ASSET_ID_ELEMENT_ATTRIBUTE = 'hb_native_asset_id';
|
5
|
+
|
6
|
+
export function fireNativeImpressionTrackers(adId, sendMessage) {
|
7
|
+
const message = {
|
8
|
+
message: 'Prebid Native',
|
9
|
+
action: 'fireNativeImpressionTrackers',
|
10
|
+
adId
|
11
|
+
};
|
12
|
+
sendMessage(message);
|
13
|
+
}
|
14
|
+
|
15
|
+
export function addNativeClickTrackers(adId, ortb, sendMessage) {
|
16
|
+
const message = {
|
17
|
+
message: 'Prebid Native',
|
18
|
+
action: 'click',
|
19
|
+
adId
|
20
|
+
};
|
21
|
+
const adElements = document.getElementsByClassName(AD_ANCHOR_CLASS_NAME) || [];
|
22
|
+
// get all assets that have 'link' property, map asset.id -> asset.link
|
23
|
+
for (let i = 0; i < adElements.length; i++) {
|
24
|
+
adElements[i].addEventListener('click', (event) => {
|
25
|
+
let targetElement = event.target;
|
26
|
+
// check if clicked element is associated with any native asset (look for 'hb_native_asset_id' attribute)
|
27
|
+
let assetId = targetElement && targetElement.getAttribute(ASSET_ID_ELEMENT_ATTRIBUTE);
|
28
|
+
message.assetId = assetId;
|
29
|
+
sendMessage(message);
|
30
|
+
}, true);
|
31
|
+
}
|
32
|
+
}
|
@@ -1,14 +1,14 @@
|
|
1
1
|
/*
|
2
2
|
* Script to handle firing impression and click trackers from native teamplates
|
3
3
|
*/
|
4
|
-
import {
|
5
|
-
import {
|
4
|
+
import {newNativeAssetManager} from './nativeAssetManager';
|
5
|
+
import {prebidMessenger} from './messaging.js';
|
6
6
|
|
7
7
|
const AD_ANCHOR_CLASS_NAME = 'pb-click';
|
8
8
|
const AD_DATA_ADID_ATTRIBUTE = 'pbAdId';
|
9
9
|
|
10
10
|
export function newNativeRenderManager(win) {
|
11
|
-
let
|
11
|
+
let sendMessage;
|
12
12
|
|
13
13
|
|
14
14
|
function findAdElements(className) {
|
@@ -30,8 +30,7 @@ export function newNativeRenderManager(win) {
|
|
30
30
|
if (action === 'click') {
|
31
31
|
message.action = 'click';
|
32
32
|
}
|
33
|
-
|
34
|
-
win.parent.postMessage(JSON.stringify(message), publisherDomain);
|
33
|
+
sendMessage(message);
|
35
34
|
}
|
36
35
|
}
|
37
36
|
|
@@ -51,12 +50,10 @@ export function newNativeRenderManager(win) {
|
|
51
50
|
// START OF MAIN CODE
|
52
51
|
let renderNativeAd = function(nativeTag) {
|
53
52
|
window.pbNativeData = nativeTag;
|
54
|
-
|
55
|
-
const nativeAssetManager = newNativeAssetManager(window);
|
53
|
+
sendMessage = prebidMessenger(nativeTag.pubUrl, win);
|
54
|
+
const nativeAssetManager = newNativeAssetManager(window, nativeTag.pubUrl);
|
56
55
|
|
57
56
|
if (nativeTag.hasOwnProperty('adId')) {
|
58
|
-
let parsedUrl = parseUrl(window.pbNativeData.pubUrl);
|
59
|
-
publisherDomain = parsedUrl.protocol + '://' + parsedUrl.host;
|
60
57
|
|
61
58
|
if (nativeTag.hasOwnProperty('rendererUrl') && !nativeTag.rendererUrl.match(/##.*##/i)) {
|
62
59
|
const scr = document.createElement('SCRIPT');
|
@@ -64,9 +61,10 @@ export function newNativeRenderManager(win) {
|
|
64
61
|
scr.id = 'pb-native-renderer';
|
65
62
|
document.body.appendChild(scr);
|
66
63
|
}
|
67
|
-
nativeAssetManager.loadAssets(nativeTag.adId,
|
68
|
-
|
69
|
-
|
64
|
+
nativeAssetManager.loadAssets(nativeTag.adId, () => {
|
65
|
+
fireNativeImpTracker(nativeTag.adId);
|
66
|
+
fireNativeCallback();
|
67
|
+
});
|
70
68
|
} else {
|
71
69
|
console.warn('Prebid Native Tag object was missing \'adId\'.');
|
72
70
|
}
|
@@ -3,12 +3,13 @@
|
|
3
3
|
*/
|
4
4
|
import { parseUrl, triggerPixel, transformAuctionTargetingData } from './utils';
|
5
5
|
import { newNativeAssetManager } from './nativeAssetManager';
|
6
|
+
import {prebidMessenger} from './messaging.js';
|
6
7
|
|
7
8
|
const AD_ANCHOR_CLASS_NAME = 'pb-click';
|
8
9
|
const AD_DATA_ADID_ATTRIBUTE = 'pbAdId';
|
9
10
|
|
10
11
|
export function newNativeTrackerManager(win) {
|
11
|
-
let
|
12
|
+
let sendMessage;
|
12
13
|
|
13
14
|
function findAdElements(className) {
|
14
15
|
let adElements = win.document.getElementsByClassName(className);
|
@@ -63,17 +64,18 @@ export function newNativeTrackerManager(win) {
|
|
63
64
|
message.action = 'click';
|
64
65
|
}
|
65
66
|
|
66
|
-
|
67
|
+
sendMessage(message);
|
67
68
|
}
|
68
69
|
}
|
69
70
|
|
70
71
|
// START OF MAIN CODE
|
71
72
|
let startTrackers = function (dataObject) {
|
72
73
|
const targetingData = transformAuctionTargetingData(dataObject);
|
73
|
-
|
74
|
+
sendMessage = prebidMessenger(targetingData.pubUrl, win);
|
75
|
+
const nativeAssetManager = newNativeAssetManager(window, targetingData.pubUrl);
|
74
76
|
|
75
77
|
if (targetingData && targetingData.env === 'mobile-app') {
|
76
|
-
let cb = function({clickTrackers, impTrackers} = {}) {
|
78
|
+
let cb = function({clickTrackers, impTrackers, eventtrackers} = {}) {
|
77
79
|
function loadMobileClickTrackers(clickTrackers) {
|
78
80
|
(clickTrackers || []).forEach(triggerPixel);
|
79
81
|
}
|
@@ -81,12 +83,21 @@ export function newNativeTrackerManager(win) {
|
|
81
83
|
attachClickListeners(false, boundedLoadMobileClickTrackers);
|
82
84
|
|
83
85
|
(impTrackers || []).forEach(triggerPixel);
|
86
|
+
|
87
|
+
// fire impression IMG trackers
|
88
|
+
eventtrackers
|
89
|
+
.filter(tracker => tracker.event === 1 && tracker.method === 1)
|
90
|
+
.map(tracker => tracker.url)
|
91
|
+
.forEach(triggerPixel);
|
92
|
+
|
93
|
+
// fire impression JS trackers
|
94
|
+
eventtrackers
|
95
|
+
.filter(tracker => tracker.event === 1 && tracker.method === 2)
|
96
|
+
.map(tracker => tracker.url)
|
97
|
+
.forEach(trackerUrl => loadScript(document, trackerUrl));
|
84
98
|
}
|
85
99
|
nativeAssetManager.loadMobileAssets(targetingData, cb);
|
86
100
|
} else {
|
87
|
-
let parsedUrl = parseUrl(targetingData && targetingData.pubUrl);
|
88
|
-
publisherDomain = parsedUrl.protocol + '://' + parsedUrl.host;
|
89
|
-
|
90
101
|
let adElements = findAdElements(AD_ANCHOR_CLASS_NAME);
|
91
102
|
|
92
103
|
nativeAssetManager.loadAssets(
|