prebid.js 5.16.0 → 5.20.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/.devcontainer/Dockerfile +11 -0
- package/.devcontainer/devcontainer.json +27 -0
- package/.devcontainer/postCreate.sh +6 -0
- package/browsers.json +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/adgenerationBidAdapter.js +28 -4
- package/modules/adkernelBidAdapter.js +3 -1
- package/modules/admixerBidAdapter.js +11 -0
- package/modules/adnuntiusBidAdapter.js +1 -0
- 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/aolBidAdapter.js +2 -1
- package/modules/appnexusBidAdapter.js +5 -3
- package/modules/atsAnalyticsAdapter.js +89 -63
- package/modules/atsAnalyticsAdapter.md +1 -0
- package/modules/betweenBidAdapter.js +20 -3
- package/modules/bliinkBidAdapter.js +58 -32
- package/modules/bliinkBidAdapter.md +29 -6
- package/modules/browsiRtdProvider.js +106 -18
- package/modules/cleanioRtdProvider.js +192 -0
- package/modules/cleanioRtdProvider.md +59 -0
- package/modules/codefuelBidAdapter.js +183 -0
- package/modules/codefuelBidAdapter.md +111 -0
- package/modules/connectIdSystem.js +104 -0
- package/modules/connectIdSystem.md +33 -0
- package/modules/cwireBidAdapter.js +272 -0
- package/modules/cwireBidAdapter.md +43 -0
- package/modules/deepintentBidAdapter.js +106 -9
- package/modules/deepintentBidAdapter.md +36 -1
- package/modules/deltaprojectsBidAdapter.js +252 -0
- package/modules/deltaprojectsBidAdapter.md +32 -0
- package/modules/dgkeywordRtdProvider.js +0 -1
- package/modules/engageyaBidAdapter.js +157 -0
- package/modules/glimpseBidAdapter.js +160 -48
- package/modules/glimpseBidAdapter.md +11 -74
- package/modules/gridBidAdapter.js +1 -0
- package/modules/gridNMBidAdapter.js +7 -6
- package/modules/gumgumBidAdapter.js +16 -2
- package/modules/iasRtdProvider.js +83 -67
- package/modules/inskinBidAdapter.js +7 -3
- package/modules/ixBidAdapter.js +8 -1
- package/modules/jixieBidAdapter.js +8 -2
- package/modules/justpremiumBidAdapter.js +6 -1
- package/modules/kargoBidAdapter.js +14 -7
- package/modules/kargoBidAdapter.md +20 -0
- package/modules/limelightDigitalBidAdapter.js +22 -2
- package/modules/livewrappedAnalyticsAdapter.js +53 -3
- package/modules/mediakeysBidAdapter.js +405 -14
- package/modules/mediakeysBidAdapter.md +108 -0
- package/modules/multibid/index.js +3 -3
- package/modules/mytargetBidAdapter.js +112 -0
- package/modules/nativoBidAdapter.js +48 -29
- package/modules/nativoBidAdapter.md +0 -1
- package/modules/nextMillenniumBidAdapter.js +12 -3
- package/modules/nextrollBidAdapter.js +375 -0
- package/modules/nobidBidAdapter.js +2 -1
- package/modules/oguryBidAdapter.js +36 -7
- package/modules/openxBidAdapter.js +34 -22
- 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/pixfutureBidAdapter.js +24 -4
- package/modules/pixfutureBidAdapter.md +127 -0
- package/modules/playwireBidAdapter.md +61 -0
- package/modules/prebidServerBidAdapter/index.js +1 -1
- package/modules/proxistoreBidAdapter.js +4 -6
- package/modules/publinkIdSystem.js +17 -7
- package/modules/publinkIdSystem.md +7 -2
- package/modules/pubmaticBidAdapter.js +22 -6
- package/modules/pubmaticBidAdapter.md +1 -1
- package/modules/relaidoBidAdapter.js +8 -2
- package/modules/rtdModule/index.js +2 -2
- package/modules/sharethroughBidAdapter.js +12 -19
- package/modules/slimcutBidAdapter.js +121 -0
- package/modules/sonobiBidAdapter.js +7 -0
- package/modules/sortableBidAdapter.js +1 -0
- package/modules/spotxBidAdapter.js +15 -1
- package/modules/sspBCBidAdapter.js +207 -12
- package/modules/sspBCBidAdapter.md +1 -1
- package/modules/talkadsBidAdapter.js +129 -0
- package/modules/talkadsBidAdapter.md +60 -0
- package/modules/tappxBidAdapter.js +6 -5
- package/modules/teadsBidAdapter.js +3 -0
- package/modules/tripleliftBidAdapter.js +22 -5
- package/modules/trustxBidAdapter.js +17 -11
- package/modules/undertoneBidAdapter.js +9 -5
- package/modules/undertoneBidAdapter.md +5 -1
- package/modules/unicornBidAdapter.js +3 -3
- 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 +20 -12
- package/modules/visxBidAdapter.js +15 -22
- package/modules/yahoosspBidAdapter.js +637 -0
- package/modules/yahoosspBidAdapter.md +795 -0
- package/modules/yieldlabBidAdapter.js +48 -3
- package/modules/yieldlabBidAdapter.md +16 -1
- package/modules/yieldmoBidAdapter.js +20 -6
- package/modules/yieldmoSyntheticInventoryModule.js +46 -0
- package/modules/yieldmoSyntheticInventoryModule.md +68 -0
- package/package.json +1 -1
- package/src/adapterManager.js +5 -0
- 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/.eslintrc.js +2 -1
- package/test/spec/modules/adfBidAdapter_spec.js +83 -29
- package/test/spec/modules/adgenerationBidAdapter_spec.js +121 -50
- package/test/spec/modules/adnuntiusBidAdapter_spec.js +68 -0
- 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 +2 -1
- package/test/spec/modules/atsAnalyticsAdapter_spec.js +77 -9
- package/test/spec/modules/betweenBidAdapter_spec.js +41 -0
- package/test/spec/modules/bliinkBidAdapter_spec.js +87 -36
- 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/cwireBidAdapter_spec.js +246 -0
- 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 +286 -0
- package/test/spec/modules/glimpseBidAdapter_spec.js +302 -204
- package/test/spec/modules/gridNMBidAdapter_spec.js +40 -1
- package/test/spec/modules/gumgumBidAdapter_spec.js +23 -6
- package/test/spec/modules/iasRtdProvider_spec.js +71 -6
- package/test/spec/modules/ixBidAdapter_spec.js +13 -3
- package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
- package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
- package/test/spec/modules/limelightDigitalBidAdapter_spec.js +155 -1
- package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +67 -12
- package/test/spec/modules/mediakeysBidAdapter_spec.js +406 -51
- package/test/spec/modules/multibid_spec.js +31 -31
- package/test/spec/modules/mytargetBidAdapter_spec.js +199 -0
- package/test/spec/modules/nativoBidAdapter_spec.js +50 -3
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +13 -1
- package/test/spec/modules/nextrollBidAdapter_spec.js +290 -0
- package/test/spec/modules/nobidBidAdapter_spec.js +65 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +125 -37
- package/test/spec/modules/openxBidAdapter_spec.js +85 -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/publinkIdSystem_spec.js +34 -15
- package/test/spec/modules/pubmaticBidAdapter_spec.js +217 -1
- package/test/spec/modules/relaidoBidAdapter_spec.js +21 -20
- package/test/spec/modules/sharethroughBidAdapter_spec.js +156 -136
- package/test/spec/modules/slimcutBidAdapter_spec.js +200 -0
- package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
- package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
- package/test/spec/modules/spotxBidAdapter_spec.js +36 -0
- package/test/spec/modules/sspBCBidAdapter_spec.js +210 -62
- package/test/spec/modules/talkadsBidAdapter_spec.js +231 -0
- 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 +38 -5
- package/test/spec/modules/undertoneBidAdapter_spec.js +52 -0
- package/test/spec/modules/unicornBidAdapter_spec.js +4 -4
- package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
- package/test/spec/modules/videobyteBidAdapter_spec.js +2 -2
- package/test/spec/modules/visxBidAdapter_spec.js +48 -4
- package/test/spec/modules/yahoosspBidAdapter_spec.js +1332 -0
- package/test/spec/modules/yieldlabBidAdapter_spec.js +65 -1
- package/test/spec/modules/yieldmoBidAdapter_spec.js +30 -9
- package/test/spec/modules/yieldmoSyntheticInventoryModule_spec.js +89 -0
- package/test/spec/unit/core/adapterManager_spec.js +32 -0
- 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/modules/turktelekomBidAdapter.md +0 -49
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import find from 'core-js-pure/features/array/find.js';
|
|
2
|
+
import arrayFrom from 'core-js-pure/features/array/from';
|
|
3
|
+
import { getWindowTop, isFn, logWarn, getDNT, deepAccess, isArray, inIframe, mergeDeep, isStr, isEmpty, deepSetValue, deepClone, parseUrl, cleanObj, logError, triggerPixel, isInteger, isNumber } from '../src/utils.js';
|
|
2
4
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
3
5
|
import { config } from '../src/config.js';
|
|
4
6
|
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
|
|
@@ -8,10 +10,63 @@ const AUCTION_TYPE = 1;
|
|
|
8
10
|
const BIDDER_CODE = 'mediakeys';
|
|
9
11
|
const ENDPOINT = 'https://prebid.eu-central-1.bidder.mediakeys.io/bids';
|
|
10
12
|
const GVLID = 498;
|
|
11
|
-
const SUPPORTED_MEDIA_TYPES = [BANNER];
|
|
13
|
+
const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE, VIDEO];
|
|
12
14
|
const DEFAULT_CURRENCY = 'USD';
|
|
13
15
|
const NET_REVENUE = true;
|
|
14
16
|
|
|
17
|
+
const NATIVE_ASSETS_MAPPING = [
|
|
18
|
+
{ name: 'title', id: 1, type: 0 },
|
|
19
|
+
{ name: 'image', id: 2, type: 3 },
|
|
20
|
+
{ name: 'icon', id: 3, type: 1 },
|
|
21
|
+
{ name: 'sponsoredBy', id: 5, type: 1 },
|
|
22
|
+
{ name: 'body', id: 6, type: 2 },
|
|
23
|
+
{ name: 'rating', id: 7, type: 3 },
|
|
24
|
+
{ name: 'likes', id: 8, type: 4 },
|
|
25
|
+
{ name: 'downloads', id: 9, type: 5 },
|
|
26
|
+
{ name: 'price', id: 10, type: 6 },
|
|
27
|
+
{ name: 'salePrice', id: 11, type: 7 },
|
|
28
|
+
{ name: 'phone', id: 12, type: 8 },
|
|
29
|
+
{ name: 'address', id: 13, type: 9 },
|
|
30
|
+
{ name: 'body2', id: 14, type: 10 },
|
|
31
|
+
{ name: 'displayUrl', id: 15, type: 11 },
|
|
32
|
+
{ name: 'cta', id: 16, type: 12 },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// This provide a whitelist and a basic validation of OpenRTB native 1.2 options.
|
|
36
|
+
// https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf
|
|
37
|
+
const ORTB_NATIVE_PARAMS = {
|
|
38
|
+
context: value => [1, 2, 3].indexOf(value) !== -1,
|
|
39
|
+
plcmttype: value => [1, 2, 3, 4].indexOf(value) !== -1
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// This provide a whitelist and a basic validation of OpenRTB 2.5 video options.
|
|
43
|
+
// https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf
|
|
44
|
+
const ORTB_VIDEO_PARAMS = {
|
|
45
|
+
mimes: value => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'),
|
|
46
|
+
minduration: value => isInteger(value),
|
|
47
|
+
maxduration: value => isInteger(value),
|
|
48
|
+
protocols: value => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].indexOf(v) !== -1),
|
|
49
|
+
w: value => isInteger(value),
|
|
50
|
+
h: value => isInteger(value),
|
|
51
|
+
startdelay: value => isInteger(value),
|
|
52
|
+
placement: value => [1, 2, 3, 4, 5].indexOf(value) !== -1,
|
|
53
|
+
linearity: value => [1, 2].indexOf(value) !== -1,
|
|
54
|
+
skip: value => [0, 1].indexOf(value) !== -1,
|
|
55
|
+
skipmin: value => isInteger(value),
|
|
56
|
+
skipafter: value => isInteger(value),
|
|
57
|
+
sequence: value => isInteger(value),
|
|
58
|
+
battr: value => Array.isArray(value) && value.every(v => arrayFrom({length: 17}, (_, i) => i + 1).indexOf(v) !== -1),
|
|
59
|
+
maxextended: value => isInteger(value),
|
|
60
|
+
minbitrate: value => isInteger(value),
|
|
61
|
+
maxbitrate: value => isInteger(value),
|
|
62
|
+
boxingallowed: value => [0, 1].indexOf(value) !== -1,
|
|
63
|
+
playbackmethod: value => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6].indexOf(v) !== -1),
|
|
64
|
+
playbackend: value => [1, 2, 3].indexOf(value) !== -1,
|
|
65
|
+
delivery: value => [1, 2, 3].indexOf(value) !== -1,
|
|
66
|
+
pos: value => [0, 1, 2, 3, 4, 5, 6, 7].indexOf(value) !== -1,
|
|
67
|
+
api: value => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6].indexOf(v) !== -1),
|
|
68
|
+
};
|
|
69
|
+
|
|
15
70
|
/**
|
|
16
71
|
* Detects the capability to reach window.top.
|
|
17
72
|
*
|
|
@@ -83,6 +138,33 @@ function getFloor(bid, mediaType, size = '*') {
|
|
|
83
138
|
return (!isNaN(floor.floor) && floor.currency === DEFAULT_CURRENCY) ? floor.floor : false
|
|
84
139
|
}
|
|
85
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Returns the highest floor price found when a bid have
|
|
143
|
+
* several mediaTypes.
|
|
144
|
+
*
|
|
145
|
+
* @param {*} bid a Prebid.js bid (request) object
|
|
146
|
+
* @returns {number|boolean}
|
|
147
|
+
*/
|
|
148
|
+
function getHighestFloor(bid) {
|
|
149
|
+
const floors = [];
|
|
150
|
+
|
|
151
|
+
for (let mediaType in bid.mediaTypes) {
|
|
152
|
+
const floor = getFloor(bid, mediaType);
|
|
153
|
+
|
|
154
|
+
if (isNumber(floor)) {
|
|
155
|
+
floors.push(floor);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!floors.length) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return floors.reduce((a, b) => {
|
|
164
|
+
return Math.max(a, b);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
86
168
|
/**
|
|
87
169
|
* Returns an openRTB 2.5 object.
|
|
88
170
|
* This one will be populated at each step of the buildRequest process.
|
|
@@ -153,6 +235,190 @@ function createBannerImp(bid) {
|
|
|
153
235
|
}
|
|
154
236
|
}
|
|
155
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Returns an openRtb 2.5 native object with a native 1.2 request.
|
|
240
|
+
*
|
|
241
|
+
* @param {object} bid Prebid bid object from request
|
|
242
|
+
* @returns {object}
|
|
243
|
+
*/
|
|
244
|
+
function createNativeImp(bid) {
|
|
245
|
+
if (!bid.nativeParams) {
|
|
246
|
+
logWarn(`${BIDDER_CODE}: bid.nativeParams object has not been found.`);
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const nativeParams = deepClone(bid.nativeParams);
|
|
251
|
+
|
|
252
|
+
const nativeAdUnitParams = deepAccess(bid, 'mediaTypes.native', {});
|
|
253
|
+
const nativeBidderParams = deepAccess(bid, 'params.native', {});
|
|
254
|
+
|
|
255
|
+
const extraParams = {
|
|
256
|
+
...nativeAdUnitParams,
|
|
257
|
+
...nativeBidderParams
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const nativeObject = {
|
|
261
|
+
ver: '1.2',
|
|
262
|
+
context: 1, // overwrited later if needed
|
|
263
|
+
plcmttype: 1, // overwrited later if needed
|
|
264
|
+
assets: []
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
Object.keys(ORTB_NATIVE_PARAMS).forEach(name => {
|
|
268
|
+
if (extraParams.hasOwnProperty(name)) {
|
|
269
|
+
if (ORTB_NATIVE_PARAMS[name](extraParams[name])) {
|
|
270
|
+
nativeObject[name] = extraParams[name];
|
|
271
|
+
} else {
|
|
272
|
+
logWarn(`${BIDDER_CODE}: the OpenRTB native param ${name} has been skipped due to misformating. Please refer to OpenRTB Native spec.`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// just a helper function
|
|
278
|
+
const setImageAssetSizes = function(asset, param) {
|
|
279
|
+
if (param.sizes && param.sizes.length) {
|
|
280
|
+
asset.img.w = param.sizes ? param.sizes[0] : undefined;
|
|
281
|
+
asset.img.h = param.sizes ? param.sizes[1] : undefined;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!asset.img.w) {
|
|
285
|
+
asset.img.wmin = 0;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!asset.img.h) {
|
|
289
|
+
asset.img.hmin = 0;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Prebid.js "image" type support.
|
|
294
|
+
// Add some defaults to support special type provided by Prebid.js `mediaTypes.native.type: "image"`
|
|
295
|
+
const nativeImageType = deepAccess(bid, 'mediaTypes.native.type');
|
|
296
|
+
if (nativeImageType === 'image') {
|
|
297
|
+
// Default value is ones of the recommended by the spec: https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf
|
|
298
|
+
nativeParams.title.len = 90;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
for (let key in nativeParams) {
|
|
302
|
+
if (nativeParams.hasOwnProperty(key)) {
|
|
303
|
+
const internalNativeAsset = find(NATIVE_ASSETS_MAPPING, ref => ref.name === key);
|
|
304
|
+
if (!internalNativeAsset) {
|
|
305
|
+
logWarn(`${BIDDER_CODE}: the asset "${key}" has not been found in Prebid assets map. Skipped for request.`);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const param = nativeParams[key];
|
|
310
|
+
|
|
311
|
+
const asset = {
|
|
312
|
+
id: internalNativeAsset.id,
|
|
313
|
+
required: param.required ? 1 : 0
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
switch (key) {
|
|
317
|
+
case 'title':
|
|
318
|
+
if (param.len || param.length) {
|
|
319
|
+
asset.title = {
|
|
320
|
+
len: param.len || param.length,
|
|
321
|
+
ext: param.ext
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
logWarn(`${BIDDER_CODE}: "title.length" property for native asset is required. Skipped for request.`)
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
case 'image':
|
|
330
|
+
asset.img = {
|
|
331
|
+
type: internalNativeAsset.type,
|
|
332
|
+
mimes: param.mimes,
|
|
333
|
+
ext: param.ext,
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
setImageAssetSizes(asset, param);
|
|
337
|
+
|
|
338
|
+
break;
|
|
339
|
+
case 'icon':
|
|
340
|
+
asset.img = {
|
|
341
|
+
type: internalNativeAsset.type,
|
|
342
|
+
mimes: param.mimes,
|
|
343
|
+
ext: param.ext,
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
setImageAssetSizes(asset, param);
|
|
347
|
+
break;
|
|
348
|
+
|
|
349
|
+
case 'sponsoredBy': // sponsored
|
|
350
|
+
case 'body': // desc
|
|
351
|
+
case 'rating':
|
|
352
|
+
case 'likes':
|
|
353
|
+
case 'downloads':
|
|
354
|
+
case 'price':
|
|
355
|
+
case 'salePrice':
|
|
356
|
+
case 'phone':
|
|
357
|
+
case 'address':
|
|
358
|
+
case 'body2': // desc2
|
|
359
|
+
case 'displayUrl':
|
|
360
|
+
case 'cta':
|
|
361
|
+
// generic asset.data
|
|
362
|
+
asset.data = {
|
|
363
|
+
type: internalNativeAsset.type,
|
|
364
|
+
len: param.len,
|
|
365
|
+
ext: param.ext
|
|
366
|
+
}
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
nativeObject.assets.push(asset);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (nativeObject.assets.length) {
|
|
375
|
+
return {
|
|
376
|
+
request: nativeObject
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Returns an openRtb 2.5 video object.
|
|
383
|
+
*
|
|
384
|
+
* @param {object} bid Prebid bid object from request
|
|
385
|
+
* @returns {object}
|
|
386
|
+
*/
|
|
387
|
+
function createVideoImp(bid) {
|
|
388
|
+
const videoAdUnitParams = deepAccess(bid, 'mediaTypes.video', {});
|
|
389
|
+
const videoBidderParams = deepAccess(bid, 'params.video', {});
|
|
390
|
+
const computedParams = {};
|
|
391
|
+
|
|
392
|
+
// Special case for playerSize.
|
|
393
|
+
// Eeach props will be overrided if they are defined in config.
|
|
394
|
+
if (Array.isArray(videoAdUnitParams.playerSize)) {
|
|
395
|
+
const tempSize = (Array.isArray(videoAdUnitParams.playerSize[0])) ? videoAdUnitParams.playerSize[0] : videoAdUnitParams.playerSize;
|
|
396
|
+
computedParams.w = tempSize[0];
|
|
397
|
+
computedParams.h = tempSize[1];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const videoParams = {
|
|
401
|
+
...computedParams,
|
|
402
|
+
...videoAdUnitParams,
|
|
403
|
+
...videoBidderParams
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const video = {};
|
|
407
|
+
|
|
408
|
+
// Only whitelisted OpenRTB options need to be validated.
|
|
409
|
+
Object.keys(ORTB_VIDEO_PARAMS).forEach(name => {
|
|
410
|
+
if (videoParams.hasOwnProperty(name)) {
|
|
411
|
+
if (ORTB_VIDEO_PARAMS[name](videoParams[name])) {
|
|
412
|
+
video[name] = videoParams[name];
|
|
413
|
+
} else {
|
|
414
|
+
logWarn(`${BIDDER_CODE}: the OpenRTB video param ${name} has been skipped due to misformating. Please refer to OpenRTB 2.5 spec.`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
return video
|
|
420
|
+
}
|
|
421
|
+
|
|
156
422
|
/**
|
|
157
423
|
* Create the OpenRTB 2.5 imp object.
|
|
158
424
|
*
|
|
@@ -167,20 +433,34 @@ function createImp(bid) {
|
|
|
167
433
|
secure: 1,
|
|
168
434
|
};
|
|
169
435
|
|
|
436
|
+
// There is no default floor. bidfloor is set only
|
|
437
|
+
// if the priceFloors module is activated and returns a valid floor.
|
|
438
|
+
const floor = getHighestFloor(bid);
|
|
439
|
+
if (isNumber(floor)) {
|
|
440
|
+
imp.bidfloor = floor;
|
|
441
|
+
}
|
|
442
|
+
|
|
170
443
|
// Only supports proper mediaTypes definition…
|
|
171
444
|
for (let mediaType in bid.mediaTypes) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
445
|
+
switch (mediaType) {
|
|
446
|
+
case BANNER:
|
|
447
|
+
const banner = createBannerImp(bid);
|
|
448
|
+
if (banner) {
|
|
449
|
+
imp.banner = banner;
|
|
450
|
+
}
|
|
451
|
+
break;
|
|
452
|
+
case NATIVE:
|
|
453
|
+
const native = createNativeImp(bid);
|
|
454
|
+
if (native) {
|
|
455
|
+
imp.native = native;
|
|
456
|
+
}
|
|
457
|
+
break;
|
|
458
|
+
case VIDEO:
|
|
459
|
+
const video = createVideoImp(bid);
|
|
460
|
+
if (video) {
|
|
461
|
+
imp.video = video;
|
|
462
|
+
}
|
|
463
|
+
break;
|
|
184
464
|
}
|
|
185
465
|
}
|
|
186
466
|
|
|
@@ -213,6 +493,94 @@ function getPrimaryCatFromResponse(cat) {
|
|
|
213
493
|
}
|
|
214
494
|
}
|
|
215
495
|
|
|
496
|
+
/**
|
|
497
|
+
* Create the Prebid.js native object from response.
|
|
498
|
+
*
|
|
499
|
+
* @param {*} bid bid object from response
|
|
500
|
+
* @returns {object} Prebid.js native object used in response
|
|
501
|
+
*/
|
|
502
|
+
function nativeBidResponseHandler(bid) {
|
|
503
|
+
const nativeAdm = JSON.parse(bid.adm);
|
|
504
|
+
if (!nativeAdm || !nativeAdm.assets.length) {
|
|
505
|
+
logError(`${BIDDER_CODE}: invalid native response.`);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const native = {}
|
|
510
|
+
|
|
511
|
+
nativeAdm.assets.forEach(asset => {
|
|
512
|
+
if (asset.title) {
|
|
513
|
+
native.title = asset.title.text;
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (asset.img) {
|
|
518
|
+
switch (asset.img.type) {
|
|
519
|
+
case 1:
|
|
520
|
+
native.icon = {
|
|
521
|
+
url: asset.img.url,
|
|
522
|
+
width: asset.img.w,
|
|
523
|
+
height: asset.img.h
|
|
524
|
+
};
|
|
525
|
+
break;
|
|
526
|
+
default:
|
|
527
|
+
native.image = {
|
|
528
|
+
url: asset.img.url,
|
|
529
|
+
width: asset.img.w,
|
|
530
|
+
height: asset.img.h
|
|
531
|
+
};
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (asset.data) {
|
|
538
|
+
const internalNativeAsset = find(NATIVE_ASSETS_MAPPING, ref => ref.id === asset.id);
|
|
539
|
+
if (internalNativeAsset) {
|
|
540
|
+
native[internalNativeAsset.name] = asset.data.value;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
if (nativeAdm.link) {
|
|
546
|
+
if (nativeAdm.link.url) {
|
|
547
|
+
native.clickUrl = nativeAdm.link.url;
|
|
548
|
+
}
|
|
549
|
+
if (Array.isArray(nativeAdm.link.clicktrackers)) {
|
|
550
|
+
native.clickTrackers = nativeAdm.link.clicktrackers
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (Array.isArray(nativeAdm.eventtrackers)) {
|
|
555
|
+
native.impressionTrackers = [];
|
|
556
|
+
nativeAdm.eventtrackers.forEach(tracker => {
|
|
557
|
+
// Only Impression events are supported. Prebid does not support Viewability events yet.
|
|
558
|
+
if (tracker.event !== 1) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// methods:
|
|
563
|
+
// 1: image
|
|
564
|
+
// 2: js
|
|
565
|
+
// note: javascriptTrackers is a string. If there's more than one JS tracker in bid response, the last script will be used.
|
|
566
|
+
switch (tracker.method) {
|
|
567
|
+
case 1:
|
|
568
|
+
native.impressionTrackers.push(tracker.url);
|
|
569
|
+
break;
|
|
570
|
+
case 2:
|
|
571
|
+
native.javascriptTrackers = `<script src=\"${tracker.url}\"></script>`;
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (nativeAdm.privacy) {
|
|
578
|
+
native.privacyLink = nativeAdm.privacy;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return native;
|
|
582
|
+
}
|
|
583
|
+
|
|
216
584
|
export const spec = {
|
|
217
585
|
code: BIDDER_CODE,
|
|
218
586
|
|
|
@@ -355,6 +723,29 @@ export const spec = {
|
|
|
355
723
|
meta: cleanObj(meta)
|
|
356
724
|
};
|
|
357
725
|
|
|
726
|
+
if (mediaType === NATIVE) {
|
|
727
|
+
const native = nativeBidResponseHandler(bid);
|
|
728
|
+
if (native) {
|
|
729
|
+
newBid.native = native;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
if (mediaType === VIDEO) {
|
|
734
|
+
// Note:
|
|
735
|
+
// Mediakeys bid adapter expects a publisher has set his own video player
|
|
736
|
+
// in the `mediaTypes.video` configuration object.
|
|
737
|
+
|
|
738
|
+
// Mediakeys bidder does not provide inline XML in the bid response
|
|
739
|
+
// newBid.vastXml = bid.ext.vast_url;
|
|
740
|
+
|
|
741
|
+
// For instream video, disable server cache as vast is generated per bid request
|
|
742
|
+
newBid.videoCacheKey = 'no_cache';
|
|
743
|
+
|
|
744
|
+
// The vast URL is server independently and must be fetched before video rendering in the renderer
|
|
745
|
+
// appending '&no_cache' is safe and fast as the vast url always have parameters
|
|
746
|
+
newBid.vastUrl = bid.ext.vast_url + '&no_cache';
|
|
747
|
+
}
|
|
748
|
+
|
|
358
749
|
bidResponses.push(newBid);
|
|
359
750
|
});
|
|
360
751
|
});
|
|
@@ -29,3 +29,111 @@ var adUnits = [
|
|
|
29
29
|
}]
|
|
30
30
|
},
|
|
31
31
|
```
|
|
32
|
+
|
|
33
|
+
## Native only Ad Unit
|
|
34
|
+
|
|
35
|
+
The Mediakeys adapter accepts two optional params for native requests. Please see the [OpenRTB Native Ads Specification](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) for valid values.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
var adUnits = [
|
|
39
|
+
{
|
|
40
|
+
code: 'test',
|
|
41
|
+
mediaTypes: {
|
|
42
|
+
native: {
|
|
43
|
+
type: 'image',
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
bids: [{
|
|
47
|
+
bidder: 'mediakeys',
|
|
48
|
+
params: {
|
|
49
|
+
native: {
|
|
50
|
+
context: 1, // ORTB Native Context Type IDs. Default `1`.
|
|
51
|
+
plcmttype: 1, // ORTB Native Placement Type IDs. Default `1`.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}]
|
|
55
|
+
},
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Video only Ad Unit
|
|
59
|
+
|
|
60
|
+
The Mediakeys adapter accepts any valid openRTB 2.5 video property. Properties can be defined at the adUnit `mediaTypes.video` or `bid[].params` level.
|
|
61
|
+
|
|
62
|
+
### Outstream context
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
var adUnits = [
|
|
66
|
+
{
|
|
67
|
+
code: 'test',
|
|
68
|
+
mediaTypes: {
|
|
69
|
+
video: {
|
|
70
|
+
context: 'outstream',
|
|
71
|
+
playerSize: [300, 250],
|
|
72
|
+
// additional OpenRTB video params
|
|
73
|
+
// placement: 2,
|
|
74
|
+
// api: [1],
|
|
75
|
+
// …
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
renderer: {
|
|
79
|
+
url: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js',
|
|
80
|
+
render: function (bid) {
|
|
81
|
+
var bidReqConfig = pbjs.adUnits.find(bidReq => bidReq.bidId === bid.impid);
|
|
82
|
+
|
|
83
|
+
if (bidReqConfig && bidReqConfig.mediaTypes && bidReqConfig.mediaTypes.video && bidReqConfig.mediaTypes.video.context === 'outstream') {
|
|
84
|
+
var adResponse = fetch(bid.vastUrl).then(resp => resp.text()).then(text => ({
|
|
85
|
+
ad: {
|
|
86
|
+
video: {
|
|
87
|
+
content: text,
|
|
88
|
+
player_width: bid.width || bidReqConfig.mediaTypes.video.playerSize[0],
|
|
89
|
+
player_height: bid.height || bidReqConfig.mediaTypes.video.playerSize[1],
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}))
|
|
93
|
+
|
|
94
|
+
adResponse.then((ad) => {
|
|
95
|
+
bid.renderer.push(() => {
|
|
96
|
+
ANOutstreamVideo.renderAd({
|
|
97
|
+
targetId: bid.adUnitCode,
|
|
98
|
+
adResponse: ad
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
bids: [{
|
|
106
|
+
bidder: 'mediakeys',
|
|
107
|
+
params: {
|
|
108
|
+
video: {
|
|
109
|
+
// additional OpenRTB video params. Will be merged with params defined at mediaTypes level
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}]
|
|
113
|
+
},
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Instream context
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
var adUnits = [
|
|
120
|
+
{
|
|
121
|
+
code: 'test',
|
|
122
|
+
mediaTypes: {
|
|
123
|
+
video: {
|
|
124
|
+
context: 'instream',
|
|
125
|
+
playerSize: [300, 250],
|
|
126
|
+
// additional OpenRTB video params
|
|
127
|
+
// placement: 2,
|
|
128
|
+
// api: [1],
|
|
129
|
+
// …
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
bids: [{
|
|
133
|
+
bidder: 'mediakeys',
|
|
134
|
+
params: {
|
|
135
|
+
// additional OpenRTB video params. Will be merged with params defined at mediaTypes level
|
|
136
|
+
}
|
|
137
|
+
}]
|
|
138
|
+
},
|
|
139
|
+
```
|
|
@@ -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);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { _map } from '../src/utils.js';
|
|
2
|
+
import { config } from '../src/config.js';
|
|
3
|
+
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
4
|
+
|
|
5
|
+
const BIDDER_CODE = 'mytarget';
|
|
6
|
+
const BIDDER_URL = '//ad.mail.ru/hbid_prebid/';
|
|
7
|
+
const DEFAULT_CURRENCY = 'RUB';
|
|
8
|
+
const DEFAULT_TTL = 180;
|
|
9
|
+
|
|
10
|
+
function buildPlacement(bidRequest) {
|
|
11
|
+
let { bidId, params } = bidRequest;
|
|
12
|
+
let { placementId, position, response, bidfloor } = params;
|
|
13
|
+
let placement = {
|
|
14
|
+
placementId,
|
|
15
|
+
id: bidId,
|
|
16
|
+
position: position || 0,
|
|
17
|
+
response: response || 0
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (typeof bidfloor !== 'undefined') {
|
|
21
|
+
placement.bidfloor = bidfloor;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return placement;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getSiteName(referrer) {
|
|
28
|
+
let sitename = config.getConfig('mytarget.sitename');
|
|
29
|
+
|
|
30
|
+
if (!sitename) {
|
|
31
|
+
const parsed = document.createElement('a');
|
|
32
|
+
parsed.href = decodeURIComponent(referrer);
|
|
33
|
+
sitename = parsed.hostname;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return sitename;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function generateRandomId() {
|
|
40
|
+
return Math.random().toString(16).substring(2);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const spec = {
|
|
44
|
+
code: BIDDER_CODE,
|
|
45
|
+
|
|
46
|
+
isBidRequestValid: function(bid) {
|
|
47
|
+
return !!bid.params.placementId;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
buildRequests: function(validBidRequests, bidderRequest) {
|
|
51
|
+
let referrer = '';
|
|
52
|
+
|
|
53
|
+
if (bidderRequest && bidderRequest.refererInfo) {
|
|
54
|
+
referrer = bidderRequest.refererInfo.referer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const payload = {
|
|
58
|
+
places: _map(validBidRequests, buildPlacement),
|
|
59
|
+
site: {
|
|
60
|
+
sitename: getSiteName(referrer),
|
|
61
|
+
page: referrer
|
|
62
|
+
},
|
|
63
|
+
settings: {
|
|
64
|
+
currency: DEFAULT_CURRENCY,
|
|
65
|
+
windowSize: {
|
|
66
|
+
width: window.screen.width,
|
|
67
|
+
height: window.screen.height
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
url: BIDDER_URL,
|
|
75
|
+
data: payload,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
interpretResponse: function(serverResponse, bidRequest) {
|
|
80
|
+
let { body } = serverResponse;
|
|
81
|
+
|
|
82
|
+
if (body.bids) {
|
|
83
|
+
return _map(body.bids, (bid) => {
|
|
84
|
+
let bidResponse = {
|
|
85
|
+
requestId: bid.id,
|
|
86
|
+
cpm: bid.price,
|
|
87
|
+
width: bid.size.width,
|
|
88
|
+
height: bid.size.height,
|
|
89
|
+
ttl: bid.ttl || DEFAULT_TTL,
|
|
90
|
+
currency: bid.currency || DEFAULT_CURRENCY,
|
|
91
|
+
creativeId: bid.creativeId || generateRandomId(),
|
|
92
|
+
netRevenue: true,
|
|
93
|
+
meta: {
|
|
94
|
+
advertiserDomains: bid.adomain && bid.adomain.length > 0 ? bid.adomain : [],
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (bid.adm) {
|
|
99
|
+
bidResponse.ad = bid.adm;
|
|
100
|
+
} else {
|
|
101
|
+
bidResponse.adUrl = bid.displayUrl;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return bidResponse;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
registerBidder(spec);
|