prebid.js 9.6.0 → 9.8.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/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- package/.github/codeql/codeql-config.yml +3 -0
- package/.github/codeql/queries/deviceMemory.ql +14 -0
- package/.github/codeql/queries/hardwareConcurrency.ql +14 -0
- package/.github/codeql/queries/prebid.qll +36 -0
- package/.github/codeql/queries/qlpack.yml +8 -0
- package/.github/release-drafter.yml +4 -0
- package/.github/workflows/jscpd.yml +1 -1
- package/README.md +4 -4
- package/dist/33acrossAnalyticsAdapter.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/BTBidAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adagioUtils.js +1 -1
- package/dist/addefendBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/admixerBidAdapter.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adstirBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/agmaAnalyticsAdapter.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/bridBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/ccxBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/chunk-core.js +1 -1
- package/dist/cleanmedianetBidAdapter.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/connectionInfo.js +1 -0
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/contxtfulRtdProvider.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dailymotionBidAdapter.js +1 -1
- package/dist/dependencies.json +16 -3
- package/dist/discoveryBidAdapter.js +1 -1
- package/dist/docereeAdManagerBidAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/dxkultureBidAdapter.js +1 -1
- package/dist/eightPodAnalyticsAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/exadsBidAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/gamoshiBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hypelabBidAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/idImportLibrary.js +1 -1
- package/dist/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/intentIqAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/jixieBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/kimberliteBidAdapter.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/liveIntentIdSystem.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/luceadBidAdapter.js +1 -1
- package/dist/mabidderBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.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/medianetAnalyticsAdapter.js +1 -1
- package/dist/medianetBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/mgidUtils.js +1 -0
- package/dist/mgidXBidAdapter.js +1 -1
- package/dist/missenaBidAdapter.js +1 -1
- package/dist/mobianRtdProvider.js +1 -1
- package/dist/navigatorData.js +1 -0
- package/dist/nexx360BidAdapter.js +1 -1
- package/dist/nobidAnalyticsAdapter.js +1 -1
- package/dist/nobidBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +176 -170
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/omsBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/ortbConverter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/ownadxBidAdapter.js +1 -0
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prismaBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubriseBidAdapter.js +1 -0
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pubxaiRtdProvider.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/redtramBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.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/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smarthubBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/snigelBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -1
- package/dist/tappxBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/themoneytizerBidAdapter.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/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/unrulyBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/viantOrtbBidAdapter.js +1 -1
- package/dist/vidazooUtils.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/wurflRtdProvider.js +1 -0
- package/dist/yahooAdsBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/integrationExamples/gpt/wurflRtdProvider_example.html +106 -0
- package/libraries/connectionInfo/connectionUtils.js +33 -0
- package/libraries/mgidUtils/mgidUtils.js +73 -0
- package/{src/fpd/navigator.js → libraries/navigatorData/navigatorData.js} +1 -1
- package/libraries/ortbConverter/processors/video.js +2 -24
- package/libraries/riseUtils/index.js +2 -1
- package/libraries/vidazooUtils/bidderUtils.js +16 -0
- package/modules/.submodules.json +3 -1
- package/modules/51DegreesRtdProvider.md +11 -7
- package/modules/adagioBidAdapter.js +10 -50
- package/modules/admixerBidAdapter.js +12 -5
- package/modules/appnexusBidAdapter.js +1 -1
- package/modules/ccxBidAdapter.js +6 -2
- package/modules/cleanmedianetBidAdapter.js +1 -1
- package/modules/contxtfulRtdProvider.js +15 -12
- package/modules/cwireBidAdapter.js +13 -9
- package/modules/cwireBidAdapter.md +29 -10
- package/modules/dailymotionBidAdapter.js +20 -1
- package/modules/dailymotionBidAdapter.md +11 -7
- package/modules/discoveryBidAdapter.js +1 -1
- package/modules/docereeAdManagerBidAdapter.js +9 -12
- package/modules/eightPodAnalyticsAdapter.js +13 -1
- package/modules/gamoshiBidAdapter.js +1 -1
- package/modules/greenbidsAnalyticsAdapter.js +7 -4
- package/modules/greenbidsRtdProvider.js +15 -5
- package/modules/id5IdSystem.js +14 -93
- package/modules/idImportLibrary.js +14 -6
- package/modules/ixBidAdapter.js +0 -1
- package/modules/mediagoBidAdapter.js +4 -4
- package/modules/mgidBidAdapter.js +30 -109
- package/modules/mgidXBidAdapter.js +2 -66
- package/modules/mobianRtdProvider.js +28 -14
- package/modules/omsBidAdapter.js +1 -1
- package/modules/ownadxBidAdapter.js +99 -0
- package/modules/prismaBidAdapter.js +1 -27
- package/modules/pubmaticBidAdapter.js +2 -1
- package/modules/pubriseBidAdapter.js +19 -0
- package/modules/pubriseBidAdapter.md +79 -0
- package/modules/pubxaiAnalyticsAdapter.js +9 -4
- package/modules/pubxaiRtdProvider.js +38 -18
- package/modules/pubxaiRtdProvider.md +2 -2
- package/modules/redtramBidAdapter.js +2 -6
- package/modules/rubiconBidAdapter.js +3 -3
- package/modules/sharethroughBidAdapter.js +5 -0
- package/modules/smarthubBidAdapter.js +2 -0
- package/modules/teadsBidAdapter.js +4 -3
- package/modules/ttdBidAdapter.js +14 -32
- package/modules/undertoneBidAdapter.js +1 -19
- package/modules/userId/index.js +1 -1
- package/modules/viantOrtbBidAdapter.js +1 -1
- package/modules/wurflRtdProvider.js +213 -0
- package/modules/wurflRtdProvider.md +67 -0
- package/package.json +1 -1
- package/src/adloader.js +1 -0
- package/src/prebid.js +2 -1
- package/src/utils/focusTimeout.js +17 -6
- package/src/utils/ttlCollection.js +1 -1
- package/src/utils.js +28 -0
- package/src/video.js +78 -1
- package/test/spec/modules/adagioBidAdapter_spec.js +0 -1
- package/test/spec/modules/admixerBidAdapter_spec.js +2 -2
- package/test/spec/modules/appnexusBidAdapter_spec.js +0 -33
- package/test/spec/modules/ccxBidAdapter_spec.js +81 -0
- package/test/spec/modules/cleanmedianetBidAdapter_spec.js +1 -1
- package/test/spec/modules/contxtfulRtdProvider_spec.js +19 -19
- package/test/spec/modules/dailymotionBidAdapter_spec.js +62 -12
- package/test/spec/modules/discoveryBidAdapter_spec.js +1 -1
- package/test/spec/modules/docereeAdManagerBidAdapter_spec.js +1 -0
- package/test/spec/modules/gamoshiBidAdapter_spec.js +1 -1
- package/test/spec/modules/id5IdSystem_spec.js +25 -98
- package/test/spec/modules/idImportLibrary_spec.js +14 -0
- package/test/spec/modules/ixBidAdapter_spec.js +8 -1
- package/test/spec/modules/mobianRtdProvider_spec.js +46 -43
- package/test/spec/modules/openxBidAdapter_spec.js +1 -1
- package/test/spec/modules/ownadxBidAdapter_spec.js +103 -0
- package/test/spec/modules/pubmaticBidAdapter_spec.js +18 -0
- package/test/spec/modules/pubriseBidAdapter_spec.js +514 -0
- package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +9 -4
- package/test/spec/modules/pubxaiRtdProvider_spec.js +37 -5
- package/test/spec/modules/rubiconBidAdapter_spec.js +10 -0
- package/test/spec/modules/sharethroughBidAdapter_spec.js +35 -0
- package/test/spec/modules/trafficgateBidAdapter_spec.js +1 -1
- package/test/spec/modules/ttdBidAdapter_spec.js +10 -1
- package/test/spec/modules/viantOrtbBidAdapter_spec.js +1 -1
- package/test/spec/modules/vidazooBidAdapter_spec.js +12 -4
- package/test/spec/modules/wurflRtdProvider_spec.js +324 -0
- package/test/spec/ortbConverter/userId_spec.js +23 -2
- package/test/spec/unit/utils/focusTimeout_spec.js +33 -6
- package/test/spec/video_spec.js +103 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { submodule } from '../src/hook.js';
|
|
2
|
+
import { fetch, sendBeacon } from '../src/ajax.js';
|
|
3
|
+
import { loadExternalScript } from '../src/adloader.js';
|
|
4
|
+
import {
|
|
5
|
+
mergeDeep,
|
|
6
|
+
prefixLog,
|
|
7
|
+
} from '../src/utils.js';
|
|
8
|
+
|
|
9
|
+
// Constants
|
|
10
|
+
const REAL_TIME_MODULE = 'realTimeData';
|
|
11
|
+
const MODULE_NAME = 'wurfl';
|
|
12
|
+
|
|
13
|
+
// WURFL_JS_HOST is the host for the WURFL service endpoints
|
|
14
|
+
const WURFL_JS_HOST = 'https://prebid.wurflcloud.com';
|
|
15
|
+
// WURFL_JS_ENDPOINT_PATH is the path for the WURFL.js endpoint used to load WURFL data
|
|
16
|
+
const WURFL_JS_ENDPOINT_PATH = '/wurfl.js';
|
|
17
|
+
// STATS_ENDPOINT_PATH is the path for the stats endpoint used to send analytics data
|
|
18
|
+
const STATS_ENDPOINT_PATH = '/v1/prebid/stats';
|
|
19
|
+
|
|
20
|
+
const logger = prefixLog('[WURFL RTD Submodule]');
|
|
21
|
+
|
|
22
|
+
// enrichedBidders holds a list of prebid bidder names, of bidders which have been
|
|
23
|
+
// injected with WURFL data
|
|
24
|
+
const enrichedBidders = new Set();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* init initializes the WURFL RTD submodule
|
|
28
|
+
* @param {Object} config Configuration for WURFL RTD submodule
|
|
29
|
+
* @param {Object} userConsent User consent data
|
|
30
|
+
*/
|
|
31
|
+
const init = (config, userConsent) => {
|
|
32
|
+
logger.logMessage('initialized');
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* getBidRequestData enriches the OpenRTB 2.0 device data with WURFL data
|
|
38
|
+
* @param {Object} reqBidsConfigObj Bid request configuration object
|
|
39
|
+
* @param {Function} callback Called on completion
|
|
40
|
+
* @param {Object} config Configuration for WURFL RTD submodule
|
|
41
|
+
* @param {Object} userConsent User consent data
|
|
42
|
+
*/
|
|
43
|
+
const getBidRequestData = (reqBidsConfigObj, callback, config, userConsent) => {
|
|
44
|
+
const altHost = config.params?.altHost ?? null;
|
|
45
|
+
const isDebug = config.params?.debug ?? false;
|
|
46
|
+
|
|
47
|
+
const bidders = new Set();
|
|
48
|
+
reqBidsConfigObj.adUnits.forEach(adUnit => {
|
|
49
|
+
adUnit.bids.forEach(bid => {
|
|
50
|
+
bidders.add(bid.bidder);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let host = WURFL_JS_HOST;
|
|
55
|
+
if (altHost) {
|
|
56
|
+
host = altHost;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const url = new URL(host);
|
|
60
|
+
url.pathname = WURFL_JS_ENDPOINT_PATH;
|
|
61
|
+
|
|
62
|
+
if (isDebug) {
|
|
63
|
+
url.searchParams.set('debug', 'true')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
url.searchParams.set('mode', 'prebid')
|
|
67
|
+
logger.logMessage('url', url.toString());
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
loadExternalScript(url.toString(), MODULE_NAME, () => {
|
|
71
|
+
logger.logMessage('script injected');
|
|
72
|
+
window.WURFLPromises.complete.then((res) => {
|
|
73
|
+
logger.logMessage('received data', res);
|
|
74
|
+
if (!res.wurfl_pbjs) {
|
|
75
|
+
logger.logError('invalid WURFL.js for Prebid response');
|
|
76
|
+
} else {
|
|
77
|
+
enrichBidderRequests(reqBidsConfigObj, bidders, res);
|
|
78
|
+
}
|
|
79
|
+
callback();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
} catch (err) {
|
|
83
|
+
logger.logError(err);
|
|
84
|
+
callback();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* enrichBidderRequests enriches the OpenRTB 2.0 device data with WURFL data for Business Edition
|
|
90
|
+
* @param {Object} reqBidsConfigObj Bid request configuration object
|
|
91
|
+
* @param {Array} bidders List of bidders
|
|
92
|
+
* @param {Object} wjsResponse WURFL.js response
|
|
93
|
+
*/
|
|
94
|
+
function enrichBidderRequests(reqBidsConfigObj, bidders, wjsResponse) {
|
|
95
|
+
const authBidders = wjsResponse.wurfl_pbjs?.authorized_bidders ?? {};
|
|
96
|
+
const caps = wjsResponse.wurfl_pbjs?.caps ?? [];
|
|
97
|
+
|
|
98
|
+
bidders.forEach((bidderCode) => {
|
|
99
|
+
if (bidderCode in authBidders) {
|
|
100
|
+
// inject WURFL data
|
|
101
|
+
enrichedBidders.add(bidderCode);
|
|
102
|
+
const data = bidderData(wjsResponse.WURFL, caps, authBidders[bidderCode]);
|
|
103
|
+
logger.logMessage(`injecting data for ${bidderCode}: `, data);
|
|
104
|
+
enrichBidderRequest(reqBidsConfigObj, bidderCode, data);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// inject WURFL low entropy data
|
|
108
|
+
const data = lowEntropyData(wjsResponse.WURFL, wjsResponse.wurfl_pbjs?.low_entropy_caps);
|
|
109
|
+
logger.logMessage(`injecting low entropy data for ${bidderCode}: `, data);
|
|
110
|
+
enrichBidderRequest(reqBidsConfigObj, bidderCode, data);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* bidderData returns the WURFL data for a bidder
|
|
116
|
+
* @param {Object} wurflData WURFL data
|
|
117
|
+
* @param {Array} caps Capability list
|
|
118
|
+
* @param {Array} filter Filter list
|
|
119
|
+
* @returns {Object} Bidder data
|
|
120
|
+
*/
|
|
121
|
+
export const bidderData = (wurflData, caps, filter) => {
|
|
122
|
+
const data = {};
|
|
123
|
+
caps.forEach((cap, index) => {
|
|
124
|
+
if (!filter.includes(index)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (cap in wurflData) {
|
|
128
|
+
data[cap] = wurflData[cap];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return data;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* lowEntropyData returns the WURFL low entropy data
|
|
136
|
+
* @param {Object} wurflData WURFL data
|
|
137
|
+
* @param {Array} lowEntropyCaps Low entropy capability list
|
|
138
|
+
* @returns {Object} Bidder data
|
|
139
|
+
*/
|
|
140
|
+
export const lowEntropyData = (wurflData, lowEntropyCaps) => {
|
|
141
|
+
const data = {};
|
|
142
|
+
lowEntropyCaps.forEach((cap, _) => {
|
|
143
|
+
let value = wurflData[cap];
|
|
144
|
+
if (cap == 'complete_device_name') {
|
|
145
|
+
value = value.replace(/Apple (iP(hone|ad|od)).*/, 'Apple iP$2');
|
|
146
|
+
}
|
|
147
|
+
data[cap] = value;
|
|
148
|
+
});
|
|
149
|
+
return data;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* enrichBidderRequest enriches the bidder request with WURFL data
|
|
154
|
+
* @param {Object} reqBidsConfigObj Bid request configuration object
|
|
155
|
+
* @param {String} bidderCode Bidder code
|
|
156
|
+
* @param {Object} wurflData WURFL data
|
|
157
|
+
*/
|
|
158
|
+
export const enrichBidderRequest = (reqBidsConfigObj, bidderCode, wurflData) => {
|
|
159
|
+
const ortb2data = {
|
|
160
|
+
'device': {
|
|
161
|
+
'ext': {
|
|
162
|
+
'wurfl': wurflData,
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, { [bidderCode]: ortb2data });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* onAuctionEndEvent is called when the auction ends
|
|
171
|
+
* @param {Object} auctionDetails Auction details
|
|
172
|
+
* @param {Object} config Configuration for WURFL RTD submodule
|
|
173
|
+
* @param {Object} userConsent User consent data
|
|
174
|
+
*/
|
|
175
|
+
function onAuctionEndEvent(auctionDetails, config, userConsent) {
|
|
176
|
+
const altHost = config.params?.altHost ?? null;
|
|
177
|
+
|
|
178
|
+
let host = WURFL_JS_HOST;
|
|
179
|
+
if (altHost) {
|
|
180
|
+
host = altHost;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const url = new URL(host);
|
|
184
|
+
url.pathname = STATS_ENDPOINT_PATH;
|
|
185
|
+
|
|
186
|
+
if (enrichedBidders.size === 0) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
var payload = JSON.stringify({ bidders: [...enrichedBidders] });
|
|
191
|
+
const sentBeacon = sendBeacon(url.toString(), payload);
|
|
192
|
+
if (sentBeacon) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
fetch(url.toString(), {
|
|
197
|
+
method: 'POST',
|
|
198
|
+
body: payload,
|
|
199
|
+
mode: 'no-cors',
|
|
200
|
+
keepalive: true
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// The WURFL submodule
|
|
205
|
+
export const wurflSubmodule = {
|
|
206
|
+
name: MODULE_NAME,
|
|
207
|
+
init,
|
|
208
|
+
getBidRequestData,
|
|
209
|
+
onAuctionEndEvent,
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Register the WURFL submodule as submodule of realTimeData
|
|
213
|
+
submodule(REAL_TIME_MODULE, wurflSubmodule);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# WURFL Real-time Data Submodule
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Module Name: WURFL Rtd Provider
|
|
6
|
+
Module Type: Rtd Provider
|
|
7
|
+
Maintainer: prebid@scientiamobile.com
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
The WURFL RTD module enriches the OpenRTB 2.0 device data with [WURFL data](https://www.scientiamobile.com/wurfl-js-business-edition-at-the-intersection-of-javascript-and-enterprise/).
|
|
12
|
+
The module sets the WURFL data in `device.ext.wurfl` and all the bidder adapters will always receive the low entry capabilites like `is_mobile`, `complete_device_name` and `form_factor`.
|
|
13
|
+
|
|
14
|
+
For a more detailed analysis bidders can subscribe to detect iPhone and iPad models and receive additional [WURFL device capabilities](https://www.scientiamobile.com/capabilities/?products%5B%5D=wurfl-js).
|
|
15
|
+
|
|
16
|
+
## User-Agent Client Hints
|
|
17
|
+
|
|
18
|
+
WURFL.js is fully compatible with Chromium's User-Agent Client Hints (UA-CH) initiative. If User-Agent Client Hints are absent in the HTTP headers that WURFL.js receives, the service will automatically fall back to using the User-Agent Client Hints' JS API to fetch [high entropy client hint values](https://wicg.github.io/ua-client-hints/#getHighEntropyValues) from the client device. However, we recommend that you explicitly opt-in/advertise support for User-Agent Client Hints on your website and delegate them to the WURFL.js service for the fastest detection experience. Our documentation regarding implementing User-Agent Client Hint support [is available here](https://docs.scientiamobile.com/guides/implementing-useragent-clienthints).
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Build
|
|
23
|
+
```
|
|
24
|
+
gulp build --modules="wurflRtdProvider,appnexusBidAdapter,..."
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Configuration
|
|
28
|
+
|
|
29
|
+
Use `setConfig` to instruct Prebid.js to initilize the WURFL RTD module, as specified below.
|
|
30
|
+
|
|
31
|
+
This module is configured as part of the `realTimeData.dataProviders`
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
var TIMEOUT = 1000;
|
|
35
|
+
pbjs.setConfig({
|
|
36
|
+
realTimeData: {
|
|
37
|
+
auctionDelay: TIMEOUT,
|
|
38
|
+
dataProviders: [{
|
|
39
|
+
name: 'wurfl',
|
|
40
|
+
waitForIt: true,
|
|
41
|
+
params: {
|
|
42
|
+
debug: false
|
|
43
|
+
}
|
|
44
|
+
}]
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Parameters
|
|
50
|
+
|
|
51
|
+
| Name | Type | Description | Default |
|
|
52
|
+
| :------------------------ | :------------ | :--------------------------------------------------------------- |:----------------- |
|
|
53
|
+
| name | String | Real time data module name | Always 'wurfl' |
|
|
54
|
+
| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` |
|
|
55
|
+
| params | Object | | |
|
|
56
|
+
| params.altHost | String | Alternate host to connect to WURFL.js | |
|
|
57
|
+
| params.debug | Boolean | Enable debug | `false` |
|
|
58
|
+
|
|
59
|
+
## Testing
|
|
60
|
+
|
|
61
|
+
To view an example of how the WURFL RTD module works :
|
|
62
|
+
|
|
63
|
+
`gulp serve --modules=wurflRtdProvider,appnexusBidAdapter`
|
|
64
|
+
|
|
65
|
+
and then point your browser at:
|
|
66
|
+
|
|
67
|
+
`http://localhost:9999/integrationExamples/gpt/wurflRtdProvider_example.html`
|
package/package.json
CHANGED
package/src/adloader.js
CHANGED
package/src/prebid.js
CHANGED
|
@@ -41,7 +41,7 @@ import {enrichFPD} from './fpd/enrichment.js';
|
|
|
41
41
|
import {allConsent} from './consentHandler.js';
|
|
42
42
|
import {insertLocatorFrame, renderAdDirect} from './adRendering.js';
|
|
43
43
|
import {getHighestCpm} from './utils/reducers.js';
|
|
44
|
-
import {fillVideoDefaults} from './video.js';
|
|
44
|
+
import {fillVideoDefaults, validateOrtbVideoFields} from './video.js';
|
|
45
45
|
|
|
46
46
|
const pbjsInstance = getGlobal();
|
|
47
47
|
const { triggerUserSyncs } = userSync;
|
|
@@ -134,6 +134,7 @@ function validateVideoMediaType(adUnit) {
|
|
|
134
134
|
delete validatedAdUnit.mediaTypes.video.playerSize;
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
validateOrtbVideoFields(validatedAdUnit);
|
|
137
138
|
return validatedAdUnit;
|
|
138
139
|
}
|
|
139
140
|
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
let outOfFocusStart;
|
|
1
|
+
let outOfFocusStart = null; // enforce null otherwise it could be undefined and the callback wouldn't execute
|
|
2
2
|
let timeOutOfFocus = 0;
|
|
3
3
|
let suspendedTimeouts = [];
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function trackTimeOutOfFocus() {
|
|
6
6
|
if (document.hidden) {
|
|
7
7
|
outOfFocusStart = Date.now()
|
|
8
8
|
} else {
|
|
9
|
-
timeOutOfFocus += Date.now() - outOfFocusStart
|
|
10
|
-
suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)()))
|
|
9
|
+
timeOutOfFocus += Date.now() - (outOfFocusStart ?? 0); // when the page is loaded in hidden state outOfFocusStart is undefined, which results in timeoutOffset being NaN
|
|
11
10
|
outOfFocusStart = null;
|
|
11
|
+
suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)()));
|
|
12
|
+
suspendedTimeouts = [];
|
|
12
13
|
}
|
|
13
|
-
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
document.addEventListener('visibilitychange', trackTimeOutOfFocus);
|
|
17
|
+
|
|
18
|
+
export function reset() {
|
|
19
|
+
outOfFocusStart = null;
|
|
20
|
+
timeOutOfFocus = 0;
|
|
21
|
+
suspendedTimeouts = [];
|
|
22
|
+
document.removeEventListener('visibilitychange', trackTimeOutOfFocus);
|
|
23
|
+
document.addEventListener('visibilitychange', trackTimeOutOfFocus);
|
|
24
|
+
}
|
|
14
25
|
|
|
15
26
|
/**
|
|
16
27
|
* Wraps native setTimeout function in order to count time only when page is focused
|
|
@@ -19,7 +30,7 @@ document.addEventListener('visibilitychange', () => {
|
|
|
19
30
|
* @param {number} [milliseconds] - Minimum duration (in milliseconds) that the callback will be executed after
|
|
20
31
|
* @returns {function(*): (number)} - Getter function for current timer id
|
|
21
32
|
*/
|
|
22
|
-
export
|
|
33
|
+
export function setFocusTimeout(callback, milliseconds) {
|
|
23
34
|
const startTime = timeOutOfFocus;
|
|
24
35
|
let timerId = setTimeout(() => {
|
|
25
36
|
if (timeOutOfFocus === startTime && outOfFocusStart == null) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {GreedyPromise} from './promise.js';
|
|
2
2
|
import {binarySearch, logError, timestamp} from '../utils.js';
|
|
3
|
-
import setFocusTimeout from './focusTimeout.js';
|
|
3
|
+
import {setFocusTimeout} from './focusTimeout.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Create a set-like collection that automatically forgets items after a certain time.
|
package/src/utils.js
CHANGED
|
@@ -1258,3 +1258,31 @@ export function setOnAny(collection, key) {
|
|
|
1258
1258
|
}
|
|
1259
1259
|
return undefined;
|
|
1260
1260
|
}
|
|
1261
|
+
|
|
1262
|
+
export function extractDomainFromHost(pageHost) {
|
|
1263
|
+
let domain = null;
|
|
1264
|
+
try {
|
|
1265
|
+
let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost);
|
|
1266
|
+
if (domains != null && domains.length > 0) {
|
|
1267
|
+
domain = domains[0];
|
|
1268
|
+
for (let i = 1; i < domains.length; i++) {
|
|
1269
|
+
if (domains[i].length > domain.length) {
|
|
1270
|
+
domain = domains[i];
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
} catch (e) {
|
|
1275
|
+
domain = null;
|
|
1276
|
+
}
|
|
1277
|
+
return domain;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
export function triggerNurlWithCpm(bid, cpm) {
|
|
1281
|
+
if (isStr(bid.nurl) && bid.nurl !== '') {
|
|
1282
|
+
bid.nurl = bid.nurl.replace(
|
|
1283
|
+
/\${AUCTION_PRICE}/,
|
|
1284
|
+
cpm
|
|
1285
|
+
);
|
|
1286
|
+
triggerPixel(bid.nurl);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
package/src/video.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {deepAccess, logError} from './utils.js';
|
|
1
|
+
import {deepAccess, isArrayOfNums, isInteger, isNumber, isPlainObject, isStr, logError, logWarn} from './utils.js';
|
|
2
2
|
import {config} from '../src/config.js';
|
|
3
3
|
import {hook} from './hook.js';
|
|
4
4
|
import {auctionManager} from './auctionManager.js';
|
|
@@ -6,6 +6,47 @@ import {auctionManager} from './auctionManager.js';
|
|
|
6
6
|
export const OUTSTREAM = 'outstream';
|
|
7
7
|
export const INSTREAM = 'instream';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* List of OpenRTB 2.x video object properties with simple validators.
|
|
11
|
+
* Not included: `companionad`, `durfloors`, `ext`
|
|
12
|
+
* reference: https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md
|
|
13
|
+
*/
|
|
14
|
+
export const ORTB_VIDEO_PARAMS = new Map([
|
|
15
|
+
[ 'mimes', value => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string') ],
|
|
16
|
+
[ 'minduration', isInteger ],
|
|
17
|
+
[ 'maxduration', isInteger ],
|
|
18
|
+
[ 'startdelay', isInteger ],
|
|
19
|
+
[ 'maxseq', isInteger ],
|
|
20
|
+
[ 'poddur', isInteger ],
|
|
21
|
+
[ 'protocols', isArrayOfNums ],
|
|
22
|
+
[ 'w', isInteger ],
|
|
23
|
+
[ 'h', isInteger ],
|
|
24
|
+
[ 'podid', isStr ],
|
|
25
|
+
[ 'podseq', isInteger ],
|
|
26
|
+
[ 'rqddurs', isArrayOfNums ],
|
|
27
|
+
[ 'placement', isInteger ], // deprecated, see plcmt
|
|
28
|
+
[ 'plcmt', isInteger ],
|
|
29
|
+
[ 'linearity', isInteger ],
|
|
30
|
+
[ 'skip', value => [1, 0].includes(value) ],
|
|
31
|
+
[ 'skipmin', isInteger ],
|
|
32
|
+
[ 'skipafter', isInteger ],
|
|
33
|
+
[ 'sequence', isInteger ], // deprecated
|
|
34
|
+
[ 'slotinpod', isInteger ],
|
|
35
|
+
[ 'mincpmpersec', isNumber ],
|
|
36
|
+
[ 'battr', isArrayOfNums ],
|
|
37
|
+
[ 'maxextended', isInteger ],
|
|
38
|
+
[ 'minbitrate', isInteger ],
|
|
39
|
+
[ 'maxbitrate', isInteger ],
|
|
40
|
+
[ 'boxingallowed', isInteger ],
|
|
41
|
+
[ 'playbackmethod', isArrayOfNums ],
|
|
42
|
+
[ 'playbackend', isInteger ],
|
|
43
|
+
[ 'delivery', isArrayOfNums ],
|
|
44
|
+
[ 'pos', isInteger ],
|
|
45
|
+
[ 'api', isArrayOfNums ],
|
|
46
|
+
[ 'companiontype', isArrayOfNums ],
|
|
47
|
+
[ 'poddedupe', isArrayOfNums ]
|
|
48
|
+
]);
|
|
49
|
+
|
|
9
50
|
export function fillVideoDefaults(adUnit) {
|
|
10
51
|
const video = adUnit?.mediaTypes?.video;
|
|
11
52
|
if (video != null && video.plcmt == null) {
|
|
@@ -17,6 +58,42 @@ export function fillVideoDefaults(adUnit) {
|
|
|
17
58
|
}
|
|
18
59
|
}
|
|
19
60
|
|
|
61
|
+
/**
|
|
62
|
+
* validateOrtbVideoFields mutates the `adUnit.mediaTypes.video` object by removing invalid ortb properties (default).
|
|
63
|
+
* The onInvalidParam callback can be used to handle invalid properties differently.
|
|
64
|
+
* Other properties are ignored and kept as is.
|
|
65
|
+
*
|
|
66
|
+
* @param {Object} adUnit - The adUnit object.
|
|
67
|
+
* @param {Function} onInvalidParam - The callback function to be called with key, value, and adUnit.
|
|
68
|
+
* @returns {void}
|
|
69
|
+
*/
|
|
70
|
+
export function validateOrtbVideoFields(adUnit, onInvalidParam) {
|
|
71
|
+
const videoParams = adUnit?.mediaTypes?.video;
|
|
72
|
+
|
|
73
|
+
if (!isPlainObject(videoParams)) {
|
|
74
|
+
logWarn(`validateOrtbVideoFields: videoParams must be an object.`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (videoParams != null) {
|
|
79
|
+
Object.entries(videoParams)
|
|
80
|
+
.forEach(([key, value]) => {
|
|
81
|
+
if (!ORTB_VIDEO_PARAMS.has(key)) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
const isValid = ORTB_VIDEO_PARAMS.get(key)(value);
|
|
85
|
+
if (!isValid) {
|
|
86
|
+
if (typeof onInvalidParam === 'function') {
|
|
87
|
+
onInvalidParam(key, value, adUnit);
|
|
88
|
+
} else {
|
|
89
|
+
delete videoParams[key];
|
|
90
|
+
logWarn(`Invalid prop in adUnit "${adUnit.code}": Invalid value for mediaTypes.video.${key} ORTB property. The property has been removed.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
20
97
|
/**
|
|
21
98
|
* @typedef {object} VideoBid
|
|
22
99
|
* @property {string} adId id of the bid
|
|
@@ -603,7 +603,6 @@ describe('Adagio bid adapter', () => {
|
|
|
603
603
|
const requests = spec.buildRequests([bid01], bidderRequest);
|
|
604
604
|
expect(requests).to.have.lengthOf(1);
|
|
605
605
|
expect(requests[0].data.adUnits[0].mediaTypes.video).to.deep.equal(expected);
|
|
606
|
-
sinon.assert.calledTwice(utils.logWarn.withArgs(sinon.match(new RegExp(/^Adagio: The OpenRTB/))));
|
|
607
606
|
});
|
|
608
607
|
});
|
|
609
608
|
|
|
@@ -226,12 +226,12 @@ describe('AdmixerAdapter', function () {
|
|
|
226
226
|
},
|
|
227
227
|
};
|
|
228
228
|
it('gets floor', function () {
|
|
229
|
-
|
|
229
|
+
validRequest[0].getFloor = () => {
|
|
230
230
|
return { floor: 0.6 };
|
|
231
231
|
};
|
|
232
232
|
const request = spec.buildRequests(validRequest, bidderRequest);
|
|
233
233
|
const payload = request.data;
|
|
234
|
-
expect(payload.bidFloor).to.deep.equal(0.6);
|
|
234
|
+
expect(payload.imps[0].bidFloor).to.deep.equal(0.6);
|
|
235
235
|
});
|
|
236
236
|
});
|
|
237
237
|
|
|
@@ -1783,7 +1783,6 @@ describe('AppNexusAdapter', function () {
|
|
|
1783
1783
|
'cpm': 0.5,
|
|
1784
1784
|
'cpm_publisher_currency': 0.5,
|
|
1785
1785
|
'publisher_currency_code': '$',
|
|
1786
|
-
'publisher_currency_codename': 'USD',
|
|
1787
1786
|
'client_initiated_ad_counting': true,
|
|
1788
1787
|
'viewability': {
|
|
1789
1788
|
'config': '<script type=\'text/javascript\' async=\'true\' src=\'https://cdn.adnxs.com/v/s/152/trk.js#v;vk=appnexus.com-omid;tv=native1-18h;dom_id=%native_dom_id%;st=0;d=1x1;vc=iab;vid_ccr=1;tag_id=13232354;cb=https%3A%2F%2Fams1-ib.adnxs.com%2Fvevent%3Freferrer%3Dhttps253A%252F%252Ftestpages-pmahe.tp.adnxs.net%252F01_basic_single%26e%3DwqT_3QLNB6DNAwAAAwDWAAUBCLfl_-MFEMStk8u3lPTjRxih88aF0fq_2QsqNgkAAAECCCRAEQEHEAAAJEAZEQkAIREJACkRCQAxEQmoMOLRpwY47UhA7UhIAlCDy74uWJzxW2AAaM26dXjzjwWAAQGKAQNVU0SSAQEG8FCYAQGgAQGoAQGwAQC4AQHAAQTIAQLQAQDYAQDgAQDwAQCKAjt1ZignYScsIDI1Mjk4ODUsIDE1NTE4ODkwNzkpO3VmKCdyJywgOTc0OTQ0MDM2HgDwjZIC8QEha0RXaXBnajgtTHdLRUlQTHZpNFlBQ0NjOFZzd0FEZ0FRQVJJN1VoUTR0R25CbGdBWU1rR2FBQndMSGlrTDRBQlVvZ0JwQy1RQVFHWUFRR2dBUUdvQVFPd0FRQzVBZk90YXFRQUFDUkF3UUh6cldxa0FBQWtRTWtCbWo4dDA1ZU84VF9aQVFBQUEBAyRQQV80QUVBOVFFAQ4sQW1BSUFvQUlBdFFJBRAAdg0IeHdBSUF5QUlBNEFJQTZBSUEtQUlBZ0FNQm1BTUJxQVAFzIh1Z01KUVUxVE1UbzBNekl3NEFPVENBLi6aAmEhUXcxdGNRagUoEfQkblBGYklBUW9BRAl8AEEBqAREbzJEABRRSk1JU1EBGwRBQQGsAFURDAxBQUFXHQzwWNgCAOACrZhI6gIzaHR0cDovL3Rlc3RwYWdlcy1wbWFoZS50cC5hZG54cy5uZXQvMDFfYmFzaWNfc2luZ2xl8gITCg9DVVNUT01fTU9ERUxfSUQSAPICGgoWMhYAPExFQUZfTkFNRRIA8gIeCho2HQAIQVNUAT7wnElGSUVEEgCAAwCIAwGQAwCYAxegAwGqAwDAA-CoAcgDANgD8ao-4AMA6AMA-AMBgAQAkgQNL3V0L3YzL3ByZWJpZJgEAKIECjEwLjIuMTIuMzioBIqpB7IEDggAEAEYACAAKAAwADgCuAQAwAQAyAQA0gQOOTMyNSNBTVMxOjQzMjDaBAIIAeAEAfAEg8u-LogFAZgFAKAF______8BAxgBwAUAyQUABQEU8D_SBQkJBQt8AAAA2AUB4AUB8AWZ9CH6BQQIABAAkAYBmAYAuAYAwQYBITAAAPA_yAYA2gYWChAAOgEAGBAAGADgBgw.%26s%3D971dce9d49b6bee447c8a58774fb30b40fe98171;ts=1551889079;cet=0;cecb=\'></script>'
|
|
@@ -1868,38 +1867,6 @@ describe('AppNexusAdapter', function () {
|
|
|
1868
1867
|
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
|
|
1869
1868
|
});
|
|
1870
1869
|
|
|
1871
|
-
it('should parse non-default currency', function () {
|
|
1872
|
-
let eurCpmResponse = deepClone(response);
|
|
1873
|
-
eurCpmResponse.tags[0].ads[0].publisher_currency_codename = 'EUR';
|
|
1874
|
-
|
|
1875
|
-
let bidderRequest = {
|
|
1876
|
-
bidderCode: 'appnexus',
|
|
1877
|
-
bids: [{
|
|
1878
|
-
bidId: '3db3773286ee59',
|
|
1879
|
-
adUnitCode: 'code'
|
|
1880
|
-
}]
|
|
1881
|
-
};
|
|
1882
|
-
|
|
1883
|
-
let result = spec.interpretResponse({ body: eurCpmResponse }, { bidderRequest });
|
|
1884
|
-
expect(result[0].currency).to.equal('EUR');
|
|
1885
|
-
});
|
|
1886
|
-
|
|
1887
|
-
it('should parse default currency', function () {
|
|
1888
|
-
let defaultCpmResponse = deepClone(response);
|
|
1889
|
-
delete defaultCpmResponse.tags[0].ads[0].publisher_currency_codename;
|
|
1890
|
-
|
|
1891
|
-
let bidderRequest = {
|
|
1892
|
-
bidderCode: 'appnexus',
|
|
1893
|
-
bids: [{
|
|
1894
|
-
bidId: '3db3773286ee59',
|
|
1895
|
-
adUnitCode: 'code'
|
|
1896
|
-
}]
|
|
1897
|
-
};
|
|
1898
|
-
|
|
1899
|
-
let result = spec.interpretResponse({ body: defaultCpmResponse }, { bidderRequest });
|
|
1900
|
-
expect(result[0].currency).to.equal('USD');
|
|
1901
|
-
});
|
|
1902
|
-
|
|
1903
1870
|
it('should reject 0 cpm bids', function () {
|
|
1904
1871
|
let zeroCpmResponse = deepClone(response);
|
|
1905
1872
|
zeroCpmResponse.tags[0].ads[0].cpm = 0;
|