prebid.js 6.6.0 → 6.7.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/integrationExamples/gpt/amp/creative.html +11 -33
- package/modules/adbookpspBidAdapter.js +27 -10
- package/modules/adhashBidAdapter.js +3 -3
- package/modules/colossussspBidAdapter.js +12 -8
- package/modules/colossussspBidAdapter.md +15 -1
- package/modules/compassBidAdapter.js +1 -1
- package/modules/consumableBidAdapter.md +1 -1
- package/modules/gnetBidAdapter.js +3 -3
- package/modules/gnetBidAdapter.md +4 -4
- package/modules/gumgumBidAdapter.js +4 -4
- package/modules/jwplayerRtdProvider.js +71 -6
- package/modules/jwplayerRtdProvider.md +27 -11
- package/modules/kargoBidAdapter.js +2 -2
- package/modules/pilotxBidAdapter.js +147 -0
- package/modules/pilotxBidAdapter.md +50 -0
- package/modules/rtdModule/index.js +8 -10
- package/modules/rubiconAnalyticsAdapter.js +3 -2
- package/modules/seedingAllianceBidAdapter.js +3 -3
- package/modules/sharethroughBidAdapter.js +12 -17
- package/modules/synacormediaBidAdapter.js +31 -10
- package/modules/viewability.js +177 -0
- package/modules/viewability.md +87 -0
- package/package.json +1 -1
- package/src/secureCreatives.js +3 -2
- package/test/spec/modules/adbookpspBidAdapter_spec.js +17 -3
- package/test/spec/modules/adhashBidAdapter_spec.js +2 -2
- package/test/spec/modules/colossussspBidAdapter_spec.js +5 -2
- package/test/spec/modules/gnetBidAdapter_spec.js +6 -6
- package/test/spec/modules/jwplayerRtdProvider_spec.js +195 -2
- package/test/spec/modules/kargoBidAdapter_spec.js +1 -1
- package/test/spec/modules/pilotxBidAdapter_spec.js +244 -0
- package/test/spec/modules/realTimeDataModule_spec.js +51 -2
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +30 -0
- package/test/spec/modules/sharethroughBidAdapter_spec.js +91 -6
- package/test/spec/modules/synacormediaBidAdapter_spec.js +70 -0
- package/test/spec/modules/viewability_spec.js +280 -0
|
@@ -1,38 +1,16 @@
|
|
|
1
1
|
<!-- This script tag should be returned by your ad server -->
|
|
2
2
|
|
|
3
|
+
<script src="https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js"></script>
|
|
3
4
|
<script>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
data = JSON.parse(ev[key]);
|
|
10
|
-
} catch (e) {
|
|
11
|
-
// Do nothing. No ad found.
|
|
12
|
-
}
|
|
13
|
-
if (data.ad || data.adUrl) {
|
|
14
|
-
if (data.ad) {
|
|
15
|
-
document.write(data.ad);
|
|
16
|
-
document.close();
|
|
17
|
-
} else if (data.adUrl) {
|
|
18
|
-
document.write('<IFRAME SRC="' + data.adUrl + '" WIDTH="'+ data.width +'" HEIGHT="'+ data.height +'" FRAMEBORDER="0" SCROLLING="no" MARGINHEIGHT="0" MARGINWIDTH="0" TOPMARGIN="0" LEFTMARGIN="0" ALLOWTRANSPARENCY="true"></IFRAME>');
|
|
19
|
-
document.close();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
};
|
|
5
|
+
var ucTagData = {};
|
|
6
|
+
ucTagData.adServerDomain = "";
|
|
7
|
+
ucTagData.pubUrl = "%%PATTERN:url%%";
|
|
8
|
+
ucTagData.targetingMap = "%%PATTERN:TARGETINGMAP%%";
|
|
9
|
+
ucTagData.hbPb = "%%PATTERN:hb_pb%%";
|
|
23
10
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
window.parent.postMessage(message, '*');
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
var listenAdFromPrebid = function () {
|
|
33
|
-
window.addEventListener("message", renderAd, false);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
listenAdFromPrebid();
|
|
37
|
-
requestAdFromPrebid();
|
|
11
|
+
try {
|
|
12
|
+
ucTag.renderAd(document, ucTagData);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.log(e);
|
|
15
|
+
}
|
|
38
16
|
</script>
|
|
@@ -363,7 +363,7 @@ function impBidsToPrebidBids(
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
const impToPrebidBid =
|
|
366
|
-
(bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid) => {
|
|
366
|
+
(bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid, bidIndex) => {
|
|
367
367
|
try {
|
|
368
368
|
const bidRequest = findBidRequest(bidderRequestBody, bid);
|
|
369
369
|
|
|
@@ -377,7 +377,7 @@ const impToPrebidBid =
|
|
|
377
377
|
let prebidBid = {
|
|
378
378
|
ad: bid.adm,
|
|
379
379
|
adId: bid.adid,
|
|
380
|
-
adserverTargeting: targetingMap[
|
|
380
|
+
adserverTargeting: targetingMap[bidIndex],
|
|
381
381
|
adUnitCode: bidRequest.tagid,
|
|
382
382
|
bidderRequestId: bidderRequestBody.id,
|
|
383
383
|
bidId: bid.id,
|
|
@@ -408,6 +408,9 @@ const impToPrebidBid =
|
|
|
408
408
|
};
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
if (deepAccess(bid, 'ext.pa_win') === true) {
|
|
412
|
+
prebidBid.auctionWinner = true;
|
|
413
|
+
}
|
|
411
414
|
return prebidBid;
|
|
412
415
|
} catch (error) {
|
|
413
416
|
logError(`${BIDDER_CODE}: Error while building bid`, error);
|
|
@@ -429,29 +432,43 @@ function buildTargetingMap(bids) {
|
|
|
429
432
|
const values = impIds.reduce((result, id) => {
|
|
430
433
|
result[id] = {
|
|
431
434
|
lineItemIds: [],
|
|
435
|
+
orderIds: [],
|
|
432
436
|
dealIds: [],
|
|
433
437
|
adIds: [],
|
|
438
|
+
adAndOrderIndexes: []
|
|
434
439
|
};
|
|
435
440
|
|
|
436
441
|
return result;
|
|
437
442
|
}, {});
|
|
438
443
|
|
|
439
|
-
bids.forEach((bid) => {
|
|
440
|
-
|
|
441
|
-
values[
|
|
442
|
-
values[
|
|
444
|
+
bids.forEach((bid, bidIndex) => {
|
|
445
|
+
let impId = bid.impid;
|
|
446
|
+
values[impId].lineItemIds.push(bid.ext.liid);
|
|
447
|
+
values[impId].dealIds.push(bid.dealid);
|
|
448
|
+
values[impId].adIds.push(bid.adid);
|
|
449
|
+
|
|
450
|
+
if (deepAccess(bid, 'ext.ordid')) {
|
|
451
|
+
values[impId].orderIds.push(bid.ext.ordid);
|
|
452
|
+
bid.ext.ordid.split(TARGETING_VALUE_SEPARATOR).forEach((ordid, ordIndex) => {
|
|
453
|
+
let adIdIndex = values[impId].adIds.indexOf(bid.adid);
|
|
454
|
+
values[impId].adAndOrderIndexes.push(adIdIndex + '_' + ordIndex)
|
|
455
|
+
})
|
|
456
|
+
}
|
|
443
457
|
});
|
|
444
458
|
|
|
445
459
|
const targetingMap = {};
|
|
446
460
|
|
|
447
|
-
|
|
448
|
-
|
|
461
|
+
bids.forEach((bid, bidIndex) => {
|
|
462
|
+
let id = bid.impid;
|
|
463
|
+
|
|
464
|
+
targetingMap[bidIndex] = {
|
|
449
465
|
hb_liid_adbookpsp: values[id].lineItemIds.join(TARGETING_VALUE_SEPARATOR),
|
|
450
466
|
hb_deal_adbookpsp: values[id].dealIds.join(TARGETING_VALUE_SEPARATOR),
|
|
467
|
+
hb_ad_ord_adbookpsp: values[id].adAndOrderIndexes.join(TARGETING_VALUE_SEPARATOR),
|
|
451
468
|
hb_adid_c_adbookpsp: values[id].adIds.join(TARGETING_VALUE_SEPARATOR),
|
|
469
|
+
hb_ordid_adbookpsp: values[id].orderIds.join(TARGETING_VALUE_SEPARATOR),
|
|
452
470
|
};
|
|
453
|
-
}
|
|
454
|
-
|
|
471
|
+
})
|
|
455
472
|
return targetingMap;
|
|
456
473
|
}
|
|
457
474
|
|
|
@@ -6,7 +6,7 @@ const VERSION = '1.0';
|
|
|
6
6
|
|
|
7
7
|
export const spec = {
|
|
8
8
|
code: 'adhash',
|
|
9
|
-
url: 'https://bidder.adhash.
|
|
9
|
+
url: 'https://bidder.adhash.com/rtb?version=' + VERSION + '&prebid=true',
|
|
10
10
|
supportedMediaTypes: [ BANNER ],
|
|
11
11
|
|
|
12
12
|
isBidRequestValid: (bid) => {
|
|
@@ -37,7 +37,7 @@ export const spec = {
|
|
|
37
37
|
var size = validBidRequests[i].sizes[index].join('x');
|
|
38
38
|
bidRequests.push({
|
|
39
39
|
method: 'POST',
|
|
40
|
-
url: url,
|
|
40
|
+
url: url + '&publisher=' + validBidRequests[i].params.publisherId,
|
|
41
41
|
bidRequest: validBidRequests[i],
|
|
42
42
|
data: {
|
|
43
43
|
timezone: new Date().getTimezoneOffset() / 60,
|
|
@@ -87,7 +87,7 @@ export const spec = {
|
|
|
87
87
|
cpm: responseBody.creatives[0].costEUR,
|
|
88
88
|
ad:
|
|
89
89
|
`<div id="${oneTimeId}"></div>
|
|
90
|
-
<script src="https://bidder.adhash.
|
|
90
|
+
<script src="https://bidder.adhash.com/static/scripts/creative.min.js"></script>
|
|
91
91
|
<script>callAdvertiser(${bidderResponse},['${oneTimeId}'],${requestData},${publisherURL})</script>`,
|
|
92
92
|
width: request.bidRequest.sizes[0][0],
|
|
93
93
|
height: request.bidRequest.sizes[0][1],
|
|
@@ -47,7 +47,10 @@ export const spec = {
|
|
|
47
47
|
* @return boolean True if this is a valid bid, and false otherwise.
|
|
48
48
|
*/
|
|
49
49
|
isBidRequestValid: (bid) => {
|
|
50
|
-
|
|
50
|
+
const validPlacamentId = bid.params && !isNaN(bid.params.placement_id);
|
|
51
|
+
const validGroupId = bid.params && !isNaN(bid.params.group_id);
|
|
52
|
+
|
|
53
|
+
return Boolean(bid.bidId && (validPlacamentId || validGroupId));
|
|
51
54
|
},
|
|
52
55
|
|
|
53
56
|
/**
|
|
@@ -61,13 +64,13 @@ export const spec = {
|
|
|
61
64
|
const location = winTop.location;
|
|
62
65
|
let placements = [];
|
|
63
66
|
let request = {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
deviceWidth: winTop.screen.width,
|
|
68
|
+
deviceHeight: winTop.screen.height,
|
|
69
|
+
language: (navigator && navigator.language) ? navigator.language : '',
|
|
70
|
+
secure: location.protocol === 'https:' ? 1 : 0,
|
|
71
|
+
host: location.host,
|
|
72
|
+
page: location.pathname,
|
|
73
|
+
placements: placements,
|
|
71
74
|
};
|
|
72
75
|
|
|
73
76
|
if (bidderRequest) {
|
|
@@ -85,6 +88,7 @@ export const spec = {
|
|
|
85
88
|
let traff = bid.params.traffic || BANNER
|
|
86
89
|
let placement = {
|
|
87
90
|
placementId: bid.params.placement_id,
|
|
91
|
+
groupId: bid.params.group_id,
|
|
88
92
|
bidId: bid.bidId,
|
|
89
93
|
sizes: bid.mediaTypes[traff].sizes,
|
|
90
94
|
traffic: traff,
|
|
@@ -26,5 +26,19 @@ Module that connects to Colossus SSP demand sources
|
|
|
26
26
|
traffic: 'banner'
|
|
27
27
|
}
|
|
28
28
|
}]
|
|
29
|
-
|
|
29
|
+
}, {
|
|
30
|
+
code: 'placementid_1',
|
|
31
|
+
mediaTypes: {
|
|
32
|
+
banner: {
|
|
33
|
+
sizes: [[300, 250], [300,600]]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
bids: [{
|
|
37
|
+
bidder: 'colossusssp',
|
|
38
|
+
params: {
|
|
39
|
+
group_id: 0,
|
|
40
|
+
traffic: 'banner'
|
|
41
|
+
}
|
|
42
|
+
}]
|
|
43
|
+
}];
|
|
30
44
|
```
|
|
@@ -97,7 +97,7 @@ export const spec = {
|
|
|
97
97
|
|
|
98
98
|
isBidRequestValid: (bid = {}) => {
|
|
99
99
|
const { params, bidId, mediaTypes } = bid;
|
|
100
|
-
let valid = Boolean(bidId && params && params.placementId);
|
|
100
|
+
let valid = Boolean(bidId && params && (params.placementId || params.endpointId));
|
|
101
101
|
|
|
102
102
|
if (mediaTypes && mediaTypes[BANNER]) {
|
|
103
103
|
valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { _each, parseSizesInput, isEmpty } from '../src/utils.js';
|
|
2
1
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
2
|
+
import { _each, isEmpty, parseSizesInput } from '../src/utils.js';
|
|
3
3
|
import { BANNER } from '../src/mediaTypes.js';
|
|
4
4
|
|
|
5
5
|
const BIDDER_CODE = 'gnet';
|
|
6
|
-
const ENDPOINT = 'https://
|
|
6
|
+
const ENDPOINT = 'https://service.gnetrtb.com/api/adrequest';
|
|
7
7
|
|
|
8
8
|
export const spec = {
|
|
9
9
|
code: BIDDER_CODE,
|
|
@@ -16,7 +16,7 @@ export const spec = {
|
|
|
16
16
|
* @return boolean True if this is a valid bid, and false otherwise.
|
|
17
17
|
*/
|
|
18
18
|
isBidRequestValid: function (bid) {
|
|
19
|
-
return !!(bid.params.websiteId);
|
|
19
|
+
return !!(bid.params.websiteId && bid.params.adunitId);
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Overview
|
|
2
2
|
|
|
3
3
|
```
|
|
4
|
-
Module Name: Gnet Bidder Adapter
|
|
4
|
+
Module Name: Gnet RTB Bidder Adapter
|
|
5
5
|
Module Type: Bidder Adapter
|
|
6
|
-
Maintainer:
|
|
6
|
+
Maintainer: bruno.bonanho@grumft.com
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
# Description
|
|
10
10
|
|
|
11
|
-
Connect to Gnet
|
|
11
|
+
Connect to Gnet RTB exchange for bids.
|
|
12
12
|
|
|
13
13
|
# Test Parameters
|
|
14
14
|
```
|
|
@@ -24,7 +24,7 @@ Connect to Gnet Project exchange for bids.
|
|
|
24
24
|
{
|
|
25
25
|
bidder: 'gnet',
|
|
26
26
|
params: {
|
|
27
|
-
websiteId: '
|
|
27
|
+
websiteId: '1', adunitId: '1'
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
]
|
|
@@ -298,10 +298,10 @@ function buildRequests(validBidRequests, bidderRequest) {
|
|
|
298
298
|
const date = new Date();
|
|
299
299
|
const lt = date.getTime();
|
|
300
300
|
const to = date.getTimezoneOffset();
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
301
|
+
|
|
302
|
+
// ADTS-174 Removed unnecessary checks to fix failing test
|
|
303
|
+
data.lt = lt;
|
|
304
|
+
data.to = to;
|
|
305
305
|
|
|
306
306
|
// ADTS-169 add adUnitCode to requests
|
|
307
307
|
if (adUnitCode) data.aun = adUnitCode
|
|
@@ -155,8 +155,10 @@ export function enrichAdUnits(adUnits) {
|
|
|
155
155
|
if (!vat) {
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
|
+
const contentId = getContentId(vat.mediaID);
|
|
159
|
+
const contentData = getContentData(vat.segments);
|
|
158
160
|
const targeting = formatTargetingResponse(vat);
|
|
159
|
-
|
|
161
|
+
enrichBids(adUnit.bids, targeting, contentId, contentData);
|
|
160
162
|
};
|
|
161
163
|
loadVat(jwTargeting, onVatResponse);
|
|
162
164
|
});
|
|
@@ -235,6 +237,9 @@ export function getVatFromPlayer(playerID, mediaID) {
|
|
|
235
237
|
};
|
|
236
238
|
}
|
|
237
239
|
|
|
240
|
+
/*
|
|
241
|
+
deprecated
|
|
242
|
+
*/
|
|
238
243
|
export function formatTargetingResponse(vat) {
|
|
239
244
|
const { segments, mediaID } = vat;
|
|
240
245
|
const targeting = {};
|
|
@@ -243,23 +248,83 @@ export function formatTargetingResponse(vat) {
|
|
|
243
248
|
}
|
|
244
249
|
|
|
245
250
|
if (mediaID) {
|
|
246
|
-
const id = 'jw_' + mediaID;
|
|
247
251
|
targeting.content = {
|
|
248
|
-
id
|
|
252
|
+
id: getContentId(mediaID)
|
|
249
253
|
}
|
|
250
254
|
}
|
|
251
255
|
return targeting;
|
|
252
256
|
}
|
|
253
257
|
|
|
254
|
-
function
|
|
255
|
-
if (!
|
|
258
|
+
export function getContentId(mediaID) {
|
|
259
|
+
if (!mediaID) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return 'jw_' + mediaID;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function getContentData(segments) {
|
|
267
|
+
if (!segments || !segments.length) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const formattedSegments = segments.reduce((convertedSegments, rawSegment) => {
|
|
272
|
+
convertedSegments.push({
|
|
273
|
+
id: rawSegment,
|
|
274
|
+
value: rawSegment
|
|
275
|
+
});
|
|
276
|
+
return convertedSegments;
|
|
277
|
+
}, []);
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
name: 'jwplayer',
|
|
281
|
+
ext: {
|
|
282
|
+
segtax: 502
|
|
283
|
+
},
|
|
284
|
+
segment: formattedSegments
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function addOrtbSiteContent(bid, contentId, contentData) {
|
|
289
|
+
if (!contentId && !contentData) {
|
|
256
290
|
return;
|
|
257
291
|
}
|
|
258
292
|
|
|
259
|
-
|
|
293
|
+
let ortb2 = bid.ortb2 || {};
|
|
294
|
+
let site = ortb2.site = ortb2.site || {};
|
|
295
|
+
let content = site.content = site.content || {};
|
|
296
|
+
|
|
297
|
+
if (contentId) {
|
|
298
|
+
content.id = contentId;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (contentData) {
|
|
302
|
+
const data = content.data = content.data || [];
|
|
303
|
+
data.push(contentData);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
bid.ortb2 = ortb2;
|
|
260
307
|
}
|
|
261
308
|
|
|
309
|
+
function enrichBids(bids, targeting, contentId, contentData) {
|
|
310
|
+
if (!bids) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
bids.forEach(bid => {
|
|
315
|
+
addTargetingToBid(bid, targeting);
|
|
316
|
+
addOrtbSiteContent(bid, contentId, contentData);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/*
|
|
321
|
+
deprecated
|
|
322
|
+
*/
|
|
262
323
|
export function addTargetingToBid(bid, targeting) {
|
|
324
|
+
if (!targeting) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
263
328
|
const rtd = bid.rtd || {};
|
|
264
329
|
const jwRtd = {};
|
|
265
330
|
jwRtd[SUBMODULE_NAME] = Object.assign({}, rtd[SUBMODULE_NAME], { targeting });
|
|
@@ -81,20 +81,30 @@ realTimeData = {
|
|
|
81
81
|
# Usage for Bid Adapters:
|
|
82
82
|
|
|
83
83
|
Implement the `buildRequests` function. When it is called, the `bidRequests` param will be an array of bids.
|
|
84
|
-
Each bid for which targeting information was found will
|
|
84
|
+
Each bid for which targeting information was found will have a ortb2 param conforming to the [oRTB v2 object structure](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). The `ortb2` object will contain our proprietaty targeting segments in a format compliant with the [IAB's segment taxonomy structure](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/segtax.md).
|
|
85
|
+
|
|
86
|
+
Example:
|
|
85
87
|
|
|
86
88
|
```javascript
|
|
87
89
|
{
|
|
88
90
|
adUnitCode: 'xyz',
|
|
89
91
|
bidId: 'abc',
|
|
90
92
|
...,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
ortb2: {
|
|
94
|
+
site: {
|
|
95
|
+
content: {
|
|
96
|
+
id: 'jw_abc123',
|
|
97
|
+
data: [{
|
|
98
|
+
name: 'jwplayer',
|
|
99
|
+
ext: {
|
|
100
|
+
segtax: 502
|
|
101
|
+
},
|
|
102
|
+
segment: [{
|
|
103
|
+
id: '123'
|
|
104
|
+
}, {
|
|
105
|
+
id: '456'
|
|
106
|
+
}]
|
|
107
|
+
}]
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
}
|
|
@@ -102,9 +112,15 @@ Each bid for which targeting information was found will conform to the following
|
|
|
102
112
|
```
|
|
103
113
|
|
|
104
114
|
where:
|
|
105
|
-
- `
|
|
106
|
-
- `
|
|
107
|
-
|
|
115
|
+
- `ortb2` is an object containing first party data
|
|
116
|
+
- `site` is an object containing page specific information
|
|
117
|
+
- `content` is an object containing metadata for the media. It may contain the following information:
|
|
118
|
+
- `id` is a unique identifier for the specific media asset
|
|
119
|
+
- `data` is an array containing segment taxonomy objects that have the following parameters:
|
|
120
|
+
- `name` is the `jwplayer` string indicating the provider name
|
|
121
|
+
- `ext.segtax` whose `502` value is the unique identifier for JW Player's proprietary taxonomy
|
|
122
|
+
- `segment` is an array containing the segment taxonomy values as an object where:
|
|
123
|
+
- `id` is the string representation of the data segment value.
|
|
108
124
|
|
|
109
125
|
**Example:**
|
|
110
126
|
|
|
@@ -73,8 +73,8 @@ export const spec = {
|
|
|
73
73
|
let meta;
|
|
74
74
|
if (adUnit.metadata && adUnit.metadata.landingPageDomain) {
|
|
75
75
|
meta = {
|
|
76
|
-
clickUrl: adUnit.metadata.landingPageDomain,
|
|
77
|
-
advertiserDomains:
|
|
76
|
+
clickUrl: adUnit.metadata.landingPageDomain[0],
|
|
77
|
+
advertiserDomains: adUnit.metadata.landingPageDomain
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
bidResponses.push({
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
2
|
+
const BIDDER_CODE = 'pilotx';
|
|
3
|
+
const ENDPOINT_URL = '//adn.pilotx.tv/hb'
|
|
4
|
+
export const spec = {
|
|
5
|
+
code: BIDDER_CODE,
|
|
6
|
+
supportedMediaTypes: ['banner', 'video'],
|
|
7
|
+
aliases: ['pilotx'], // short code
|
|
8
|
+
/**
|
|
9
|
+
* Determines whether or not the given bid request is valid.
|
|
10
|
+
*
|
|
11
|
+
* @param {BidRequest} bid The bid params to validate.
|
|
12
|
+
* @return boolean True if this is a valid bid, and false otherwise.
|
|
13
|
+
*/
|
|
14
|
+
isBidRequestValid: function (bid) {
|
|
15
|
+
let sizesCheck = !!bid.sizes
|
|
16
|
+
let paramSizesCheck = !!bid.params.sizes
|
|
17
|
+
var sizeConfirmed = false
|
|
18
|
+
if (sizesCheck) {
|
|
19
|
+
if (bid.sizes.length < 1) {
|
|
20
|
+
return false
|
|
21
|
+
} else {
|
|
22
|
+
sizeConfirmed = true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (paramSizesCheck) {
|
|
26
|
+
if (bid.params.sizes.length < 1 && !sizeConfirmed) {
|
|
27
|
+
return false
|
|
28
|
+
} else {
|
|
29
|
+
sizeConfirmed = true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!sizeConfirmed) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
return !!(bid.params.placementId);
|
|
36
|
+
},
|
|
37
|
+
/**
|
|
38
|
+
* Make a server request from the list of BidRequests.
|
|
39
|
+
*
|
|
40
|
+
* @param {validBidRequests[]} - an array of bids
|
|
41
|
+
* @return ServerRequest Info describing the request to the server.
|
|
42
|
+
*/
|
|
43
|
+
buildRequests: function (validBidRequests, bidderRequest) {
|
|
44
|
+
let payloadItems = {};
|
|
45
|
+
validBidRequests.forEach(bidRequest => {
|
|
46
|
+
let sizes = [];
|
|
47
|
+
let placementId = this.setPlacementID(bidRequest.params.placementId)
|
|
48
|
+
payloadItems[placementId] = {}
|
|
49
|
+
if (bidRequest.sizes.length > 0) {
|
|
50
|
+
if (Array.isArray(bidRequest.sizes[0])) {
|
|
51
|
+
for (let i = 0; i < bidRequest.sizes.length; i++) {
|
|
52
|
+
sizes[i] = [(bidRequest.sizes[i])[0], (bidRequest.sizes[i])[1]]
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
sizes[0] = [bidRequest.sizes[0], bidRequest.sizes[1]]
|
|
56
|
+
}
|
|
57
|
+
payloadItems[placementId]['sizes'] = sizes
|
|
58
|
+
}
|
|
59
|
+
if (bidRequest.mediaTypes != null) {
|
|
60
|
+
for (let i in bidRequest.mediaTypes) {
|
|
61
|
+
payloadItems[placementId][i] = {
|
|
62
|
+
...bidRequest.mediaTypes[i]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
let consentTemp = ''
|
|
67
|
+
let consentRequiredTemp = false
|
|
68
|
+
if (bidderRequest && bidderRequest.gdprConsent) {
|
|
69
|
+
consentTemp = bidderRequest.gdprConsent.consentString
|
|
70
|
+
// will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true
|
|
71
|
+
consentRequiredTemp = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
payloadItems[placementId]['gdprConsentString'] = consentTemp
|
|
75
|
+
payloadItems[placementId]['gdprConsentRequired'] = consentRequiredTemp
|
|
76
|
+
payloadItems[placementId]['bidId'] = bidRequest.bidId
|
|
77
|
+
});
|
|
78
|
+
const payload = payloadItems;
|
|
79
|
+
const payloadString = JSON.stringify(payload);
|
|
80
|
+
return {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
url: ENDPOINT_URL,
|
|
83
|
+
data: payloadString,
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Unpack the response from the server into a list of bids.
|
|
88
|
+
*
|
|
89
|
+
* @param {ServerResponse} serverResponse A successful response from the server.
|
|
90
|
+
* @return {Bid[]} An array of bids which were nested inside the server.
|
|
91
|
+
*/
|
|
92
|
+
interpretResponse: function (serverResponse, bidRequest) {
|
|
93
|
+
const serverBody = serverResponse.body;
|
|
94
|
+
const bidResponses = [];
|
|
95
|
+
if (serverBody.mediaType == 'banner') {
|
|
96
|
+
const bidResponse = {
|
|
97
|
+
requestId: serverBody.requestId,
|
|
98
|
+
cpm: serverBody.cpm,
|
|
99
|
+
width: serverBody.width,
|
|
100
|
+
height: serverBody.height,
|
|
101
|
+
creativeId: serverBody.creativeId,
|
|
102
|
+
currency: serverBody.currency,
|
|
103
|
+
netRevenue: false,
|
|
104
|
+
ttl: serverBody.ttl,
|
|
105
|
+
ad: serverBody.ad,
|
|
106
|
+
mediaType: 'banner',
|
|
107
|
+
meta: {
|
|
108
|
+
mediaType: 'banner',
|
|
109
|
+
advertiserDomains: serverBody.advertiserDomains
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
bidResponses.push(bidResponse)
|
|
113
|
+
} else if (serverBody.mediaType == 'video') {
|
|
114
|
+
const bidResponse = {
|
|
115
|
+
requestId: serverBody.requestId,
|
|
116
|
+
cpm: serverBody.cpm,
|
|
117
|
+
width: serverBody.width,
|
|
118
|
+
height: serverBody.height,
|
|
119
|
+
creativeId: serverBody.creativeId,
|
|
120
|
+
currency: serverBody.currency,
|
|
121
|
+
netRevenue: false,
|
|
122
|
+
ttl: serverBody.ttl,
|
|
123
|
+
vastUrl: serverBody.vastUrl,
|
|
124
|
+
mediaType: 'video',
|
|
125
|
+
meta: {
|
|
126
|
+
mediaType: 'video',
|
|
127
|
+
advertiserDomains: serverBody.advertiserDomains
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
bidResponses.push(bidResponse)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return bidResponses;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Formats placement ids for adserver ingestion purposes
|
|
138
|
+
* @param {string[]} The placement ID/s in an array
|
|
139
|
+
*/
|
|
140
|
+
setPlacementID: function (placementId) {
|
|
141
|
+
if (Array.isArray(placementId)) {
|
|
142
|
+
return placementId.join('#')
|
|
143
|
+
}
|
|
144
|
+
return placementId
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
registerBidder(spec);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
Module Name: Pilotx Prebid Adapter
|
|
5
|
+
Module Type: Bidder Adapter
|
|
6
|
+
Maintainer: tony@pilotx.tv
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
# Description
|
|
10
|
+
|
|
11
|
+
Connects to Pilotx
|
|
12
|
+
|
|
13
|
+
Pilotx's bid adapter supports banner and video.
|
|
14
|
+
|
|
15
|
+
# Test Parameters
|
|
16
|
+
```
|
|
17
|
+
// Banner adUnit
|
|
18
|
+
var adUnits = [{
|
|
19
|
+
code: 'div-gpt-ad-1460505748561-0',
|
|
20
|
+
mediaTypes: {
|
|
21
|
+
banner: {
|
|
22
|
+
sizes: [[300, 250], [300,600]],
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
bids: [{
|
|
26
|
+
bidder: 'pilotx',
|
|
27
|
+
params: {
|
|
28
|
+
placementId: ["1423"]
|
|
29
|
+
}
|
|
30
|
+
}]
|
|
31
|
+
|
|
32
|
+
}];
|
|
33
|
+
|
|
34
|
+
// Video adUnit
|
|
35
|
+
var videoAdUnit = {
|
|
36
|
+
code: 'video1',
|
|
37
|
+
mediaTypes: {
|
|
38
|
+
video: {
|
|
39
|
+
context: 'instream',
|
|
40
|
+
playerSize: [640, 480],
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
bids: [{
|
|
44
|
+
bidder: 'pilotx',
|
|
45
|
+
params: {
|
|
46
|
+
placementId: '1422',
|
|
47
|
+
}
|
|
48
|
+
}]
|
|
49
|
+
};
|
|
50
|
+
```
|