prebid.js 5.18.0 → 6.1.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/.babelrc.js +1 -10
- package/README.md +3 -1
- package/browsers.json +1 -8
- package/gulpfile.js +1 -0
- package/integrationExamples/gpt/akamaidap_segments_example.html +132 -0
- package/modules/.submodules.json +1 -0
- package/modules/adfBidAdapter.js +21 -16
- package/modules/adheseBidAdapter.js +7 -2
- package/modules/adkernelBidAdapter.js +1 -0
- package/modules/adlivetechBidAdapter.md +61 -0
- package/modules/adomikAnalyticsAdapter.js +10 -4
- package/modules/adtelligentBidAdapter.js +2 -1
- package/modules/airgridRtdProvider.js +1 -1
- package/modules/akamaiDapRtdProvider.js +474 -0
- package/modules/akamaiDapRtdProvider.md +47 -0
- package/modules/appnexusBidAdapter.js +9 -3
- package/modules/atsAnalyticsAdapter.js +67 -46
- package/modules/atsAnalyticsAdapter.md +1 -0
- package/modules/betweenBidAdapter.js +20 -3
- package/modules/browsiRtdProvider.js +106 -18
- package/modules/cleanioRtdProvider.js +192 -0
- package/modules/cleanioRtdProvider.md +59 -0
- package/modules/codefuelBidAdapter.js +181 -0
- package/modules/codefuelBidAdapter.md +111 -0
- package/modules/connectIdSystem.js +104 -0
- package/modules/connectIdSystem.md +33 -0
- package/modules/datablocksBidAdapter.js +3 -3
- package/modules/deepintentBidAdapter.js +107 -10
- package/modules/deepintentBidAdapter.md +36 -1
- package/modules/deltaprojectsBidAdapter.js +252 -0
- package/modules/deltaprojectsBidAdapter.md +32 -0
- package/modules/engageyaBidAdapter.js +171 -0
- package/modules/glimpseBidAdapter.js +31 -16
- package/modules/gptPreAuction.js +11 -5
- package/modules/gridBidAdapter.js +1 -0
- package/modules/gumgumBidAdapter.js +8 -0
- package/modules/id5IdSystem.md +6 -6
- package/modules/imRtdProvider.js +31 -0
- package/modules/inskinBidAdapter.js +7 -3
- package/modules/ixBidAdapter.js +174 -22
- package/modules/jixieBidAdapter.js +8 -2
- package/modules/justpremiumBidAdapter.js +6 -1
- package/modules/limelightDigitalBidAdapter.js +22 -2
- package/modules/livewrappedAnalyticsAdapter.js +49 -1
- package/modules/merkleIdSystem.js +5 -0
- package/modules/multibid/index.js +3 -3
- package/modules/nativoBidAdapter.js +32 -2
- package/modules/nextMillenniumBidAdapter.js +12 -3
- package/modules/oguryBidAdapter.js +16 -2
- package/modules/openxBidAdapter.js +40 -23
- package/modules/operaadsBidAdapter.js +21 -1
- package/modules/otmBidAdapter.js +146 -0
- package/modules/otmBidAdapter.md +27 -26
- package/modules/outbrainBidAdapter.js +5 -0
- package/modules/playwireBidAdapter.md +61 -0
- package/modules/prebidServerBidAdapter/index.js +3 -3
- package/modules/publinkIdSystem.js +11 -6
- package/modules/pubmaticBidAdapter.js +2 -0
- package/modules/rtdModule/index.js +2 -2
- package/modules/saambaaBidAdapter.js +420 -0
- package/modules/saambaaBidAdapter.md +65 -68
- package/modules/seedtagBidAdapter.js +6 -0
- package/modules/smaatoBidAdapter.js +6 -1
- package/modules/sonobiBidAdapter.js +7 -0
- package/modules/sortableBidAdapter.js +1 -0
- package/modules/sspBCBidAdapter.js +34 -3
- package/modules/teadsBidAdapter.js +3 -0
- package/modules/tripleliftBidAdapter.js +22 -5
- package/modules/trustxBidAdapter.js +18 -7
- package/modules/undertoneBidAdapter.js +9 -5
- package/modules/undertoneBidAdapter.md +5 -1
- package/modules/userId/eids.js +18 -0
- package/modules/userId/eids.md +7 -0
- package/modules/userId/userId.md +12 -0
- package/modules/ventesBidAdapter.js +370 -0
- package/modules/ventesBidAdapter.md +94 -0
- package/modules/videobyteBidAdapter.js +13 -6
- package/modules/videobyteBidAdapter.md +49 -0
- package/modules/vidoomyBidAdapter.js +51 -100
- package/modules/visxBidAdapter.js +1 -1
- package/modules/yahoosspBidAdapter.js +6 -6
- package/modules/yieldlabBidAdapter.js +41 -10
- package/modules/yieldlabBidAdapter.md +91 -48
- package/modules/yieldmoSyntheticInventoryModule.js +46 -0
- package/modules/yieldmoSyntheticInventoryModule.md +68 -0
- package/package.json +6 -1
- package/src/adapterManager.js +19 -8
- package/src/adapters/bidderFactory.js +4 -3
- package/src/auction.js +11 -11
- package/src/constants.json +1 -0
- package/src/secureCreatives.js +6 -7
- package/src/targeting.js +11 -9
- package/test/spec/modules/adfBidAdapter_spec.js +83 -29
- package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
- package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
- package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
- package/test/spec/modules/akamaiDapRtdProvider_spec.js +246 -0
- package/test/spec/modules/appnexusBidAdapter_spec.js +16 -1
- package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
- package/test/spec/modules/betweenBidAdapter_spec.js +41 -0
- package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
- package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
- package/test/spec/modules/codefuelBidAdapter_spec.js +316 -0
- package/test/spec/modules/connectIdSystem_spec.js +189 -0
- package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
- package/test/spec/modules/deepintentBidAdapter_spec.js +153 -3
- package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
- package/test/spec/modules/engageyaBidAdapter_spec.js +422 -0
- package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
- package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
- package/test/spec/modules/gptPreAuction_spec.js +58 -4
- package/test/spec/modules/gumgumBidAdapter_spec.js +5 -1
- package/test/spec/modules/imRtdProvider_spec.js +25 -0
- package/test/spec/modules/ixBidAdapter_spec.js +298 -5
- package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
- package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
- package/test/spec/modules/konduitWrapper_spec.js +0 -1
- package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
- package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +52 -7
- package/test/spec/modules/merkleIdSystem_spec.js +18 -0
- package/test/spec/modules/multibid_spec.js +31 -31
- package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +66 -23
- package/test/spec/modules/openxBidAdapter_spec.js +90 -13
- package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
- package/test/spec/modules/otmBidAdapter_spec.js +67 -0
- package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
- package/test/spec/modules/prebidServerBidAdapter_spec.js +19 -2
- package/test/spec/modules/publinkIdSystem_spec.js +6 -6
- package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
- package/test/spec/modules/smaatoBidAdapter_spec.js +30 -0
- package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
- package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
- package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
- package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
- package/test/spec/modules/tripleliftBidAdapter_spec.js +128 -0
- package/test/spec/modules/trustxBidAdapter_spec.js +45 -3
- package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
- package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
- package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
- package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
- package/test/spec/modules/visxBidAdapter_spec.js +1 -1
- package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
- package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
- package/test/spec/unit/core/adapterManager_spec.js +56 -6
- package/test/spec/unit/core/bidderFactory_spec.js +61 -1
- package/test/spec/unit/pbjs_api_spec.js +37 -2
- package/test/spec/unit/secureCreatives_spec.js +54 -25
- package/wdio.conf.js +1 -1
|
@@ -3,6 +3,7 @@ import {ajax} from '../src/ajax.js';
|
|
|
3
3
|
import adapter from '../src/AnalyticsAdapter.js';
|
|
4
4
|
import CONSTANTS from '../src/constants.json';
|
|
5
5
|
import adapterManager from '../src/adapterManager.js';
|
|
6
|
+
import { getGlobal } from '../src/prebidGlobal.js';
|
|
6
7
|
|
|
7
8
|
const ANALYTICSTYPE = 'endpoint';
|
|
8
9
|
const URL = 'https://lwadm.com/analytics/10';
|
|
@@ -11,8 +12,10 @@ const REQUESTSENT = 1;
|
|
|
11
12
|
const RESPONSESENT = 2;
|
|
12
13
|
const WINSENT = 4;
|
|
13
14
|
const TIMEOUTSENT = 8;
|
|
15
|
+
const ADRENDERFAILEDSENT = 16;
|
|
14
16
|
|
|
15
17
|
let initOptions;
|
|
18
|
+
let prebidGlobal = getGlobal();
|
|
16
19
|
export const BID_WON_TIMEOUT = 500;
|
|
17
20
|
|
|
18
21
|
const cache = {
|
|
@@ -78,6 +81,7 @@ let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE
|
|
|
78
81
|
bidResponse.width = args.width;
|
|
79
82
|
bidResponse.height = args.height;
|
|
80
83
|
bidResponse.cpm = args.cpm;
|
|
84
|
+
bidResponse.originalCpm = prebidGlobal.convertCurrency(args.originalCpm, args.originalCurrency, args.currency);
|
|
81
85
|
bidResponse.ttr = args.timeToRespond;
|
|
82
86
|
bidResponse.readyToSend = 1;
|
|
83
87
|
bidResponse.mediaType = args.mediaType == 'native' ? 2 : (args.mediaType == 'video' ? 4 : 1);
|
|
@@ -114,6 +118,16 @@ let livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTYPE
|
|
|
114
118
|
livewrappedAnalyticsAdapter.sendEvents();
|
|
115
119
|
}
|
|
116
120
|
break;
|
|
121
|
+
case CONSTANTS.EVENTS.AD_RENDER_FAILED:
|
|
122
|
+
logInfo('LIVEWRAPPED_AD_RENDER_FAILED:', args);
|
|
123
|
+
let adRenderFailedBid = cache.auctions[args.bid.auctionId].bids[args.bid.requestId];
|
|
124
|
+
adRenderFailedBid.adRenderFailed = true;
|
|
125
|
+
adRenderFailedBid.reason = args.reason;
|
|
126
|
+
adRenderFailedBid.message = args.message;
|
|
127
|
+
if (adRenderFailedBid.sendStatus != 0) {
|
|
128
|
+
livewrappedAnalyticsAdapter.sendEvents();
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
117
131
|
case CONSTANTS.EVENTS.BID_TIMEOUT:
|
|
118
132
|
logInfo('LIVEWRAPPED_BID_TIMEOUT:', args);
|
|
119
133
|
args.forEach(timeout => {
|
|
@@ -151,13 +165,15 @@ livewrappedAnalyticsAdapter.sendEvents = function() {
|
|
|
151
165
|
wins: getWins(sentRequests.gdpr, sentRequests.auctionIds),
|
|
152
166
|
timeouts: getTimeouts(sentRequests.auctionIds),
|
|
153
167
|
bidAdUnits: getbidAdUnits(),
|
|
168
|
+
rf: getAdRenderFailed(sentRequests.auctionIds),
|
|
154
169
|
rcv: getAdblockerRecovered()
|
|
155
170
|
};
|
|
156
171
|
|
|
157
172
|
if (events.requests.length == 0 &&
|
|
158
173
|
events.responses.length == 0 &&
|
|
159
174
|
events.wins.length == 0 &&
|
|
160
|
-
events.timeouts.length == 0
|
|
175
|
+
events.timeouts.length == 0 &&
|
|
176
|
+
events.rf.length == 0) {
|
|
161
177
|
return;
|
|
162
178
|
}
|
|
163
179
|
|
|
@@ -224,6 +240,7 @@ function getResponses(gdpr, auctionIds) {
|
|
|
224
240
|
width: bid.width,
|
|
225
241
|
height: bid.height,
|
|
226
242
|
cpm: bid.cpm,
|
|
243
|
+
orgCpm: bid.originalCpm,
|
|
227
244
|
ttr: bid.ttr,
|
|
228
245
|
IsBid: bid.isBid,
|
|
229
246
|
mediaType: bid.mediaType,
|
|
@@ -263,6 +280,7 @@ function getWins(gdpr, auctionIds) {
|
|
|
263
280
|
width: bid.width,
|
|
264
281
|
height: bid.height,
|
|
265
282
|
cpm: bid.cpm,
|
|
283
|
+
orgCpm: bid.originalCpm,
|
|
266
284
|
mediaType: bid.mediaType,
|
|
267
285
|
gdpr: gdprPos,
|
|
268
286
|
floor: bid.lwFloor ? bid.lwFloor : (bid.floorData ? bid.floorData.floorValue : undefined),
|
|
@@ -338,6 +356,36 @@ function getTimeouts(auctionIds) {
|
|
|
338
356
|
return timeouts;
|
|
339
357
|
}
|
|
340
358
|
|
|
359
|
+
function getAdRenderFailed(auctionIds) {
|
|
360
|
+
var adRenderFails = [];
|
|
361
|
+
|
|
362
|
+
Object.keys(cache.auctions).forEach(auctionId => {
|
|
363
|
+
let auctionIdPos = getAuctionIdPos(auctionIds, auctionId);
|
|
364
|
+
Object.keys(cache.auctions[auctionId].bids).forEach(bidId => {
|
|
365
|
+
let auction = cache.auctions[auctionId];
|
|
366
|
+
let bid = auction.bids[bidId];
|
|
367
|
+
if (!(bid.sendStatus & ADRENDERFAILEDSENT) && bid.adRenderFailed) {
|
|
368
|
+
bid.sendStatus |= ADRENDERFAILEDSENT;
|
|
369
|
+
|
|
370
|
+
adRenderFails.push({
|
|
371
|
+
bidder: bid.bidder,
|
|
372
|
+
adUnit: bid.adUnit,
|
|
373
|
+
adUnitId: bid.adUnitId,
|
|
374
|
+
timeStamp: auction.timeStamp,
|
|
375
|
+
auctionId: auctionIdPos,
|
|
376
|
+
auc: bid.auc,
|
|
377
|
+
buc: bid.buc,
|
|
378
|
+
lw: bid.lw,
|
|
379
|
+
rsn: bid.reason,
|
|
380
|
+
msg: bid.message
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
return adRenderFails;
|
|
387
|
+
}
|
|
388
|
+
|
|
341
389
|
function getbidAdUnits() {
|
|
342
390
|
var bidAdUnits = [];
|
|
343
391
|
|
|
@@ -149,6 +149,11 @@ export const merkleIdSubmodule = {
|
|
|
149
149
|
logInfo('User ID - merkleId stored id ' + storedId);
|
|
150
150
|
const configParams = (config && config.params) || {};
|
|
151
151
|
|
|
152
|
+
if (typeof configParams.endpoint !== 'string') {
|
|
153
|
+
logWarn('User ID - merkleId submodule endpoint string is not defined');
|
|
154
|
+
configParams.endpoint = ID_URL
|
|
155
|
+
}
|
|
156
|
+
|
|
152
157
|
if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) {
|
|
153
158
|
logError('User ID - merkleId submodule does not currently handle consent strings');
|
|
154
159
|
return;
|
|
@@ -112,7 +112,7 @@ export function addBidResponseHook(fn, adUnitCode, bid) {
|
|
|
112
112
|
if (multiConfig[bid.bidderCode].prefix) bid.multibidPrefix = multiConfig[bid.bidderCode].prefix;
|
|
113
113
|
bid.originalBidder = bid.bidderCode;
|
|
114
114
|
// Check if stored bids for auction include adUnitCode.bidder and max limit not reach for ad unit
|
|
115
|
-
if (deepAccess(multibidUnits,
|
|
115
|
+
if (deepAccess(multibidUnits, [adUnitCode, bid.bidderCode])) {
|
|
116
116
|
// Store request id under new property originalRequestId, create new unique bidId,
|
|
117
117
|
// and push bid into multibid stored bids for auction if max not reached and bid cpm above floor
|
|
118
118
|
if (!multibidUnits[adUnitCode][bid.bidderCode].maxReached && (!floor || floor <= bid.cpm)) {
|
|
@@ -131,9 +131,9 @@ export function addBidResponseHook(fn, adUnitCode, bid) {
|
|
|
131
131
|
logWarn(`Filtering multibid received from bidder ${bid.bidderCode}: ` + ((multibidUnits[adUnitCode][bid.bidderCode].maxReached) ? `Maximum bid limit reached for ad unit code ${adUnitCode}` : 'Bid cpm under floors value.'));
|
|
132
132
|
}
|
|
133
133
|
} else {
|
|
134
|
-
if (deepAccess(bid, 'floorData.floorValue')) deepSetValue(multibidUnits,
|
|
134
|
+
if (deepAccess(bid, 'floorData.floorValue')) deepSetValue(multibidUnits, [adUnitCode, bid.bidderCode], {floor: deepAccess(bid, 'floorData.floorValue')});
|
|
135
135
|
|
|
136
|
-
deepSetValue(multibidUnits,
|
|
136
|
+
deepSetValue(multibidUnits, [adUnitCode, bid.bidderCode], {ads: [bid]});
|
|
137
137
|
if (multibidUnits[adUnitCode][bid.bidderCode].ads.length === multiConfig[bid.bidderCode].maxbids) multibidUnits[adUnitCode][bid.bidderCode].maxReached = true;
|
|
138
138
|
|
|
139
139
|
fn.call(this, adUnitCode, bid);
|
|
@@ -17,6 +17,16 @@ const adUnitsRequested = {}
|
|
|
17
17
|
|
|
18
18
|
// Prebid adapter referrence doc: https://docs.prebid.org/dev-docs/bidder-adaptor.html
|
|
19
19
|
|
|
20
|
+
// Validity checks for optionsl paramters
|
|
21
|
+
const validParameter = {
|
|
22
|
+
url: (value) => typeof value === 'string',
|
|
23
|
+
placementId: (value) => {
|
|
24
|
+
const isString = typeof value === 'string'
|
|
25
|
+
const isNumber = typeof value === 'number'
|
|
26
|
+
return isString || isNumber
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
export const spec = {
|
|
21
31
|
code: BIDDER_CODE,
|
|
22
32
|
gvlid: GVLID,
|
|
@@ -30,7 +40,23 @@ export const spec = {
|
|
|
30
40
|
* @return boolean True if this is a valid bid, and false otherwise.
|
|
31
41
|
*/
|
|
32
42
|
isBidRequestValid: function (bid) {
|
|
33
|
-
|
|
43
|
+
// We don't need any specific parameters to make a bid request
|
|
44
|
+
// If not parameters are supplied just verify it's the correct bidder code
|
|
45
|
+
if (!bid.params) return bid.bidder === BIDDER_CODE
|
|
46
|
+
|
|
47
|
+
// Check if any supplied parameters are invalid
|
|
48
|
+
const hasInvalidParameters = Object.keys(bid.params).some(key => {
|
|
49
|
+
const value = bid.params[key]
|
|
50
|
+
const validityCheck = validParameter[key]
|
|
51
|
+
|
|
52
|
+
// We don't have a test for this so it's not a paramter we care about
|
|
53
|
+
if (!validityCheck) return false
|
|
54
|
+
|
|
55
|
+
// Return if the check is not passed
|
|
56
|
+
return !validityCheck(value)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
return !hasInvalidParameters
|
|
34
60
|
},
|
|
35
61
|
|
|
36
62
|
/**
|
|
@@ -98,7 +124,11 @@ export const spec = {
|
|
|
98
124
|
]
|
|
99
125
|
|
|
100
126
|
if (placementIds.size > 0) {
|
|
101
|
-
|
|
127
|
+
// Convert Set to Array (IE 11 Safe)
|
|
128
|
+
const placements = []
|
|
129
|
+
placementIds.forEach((value) => placements.push(value))
|
|
130
|
+
// Append to query string paramters
|
|
131
|
+
params.unshift({ key: 'ntv_ptd', value: placements.join(',') })
|
|
102
132
|
}
|
|
103
133
|
|
|
104
134
|
if (bidderRequest.gdprConsent) {
|
|
@@ -30,14 +30,23 @@ export const spec = {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
|
|
33
34
|
const gdprConsent = bidderRequest && bidderRequest.gdprConsent;
|
|
35
|
+
const uspConsent = bidderRequest && bidderRequest.uspConsent
|
|
36
|
+
|
|
37
|
+
if (gdprConsent || uspConsent) {
|
|
38
|
+
postBody.regs = { ext: {} }
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
if (uspConsent) {
|
|
41
|
+
postBody.regs.ext.us_privacy = uspConsent;
|
|
42
|
+
}
|
|
36
43
|
if (typeof gdprConsent.gdprApplies !== 'undefined') {
|
|
37
|
-
postBody.
|
|
44
|
+
postBody.regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0;
|
|
38
45
|
}
|
|
39
46
|
if (typeof gdprConsent.consentString !== 'undefined') {
|
|
40
|
-
postBody.
|
|
47
|
+
postBody.user = {
|
|
48
|
+
ext: { consent: gdprConsent.consentString }
|
|
49
|
+
}
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
52
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import { BANNER } from '../src/mediaTypes.js';
|
|
4
|
-
import { getAdUnitSizes, logWarn, isFn } from '../src/utils.js';
|
|
4
|
+
import { getAdUnitSizes, logWarn, isFn, getWindowTop, getWindowSelf } from '../src/utils.js';
|
|
5
5
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
6
6
|
import { ajax } from '../src/ajax.js'
|
|
7
7
|
|
|
@@ -83,7 +83,8 @@ function buildRequests(validBidRequests, bidderRequest) {
|
|
|
83
83
|
bidfloor: getFloor(bidRequest),
|
|
84
84
|
banner: {
|
|
85
85
|
format: sizes
|
|
86
|
-
}
|
|
86
|
+
},
|
|
87
|
+
ext: bidRequest.params
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
});
|
|
@@ -145,7 +146,19 @@ function getFloor(bid) {
|
|
|
145
146
|
return floorResult.currency === 'USD' ? floorResult.floor : 0;
|
|
146
147
|
}
|
|
147
148
|
|
|
149
|
+
function getWindowContext() {
|
|
150
|
+
try {
|
|
151
|
+
return getWindowTop()
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return getWindowSelf()
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
148
157
|
function onBidWon(bid) {
|
|
158
|
+
const w = getWindowContext()
|
|
159
|
+
w.OG_PREBID_BID_OBJECT = {
|
|
160
|
+
...(bid && { ...bid }),
|
|
161
|
+
}
|
|
149
162
|
if (bid && bid.hasOwnProperty('nurl') && bid.nurl.length > 0) ajax(bid['nurl'], null);
|
|
150
163
|
}
|
|
151
164
|
|
|
@@ -165,6 +178,7 @@ export const spec = {
|
|
|
165
178
|
interpretResponse,
|
|
166
179
|
getFloor,
|
|
167
180
|
onBidWon,
|
|
181
|
+
getWindowContext,
|
|
168
182
|
onTimeout
|
|
169
183
|
}
|
|
170
184
|
|
|
@@ -42,7 +42,12 @@ export const USER_ID_CODE_TO_QUERY_ARG = {
|
|
|
42
42
|
novatiq: 'novatiqid', // Novatiq ID
|
|
43
43
|
mwOpenLinkId: 'mwopenlinkid', // MediaWallah OpenLink ID
|
|
44
44
|
dapId: 'dapid', // Akamai DAP ID
|
|
45
|
-
amxId: 'amxid' // AMX RTB ID
|
|
45
|
+
amxId: 'amxid', // AMX RTB ID
|
|
46
|
+
kpuid: 'kpuid', // Kinesso ID
|
|
47
|
+
publinkId: 'publinkid', // Publisher Link
|
|
48
|
+
naveggId: 'naveggid', // Navegg ID
|
|
49
|
+
imuid: 'imuid', // IM-UID by Intimate Merger
|
|
50
|
+
adtelligentId: 'adtelligentid' // Adtelligent ID
|
|
46
51
|
};
|
|
47
52
|
|
|
48
53
|
export const spec = {
|
|
@@ -256,27 +261,14 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) {
|
|
|
256
261
|
nocache: new Date().getTime()
|
|
257
262
|
};
|
|
258
263
|
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
data.name.length > 0)
|
|
268
|
-
)
|
|
269
|
-
.reduce((acc, data) => {
|
|
270
|
-
const name = typeof data.ext === 'object' && data.ext.segtax ? `${data.name}/${data.ext.segtax}` : data.name;
|
|
271
|
-
acc[name] = (acc[name] || []).concat(data.segment.map(seg => seg.id));
|
|
272
|
-
return acc;
|
|
273
|
-
}, {})
|
|
274
|
-
const sm = Object.keys(fpd)
|
|
275
|
-
.map((name, _) => name + ':' + fpd[name].join('|'))
|
|
276
|
-
.join(',')
|
|
277
|
-
if (sm.length > 0) {
|
|
278
|
-
defaultParams.sm = encodeURIComponent(sm);
|
|
279
|
-
}
|
|
264
|
+
const userDataSegments = buildFpdQueryParams('ortb2.user.data');
|
|
265
|
+
if (userDataSegments.length > 0) {
|
|
266
|
+
defaultParams.sm = userDataSegments;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const siteContentDataSegments = buildFpdQueryParams('ortb2.site.content.data');
|
|
270
|
+
if (siteContentDataSegments.length > 0) {
|
|
271
|
+
defaultParams.scsm = siteContentDataSegments;
|
|
280
272
|
}
|
|
281
273
|
|
|
282
274
|
if (bids[0].params.platform) {
|
|
@@ -317,12 +309,37 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) {
|
|
|
317
309
|
return defaultParams;
|
|
318
310
|
}
|
|
319
311
|
|
|
312
|
+
function buildFpdQueryParams(fpdPath) {
|
|
313
|
+
const firstPartyData = config.getConfig(fpdPath);
|
|
314
|
+
if (!Array.isArray(firstPartyData) || !firstPartyData.length) {
|
|
315
|
+
return '';
|
|
316
|
+
}
|
|
317
|
+
const fpd = firstPartyData
|
|
318
|
+
.filter(
|
|
319
|
+
data => (Array.isArray(data.segment) &&
|
|
320
|
+
data.segment.length > 0 &&
|
|
321
|
+
data.name !== undefined &&
|
|
322
|
+
data.name.length > 0)
|
|
323
|
+
)
|
|
324
|
+
.reduce((acc, data) => {
|
|
325
|
+
const name = typeof data.ext === 'object' && data.ext.segtax ? `${data.name}/${data.ext.segtax}` : data.name;
|
|
326
|
+
acc[name] = (acc[name] || []).concat(data.segment.map(seg => seg.id));
|
|
327
|
+
return acc;
|
|
328
|
+
}, {})
|
|
329
|
+
return Object.keys(fpd)
|
|
330
|
+
.map((name, _) => name + ':' + fpd[name].join('|'))
|
|
331
|
+
.join(',')
|
|
332
|
+
}
|
|
333
|
+
|
|
320
334
|
function appendUserIdsToQueryParams(queryParams, userIds) {
|
|
321
335
|
_each(userIds, (userIdObjectOrValue, userIdProviderKey) => {
|
|
322
336
|
const key = USER_ID_CODE_TO_QUERY_ARG[userIdProviderKey];
|
|
323
337
|
|
|
324
338
|
if (USER_ID_CODE_TO_QUERY_ARG.hasOwnProperty(userIdProviderKey)) {
|
|
325
339
|
switch (userIdProviderKey) {
|
|
340
|
+
case 'merkleId':
|
|
341
|
+
queryParams[key] = userIdObjectOrValue.id;
|
|
342
|
+
break;
|
|
326
343
|
case 'flocId':
|
|
327
344
|
queryParams[key] = userIdObjectOrValue.id;
|
|
328
345
|
break;
|
|
@@ -333,7 +350,7 @@ function appendUserIdsToQueryParams(queryParams, userIds) {
|
|
|
333
350
|
queryParams[key] = userIdObjectOrValue.lipbid;
|
|
334
351
|
if (Array.isArray(userIdObjectOrValue.segments) && userIdObjectOrValue.segments.length > 0) {
|
|
335
352
|
const liveIntentSegments = 'liveintent:' + userIdObjectOrValue.segments.join('|')
|
|
336
|
-
queryParams.sm = `${queryParams.sm ? queryParams.sm +
|
|
353
|
+
queryParams.sm = `${queryParams.sm ? queryParams.sm + ',' : ''}${liveIntentSegments}`;
|
|
337
354
|
}
|
|
338
355
|
break;
|
|
339
356
|
case 'parrableId':
|
|
@@ -8,6 +8,7 @@ import { OUTSTREAM } from '../src/video.js';
|
|
|
8
8
|
const BIDDER_CODE = 'operaads';
|
|
9
9
|
|
|
10
10
|
const ENDPOINT = 'https://s.adx.opera.com/ortb/v2/';
|
|
11
|
+
const USER_SYNC_ENDPOINT = 'https://s.adx.opera.com/usersync/page';
|
|
11
12
|
|
|
12
13
|
const OUTSTREAM_RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js';
|
|
13
14
|
|
|
@@ -137,6 +138,25 @@ export const spec = {
|
|
|
137
138
|
* @return {UserSync[]} The user syncs which should be dropped.
|
|
138
139
|
*/
|
|
139
140
|
getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) {
|
|
141
|
+
if ('iframeEnabled' in syncOptions && syncOptions.iframeEnabled) {
|
|
142
|
+
return [{
|
|
143
|
+
type: 'iframe',
|
|
144
|
+
url: USER_SYNC_ENDPOINT
|
|
145
|
+
}];
|
|
146
|
+
}
|
|
147
|
+
if ('pixelEnabled' in syncOptions && syncOptions.pixelEnabled) {
|
|
148
|
+
const pixels = deepAccess(serverResponses, '0.body.pixels')
|
|
149
|
+
if (Array.isArray(pixels)) {
|
|
150
|
+
const userSyncPixels = []
|
|
151
|
+
for (const pixel of pixels) {
|
|
152
|
+
userSyncPixels.push({
|
|
153
|
+
type: 'image',
|
|
154
|
+
url: pixel
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
return userSyncPixels;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
140
160
|
return [];
|
|
141
161
|
},
|
|
142
162
|
|
|
@@ -212,7 +232,7 @@ function buildOpenRtbBidRequest(bidRequest, bidderRequest) {
|
|
|
212
232
|
ext: {}
|
|
213
233
|
},
|
|
214
234
|
user: {
|
|
215
|
-
|
|
235
|
+
buyeruid: getUserId(bidRequest)
|
|
216
236
|
}
|
|
217
237
|
}
|
|
218
238
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
2
|
+
import {logInfo, logError, getBidIdParameter, _each, getValue, isFn, isPlainObject} from '../src/utils.js';
|
|
3
|
+
import { BANNER } from '../src/mediaTypes.js';
|
|
4
|
+
|
|
5
|
+
const BIDDER_CODE = 'otm';
|
|
6
|
+
const OTM_BID_URL = 'https://ssp.otm-r.com/adjson';
|
|
7
|
+
const DEF_CUR = 'RUB'
|
|
8
|
+
|
|
9
|
+
export const spec = {
|
|
10
|
+
|
|
11
|
+
code: BIDDER_CODE,
|
|
12
|
+
url: OTM_BID_URL,
|
|
13
|
+
supportedMediaTypes: [ BANNER ],
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Determines whether or not the given bid request is valid.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} bid The bid to validate.
|
|
19
|
+
* @return boolean True if this is a valid bid, and false otherwise.
|
|
20
|
+
*/
|
|
21
|
+
isBidRequestValid: function (bid) {
|
|
22
|
+
return !!bid.params.tid;
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build bidder requests.
|
|
27
|
+
*
|
|
28
|
+
* @param validBidRequests
|
|
29
|
+
* @param bidderRequest
|
|
30
|
+
* @returns {[]}
|
|
31
|
+
*/
|
|
32
|
+
buildRequests: function (validBidRequests, bidderRequest) {
|
|
33
|
+
logInfo('validBidRequests', validBidRequests);
|
|
34
|
+
|
|
35
|
+
const bidRequests = [];
|
|
36
|
+
let tz = new Date().getTimezoneOffset()
|
|
37
|
+
let referrer = '';
|
|
38
|
+
if (bidderRequest && bidderRequest.refererInfo) {
|
|
39
|
+
referrer = bidderRequest.refererInfo.referer;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_each(validBidRequests, (bid) => {
|
|
43
|
+
let domain = getValue(bid.params, 'domain') || ''
|
|
44
|
+
let tid = getValue(bid.params, 'tid')
|
|
45
|
+
let cur = getValue(bid.params, 'currency') || DEF_CUR
|
|
46
|
+
let bidid = getBidIdParameter('bidId', bid)
|
|
47
|
+
let transactionid = getBidIdParameter('transactionId', bid)
|
|
48
|
+
let auctionid = getBidIdParameter('auctionId', bid)
|
|
49
|
+
let bidfloor = _getBidFloor(bid)
|
|
50
|
+
|
|
51
|
+
_each(bid.sizes, size => {
|
|
52
|
+
let width = 0;
|
|
53
|
+
let height = 0;
|
|
54
|
+
if (size.length && typeof size[0] === 'number' && typeof size[1] === 'number') {
|
|
55
|
+
width = size[0];
|
|
56
|
+
height = size[1];
|
|
57
|
+
}
|
|
58
|
+
bidRequests.push({
|
|
59
|
+
method: 'GET',
|
|
60
|
+
url: OTM_BID_URL,
|
|
61
|
+
data: {
|
|
62
|
+
tz: tz,
|
|
63
|
+
w: width,
|
|
64
|
+
h: height,
|
|
65
|
+
domain: domain,
|
|
66
|
+
l: referrer,
|
|
67
|
+
s: tid,
|
|
68
|
+
cur: cur,
|
|
69
|
+
bidid: bidid,
|
|
70
|
+
transactionid: transactionid,
|
|
71
|
+
auctionid: auctionid,
|
|
72
|
+
bidfloor: bidfloor,
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
return bidRequests;
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generate response.
|
|
82
|
+
*
|
|
83
|
+
* @param serverResponse
|
|
84
|
+
* @param request
|
|
85
|
+
* @returns {[]|*[]}
|
|
86
|
+
*/
|
|
87
|
+
interpretResponse: function (serverResponse, request) {
|
|
88
|
+
logInfo('serverResponse', serverResponse.body);
|
|
89
|
+
|
|
90
|
+
const responsesBody = serverResponse ? serverResponse.body : {};
|
|
91
|
+
const bidResponses = [];
|
|
92
|
+
try {
|
|
93
|
+
if (responsesBody.length === 0) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_each(responsesBody, (bid) => {
|
|
98
|
+
if (bid.ad) {
|
|
99
|
+
bidResponses.push({
|
|
100
|
+
requestId: bid.bidid,
|
|
101
|
+
cpm: bid.cpm,
|
|
102
|
+
width: bid.w,
|
|
103
|
+
height: bid.h,
|
|
104
|
+
creativeId: bid.creativeid,
|
|
105
|
+
currency: bid.currency || 'RUB',
|
|
106
|
+
netRevenue: true,
|
|
107
|
+
ad: bid.ad,
|
|
108
|
+
ttl: bid.ttl,
|
|
109
|
+
transactionId: bid.transactionid,
|
|
110
|
+
meta: {
|
|
111
|
+
advertiserDomains: bid.adDomain ? [bid.adDomain] : []
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
logError(error);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return bidResponses;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get floor value
|
|
126
|
+
* @param bid
|
|
127
|
+
* @returns {null|*}
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
function _getBidFloor(bid) {
|
|
131
|
+
if (!isFn(bid.getFloor)) {
|
|
132
|
+
return bid.params.bidfloor ? bid.params.bidfloor : 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let floor = bid.getFloor({
|
|
136
|
+
currency: DEF_CUR,
|
|
137
|
+
mediaType: '*',
|
|
138
|
+
size: '*'
|
|
139
|
+
});
|
|
140
|
+
if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === DEF_CUR) {
|
|
141
|
+
return floor.floor;
|
|
142
|
+
}
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
registerBidder(spec);
|
package/modules/otmBidAdapter.md
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
# Overview
|
|
2
2
|
|
|
3
|
-
Module Name
|
|
4
|
-
Module Type
|
|
5
|
-
Maintainer
|
|
3
|
+
**Module Name**: OTM Bidder Adapter
|
|
4
|
+
**Module Type**: Bidder Adapter
|
|
5
|
+
**Maintainer**: e.kretsu@otm-r.com
|
|
6
6
|
|
|
7
7
|
# Description
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
OTM Bidder Adapter for Prebid.js. About: https://otm-r.com
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Use `otm` as bidder:
|
|
12
12
|
|
|
13
|
+
# Params
|
|
14
|
+
- `tid` required, specific id AdUnit slot.
|
|
15
|
+
- `domain` optional, specific custom domain.
|
|
16
|
+
- `bidfloor` optional.
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
var adUnits = [
|
|
17
|
-
{
|
|
18
|
-
code: 'div-otm-example',
|
|
19
|
-
sizes: [[320, 480]],
|
|
20
|
-
bids: [
|
|
21
|
-
{
|
|
22
|
-
bidder: "otm",
|
|
23
|
-
params: {
|
|
24
|
-
tid: "99",
|
|
25
|
-
bidfloor: 20
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
];
|
|
18
|
+
## AdUnits configuration example
|
|
31
19
|
```
|
|
20
|
+
var adUnits = [{
|
|
21
|
+
code: 'your-slot', //use exactly the same code as your slot div id.
|
|
22
|
+
mediaTypes: {
|
|
23
|
+
banner: {
|
|
24
|
+
sizes: [[320, 480]]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
bids: [{
|
|
28
|
+
bidder: 'otm',
|
|
29
|
+
params: {
|
|
30
|
+
tid: 'XXXXX',
|
|
31
|
+
domain: 'specific custom domain, if needed',
|
|
32
|
+
bidfloor: 20
|
|
33
|
+
}
|
|
34
|
+
}]
|
|
35
|
+
}];
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* tid - A tag id (should have low cardinality)
|
|
36
|
-
* bidfloor - Floor price
|
|
37
|
+
```
|
|
@@ -40,6 +40,7 @@ export const spec = {
|
|
|
40
40
|
const publisher = setOnAny(validBidRequests, 'params.publisher');
|
|
41
41
|
const bcat = setOnAny(validBidRequests, 'params.bcat');
|
|
42
42
|
const badv = setOnAny(validBidRequests, 'params.badv');
|
|
43
|
+
const eids = setOnAny(validBidRequests, 'userIdAsEids')
|
|
43
44
|
const cur = CURRENCY;
|
|
44
45
|
const endpointUrl = config.getConfig('outbrain.bidderUrl');
|
|
45
46
|
const timeout = bidderRequest.timeout;
|
|
@@ -105,6 +106,10 @@ export const spec = {
|
|
|
105
106
|
deepSetValue(request, 'regs.coppa', config.getConfig('coppa') & 1)
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
if (eids) {
|
|
110
|
+
deepSetValue(request, 'user.ext.eids', eids);
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
return {
|
|
109
114
|
method: 'POST',
|
|
110
115
|
url: endpointUrl,
|