prebid.js 9.53.2 → 9.53.4
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/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/adagioRtdProvider.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/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/aniviewBidAdapter.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/beopBidAdapter.js +1 -1
- package/dist/bidderTimeoutUtils.js +1 -0
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bitmediaBidAdapter.js +1 -1
- package/dist/bridBidAdapter.js +1 -1
- package/dist/bridgeuppBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/chunk-core.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/contxtfulBidAdapter.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/debugging-standalone.js +1 -1
- package/dist/dependencies.json +10 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/dxkultureBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/equativBidAdapter.js +1 -1
- package/dist/eskimiBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/exadsBidAdapter.js +1 -1
- package/dist/excoBidAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/fwsspBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsBidAdapter.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/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmobiBidAdapter.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/liveIntentId.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/madsenseBidAdapter.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/medianetBidAdapter.js +1 -1
- package/dist/medianetUtils.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/missenaBidAdapter.js +1 -1
- package/dist/mobilefuseBidAdapter.js +1 -1
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/nexx360Utils.js +1 -1
- package/dist/nobidAnalyticsAdapter.js +1 -1
- package/dist/nobidBidAdapter.js +1 -1
- package/dist/nodalsAiRtdProvider.js +1 -1
- package/dist/not-for-prod/prebid.js +178 -175
- package/dist/objectGuard.js +1 -1
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/optableRtdProvider.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubmaticIdSystem.js +1 -1
- package/dist/pubmaticRtdProvider.js +1 -1
- package/dist/pubmaticUtils.js +1 -0
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.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/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.js +1 -1
- package/dist/rtdModule.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sevioBidAdapter.js +1 -0
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/showheroes-bsBidAdapter.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/snigelBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sparteoBidAdapter.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/timeoutRtdProvider.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/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/yahooAdsBidAdapter.js +1 -1
- package/dist/yandexBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/integrationExamples/gpt/pubmaticRtdProvider_Example.html +161 -0
- package/libraries/bidderTimeoutUtils/bidderTimeoutUtils.js +119 -0
- package/libraries/objectGuard/objectGuard.js +170 -48
- package/libraries/objectGuard/ortbGuard.js +33 -43
- package/libraries/pubmaticUtils/plugins/dynamicTimeout.js +209 -0
- package/libraries/pubmaticUtils/plugins/floorProvider.js +168 -0
- package/libraries/pubmaticUtils/plugins/pluginManager.js +106 -0
- package/libraries/pubmaticUtils/plugins/unifiedPricingRule.js +375 -0
- package/libraries/pubmaticUtils/pubmaticUtils.js +76 -0
- package/modules/adagioAnalyticsAdapter.js +6 -1
- package/modules/adagioBidAdapter.js +12 -5
- package/modules/adagioRtdProvider.js +41 -35
- package/modules/fwsspBidAdapter.js +134 -69
- package/modules/fwsspBidAdapter.md +121 -26
- package/modules/optableRtdProvider.js +33 -12
- package/modules/pubmaticAnalyticsAdapter.js +315 -587
- package/modules/pubmaticBidAdapter.js +71 -8
- package/modules/pubmaticIdSystem.js +4 -4
- package/modules/pubmaticRtdProvider.js +105 -613
- package/modules/rtdModule/index.js +23 -6
- package/modules/sevioBidAdapter.js +413 -0
- package/modules/sevioBidAdapter.md +29 -0
- package/modules/sparteoBidAdapter.js +122 -10
- package/modules/timeoutRtdProvider.js +2 -105
- package/modules/ttdBidAdapter.js +0 -5
- package/modules/userId/eids.js +1 -1
- package/modules/userId/index.js +32 -1
- package/package.json +1 -1
- package/src/auction.js +3 -0
- package/test/spec/activities/objectGuard_spec.js +189 -32
- package/test/spec/activities/ortbGuard_spec.js +10 -15
- package/test/spec/libraries/bidderTimeoutUtils/bidderTimeoutUtils_spec.js +213 -0
- package/test/spec/libraries/pubmaticUtils/plugins/dynamicTimeout_spec.js +746 -0
- package/test/spec/libraries/pubmaticUtils/plugins/floorProvider_spec.js +184 -0
- package/test/spec/libraries/pubmaticUtils/plugins/pluginManager_spec.js +489 -0
- package/test/spec/libraries/pubmaticUtils/plugins/unifiedPricingRule_spec.js +359 -0
- package/test/spec/libraries/pubmaticUtils/pubmaticUtils_spec.js +236 -0
- package/test/spec/modules/adagioAnalyticsAdapter_spec.js +94 -24
- package/test/spec/modules/adagioRtdProvider_spec.js +17 -17
- package/test/spec/modules/fwsspBidAdapter_spec.js +513 -78
- package/test/spec/modules/optableRtdProvider_spec.js +55 -5
- package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +634 -916
- package/test/spec/modules/pubmaticBidAdapter_spec.js +260 -1
- package/test/spec/modules/pubmaticRtdProvider_spec.js +252 -1505
- package/test/spec/modules/realTimeDataModule_spec.js +58 -8
- package/test/spec/modules/sevioBidAdapter_spec.js +513 -0
- package/test/spec/modules/sparteoBidAdapter_spec.js +528 -43
- package/test/spec/modules/timeoutRtdProvider_spec.js +1 -201
- package/test/spec/modules/ttdBidAdapter_spec.js +0 -33
- package/test/spec/modules/userId_spec.js +115 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logInfo, logError, logWarn, isArray, isFn, deepAccess
|
|
1
|
+
import { logInfo, logError, logWarn, isArray, isFn, deepAccess } from '../src/utils.js';
|
|
2
2
|
import { BANNER, VIDEO } from '../src/mediaTypes.js';
|
|
3
3
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
4
4
|
import { config } from '../src/config.js';
|
|
@@ -6,7 +6,8 @@ import { getGlobal } from '../src/prebidGlobal.js';
|
|
|
6
6
|
|
|
7
7
|
const BIDDER_CODE = 'fwssp';
|
|
8
8
|
const GVL_ID = 285;
|
|
9
|
-
const USER_SYNC_URL = 'https://
|
|
9
|
+
const USER_SYNC_URL = 'https://user-sync.fwmrm.net/ad/u?';
|
|
10
|
+
let PRIVACY_VALUES = {};
|
|
10
11
|
|
|
11
12
|
export const spec = {
|
|
12
13
|
code: BIDDER_CODE,
|
|
@@ -21,7 +22,7 @@ export const spec = {
|
|
|
21
22
|
* @return boolean True if this is a valid bid, and false otherwise.
|
|
22
23
|
*/
|
|
23
24
|
isBidRequestValid(bid) {
|
|
24
|
-
return !!(bid.params.serverUrl && bid.params.networkId && bid.params.profile && bid.params.siteSectionId
|
|
25
|
+
return !!(bid.params.serverUrl && bid.params.networkId && bid.params.profile && bid.params.siteSectionId);
|
|
25
26
|
},
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -46,9 +47,9 @@ export const spec = {
|
|
|
46
47
|
const buildRequest = (currentBidRequest, bidderRequest) => {
|
|
47
48
|
const globalParams = constructGlobalParams(currentBidRequest);
|
|
48
49
|
const keyValues = constructKeyValues(currentBidRequest, bidderRequest);
|
|
49
|
-
|
|
50
50
|
const slotParams = constructSlotParams(currentBidRequest);
|
|
51
|
-
const
|
|
51
|
+
const serializedSChain = constructSupplyChain(currentBidRequest, bidderRequest);
|
|
52
|
+
const dataString = constructDataString(globalParams, keyValues, serializedSChain, slotParams);
|
|
52
53
|
return {
|
|
53
54
|
method: 'GET',
|
|
54
55
|
url: currentBidRequest.params.serverUrl,
|
|
@@ -57,6 +58,19 @@ export const spec = {
|
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
const constructSupplyChain = (currentBidRequest, bidderRequest) => {
|
|
62
|
+
// Add schain object
|
|
63
|
+
let schain = deepAccess(bidderRequest, 'ortb2.source.schain');
|
|
64
|
+
if (!schain) {
|
|
65
|
+
schain = deepAccess(bidderRequest, 'ortb2.source.ext.schain');
|
|
66
|
+
}
|
|
67
|
+
if (!schain) {
|
|
68
|
+
schain = currentBidRequest.schain;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return this.serializeSupplyChain(schain)
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
const constructGlobalParams = currentBidRequest => {
|
|
61
75
|
const sdkVersion = getSDKVersion(currentBidRequest);
|
|
62
76
|
const prebidVersion = getGlobal().version;
|
|
@@ -65,7 +79,7 @@ export const spec = {
|
|
|
65
79
|
resp: 'vast4',
|
|
66
80
|
prof: currentBidRequest.params.profile,
|
|
67
81
|
csid: currentBidRequest.params.siteSectionId,
|
|
68
|
-
caid: currentBidRequest.params.videoAssetId,
|
|
82
|
+
caid: currentBidRequest.params.videoAssetId ? currentBidRequest.params.videoAssetId : 0,
|
|
69
83
|
pvrn: getRandomNumber(),
|
|
70
84
|
vprn: getRandomNumber(),
|
|
71
85
|
flag: setFlagParameter(currentBidRequest.params.flags),
|
|
@@ -88,9 +102,9 @@ export const spec = {
|
|
|
88
102
|
const keyValues = currentBidRequest.params.adRequestKeyValues || {};
|
|
89
103
|
|
|
90
104
|
// Add bidfloor to keyValues
|
|
91
|
-
const
|
|
92
|
-
keyValues._fw_bidfloor =
|
|
93
|
-
keyValues._fw_bidfloorcur =
|
|
105
|
+
const { floor, currency } = getBidFloor(currentBidRequest, config);
|
|
106
|
+
keyValues._fw_bidfloor = floor;
|
|
107
|
+
keyValues._fw_bidfloorcur = currency;
|
|
94
108
|
|
|
95
109
|
// Add GDPR flag and consent string
|
|
96
110
|
if (bidderRequest && bidderRequest.gdprConsent) {
|
|
@@ -127,16 +141,6 @@ export const spec = {
|
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
143
|
|
|
130
|
-
// Add schain object
|
|
131
|
-
const schain = currentBidRequest.schain;
|
|
132
|
-
if (schain) {
|
|
133
|
-
try {
|
|
134
|
-
keyValues.schain = JSON.stringify(schain);
|
|
135
|
-
} catch (error) {
|
|
136
|
-
logWarn('PREBID - ' + BIDDER_CODE + ': Unable to stringify the schain: ' + error);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
144
|
// Add 3rd party user ID
|
|
141
145
|
if (currentBidRequest.userIdAsEids && currentBidRequest.userIdAsEids.length > 0) {
|
|
142
146
|
try {
|
|
@@ -179,7 +183,7 @@ export const spec = {
|
|
|
179
183
|
let videoPlacement = currentBidRequest.mediaTypes.video.placement ? currentBidRequest.mediaTypes.video.placement : null;
|
|
180
184
|
const videoPlcmt = currentBidRequest.mediaTypes.video.plcmt ? currentBidRequest.mediaTypes.video.plcmt : null;
|
|
181
185
|
|
|
182
|
-
if (currentBidRequest.params.format
|
|
186
|
+
if (currentBidRequest.params.format === 'inbanner') {
|
|
183
187
|
videoContext = 'In-Banner';
|
|
184
188
|
videoPlacement = 2;
|
|
185
189
|
}
|
|
@@ -188,6 +192,34 @@ export const spec = {
|
|
|
188
192
|
keyValues._fw_placement_type = videoPlacement;
|
|
189
193
|
keyValues._fw_plcmt_type = videoPlcmt;
|
|
190
194
|
}
|
|
195
|
+
|
|
196
|
+
const coppa = deepAccess(bidderRequest, 'ortb2.regs.coppa');
|
|
197
|
+
if (typeof coppa === 'number') {
|
|
198
|
+
keyValues._fw_coppa = coppa;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const atts = deepAccess(bidderRequest, 'ortb2.device.ext.atts');
|
|
202
|
+
if (typeof atts === 'number') {
|
|
203
|
+
keyValues._fw_atts = atts;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const lmt = deepAccess(bidderRequest, 'ortb2.device.lmt');
|
|
207
|
+
if (typeof lmt === 'number') {
|
|
208
|
+
keyValues._fw_is_lat = lmt;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
PRIVACY_VALUES = {}
|
|
212
|
+
if (keyValues._fw_coppa != null) {
|
|
213
|
+
PRIVACY_VALUES._fw_coppa = keyValues._fw_coppa;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (keyValues._fw_atts != null) {
|
|
217
|
+
PRIVACY_VALUES._fw_atts = keyValues._fw_atts;
|
|
218
|
+
}
|
|
219
|
+
if (keyValues._fw_is_lat != null) {
|
|
220
|
+
PRIVACY_VALUES._fw_is_lat = keyValues._fw_is_lat;
|
|
221
|
+
}
|
|
222
|
+
|
|
191
223
|
return keyValues;
|
|
192
224
|
}
|
|
193
225
|
|
|
@@ -212,28 +244,23 @@ export const spec = {
|
|
|
212
244
|
slid: currentBidRequest.params.slid ? currentBidRequest.params.slid : 'Preroll_1',
|
|
213
245
|
slau: currentBidRequest.params.slau ? currentBidRequest.params.slau : 'preroll',
|
|
214
246
|
}
|
|
215
|
-
|
|
216
|
-
|
|
247
|
+
const video = deepAccess(currentBidRequest, 'mediaTypes.video') || {};
|
|
248
|
+
const mind = video.minduration || currentBidRequest.params.minD;
|
|
249
|
+
const maxd = video.maxduration || currentBidRequest.params.maxD;
|
|
250
|
+
|
|
251
|
+
if (mind) {
|
|
252
|
+
slotParams.mind = mind;
|
|
217
253
|
}
|
|
218
|
-
if (
|
|
219
|
-
slotParams.maxd =
|
|
254
|
+
if (maxd) {
|
|
255
|
+
slotParams.maxd = maxd;
|
|
220
256
|
}
|
|
221
257
|
return slotParams
|
|
222
258
|
}
|
|
223
259
|
|
|
224
|
-
const constructDataString = (globalParams, keyValues, slotParams) => {
|
|
225
|
-
// Helper function to append parameters to the data string and to not include the last '&' param before ';
|
|
226
|
-
const appendParams = (params) => {
|
|
227
|
-
const keys = Object.keys(params);
|
|
228
|
-
return keys.map((key, index) => {
|
|
229
|
-
const encodedKey = encodeURIComponent(key);
|
|
230
|
-
const encodedValue = encodeURIComponent(params[key]);
|
|
231
|
-
return `${encodedKey}=${encodedValue}${index < keys.length - 1 ? '&' : ''}`;
|
|
232
|
-
}).join('');
|
|
233
|
-
};
|
|
234
|
-
|
|
260
|
+
const constructDataString = (globalParams, keyValues, serializedSChain, slotParams) => {
|
|
235
261
|
const globalParamsString = appendParams(globalParams) + ';';
|
|
236
|
-
|
|
262
|
+
// serializedSChain requires special encoding logic as outlined in the ORTB spec https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/supplychainobject.md
|
|
263
|
+
const keyValuesString = appendParams(keyValues) + serializedSChain + ';';
|
|
237
264
|
const slotParamsString = appendParams(slotParams) + ';';
|
|
238
265
|
|
|
239
266
|
return globalParamsString + keyValuesString + slotParamsString;
|
|
@@ -244,6 +271,21 @@ export const spec = {
|
|
|
244
271
|
});
|
|
245
272
|
},
|
|
246
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Serialize a supply chain object to a string uri encoded
|
|
276
|
+
*
|
|
277
|
+
* @param {*} schain object
|
|
278
|
+
*/
|
|
279
|
+
serializeSupplyChain: function(schain) {
|
|
280
|
+
if (!schain || !schain.nodes) return '';
|
|
281
|
+
const nodesProperties = ['asi', 'sid', 'hp', 'rid', 'name', 'domain'];
|
|
282
|
+
return `&schain=${schain.ver},${schain.complete}!` +
|
|
283
|
+
schain.nodes.map(node => nodesProperties.map(prop =>
|
|
284
|
+
node[prop] ? encodeURIComponent(node[prop]) : '')
|
|
285
|
+
.join(','))
|
|
286
|
+
.join('!');
|
|
287
|
+
},
|
|
288
|
+
|
|
247
289
|
/**
|
|
248
290
|
* Unpack the response from the server into a list of bids.
|
|
249
291
|
*
|
|
@@ -269,7 +311,7 @@ export const spec = {
|
|
|
269
311
|
playerSize = getBiggerSize(bidrequest.sizes);
|
|
270
312
|
}
|
|
271
313
|
|
|
272
|
-
if (typeof serverResponse
|
|
314
|
+
if (typeof serverResponse === 'object' && typeof serverResponse.body === 'string') {
|
|
273
315
|
serverResponse = serverResponse.body;
|
|
274
316
|
}
|
|
275
317
|
|
|
@@ -323,7 +365,10 @@ export const spec = {
|
|
|
323
365
|
},
|
|
324
366
|
|
|
325
367
|
getUserSyncs: function(syncOptions, responses, gdprConsent, uspConsent, gppConsent) {
|
|
326
|
-
const params = {
|
|
368
|
+
const params = {
|
|
369
|
+
mode: 'auto-user-sync',
|
|
370
|
+
...PRIVACY_VALUES
|
|
371
|
+
};
|
|
327
372
|
|
|
328
373
|
if (gdprConsent) {
|
|
329
374
|
if (typeof gdprConsent.gdprApplies === 'boolean') {
|
|
@@ -347,21 +392,19 @@ export const spec = {
|
|
|
347
392
|
}
|
|
348
393
|
}
|
|
349
394
|
|
|
350
|
-
|
|
351
|
-
if (params) {
|
|
352
|
-
queryString = '?' + `${formatQS(params)}`;
|
|
353
|
-
}
|
|
395
|
+
const url = USER_SYNC_URL + appendParams(params);
|
|
354
396
|
|
|
355
397
|
const syncs = [];
|
|
356
398
|
if (syncOptions && syncOptions.pixelEnabled) {
|
|
357
399
|
syncs.push({
|
|
358
400
|
type: 'image',
|
|
359
|
-
url:
|
|
401
|
+
url: url
|
|
360
402
|
});
|
|
361
|
-
}
|
|
403
|
+
}
|
|
404
|
+
if (syncOptions && syncOptions.iframeEnabled) {
|
|
362
405
|
syncs.push({
|
|
363
406
|
type: 'iframe',
|
|
364
|
-
url:
|
|
407
|
+
url: url
|
|
365
408
|
});
|
|
366
409
|
}
|
|
367
410
|
|
|
@@ -379,8 +422,8 @@ export function formatAdHTML(bidrequest, size) {
|
|
|
379
422
|
const sdkUrl = getSdkUrl(bidrequest);
|
|
380
423
|
const displayBaseId = 'fwssp_display_base';
|
|
381
424
|
|
|
382
|
-
const startMuted = typeof bidrequest.params.isMuted
|
|
383
|
-
const showMuteButton = typeof bidrequest.params.showMuteButton
|
|
425
|
+
const startMuted = typeof bidrequest.params.isMuted === 'boolean' ? bidrequest.params.isMuted : true
|
|
426
|
+
const showMuteButton = typeof bidrequest.params.showMuteButton === 'boolean' ? bidrequest.params.showMuteButton : false
|
|
384
427
|
|
|
385
428
|
let playerParams = null;
|
|
386
429
|
try {
|
|
@@ -450,7 +493,7 @@ export function formatAdHTML(bidrequest, size) {
|
|
|
450
493
|
}
|
|
451
494
|
|
|
452
495
|
function getSdkUrl(bidrequest) {
|
|
453
|
-
const isStg = bidrequest.params.env && bidrequest.params.env.toLowerCase()
|
|
496
|
+
const isStg = bidrequest.params.env && bidrequest.params.env.toLowerCase() === 'stg';
|
|
454
497
|
const host = isStg ? 'adm.stg.fwmrm.net' : 'mssl.fwmrm.net';
|
|
455
498
|
const sdkVersion = getSDKVersion(bidrequest);
|
|
456
499
|
return `https://${host}/libs/adm/${sdkVersion}/AdManager-prebid.js`
|
|
@@ -463,7 +506,7 @@ function getSdkUrl(bidrequest) {
|
|
|
463
506
|
* @returns {string} The SDK version to use, defaults to '7.10.0' if version parsing fails
|
|
464
507
|
*/
|
|
465
508
|
export function getSDKVersion(bidRequest) {
|
|
466
|
-
const DEFAULT = '7.
|
|
509
|
+
const DEFAULT = '7.11.0';
|
|
467
510
|
|
|
468
511
|
try {
|
|
469
512
|
const paramVersion = getSdkVersionFromBidRequest(bidRequest);
|
|
@@ -519,25 +562,37 @@ function compareVersions(versionA, versionB) {
|
|
|
519
562
|
return 0;
|
|
520
563
|
};
|
|
521
564
|
|
|
522
|
-
function getBidFloor(bid, config) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
565
|
+
export function getBidFloor(bid, config) {
|
|
566
|
+
logInfo('PREBID -: getBidFloor called with:', bid);
|
|
567
|
+
let floor = deepAccess(bid, 'params.bidfloor', 0); // fallback bid params
|
|
568
|
+
let currency = deepAccess(bid, 'params.bidfloorcur', 'USD'); // fallback bid params
|
|
526
569
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
570
|
+
if (isFn(bid.getFloor)) {
|
|
571
|
+
logInfo('PREBID - : getFloor() present and use it to retrieve floor and currency.');
|
|
572
|
+
try {
|
|
573
|
+
const floorInfo = bid.getFloor({
|
|
574
|
+
currency: config.getConfig('floors.data.currency') || 'USD',
|
|
575
|
+
mediaType: bid.mediaTypes.banner ? 'banner' : 'video',
|
|
576
|
+
size: '*',
|
|
577
|
+
}) || {};
|
|
578
|
+
|
|
579
|
+
// Use getFloor's results if valid
|
|
580
|
+
if (typeof floorInfo.floor === 'number') {
|
|
581
|
+
floor = floorInfo.floor;
|
|
582
|
+
}
|
|
538
583
|
|
|
539
|
-
|
|
540
|
-
|
|
584
|
+
if (floorInfo.currency) {
|
|
585
|
+
currency = floorInfo.currency;
|
|
586
|
+
}
|
|
587
|
+
logInfo('PREBID - : getFloor() returned floor:', floor, 'currency:', currency);
|
|
588
|
+
} catch (e) {
|
|
589
|
+
// fallback to static bid.params.bidfloor
|
|
590
|
+
floor = deepAccess(bid, 'params.bidfloor', 0);
|
|
591
|
+
currency = deepAccess(bid, 'params.bidfloorcur', 'USD');
|
|
592
|
+
logInfo('PREBID - : getFloor() exception, fallback to static bid.params.bidfloor:', floor, 'currency:', currency);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return { floor, currency };
|
|
541
596
|
}
|
|
542
597
|
|
|
543
598
|
function isValidUrl(str) {
|
|
@@ -658,13 +713,13 @@ function getValueFromKeyInImpressionNode(xmlNode, key) {
|
|
|
658
713
|
let tempValue = '';
|
|
659
714
|
queries.forEach(item => {
|
|
660
715
|
const split = item.split('=');
|
|
661
|
-
if (split[0]
|
|
716
|
+
if (split[0] === key) {
|
|
662
717
|
tempValue = split[1];
|
|
663
718
|
}
|
|
664
|
-
if (split[0]
|
|
719
|
+
if (split[0] === 'reqType' && split[1] === 'AdsDisplayStarted') {
|
|
665
720
|
isAdsDisplayStartedPresent = true;
|
|
666
721
|
}
|
|
667
|
-
if (split[0]
|
|
722
|
+
if (split[0] === 'rootViewKey') {
|
|
668
723
|
isRootViewKeyPresent = true;
|
|
669
724
|
}
|
|
670
725
|
});
|
|
@@ -705,4 +760,14 @@ function getTopMostWindow() {
|
|
|
705
760
|
return res;
|
|
706
761
|
}
|
|
707
762
|
|
|
763
|
+
// Helper function to append parameters to the data string and to not include the last '&' param before ';
|
|
764
|
+
function appendParams(params) {
|
|
765
|
+
const keys = Object.keys(params);
|
|
766
|
+
return keys.map((key, index) => {
|
|
767
|
+
const encodedKey = encodeURIComponent(key);
|
|
768
|
+
const encodedValue = encodeURIComponent(params[key]);
|
|
769
|
+
return `${encodedKey}=${encodedValue}${index < keys.length - 1 ? '&' : ''}`;
|
|
770
|
+
}).join('');
|
|
771
|
+
}
|
|
772
|
+
|
|
708
773
|
registerBidder(spec);
|
|
@@ -8,31 +8,126 @@ Maintainer: vis@freewheel.com
|
|
|
8
8
|
|
|
9
9
|
Module that connects to Freewheel MRM's demand sources
|
|
10
10
|
|
|
11
|
-
# Test
|
|
11
|
+
# Basic Test Request
|
|
12
12
|
```
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
13
|
+
const adUnits = [{
|
|
14
|
+
code: 'adunit-code',
|
|
15
|
+
mediaTypes: {
|
|
16
|
+
video: {
|
|
17
|
+
playerSize: [640, 480],
|
|
18
|
+
minduration: 30,
|
|
19
|
+
maxduration: 60
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
bids: [{
|
|
23
|
+
bidder: 'fwssp', // or use alias 'freewheel-mrm'
|
|
24
|
+
params: {
|
|
25
|
+
serverUrl: 'https://example.com/ad/g/1',
|
|
26
|
+
networkId: '42015',
|
|
27
|
+
profile: '42015:js_allinone_profile',
|
|
28
|
+
siteSectionId: 'js_allinone_demo_site_section',
|
|
29
|
+
videoAssetId: '1', // optional: default value of 0 will used if not included
|
|
30
|
+
flags: '+play-uapl' // optional: users may include capability if needed
|
|
31
|
+
mode: 'live',
|
|
32
|
+
adRequestKeyValues: { // optional: users may include adRequestKeyValues if needed
|
|
33
|
+
_fw_player_width: '1920',
|
|
34
|
+
_fw_player_height: '1080'
|
|
35
|
+
},
|
|
36
|
+
format: 'inbanner'
|
|
37
|
+
}
|
|
38
|
+
}]
|
|
39
|
+
}];
|
|
38
40
|
```
|
|
41
|
+
|
|
42
|
+
# Example Inbanner Ad Request
|
|
43
|
+
```
|
|
44
|
+
{
|
|
45
|
+
code: 'adunit-code',
|
|
46
|
+
mediaTypes: {
|
|
47
|
+
banner: {
|
|
48
|
+
'sizes': [[300, 250], [300, 600]]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
bids: [{
|
|
52
|
+
bidder: 'fwssp',
|
|
53
|
+
schain: {
|
|
54
|
+
ver: '1.0',
|
|
55
|
+
complete: 1,
|
|
56
|
+
nodes: [{
|
|
57
|
+
asi: 'example.com',
|
|
58
|
+
sid: '0',
|
|
59
|
+
hp: 1,
|
|
60
|
+
rid: 'bidrequestid',
|
|
61
|
+
domain: 'example.com'
|
|
62
|
+
}]
|
|
63
|
+
},
|
|
64
|
+
params: {
|
|
65
|
+
bidfloor: 2.00,
|
|
66
|
+
serverUrl: 'https://example.com/ad/g/1',
|
|
67
|
+
networkId: '42015',
|
|
68
|
+
profile: '42015:js_allinone_profile',
|
|
69
|
+
siteSectionId: 'js_allinone_demo_site_section',
|
|
70
|
+
flags: '+play',
|
|
71
|
+
videoAssetId: '1`, // optional: default value of 0 will used if not included
|
|
72
|
+
timePosition: 120,
|
|
73
|
+
adRequestKeyValues: {
|
|
74
|
+
_fw_player_width: '1920',
|
|
75
|
+
_fw_player_height: '1080',
|
|
76
|
+
_fw_content_programmer_brand: 'NEEDS_TO_REPLACE_BY_BRAND_NAME',
|
|
77
|
+
_fw_content_programmer_brand_channel: 'NEEDS_TO_REPLACE_BY_CHANNEL_NAME',
|
|
78
|
+
_fw_content_genre: 'NEEDS_TO_REPLACE_BY_CONTENT_GENRE'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
# Example Instream Ad Request
|
|
86
|
+
```
|
|
87
|
+
{
|
|
88
|
+
code: 'adunit-code',
|
|
89
|
+
mediaTypes: {
|
|
90
|
+
video: {
|
|
91
|
+
playerSize: [300, 600],
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
bids: [{
|
|
95
|
+
bidder: 'fwssp',
|
|
96
|
+
schain: {
|
|
97
|
+
ver: '1.0',
|
|
98
|
+
complete: 1,
|
|
99
|
+
nodes: [{
|
|
100
|
+
asi: 'example.com',
|
|
101
|
+
sid: '0',
|
|
102
|
+
hp: 1,
|
|
103
|
+
rid: 'bidrequestid',
|
|
104
|
+
domain: 'example.com'
|
|
105
|
+
}]
|
|
106
|
+
},
|
|
107
|
+
params: {
|
|
108
|
+
bidfloor: 2.00,
|
|
109
|
+
serverUrl: 'https://example.com/ad/g/1',
|
|
110
|
+
networkId: '42015',
|
|
111
|
+
profile: '42015:js_allinone_profile',
|
|
112
|
+
siteSectionId: 'js_allinone_demo_site_section',
|
|
113
|
+
flags: '+play',
|
|
114
|
+
videoAssetId: '1', // optional: default value of 0 will used if not included
|
|
115
|
+
mode: 'live',
|
|
116
|
+
timePosition: 120,
|
|
117
|
+
tpos: 300,
|
|
118
|
+
slid: 'Midroll',
|
|
119
|
+
slau: 'midroll',
|
|
120
|
+
minD: 30,
|
|
121
|
+
maxD: 60,
|
|
122
|
+
adRequestKeyValues: {
|
|
123
|
+
_fw_player_width: '1920',
|
|
124
|
+
_fw_player_height: '1080',
|
|
125
|
+
_fw_content_progrmmer_brand: 'NEEDS_TO_REPLACE_BY_BRAND_NAME',
|
|
126
|
+
_fw_content_programmer_brand_channel: 'NEEDS_TO_REPLACE_BY_CHANNEL_NAME',
|
|
127
|
+
_fw_content_genre: 'NEEDS_TO_REPLACE_BY_CONTENT_GENRE'
|
|
128
|
+
},
|
|
129
|
+
gdpr_consented_providers: 'test_providers'
|
|
130
|
+
}
|
|
131
|
+
}]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
@@ -15,8 +15,8 @@ const {logMessage, logWarn, logError} = optableLog;
|
|
|
15
15
|
*/
|
|
16
16
|
export const parseConfig = (moduleConfig) => {
|
|
17
17
|
let bundleUrl = deepAccess(moduleConfig, 'params.bundleUrl', null);
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const adserverTargeting = deepAccess(moduleConfig, 'params.adserverTargeting', true);
|
|
19
|
+
const handleRtd = deepAccess(moduleConfig, 'params.handleRtd', null);
|
|
20
20
|
|
|
21
21
|
// If present, trim the bundle URL
|
|
22
22
|
if (typeof bundleUrl === 'string') {
|
|
@@ -37,6 +37,35 @@ export const parseConfig = (moduleConfig) => {
|
|
|
37
37
|
return {bundleUrl, adserverTargeting, handleRtd};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Wait for Optable SDK event to fire with targeting data
|
|
42
|
+
* @param {string} eventName Name of the event to listen for
|
|
43
|
+
* @returns {Promise<Object|null>} Promise that resolves with targeting data or null
|
|
44
|
+
*/
|
|
45
|
+
const waitForOptableEvent = (eventName) => {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const optableBundle = /** @type {Object} */ (window.optable);
|
|
48
|
+
const cachedData = optableBundle?.instance?.targetingFromCache();
|
|
49
|
+
|
|
50
|
+
if (cachedData && cachedData.ortb2) {
|
|
51
|
+
logMessage('Optable SDK already has cached data');
|
|
52
|
+
resolve(cachedData);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const eventListener = (event) => {
|
|
57
|
+
logMessage(`Received ${eventName} event`);
|
|
58
|
+
// Extract targeting data from event detail
|
|
59
|
+
const targetingData = event.detail;
|
|
60
|
+
window.removeEventListener(eventName, eventListener);
|
|
61
|
+
resolve(targetingData);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
window.addEventListener(eventName, eventListener);
|
|
65
|
+
logMessage(`Waiting for ${eventName} event`);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
40
69
|
/**
|
|
41
70
|
* Default function to handle/enrich RTD data
|
|
42
71
|
* @param reqBidsConfigObj Bid request configuration object
|
|
@@ -45,15 +74,8 @@ export const parseConfig = (moduleConfig) => {
|
|
|
45
74
|
* @returns {Promise<void>}
|
|
46
75
|
*/
|
|
47
76
|
export const defaultHandleRtd = async (reqBidsConfigObj, optableExtraData, mergeFn) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let targetingData = optableBundle?.instance?.targetingFromCache();
|
|
51
|
-
// If no targeting data is found in the cache, call the targeting function
|
|
52
|
-
if (!targetingData) {
|
|
53
|
-
// Call Optable DCN for targeting data and return the ORTB2 object
|
|
54
|
-
targetingData = await optableBundle?.instance?.targeting();
|
|
55
|
-
}
|
|
56
|
-
logMessage('Original targeting data from targeting(): ', targetingData);
|
|
77
|
+
// Wait for the Optable SDK to dispatch targeting data via event
|
|
78
|
+
let targetingData = await waitForOptableEvent('optable-targeting:change');
|
|
57
79
|
|
|
58
80
|
if (!targetingData || !targetingData.ortb2) {
|
|
59
81
|
logWarn('No targeting data found');
|
|
@@ -92,7 +114,6 @@ export const getBidRequestData = (reqBidsConfigObj, callback, moduleConfig, user
|
|
|
92
114
|
try {
|
|
93
115
|
// Extract the bundle URL from the module configuration
|
|
94
116
|
const {bundleUrl, handleRtd} = parseConfig(moduleConfig);
|
|
95
|
-
|
|
96
117
|
const handleRtdFn = handleRtd || defaultHandleRtd;
|
|
97
118
|
const optableExtraData = config.getConfig('optableRtdConfig') || {};
|
|
98
119
|
|