prebid.js 7.16.0 → 7.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +0 -18
- package/dist/1plusXRtdProvider.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -0
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gridNMBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediagoBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +108 -107
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/karma.conf.maker.js +2 -4
- package/modules/1plusXRtdProvider.js +27 -7
- package/modules/adagioBidAdapter.js +16 -2
- package/modules/adagioBidAdapter.md +11 -1
- package/modules/appnexusBidAdapter.js +24 -22
- package/modules/carodaBidAdapter.js +217 -0
- package/modules/carodaBidAdapter.md +43 -0
- package/modules/improvedigitalBidAdapter.js +3 -1
- package/modules/ixBidAdapter.js +17 -12
- package/modules/mediagoBidAdapter.js +15 -11
- package/modules/mediasquareBidAdapter.js +1 -1
- package/modules/rubiconAnalyticsAdapter.js +2 -2
- package/modules/rubiconBidAdapter.js +16 -6
- package/package.json +1 -1
- package/test/spec/modules/1plusXRtdProvider_spec.js +77 -1
- package/test/spec/modules/adagioBidAdapter_spec.js +23 -2
- package/test/spec/modules/appnexusBidAdapter_spec.js +76 -0
- package/test/spec/modules/carodaBidAdapter_spec.js +494 -0
- package/test/spec/modules/improvedigitalBidAdapter_spec.js +10 -0
- package/test/spec/modules/ixBidAdapter_spec.js +32 -16
- package/test/spec/modules/mediasquareBidAdapter_spec.js +2 -0
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +7 -7
- package/test/spec/modules/rubiconBidAdapter_spec.js +28 -35
|
@@ -57,16 +57,39 @@ export const extractConfig = (moduleConfig, reqBidsConfigObj) => {
|
|
|
57
57
|
return { customerId, timeout, bidders };
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export const extractConsent = ({ gdpr }) => {
|
|
61
|
+
if (!gdpr) {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
const { gdprApplies, consentString } = gdpr
|
|
65
|
+
if (!(gdprApplies == '0' || gdprApplies == '1')) {
|
|
66
|
+
throw 'TCF Consent: gdprApplies has wrong format'
|
|
67
|
+
}
|
|
68
|
+
if (!(typeof consentString === 'string')) {
|
|
69
|
+
throw 'TCF Consent: consentString is not string'
|
|
70
|
+
}
|
|
71
|
+
const result = {
|
|
72
|
+
'gdpr_applies': gdprApplies,
|
|
73
|
+
'consent_string': consentString
|
|
74
|
+
}
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
60
77
|
/**
|
|
61
78
|
* Gets the URL of Profile Api from which targeting data will be fetched
|
|
62
79
|
* @param {Object} config
|
|
63
80
|
* @param {string} config.customerId
|
|
64
81
|
* @returns {string} URL to access 1plusX Profile API
|
|
65
82
|
*/
|
|
66
|
-
const getPapiUrl = (
|
|
83
|
+
export const getPapiUrl = (customerId, consent) => {
|
|
67
84
|
// https://[yourClientId].profiles.tagger.opecloud.com/[VERSION]/targeting?url=
|
|
68
85
|
const currentUrl = encodeURIComponent(window.location.href);
|
|
69
|
-
|
|
86
|
+
var papiUrl = `https://${customerId}.profiles.tagger.opecloud.com/${PAPI_VERSION}/targeting?url=${currentUrl}`;
|
|
87
|
+
if (consent) {
|
|
88
|
+
Object.entries(consent).forEach(([key, value]) => {
|
|
89
|
+
papiUrl += `&${key}=${value}`
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
70
93
|
return papiUrl;
|
|
71
94
|
}
|
|
72
95
|
|
|
@@ -216,14 +239,14 @@ const init = (config, userConsent) => {
|
|
|
216
239
|
* @param {Object} reqBidsConfigObj Bid request configuration object
|
|
217
240
|
* @param {Function} callback Called on completion
|
|
218
241
|
* @param {Object} moduleConfig Configuration for 1plusX RTD module
|
|
219
|
-
* @param {
|
|
242
|
+
* @param {Object} userConsent
|
|
220
243
|
*/
|
|
221
244
|
const getBidRequestData = (reqBidsConfigObj, callback, moduleConfig, userConsent) => {
|
|
222
245
|
try {
|
|
223
246
|
// Get the required config
|
|
224
247
|
const { customerId, bidders } = extractConfig(moduleConfig, reqBidsConfigObj);
|
|
225
248
|
// Get PAPI URL
|
|
226
|
-
const papiUrl = getPapiUrl(
|
|
249
|
+
const papiUrl = getPapiUrl(customerId, extractConsent(userConsent) || {})
|
|
227
250
|
// Call PAPI
|
|
228
251
|
getTargetingDataFromPapi(papiUrl)
|
|
229
252
|
.then((papiResponse) => {
|
|
@@ -231,9 +254,6 @@ const getBidRequestData = (reqBidsConfigObj, callback, moduleConfig, userConsent
|
|
|
231
254
|
setTargetingDataToConfig(papiResponse, { bidders });
|
|
232
255
|
callback();
|
|
233
256
|
})
|
|
234
|
-
.catch((error) => {
|
|
235
|
-
throw error;
|
|
236
|
-
})
|
|
237
257
|
} catch (error) {
|
|
238
258
|
logError(LOG_PREFIX, error);
|
|
239
259
|
callback();
|
|
@@ -532,7 +532,12 @@ function _parseNativeBidResponse(bid) {
|
|
|
532
532
|
native.impressionTrackers.push(tracker.url);
|
|
533
533
|
break;
|
|
534
534
|
case 2:
|
|
535
|
-
|
|
535
|
+
const script = `<script async src=\"${tracker.url}\"></script>`;
|
|
536
|
+
if (!native.javascriptTrackers) {
|
|
537
|
+
native.javascriptTrackers = script;
|
|
538
|
+
} else {
|
|
539
|
+
native.javascriptTrackers += `\n${script}`;
|
|
540
|
+
}
|
|
536
541
|
break;
|
|
537
542
|
}
|
|
538
543
|
});
|
|
@@ -623,7 +628,16 @@ export function setExtraParam(bid, paramName) {
|
|
|
623
628
|
|
|
624
629
|
const detected = adgGlobalConf[paramName] || deepAccess(ortb2Conf, `site.ext.data.${paramName}`, null);
|
|
625
630
|
if (detected) {
|
|
626
|
-
|
|
631
|
+
// First Party Data can be an array.
|
|
632
|
+
// As we consider that params detected from FPD are fallbacks, we just keep the 1st value.
|
|
633
|
+
if (Array.isArray(detected)) {
|
|
634
|
+
if (detected.length) {
|
|
635
|
+
bid.params[paramName] = detected[0].toString();
|
|
636
|
+
}
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
bid.params[paramName] = detected.toString();
|
|
627
641
|
}
|
|
628
642
|
}
|
|
629
643
|
|
|
@@ -10,7 +10,7 @@ Connects to Adagio demand source to fetch bids.
|
|
|
10
10
|
|
|
11
11
|
## Configuration
|
|
12
12
|
|
|
13
|
-
Adagio require several params. These params must be set at Prebid.js
|
|
13
|
+
Adagio require several params. These params must be set at Prebid.js BidderConfig config level or at adUnit level.
|
|
14
14
|
|
|
15
15
|
Below, the list of Adagio params and where they can be set.
|
|
16
16
|
|
|
@@ -58,6 +58,16 @@ pbjs.setConfig({
|
|
|
58
58
|
});
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
#### Note on FPD support
|
|
62
|
+
|
|
63
|
+
Adagio will use FPD data as fallback for the params below:
|
|
64
|
+
- pagetype
|
|
65
|
+
- environment
|
|
66
|
+
- category
|
|
67
|
+
- subcategory
|
|
68
|
+
|
|
69
|
+
If the FPD value is an array, the 1st value of this array will be used.
|
|
70
|
+
|
|
61
71
|
### adUnit configuration
|
|
62
72
|
|
|
63
73
|
```javascript
|
|
@@ -250,10 +250,10 @@ export const spec = {
|
|
|
250
250
|
// need to convert the string values into array of strings, to properly merge values with other existing keys later
|
|
251
251
|
Object.keys(anAuctionKeywords).forEach(k => { if (isStr(anAuctionKeywords[k]) || isNumber(anAuctionKeywords[k])) anAuctionKeywords[k] = [anAuctionKeywords[k]] });
|
|
252
252
|
// combine all sources of keywords (converted from string comma list to object format) into one object (that combines the values for shared keys)
|
|
253
|
-
let
|
|
253
|
+
let mergedAuctionKeywords = mergeDeep({}, anAuctionKeywords, ...ortb2KeywordsObjList);
|
|
254
254
|
|
|
255
255
|
// convert to final format used by adserver
|
|
256
|
-
let auctionKeywords = transformBidderParamKeywords(
|
|
256
|
+
let auctionKeywords = transformBidderParamKeywords(mergedAuctionKeywords);
|
|
257
257
|
if (auctionKeywords.length > 0) {
|
|
258
258
|
auctionKeywords.forEach(deleteValues);
|
|
259
259
|
payload.keywords = auctionKeywords;
|
|
@@ -1202,28 +1202,30 @@ function convertKeywordsToString(keywords) {
|
|
|
1202
1202
|
function convertStringToKeywordsObj(keyStr) {
|
|
1203
1203
|
let result = {};
|
|
1204
1204
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
result
|
|
1205
|
+
if (isStr(keyStr) && keyStr !== '') {
|
|
1206
|
+
// will split based on commas and will eat white space before/after the comma
|
|
1207
|
+
let keywordList = keyStr.split(/\s*(?:,)\s*/);
|
|
1208
|
+
keywordList.forEach(kw => {
|
|
1209
|
+
// if = exists, then split
|
|
1210
|
+
if (kw.indexOf('=') !== -1) {
|
|
1211
|
+
let kwPair = kw.split('=');
|
|
1212
|
+
let key = kwPair[0];
|
|
1213
|
+
let val = kwPair[1];
|
|
1214
|
+
|
|
1215
|
+
// then check for existing key in result > if so add value to the array > if not, add new key and create value array
|
|
1216
|
+
if (result.hasOwnProperty(key)) {
|
|
1217
|
+
result[key].push(val);
|
|
1218
|
+
} else {
|
|
1219
|
+
result[key] = [val];
|
|
1220
|
+
}
|
|
1217
1221
|
} else {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
if (!result.hasOwnProperty(kw)) {
|
|
1223
|
-
result[kw] = [''];
|
|
1222
|
+
// make a key with '' value; if key already exists > don't add
|
|
1223
|
+
if (!result.hasOwnProperty(kw)) {
|
|
1224
|
+
result[kw] = [''];
|
|
1225
|
+
}
|
|
1224
1226
|
}
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1227
1229
|
|
|
1228
1230
|
return result;
|
|
1229
1231
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// jshint esversion: 6, es3: false, node: true
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
5
|
+
import { BANNER, VIDEO } from '../src/mediaTypes.js';
|
|
6
|
+
import {
|
|
7
|
+
deepAccess,
|
|
8
|
+
deepSetValue,
|
|
9
|
+
logError,
|
|
10
|
+
mergeDeep,
|
|
11
|
+
parseSizesInput
|
|
12
|
+
} from '../src/utils.js';
|
|
13
|
+
import { config } from '../src/config.js';
|
|
14
|
+
|
|
15
|
+
const { getConfig } = config;
|
|
16
|
+
|
|
17
|
+
const BIDDER_CODE = 'caroda';
|
|
18
|
+
const GVLID = 954;
|
|
19
|
+
|
|
20
|
+
// some state info is required to synchronize with Caroda ad server
|
|
21
|
+
const topUsableWindow = getTopUsableWindow();
|
|
22
|
+
|
|
23
|
+
export const spec = {
|
|
24
|
+
code: BIDDER_CODE,
|
|
25
|
+
gvlid: GVLID,
|
|
26
|
+
supportedMediaTypes: [BANNER, VIDEO],
|
|
27
|
+
isBidRequestValid: bid => {
|
|
28
|
+
const params = bid.params || {};
|
|
29
|
+
const { ctok, placementId, priceType } = params;
|
|
30
|
+
return typeof ctok === 'string' && (
|
|
31
|
+
typeof placementId === 'string' ||
|
|
32
|
+
typeof placementId === 'undefined'
|
|
33
|
+
) && (
|
|
34
|
+
typeof priceType === 'undefined' ||
|
|
35
|
+
priceType === 'gross' ||
|
|
36
|
+
priceType === 'net'
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
buildRequests: (validBidRequests, bidderRequest) => {
|
|
40
|
+
topUsableWindow.carodaPageViewId = topUsableWindow.carodaPageViewId || Math.floor(Math.random() * 1e9);
|
|
41
|
+
const pageViewId = topUsableWindow.carodaPageViewId;
|
|
42
|
+
const ortbCommon = getORTBCommon(bidderRequest);
|
|
43
|
+
const priceType =
|
|
44
|
+
getFirstWithKey(validBidRequests, 'params.priceType') ||
|
|
45
|
+
'net';
|
|
46
|
+
const test = getFirstWithKey(validBidRequests, 'params.test');
|
|
47
|
+
const currency = getConfig('currency.adServerCurrency');
|
|
48
|
+
const eids = getFirstWithKey(validBidRequests, 'userIdAsEids');
|
|
49
|
+
const schain = getFirstWithKey(validBidRequests, 'schain');
|
|
50
|
+
const request = {
|
|
51
|
+
auctionId: bidderRequest.auctionId,
|
|
52
|
+
currency,
|
|
53
|
+
hb_version: '$prebid.version$',
|
|
54
|
+
...ortbCommon,
|
|
55
|
+
price_type: priceType
|
|
56
|
+
};
|
|
57
|
+
if (test) {
|
|
58
|
+
request.test = 1;
|
|
59
|
+
}
|
|
60
|
+
if (schain) {
|
|
61
|
+
request.schain = schain;
|
|
62
|
+
}
|
|
63
|
+
if (config.getConfig('coppa')) {
|
|
64
|
+
deepSetValue(request, 'privacy.coppa', 1);
|
|
65
|
+
}
|
|
66
|
+
if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies') !== undefined) {
|
|
67
|
+
deepSetValue(
|
|
68
|
+
request,
|
|
69
|
+
'privacy.gdpr_consent',
|
|
70
|
+
bidderRequest.gdprConsent.consentString
|
|
71
|
+
);
|
|
72
|
+
deepSetValue(
|
|
73
|
+
request,
|
|
74
|
+
'privacy.gdpr',
|
|
75
|
+
bidderRequest.gdprConsent.gdprApplies & 1
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (bidderRequest.uspConsent) {
|
|
79
|
+
deepSetValue(request, 'privacy.us_privacy', bidderRequest.uspConsent);
|
|
80
|
+
}
|
|
81
|
+
if (eids) {
|
|
82
|
+
deepSetValue(request, 'user.eids', eids);
|
|
83
|
+
}
|
|
84
|
+
return getImps(validBidRequests, request).map(imp => ({
|
|
85
|
+
method: 'POST',
|
|
86
|
+
url: 'https://prebid.caroda.io/api/hb?entry_id=' + pageViewId,
|
|
87
|
+
data: JSON.stringify(imp)
|
|
88
|
+
}));
|
|
89
|
+
},
|
|
90
|
+
interpretResponse: (serverResponse) => {
|
|
91
|
+
if (!serverResponse.body) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { ok, error } = serverResponse.body
|
|
95
|
+
if (error) {
|
|
96
|
+
logError(BIDDER_CODE, ': server caught', error.message);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
return JSON.parse(ok.value)
|
|
101
|
+
.map((bid) => {
|
|
102
|
+
const ret = {
|
|
103
|
+
requestId: bid.bid_id,
|
|
104
|
+
cpm: bid.cpm,
|
|
105
|
+
creativeId: bid.creative_id,
|
|
106
|
+
ttl: 300,
|
|
107
|
+
netRevenue: true,
|
|
108
|
+
currency: bid.currency,
|
|
109
|
+
width: bid.w,
|
|
110
|
+
height: bid.h,
|
|
111
|
+
meta: {
|
|
112
|
+
advertiserDomains: bid.adomain || []
|
|
113
|
+
},
|
|
114
|
+
ad: bid.ad,
|
|
115
|
+
placementId: bid.placement_id
|
|
116
|
+
}
|
|
117
|
+
if (bid.adserver_targeting) {
|
|
118
|
+
ret.adserverTargeting = bid.adserver_targeting
|
|
119
|
+
}
|
|
120
|
+
return ret
|
|
121
|
+
})
|
|
122
|
+
.filter(Boolean);
|
|
123
|
+
} catch (e) {
|
|
124
|
+
logError(BIDDER_CODE, ': caught', e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
registerBidder(spec)
|
|
130
|
+
|
|
131
|
+
function getFirstWithKey (collection, key) {
|
|
132
|
+
for (let i = 0, result; i < collection.length; i++) {
|
|
133
|
+
result = deepAccess(collection[i], key);
|
|
134
|
+
if (result) {
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function getTopUsableWindow () {
|
|
141
|
+
let res = window;
|
|
142
|
+
try {
|
|
143
|
+
while (window.top !== res && res.parent.location.href.length) {
|
|
144
|
+
res = res.parent;
|
|
145
|
+
}
|
|
146
|
+
} catch (e) {}
|
|
147
|
+
return res;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getORTBCommon (bidderRequest) {
|
|
151
|
+
let app, site;
|
|
152
|
+
const commonFpd = bidderRequest.ortb2 || {};
|
|
153
|
+
let { user } = commonFpd;
|
|
154
|
+
if (typeof getConfig('app') === 'object') {
|
|
155
|
+
app = getConfig('app') || {}
|
|
156
|
+
if (commonFpd.app) {
|
|
157
|
+
mergeDeep(app, commonFpd.app);
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
site = getConfig('site') || {};
|
|
161
|
+
if (commonFpd.site) {
|
|
162
|
+
mergeDeep(site, commonFpd.site);
|
|
163
|
+
}
|
|
164
|
+
if (!site.page) {
|
|
165
|
+
site.page = bidderRequest.refererInfo.page;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const device = getConfig('device') || {};
|
|
169
|
+
device.w = device.w || window.innerWidth;
|
|
170
|
+
device.h = device.h || window.innerHeight;
|
|
171
|
+
device.ua = device.ua || navigator.userAgent;
|
|
172
|
+
return {
|
|
173
|
+
app,
|
|
174
|
+
site,
|
|
175
|
+
user,
|
|
176
|
+
device
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function getImps (validBidRequests, common) {
|
|
181
|
+
return validBidRequests.map((bid) => {
|
|
182
|
+
const floorInfo = bid.getFloor
|
|
183
|
+
? bid.getFloor({ currency: common.currency || 'EUR' })
|
|
184
|
+
: {};
|
|
185
|
+
const bidfloor = floorInfo.floor;
|
|
186
|
+
const bidfloorcur = floorInfo.currency;
|
|
187
|
+
const { ctok, placementId } = bid.params;
|
|
188
|
+
const imp = {
|
|
189
|
+
bid_id: bid.bidId,
|
|
190
|
+
ctok,
|
|
191
|
+
bidfloor,
|
|
192
|
+
bidfloorcur,
|
|
193
|
+
...common
|
|
194
|
+
};
|
|
195
|
+
const bannerParams = deepAccess(bid, 'mediaTypes.banner');
|
|
196
|
+
if (bannerParams && bannerParams.sizes) {
|
|
197
|
+
const sizes = parseSizesInput(bannerParams.sizes);
|
|
198
|
+
const format = sizes.map(size => {
|
|
199
|
+
const [width, height] = size.split('x');
|
|
200
|
+
const w = parseInt(width, 10);
|
|
201
|
+
const h = parseInt(height, 10);
|
|
202
|
+
return { w, h };
|
|
203
|
+
});
|
|
204
|
+
imp.banner = {
|
|
205
|
+
format
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (placementId) {
|
|
209
|
+
imp.placement_id = placementId;
|
|
210
|
+
}
|
|
211
|
+
const videoParams = deepAccess(bid, 'mediaTypes.video');
|
|
212
|
+
if (videoParams) {
|
|
213
|
+
imp.video = videoParams;
|
|
214
|
+
}
|
|
215
|
+
return imp;
|
|
216
|
+
})
|
|
217
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Overview
|
|
2
|
+
|
|
3
|
+
Module Name: Caroda Adapter
|
|
4
|
+
Module Type: Bidder Adapter
|
|
5
|
+
Maintainer: dev@caroda.io
|
|
6
|
+
|
|
7
|
+
# Description
|
|
8
|
+
|
|
9
|
+
Module that connects to Caroda demand sources to fetch bids.
|
|
10
|
+
Banner and video formats are supported.
|
|
11
|
+
Use `caroda` as bidder.
|
|
12
|
+
|
|
13
|
+
# Test Parameters
|
|
14
|
+
```
|
|
15
|
+
var adUnits = [{
|
|
16
|
+
code: '/19968336/prebid_banner_example_1',
|
|
17
|
+
mediaTypes: {
|
|
18
|
+
banner: {
|
|
19
|
+
sizes: [[ 300, 250 ]]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
bids: [{
|
|
23
|
+
bidder: 'caroda',
|
|
24
|
+
params: {
|
|
25
|
+
ctok: '230ce9490c5434354'
|
|
26
|
+
}
|
|
27
|
+
}]
|
|
28
|
+
}, {
|
|
29
|
+
code: '/19968336/prebid_video_example_1',
|
|
30
|
+
mediaTypes: {
|
|
31
|
+
video: {
|
|
32
|
+
context: 'outstream',
|
|
33
|
+
mimes: ['video/mp4']
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
bids: [{
|
|
37
|
+
bidder: 'caroda',
|
|
38
|
+
params: {
|
|
39
|
+
ctok: '230ce9490c5434354'
|
|
40
|
+
}
|
|
41
|
+
}]
|
|
42
|
+
}];
|
|
43
|
+
```
|
|
@@ -25,6 +25,7 @@ const BIDDER_CODE = 'improvedigital';
|
|
|
25
25
|
const CREATIVE_TTL = 300;
|
|
26
26
|
|
|
27
27
|
const AD_SERVER_URL = 'https://ad.360yield.com/pb';
|
|
28
|
+
const BASIC_ADS_URL = 'https://ad.360yield-basic.com/pb';
|
|
28
29
|
const EXTEND_URL = 'https://pbs.360yield.com/openrtb2/auction';
|
|
29
30
|
const IFRAME_SYNC_URL = 'https://hb.360yield.com/prebid-universal-creative/load-cookie.html';
|
|
30
31
|
|
|
@@ -282,9 +283,10 @@ const ID_REQUEST = {
|
|
|
282
283
|
if (transactionId) {
|
|
283
284
|
deepSetValue(request, 'source.tid', transactionId);
|
|
284
285
|
}
|
|
286
|
+
const adServerUrl = hasPurpose1Consent(bidderRequest?.gdprConsent) ? AD_SERVER_URL : BASIC_ADS_URL;
|
|
285
287
|
return {
|
|
286
288
|
method: 'POST',
|
|
287
|
-
url: extendMode ? EXTEND_URL :
|
|
289
|
+
url: extendMode ? EXTEND_URL : adServerUrl,
|
|
288
290
|
data: JSON.stringify(request),
|
|
289
291
|
bidderRequest
|
|
290
292
|
}
|
package/modules/ixBidAdapter.js
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
logError,
|
|
14
14
|
logWarn,
|
|
15
15
|
mergeDeep,
|
|
16
|
-
parseGPTSingleSizeArray,
|
|
17
16
|
parseQueryStringParameters
|
|
18
17
|
} from '../src/utils.js';
|
|
19
18
|
import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js';
|
|
@@ -127,10 +126,6 @@ function bidToBannerImp(bid) {
|
|
|
127
126
|
if (impSize) {
|
|
128
127
|
imp.banner.w = impSize[0];
|
|
129
128
|
imp.banner.h = impSize[1];
|
|
130
|
-
// populate sid with size if not id
|
|
131
|
-
if (!deepAccess(imp, 'ext.sid')) {
|
|
132
|
-
imp.ext.sid = parseGPTSingleSizeArray(impSize);
|
|
133
|
-
}
|
|
134
129
|
}
|
|
135
130
|
|
|
136
131
|
imp.banner.topframe = inIframe() ? 0 : 1;
|
|
@@ -197,9 +192,6 @@ function bidToVideoImp(bid) {
|
|
|
197
192
|
if (impSize) {
|
|
198
193
|
imp.video.w = impSize[0];
|
|
199
194
|
imp.video.h = impSize[1];
|
|
200
|
-
if (!(deepAccess(imp, 'ext.sid'))) {
|
|
201
|
-
imp.ext.sid = parseGPTSingleSizeArray(impSize);
|
|
202
|
-
}
|
|
203
195
|
} else {
|
|
204
196
|
logWarn('IX Bid Adapter: Video size is missing in [mediaTypes.video]');
|
|
205
197
|
return {};
|
|
@@ -253,8 +245,8 @@ function bidToImp(bid) {
|
|
|
253
245
|
imp.ext = {};
|
|
254
246
|
imp.ext.siteID = bid.params.siteId.toString();
|
|
255
247
|
|
|
256
|
-
|
|
257
|
-
|
|
248
|
+
// populate imp level sid
|
|
249
|
+
if (bid.params.hasOwnProperty('id') && (typeof bid.params.id === 'string' || typeof bid.params.id === 'number')) {
|
|
258
250
|
imp.ext.sid = String(bid.params.id);
|
|
259
251
|
}
|
|
260
252
|
|
|
@@ -758,6 +750,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
|
|
|
758
750
|
const gpid = impressions[transactionIds[adUnitIndex]].gpid;
|
|
759
751
|
const dfpAdUnitCode = impressions[transactionIds[adUnitIndex]].dfp_ad_unit_code;
|
|
760
752
|
const tid = impressions[transactionIds[adUnitIndex]].tid;
|
|
753
|
+
const sid = impressions[transactionIds[adUnitIndex]].sid
|
|
761
754
|
|
|
762
755
|
if (impressionObjects.length && BANNER in impressionObjects[0]) {
|
|
763
756
|
const { id, banner: { topframe } } = impressionObjects[0];
|
|
@@ -769,16 +762,24 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
|
|
|
769
762
|
},
|
|
770
763
|
};
|
|
771
764
|
|
|
765
|
+
// We add sid in imp.ext.sid therefore, remove from banner.format[].ext
|
|
766
|
+
for (let bannerFormat of _bannerImpression.banner.format) {
|
|
767
|
+
if (bannerFormat.ext != null && bannerFormat.ext.sid != null) {
|
|
768
|
+
delete bannerFormat.ext.sid;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
772
|
const position = impressions[transactionIds[adUnitIndex]].pos;
|
|
773
773
|
if (isInteger(position)) {
|
|
774
774
|
_bannerImpression.banner.pos = position;
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
-
if (dfpAdUnitCode || gpid || tid) {
|
|
777
|
+
if (dfpAdUnitCode || gpid || tid || sid) {
|
|
778
778
|
_bannerImpression.ext = {};
|
|
779
779
|
_bannerImpression.ext.dfp_ad_unit_code = dfpAdUnitCode;
|
|
780
780
|
_bannerImpression.ext.gpid = gpid;
|
|
781
781
|
_bannerImpression.ext.tid = tid;
|
|
782
|
+
_bannerImpression.ext.sid = sid;
|
|
782
783
|
}
|
|
783
784
|
|
|
784
785
|
if ('bidfloor' in impressionObjects[0]) {
|
|
@@ -1040,6 +1041,11 @@ function createBannerImps(validBidRequest, missingBannerSizes, bannerImps) {
|
|
|
1040
1041
|
bannerImps[validBidRequest.transactionId].tagId = deepAccess(validBidRequest, 'params.tagId');
|
|
1041
1042
|
bannerImps[validBidRequest.transactionId].pos = deepAccess(validBidRequest, 'mediaTypes.banner.pos');
|
|
1042
1043
|
|
|
1044
|
+
const sid = deepAccess(validBidRequest, 'params.id');
|
|
1045
|
+
if (sid && (typeof sid === 'string' || typeof sid === 'number')) {
|
|
1046
|
+
bannerImps[validBidRequest.transactionId].sid = String(sid);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1043
1049
|
const adUnitCode = validBidRequest.adUnitCode;
|
|
1044
1050
|
const divId = document.getElementById(adUnitCode) ? adUnitCode : getGptSlotInfoForAdUnitCode(adUnitCode).divId;
|
|
1045
1051
|
bannerImps[validBidRequest.transactionId].adUnitCode = adUnitCode;
|
|
@@ -1094,7 +1100,6 @@ function updateMissingSizes(validBidRequest, missingBannerSizes, imp) {
|
|
|
1094
1100
|
*/
|
|
1095
1101
|
function createMissingBannerImp(bid, imp, newSize) {
|
|
1096
1102
|
const newImp = deepClone(imp);
|
|
1097
|
-
newImp.ext.sid = parseGPTSingleSizeArray(newSize);
|
|
1098
1103
|
newImp.banner.w = newSize[0];
|
|
1099
1104
|
newImp.banner.h = newSize[1];
|
|
1100
1105
|
|
|
@@ -293,14 +293,19 @@ function getItems(validBidRequests, bidderRequest) {
|
|
|
293
293
|
*/
|
|
294
294
|
function getParam(validBidRequests, bidderRequest) {
|
|
295
295
|
const pubcid = utils.deepAccess(validBidRequests[0], 'crumbs.pubcid');
|
|
296
|
-
|
|
296
|
+
const sharedid =
|
|
297
|
+
utils.deepAccess(validBidRequests[0], 'userId.sharedid.id') ||
|
|
298
|
+
utils.deepAccess(validBidRequests[0], 'userId.pubcid');
|
|
297
299
|
let isMobile = isMobileAndTablet() ? 1 : 0;
|
|
298
300
|
let isTest = 0;
|
|
299
301
|
let auctionId = getProperty(bidderRequest, 'auctionId');
|
|
300
302
|
let items = getItems(validBidRequests, bidderRequest);
|
|
301
303
|
|
|
302
|
-
const domain =
|
|
303
|
-
|
|
304
|
+
const domain =
|
|
305
|
+
utils.deepAccess(bidderRequest, 'refererInfo.domain') || document.domain;
|
|
306
|
+
const location = utils.deepAccess(bidderRequest, 'refererInfo.location');
|
|
307
|
+
const page = utils.deepAccess(bidderRequest, 'refererInfo.page');
|
|
308
|
+
const referer = utils.deepAccess(bidderRequest, 'refererInfo.ref');
|
|
304
309
|
|
|
305
310
|
const timeout = bidderRequest.timeout || 2000;
|
|
306
311
|
|
|
@@ -323,14 +328,13 @@ function getParam(validBidRequests, bidderRequest) {
|
|
|
323
328
|
},
|
|
324
329
|
ext: {},
|
|
325
330
|
user: {
|
|
326
|
-
|
|
327
|
-
id: pubcid,
|
|
331
|
+
id: sharedid || pubcid || getUserID(),
|
|
328
332
|
},
|
|
329
333
|
site: {
|
|
330
334
|
name: domain,
|
|
331
335
|
domain: domain,
|
|
332
|
-
page: location,
|
|
333
|
-
ref:
|
|
336
|
+
page: page || location,
|
|
337
|
+
ref: referer,
|
|
334
338
|
mobile: isMobile,
|
|
335
339
|
cat: [], // todo
|
|
336
340
|
publisher: {
|
|
@@ -454,9 +458,9 @@ export const spec = {
|
|
|
454
458
|
* Register bidder specific code, which will execute when the adserver targeting has been set for a bid from this bidder
|
|
455
459
|
* @param {Bid} The bid of which the targeting has been set
|
|
456
460
|
*/
|
|
457
|
-
// onSetTargeting: function (bid) {
|
|
458
|
-
// // console.log('onSetTargeting', bid);
|
|
459
|
-
// // Bidder specific code
|
|
460
|
-
// },
|
|
461
|
+
// onSetTargeting: function (bid) {
|
|
462
|
+
// // console.log('onSetTargeting', bid);
|
|
463
|
+
// // Bidder specific code
|
|
464
|
+
// },
|
|
461
465
|
};
|
|
462
466
|
registerBidder(spec);
|
|
@@ -164,7 +164,7 @@ export const spec = {
|
|
|
164
164
|
// fires a pixel to confirm a winning bid
|
|
165
165
|
let params = {'pbjs': '$prebid.version$'};
|
|
166
166
|
let endpoint = document.location.search.match(/msq_test=true/) ? BIDDER_URL_TEST : BIDDER_URL_PROD;
|
|
167
|
-
let paramsToSearchFor = ['cpm', 'size', 'mediaType', 'currency', 'creativeId', 'adUnitCode', 'timeToRespond', 'requestId', 'auctionId']
|
|
167
|
+
let paramsToSearchFor = ['cpm', 'size', 'mediaType', 'currency', 'creativeId', 'adUnitCode', 'timeToRespond', 'requestId', 'auctionId', 'originalCpm', 'originalCurrency'];
|
|
168
168
|
if (bid.hasOwnProperty('mediasquare')) {
|
|
169
169
|
if (bid['mediasquare'].hasOwnProperty('bidder')) { params['bidder'] = bid['mediasquare']['bidder']; }
|
|
170
170
|
if (bid['mediasquare'].hasOwnProperty('code')) { params['code'] = bid['mediasquare']['code']; }
|
|
@@ -124,9 +124,9 @@ function formatSource(src) {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
function getBillingPayload(event) {
|
|
127
|
-
// for now we are mapping all events to type "general", later we will expand support for specific types
|
|
128
127
|
let billingEvent = deepClone(event);
|
|
129
|
-
|
|
128
|
+
// Pass along type if is string and not empty else general
|
|
129
|
+
billingEvent.type = (typeof event.type === 'string' && event.type) || 'general';
|
|
130
130
|
billingEvent.accountId = accountId;
|
|
131
131
|
// mark as sent
|
|
132
132
|
deepSetValue(cache.billing, `${event.vendor}.${event.billingId}`, true);
|