prebid.js 6.29.2 → 6.29.3
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/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/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/bidwatchAnalyticsAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- 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/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/lassoBidAdapter.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/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +105 -105
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/oneVideoBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxAnalyticsAdapter.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 +3 -3
- 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/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/sortableBidAdapter.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/trustxBidAdapter.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/modules/bidwatchAnalyticsAdapter.js +132 -20
- package/modules/openxAnalyticsAdapter.js +7 -746
- package/modules/openxAnalyticsAdapter.md +3 -0
- package/modules/yahoosspBidAdapter.js +2 -1
- package/package.json +1 -1
- package/test/spec/modules/bidwatchAnalyticsAdapter_spec.js +37 -5
- package/test/spec/modules/openxAnalyticsAdapter_spec.js +6 -638
- package/test/spec/modules/yahoosspBidAdapter_spec.js +13 -0
|
@@ -1,128 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
_map,
|
|
4
|
-
deepAccess,
|
|
5
|
-
flatten,
|
|
6
|
-
getWindowLocation,
|
|
7
|
-
isEmpty,
|
|
8
|
-
logError,
|
|
9
|
-
logInfo,
|
|
10
|
-
logMessage,
|
|
11
|
-
logWarn,
|
|
12
|
-
parseQS,
|
|
13
|
-
parseSizesInput,
|
|
14
|
-
uniques
|
|
2
|
+
logWarn
|
|
15
3
|
} from '../src/utils.js';
|
|
16
|
-
import adapter from '../src/AnalyticsAdapter.js'
|
|
17
|
-
import
|
|
18
|
-
import adapterManager from '../src/adapterManager.js';
|
|
19
|
-
import {ajax} from '../src/ajax.js';
|
|
20
|
-
import {find, includes} from '../src/polyfill.js';
|
|
4
|
+
import adapter from '../src/AnalyticsAdapter.js'
|
|
5
|
+
import adapterManager from '../src/adapterManager.js'
|
|
21
6
|
|
|
22
|
-
|
|
23
|
-
INIT: 'initialized', // auction has initialized
|
|
24
|
-
ENDED: 'ended', // all auction requests have been accounted for
|
|
25
|
-
COMPLETED: 'completed' // all slots have rendered
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const ADAPTER_VERSION = '0.1';
|
|
29
|
-
const SCHEMA_VERSION = '0.1';
|
|
30
|
-
|
|
31
|
-
const AUCTION_END_WAIT_TIME = 1000;
|
|
32
|
-
const URL_PARAM = '';
|
|
33
|
-
const ANALYTICS_TYPE = 'endpoint';
|
|
34
|
-
const ENDPOINT = 'https://prebid.openx.net/ox/analytics/';
|
|
35
|
-
|
|
36
|
-
// Event Types
|
|
37
|
-
const {
|
|
38
|
-
EVENTS: { AUCTION_INIT, BID_REQUESTED, BID_RESPONSE, BID_TIMEOUT, AUCTION_END, BID_WON }
|
|
39
|
-
} = CONSTANTS;
|
|
40
|
-
const SLOT_LOADED = 'slotOnload';
|
|
41
|
-
|
|
42
|
-
const UTM_TAGS = [
|
|
43
|
-
'utm_campaign',
|
|
44
|
-
'utm_source',
|
|
45
|
-
'utm_medium',
|
|
46
|
-
'utm_term',
|
|
47
|
-
'utm_content'
|
|
48
|
-
];
|
|
49
|
-
const UTM_TO_CAMPAIGN_PROPERTIES = {
|
|
50
|
-
'utm_campaign': 'name',
|
|
51
|
-
'utm_source': 'source',
|
|
52
|
-
'utm_medium': 'medium',
|
|
53
|
-
'utm_term': 'term',
|
|
54
|
-
'utm_content': 'content'
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @typedef {Object} OxAnalyticsConfig
|
|
59
|
-
* @property {string} orgId
|
|
60
|
-
* @property {string} publisherPlatformId
|
|
61
|
-
* @property {number} publisherAccountId
|
|
62
|
-
* @property {string} configId
|
|
63
|
-
* @property {string} optimizerConfig
|
|
64
|
-
* @property {number} sampling
|
|
65
|
-
* @property {Object} campaign
|
|
66
|
-
* @property {number} payloadWaitTime
|
|
67
|
-
* @property {number} payloadWaitTimePadding
|
|
68
|
-
* @property {Array<string>} adUnits
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @type {OxAnalyticsConfig}
|
|
73
|
-
*/
|
|
74
|
-
const DEFAULT_ANALYTICS_CONFIG = {
|
|
75
|
-
orgId: void (0),
|
|
76
|
-
publisherPlatformId: void (0),
|
|
77
|
-
publisherAccountId: void (0),
|
|
78
|
-
sampling: 0.05, // default sampling rate of 5%
|
|
79
|
-
testCode: 'default',
|
|
80
|
-
campaign: {},
|
|
81
|
-
adUnits: [],
|
|
82
|
-
payloadWaitTime: AUCTION_END_WAIT_TIME,
|
|
83
|
-
payloadWaitTimePadding: 2000
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
// Initialization
|
|
87
|
-
/**
|
|
88
|
-
* @type {OxAnalyticsConfig}
|
|
89
|
-
*/
|
|
90
|
-
let analyticsConfig;
|
|
91
|
-
let auctionMap = {};
|
|
92
|
-
let auctionOrder = 1; // tracks the number of auctions ran on the page
|
|
93
|
-
|
|
94
|
-
let googletag = window.googletag || {};
|
|
95
|
-
googletag.cmd = googletag.cmd || [];
|
|
96
|
-
|
|
97
|
-
let openxAdapter = Object.assign(adapter({ urlParam: URL_PARAM, analyticsType: ANALYTICS_TYPE }));
|
|
7
|
+
let openxAdapter = Object.assign(adapter({ urlParam: '', analyticsType: 'endpoint' }));
|
|
98
8
|
|
|
99
9
|
openxAdapter.originEnableAnalytics = openxAdapter.enableAnalytics;
|
|
100
10
|
|
|
101
11
|
openxAdapter.enableAnalytics = function(adapterConfig = {options: {}}) {
|
|
102
|
-
|
|
103
|
-
analyticsConfig = {...DEFAULT_ANALYTICS_CONFIG, ...adapterConfig.options};
|
|
104
|
-
|
|
105
|
-
// campaign properties defined by config will override utm query parameters
|
|
106
|
-
analyticsConfig.campaign = {...buildCampaignFromUtmCodes(), ...analyticsConfig.campaign};
|
|
107
|
-
|
|
108
|
-
logInfo('OpenX Analytics enabled with config', analyticsConfig);
|
|
12
|
+
logWarn('OpenX Analytics has been deprecated, this adapter will be removed in Prebid 8');
|
|
109
13
|
|
|
110
|
-
|
|
111
|
-
openxAdapter.track = prebidAnalyticsEventHandler;
|
|
14
|
+
openxAdapter.track = prebidAnalyticsEventHandler;
|
|
112
15
|
|
|
113
|
-
|
|
114
|
-
let pubads = googletag.pubads();
|
|
115
|
-
|
|
116
|
-
if (pubads.addEventListener) {
|
|
117
|
-
pubads.addEventListener(SLOT_LOADED, args => {
|
|
118
|
-
openxAdapter.track({eventType: SLOT_LOADED, args});
|
|
119
|
-
logInfo('OX: SlotOnLoad event triggered');
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
openxAdapter.originEnableAnalytics(adapterConfig);
|
|
125
|
-
}
|
|
16
|
+
openxAdapter.originEnableAnalytics(adapterConfig);
|
|
126
17
|
};
|
|
127
18
|
|
|
128
19
|
adapterManager.registerAnalyticsAdapter({
|
|
@@ -132,635 +23,5 @@ adapterManager.registerAnalyticsAdapter({
|
|
|
132
23
|
|
|
133
24
|
export default openxAdapter;
|
|
134
25
|
|
|
135
|
-
/**
|
|
136
|
-
* Test Helper Functions
|
|
137
|
-
*/
|
|
138
|
-
|
|
139
|
-
// reset the cache for unit tests
|
|
140
|
-
openxAdapter.reset = function() {
|
|
141
|
-
auctionMap = {};
|
|
142
|
-
auctionOrder = 1;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Private Functions
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
|
-
function isValidConfig({options: analyticsOptions}) {
|
|
150
|
-
let hasOrgId = analyticsOptions && analyticsOptions.orgId !== void (0);
|
|
151
|
-
|
|
152
|
-
const fieldValidations = [
|
|
153
|
-
// tuple of property, type, required
|
|
154
|
-
['orgId', 'string', hasOrgId],
|
|
155
|
-
['publisherPlatformId', 'string', !hasOrgId],
|
|
156
|
-
['publisherAccountId', 'number', !hasOrgId],
|
|
157
|
-
['configId', 'string', false],
|
|
158
|
-
['optimizerConfig', 'string', false],
|
|
159
|
-
['sampling', 'number', false],
|
|
160
|
-
['adIdKey', 'string', false],
|
|
161
|
-
['payloadWaitTime', 'number', false],
|
|
162
|
-
['payloadWaitTimePadding', 'number', false],
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
let failedValidation = find(fieldValidations, ([property, type, required]) => {
|
|
166
|
-
// if required, the property has to exist
|
|
167
|
-
// if property exists, type check value
|
|
168
|
-
return (required && !analyticsOptions.hasOwnProperty(property)) ||
|
|
169
|
-
/* eslint-disable valid-typeof */
|
|
170
|
-
(analyticsOptions.hasOwnProperty(property) && typeof analyticsOptions[property] !== type);
|
|
171
|
-
});
|
|
172
|
-
if (failedValidation) {
|
|
173
|
-
let [property, type, required] = failedValidation;
|
|
174
|
-
|
|
175
|
-
if (required) {
|
|
176
|
-
logError(`OpenXAnalyticsAdapter: Expected '${property}' to exist and of type '${type}'`);
|
|
177
|
-
} else {
|
|
178
|
-
logError(`OpenXAnalyticsAdapter: Expected '${property}' to be type '${type}'`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return !failedValidation;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function buildCampaignFromUtmCodes() {
|
|
186
|
-
const location = getWindowLocation();
|
|
187
|
-
const queryParams = parseQS(location && location.search);
|
|
188
|
-
let campaign = {};
|
|
189
|
-
|
|
190
|
-
UTM_TAGS.forEach(function(utmKey) {
|
|
191
|
-
let utmValue = queryParams[utmKey];
|
|
192
|
-
if (utmValue) {
|
|
193
|
-
let key = UTM_TO_CAMPAIGN_PROPERTIES[utmKey];
|
|
194
|
-
campaign[key] = decodeURIComponent(utmValue);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
return campaign;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function detectMob() {
|
|
201
|
-
if (
|
|
202
|
-
navigator.userAgent.match(/Android/i) ||
|
|
203
|
-
navigator.userAgent.match(/webOS/i) ||
|
|
204
|
-
navigator.userAgent.match(/iPhone/i) ||
|
|
205
|
-
navigator.userAgent.match(/iPad/i) ||
|
|
206
|
-
navigator.userAgent.match(/iPod/i) ||
|
|
207
|
-
navigator.userAgent.match(/BlackBerry/i) ||
|
|
208
|
-
navigator.userAgent.match(/Windows Phone/i)
|
|
209
|
-
) {
|
|
210
|
-
return true;
|
|
211
|
-
} else {
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function detectOS() {
|
|
217
|
-
if (navigator.userAgent.indexOf('Android') != -1) return 'Android';
|
|
218
|
-
if (navigator.userAgent.indexOf('like Mac') != -1) return 'iOS';
|
|
219
|
-
if (navigator.userAgent.indexOf('Win') != -1) return 'Windows';
|
|
220
|
-
if (navigator.userAgent.indexOf('Mac') != -1) return 'Macintosh';
|
|
221
|
-
if (navigator.userAgent.indexOf('Linux') != -1) return 'Linux';
|
|
222
|
-
if (navigator.appVersion.indexOf('X11') != -1) return 'Unix';
|
|
223
|
-
return 'Others';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function detectBrowser() {
|
|
227
|
-
var isChrome =
|
|
228
|
-
/Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
|
229
|
-
var isCriOS = navigator.userAgent.match('CriOS');
|
|
230
|
-
var isSafari =
|
|
231
|
-
/Safari/.test(navigator.userAgent) &&
|
|
232
|
-
/Apple Computer/.test(navigator.vendor);
|
|
233
|
-
var isFirefox = /Firefox/.test(navigator.userAgent);
|
|
234
|
-
var isIE =
|
|
235
|
-
/Trident/.test(navigator.userAgent) || /MSIE/.test(navigator.userAgent);
|
|
236
|
-
var isEdge = /Edge/.test(navigator.userAgent);
|
|
237
|
-
if (isIE) return 'Internet Explorer';
|
|
238
|
-
if (isEdge) return 'Microsoft Edge';
|
|
239
|
-
if (isCriOS) return 'Chrome';
|
|
240
|
-
if (isSafari) return 'Safari';
|
|
241
|
-
if (isFirefox) return 'Firefox';
|
|
242
|
-
if (isChrome) return 'Chrome';
|
|
243
|
-
return 'Others';
|
|
244
|
-
}
|
|
245
|
-
|
|
246
26
|
function prebidAnalyticsEventHandler({eventType, args}) {
|
|
247
|
-
logMessage(eventType, Object.assign({}, args));
|
|
248
|
-
switch (eventType) {
|
|
249
|
-
case AUCTION_INIT:
|
|
250
|
-
onAuctionInit(args);
|
|
251
|
-
break;
|
|
252
|
-
case BID_REQUESTED:
|
|
253
|
-
onBidRequested(args);
|
|
254
|
-
break;
|
|
255
|
-
case BID_RESPONSE:
|
|
256
|
-
onBidResponse(args);
|
|
257
|
-
break;
|
|
258
|
-
case BID_TIMEOUT:
|
|
259
|
-
onBidTimeout(args);
|
|
260
|
-
break;
|
|
261
|
-
case AUCTION_END:
|
|
262
|
-
onAuctionEnd(args);
|
|
263
|
-
break;
|
|
264
|
-
case BID_WON:
|
|
265
|
-
onBidWon(args);
|
|
266
|
-
break;
|
|
267
|
-
case SLOT_LOADED:
|
|
268
|
-
onSlotLoadedV2(args);
|
|
269
|
-
break;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* @typedef {Object} PbAuction
|
|
275
|
-
* @property {string} auctionId - Auction ID of the request this bid responded to
|
|
276
|
-
* @property {number} timestamp //: 1586675964364
|
|
277
|
-
* @property {number} auctionEnd - timestamp of when auction ended //: 1586675964364
|
|
278
|
-
* @property {string} auctionStatus //: "inProgress"
|
|
279
|
-
* @property {Array<Adunit>} adUnits //: [{…}]
|
|
280
|
-
* @property {string} adUnitCodes //: ["video1"]
|
|
281
|
-
* @property {string} labels //: undefined
|
|
282
|
-
* @property {Array<BidRequest>} bidderRequests //: (2) [{…}, {…}]
|
|
283
|
-
* @property {Array<BidRequest>} noBids //: []
|
|
284
|
-
* @property {Array<BidResponse>} bidsReceived //: []
|
|
285
|
-
* @property {Array<BidResponse>} winningBids //: []
|
|
286
|
-
* @property {number} timeout //: 3000
|
|
287
|
-
* @property {Object} config //: {publisherPlatformId: "a3aece0c-9e80-4316-8deb-faf804779bd1", publisherAccountId: 537143056, sampling: 1}/*
|
|
288
|
-
*/
|
|
289
|
-
|
|
290
|
-
function onAuctionInit({auctionId, timestamp: startTime, timeout, adUnitCodes}) {
|
|
291
|
-
auctionMap[auctionId] = {
|
|
292
|
-
id: auctionId,
|
|
293
|
-
startTime,
|
|
294
|
-
endTime: void (0),
|
|
295
|
-
timeout,
|
|
296
|
-
auctionOrder,
|
|
297
|
-
userIds: [],
|
|
298
|
-
adUnitCodesCount: adUnitCodes.length,
|
|
299
|
-
adunitCodesRenderedCount: 0,
|
|
300
|
-
state: AUCTION_STATES.INIT,
|
|
301
|
-
auctionSendDelayTimer: void (0),
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
// setup adunit properties in map
|
|
305
|
-
auctionMap[auctionId].adUnitCodeToAdUnitMap = adUnitCodes.reduce((obj, adunitCode) => {
|
|
306
|
-
obj[adunitCode] = {
|
|
307
|
-
code: adunitCode,
|
|
308
|
-
adPosition: void (0),
|
|
309
|
-
bidRequestsMap: {}
|
|
310
|
-
};
|
|
311
|
-
return obj;
|
|
312
|
-
}, {});
|
|
313
|
-
|
|
314
|
-
auctionOrder++;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* @typedef {Object} PbBidRequest
|
|
319
|
-
* @property {string} auctionId - Auction ID of the request this bid responded to
|
|
320
|
-
* @property {number} auctionStart //: 1586675964364
|
|
321
|
-
* @property {Object} refererInfo
|
|
322
|
-
* @property {PbBidderRequest} bids
|
|
323
|
-
* @property {number} start - Start timestamp of the bidder request
|
|
324
|
-
*
|
|
325
|
-
*/
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* @typedef {Object} PbBidderRequest
|
|
329
|
-
* @property {string} adUnitCode - Name of div or google adunit path
|
|
330
|
-
* @property {string} bidder - Bame of bidder
|
|
331
|
-
* @property {string} bidId - Identifies the bid request
|
|
332
|
-
* @property {Object} mediaTypes
|
|
333
|
-
* @property {Object} params
|
|
334
|
-
* @property {string} src
|
|
335
|
-
* @property {Object} userId - Map of userId module to module object
|
|
336
|
-
*/
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Tracks the bid request
|
|
340
|
-
* @param {PbBidRequest} bidRequest
|
|
341
|
-
*/
|
|
342
|
-
function onBidRequested(bidRequest) {
|
|
343
|
-
const {auctionId, bids: bidderRequests, start, timeout} = bidRequest;
|
|
344
|
-
const auction = auctionMap[auctionId];
|
|
345
|
-
const adUnitCodeToAdUnitMap = auction.adUnitCodeToAdUnitMap;
|
|
346
|
-
|
|
347
|
-
bidderRequests.forEach(bidderRequest => {
|
|
348
|
-
const { adUnitCode, bidder, bidId: requestId, mediaTypes, params, src, userId } = bidderRequest;
|
|
349
|
-
|
|
350
|
-
auction.userIds.push(userId);
|
|
351
|
-
adUnitCodeToAdUnitMap[adUnitCode].bidRequestsMap[requestId] = {
|
|
352
|
-
bidder,
|
|
353
|
-
params,
|
|
354
|
-
mediaTypes,
|
|
355
|
-
source: src,
|
|
356
|
-
startTime: start,
|
|
357
|
-
timedOut: false,
|
|
358
|
-
timeLimit: timeout,
|
|
359
|
-
bids: {}
|
|
360
|
-
};
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
*
|
|
366
|
-
* @param {BidResponse} bidResponse
|
|
367
|
-
*/
|
|
368
|
-
function onBidResponse(bidResponse) {
|
|
369
|
-
let {
|
|
370
|
-
auctionId,
|
|
371
|
-
adUnitCode,
|
|
372
|
-
requestId,
|
|
373
|
-
cpm,
|
|
374
|
-
creativeId,
|
|
375
|
-
requestTimestamp,
|
|
376
|
-
responseTimestamp,
|
|
377
|
-
ts,
|
|
378
|
-
mediaType,
|
|
379
|
-
dealId,
|
|
380
|
-
ttl,
|
|
381
|
-
netRevenue,
|
|
382
|
-
currency,
|
|
383
|
-
originalCpm,
|
|
384
|
-
originalCurrency,
|
|
385
|
-
width,
|
|
386
|
-
height,
|
|
387
|
-
timeToRespond: latency,
|
|
388
|
-
adId,
|
|
389
|
-
meta
|
|
390
|
-
} = bidResponse;
|
|
391
|
-
|
|
392
|
-
auctionMap[auctionId].adUnitCodeToAdUnitMap[adUnitCode].bidRequestsMap[requestId].bids[adId] = {
|
|
393
|
-
cpm,
|
|
394
|
-
creativeId,
|
|
395
|
-
requestTimestamp,
|
|
396
|
-
responseTimestamp,
|
|
397
|
-
ts,
|
|
398
|
-
adId,
|
|
399
|
-
meta,
|
|
400
|
-
mediaType,
|
|
401
|
-
dealId,
|
|
402
|
-
ttl,
|
|
403
|
-
netRevenue,
|
|
404
|
-
currency,
|
|
405
|
-
originalCpm,
|
|
406
|
-
originalCurrency,
|
|
407
|
-
width,
|
|
408
|
-
height,
|
|
409
|
-
latency,
|
|
410
|
-
winner: false,
|
|
411
|
-
rendered: false,
|
|
412
|
-
renderTime: 0,
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function onBidTimeout(args) {
|
|
417
|
-
_each(args, ({auctionId, adUnitCode, bidId: requestId}) => {
|
|
418
|
-
let timedOutRequest = deepAccess(auctionMap,
|
|
419
|
-
`${auctionId}.adUnitCodeToAdUnitMap.${adUnitCode}.bidRequestsMap.${requestId}`);
|
|
420
|
-
|
|
421
|
-
if (timedOutRequest) {
|
|
422
|
-
timedOutRequest.timedOut = true;
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
*
|
|
428
|
-
* @param {PbAuction} endedAuction
|
|
429
|
-
*/
|
|
430
|
-
function onAuctionEnd(endedAuction) {
|
|
431
|
-
let auction = auctionMap[endedAuction.auctionId];
|
|
432
|
-
|
|
433
|
-
if (!auction) {
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
clearAuctionTimer(auction);
|
|
438
|
-
auction.endTime = endedAuction.auctionEnd;
|
|
439
|
-
auction.state = AUCTION_STATES.ENDED;
|
|
440
|
-
delayedSend(auction);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
*
|
|
445
|
-
* @param {BidResponse} bidResponse
|
|
446
|
-
*/
|
|
447
|
-
function onBidWon(bidResponse) {
|
|
448
|
-
const { auctionId, adUnitCode, requestId, adId } = bidResponse;
|
|
449
|
-
let winningBid = deepAccess(auctionMap,
|
|
450
|
-
`${auctionId}.adUnitCodeToAdUnitMap.${adUnitCode}.bidRequestsMap.${requestId}.bids.${adId}`);
|
|
451
|
-
|
|
452
|
-
if (winningBid) {
|
|
453
|
-
winningBid.winner = true;
|
|
454
|
-
const auction = auctionMap[auctionId];
|
|
455
|
-
if (auction.sent) {
|
|
456
|
-
const endpoint = (analyticsConfig.endpoint || ENDPOINT) + 'event';
|
|
457
|
-
const bidder = auction.adUnitCodeToAdUnitMap[adUnitCode].bidRequestsMap[requestId].bidder;
|
|
458
|
-
ajax(`${endpoint}?t=win&b=${adId}&a=${analyticsConfig.orgId}&bidder=${bidder}&ts=${auction.startTime}`,
|
|
459
|
-
() => {
|
|
460
|
-
logInfo(`Openx Analytics - Sending complete impression event for ${adId} at ${Date.now()}`)
|
|
461
|
-
});
|
|
462
|
-
} else {
|
|
463
|
-
logInfo(`Openx Analytics - impression event for ${adId} will be sent with auction data`)
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
*
|
|
470
|
-
* @param {GoogleTagSlot} slot
|
|
471
|
-
* @param {string} serviceName
|
|
472
|
-
*/
|
|
473
|
-
function onSlotLoadedV2({ slot }) {
|
|
474
|
-
const renderTime = Date.now();
|
|
475
|
-
const elementId = slot.getSlotElementId();
|
|
476
|
-
const bidId = slot.getTargeting('hb_adid')[0];
|
|
477
|
-
|
|
478
|
-
let [auction, adUnit, bid] = getPathToBidResponseByBidId(bidId);
|
|
479
|
-
|
|
480
|
-
if (!auction) {
|
|
481
|
-
// attempt to get auction by adUnitCode
|
|
482
|
-
auction = getAuctionByGoogleTagSLot(slot);
|
|
483
|
-
|
|
484
|
-
if (!auction) {
|
|
485
|
-
return; // slot is not participating in an active prebid auction
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
clearAuctionTimer(auction);
|
|
490
|
-
|
|
491
|
-
// track that an adunit code has completed within an auction
|
|
492
|
-
auction.adunitCodesRenderedCount++;
|
|
493
|
-
|
|
494
|
-
// mark adunit as rendered
|
|
495
|
-
if (bid) {
|
|
496
|
-
let {x, y} = getPageOffset();
|
|
497
|
-
bid.rendered = true;
|
|
498
|
-
bid.renderTime = renderTime;
|
|
499
|
-
adUnit.adPosition = isAtf(elementId, x, y) ? 'ATF' : 'BTF';
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
if (auction.adunitCodesRenderedCount === auction.adUnitCodesCount) {
|
|
503
|
-
auction.state = AUCTION_STATES.COMPLETED;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// prepare to send regardless if auction is complete or not as a failsafe in case not all events are tracked
|
|
507
|
-
// add additional padding when not all slots are rendered
|
|
508
|
-
delayedSend(auction);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
function isAtf(elementId, scrollLeft = 0, scrollTop = 0) {
|
|
512
|
-
let elem = document.querySelector('#' + elementId);
|
|
513
|
-
let isAtf = false;
|
|
514
|
-
if (elem) {
|
|
515
|
-
let bounding = elem.getBoundingClientRect();
|
|
516
|
-
if (bounding) {
|
|
517
|
-
let windowWidth = (window.innerWidth || document.documentElement.clientWidth);
|
|
518
|
-
let windowHeight = (window.innerHeight || document.documentElement.clientHeight);
|
|
519
|
-
|
|
520
|
-
// intersection coordinates
|
|
521
|
-
let left = Math.max(0, bounding.left + scrollLeft);
|
|
522
|
-
let right = Math.min(windowWidth, bounding.right + scrollLeft);
|
|
523
|
-
let top = Math.max(0, bounding.top + scrollTop);
|
|
524
|
-
let bottom = Math.min(windowHeight, bounding.bottom + scrollTop);
|
|
525
|
-
|
|
526
|
-
let intersectionWidth = right - left;
|
|
527
|
-
let intersectionHeight = bottom - top;
|
|
528
|
-
|
|
529
|
-
let intersectionArea = (intersectionHeight > 0 && intersectionWidth > 0) ? (intersectionHeight * intersectionWidth) : 0;
|
|
530
|
-
let adSlotArea = (bounding.right - bounding.left) * (bounding.bottom - bounding.top);
|
|
531
|
-
|
|
532
|
-
if (adSlotArea > 0) {
|
|
533
|
-
// Atleast 50% of intersection in window
|
|
534
|
-
isAtf = intersectionArea * 2 >= adSlotArea;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
} else {
|
|
538
|
-
logWarn('OX: DOM element not for id ' + elementId);
|
|
539
|
-
}
|
|
540
|
-
return isAtf;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// backwards compatible pageOffset from https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollX
|
|
544
|
-
function getPageOffset() {
|
|
545
|
-
var x = (window.pageXOffset !== undefined)
|
|
546
|
-
? window.pageXOffset
|
|
547
|
-
: (document.documentElement || document.body.parentNode || document.body).scrollLeft;
|
|
548
|
-
|
|
549
|
-
var y = (window.pageYOffset !== undefined)
|
|
550
|
-
? window.pageYOffset
|
|
551
|
-
: (document.documentElement || document.body.parentNode || document.body).scrollTop;
|
|
552
|
-
return {x, y};
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function delayedSend(auction) {
|
|
556
|
-
if (auction.sent) {
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
const delayTime = auction.adunitCodesRenderedCount === auction.adUnitCodesCount
|
|
560
|
-
? analyticsConfig.payloadWaitTime
|
|
561
|
-
: analyticsConfig.payloadWaitTime + analyticsConfig.payloadWaitTimePadding;
|
|
562
|
-
|
|
563
|
-
auction.auctionSendDelayTimer = setTimeout(() => {
|
|
564
|
-
auction.sent = true; // any BidWon emitted after this will be recorded separately
|
|
565
|
-
let payload = JSON.stringify([buildAuctionPayload(auction)]);
|
|
566
|
-
|
|
567
|
-
ajax(analyticsConfig.endpoint || ENDPOINT, () => {
|
|
568
|
-
logInfo(`OpenX Analytics - Sending complete auction at ${Date.now()}`);
|
|
569
|
-
}, payload, { contentType: 'application/json' });
|
|
570
|
-
}, delayTime);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
function clearAuctionTimer(auction) {
|
|
574
|
-
// reset the delay timer to send the auction data
|
|
575
|
-
if (auction.auctionSendDelayTimer) {
|
|
576
|
-
clearTimeout(auction.auctionSendDelayTimer);
|
|
577
|
-
auction.auctionSendDelayTimer = void (0);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* Returns the path to a bid (auction, adunit, bidRequest, and bid) based on a bidId
|
|
583
|
-
* @param {string} bidId
|
|
584
|
-
* @returns {Array<*>}
|
|
585
|
-
*/
|
|
586
|
-
function getPathToBidResponseByBidId(bidId) {
|
|
587
|
-
let auction;
|
|
588
|
-
let adUnit;
|
|
589
|
-
let bidResponse;
|
|
590
|
-
|
|
591
|
-
if (!bidId) {
|
|
592
|
-
return [];
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
_each(auctionMap, currentAuction => {
|
|
596
|
-
// skip completed auctions
|
|
597
|
-
if (currentAuction.state === AUCTION_STATES.COMPLETED) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
_each(currentAuction.adUnitCodeToAdUnitMap, (currentAdunit) => {
|
|
602
|
-
_each(currentAdunit.bidRequestsMap, currentBiddRequest => {
|
|
603
|
-
_each(currentBiddRequest.bids, (currentBidResponse, bidResponseId) => {
|
|
604
|
-
if (bidId === bidResponseId) {
|
|
605
|
-
auction = currentAuction;
|
|
606
|
-
adUnit = currentAdunit;
|
|
607
|
-
bidResponse = currentBidResponse;
|
|
608
|
-
}
|
|
609
|
-
});
|
|
610
|
-
});
|
|
611
|
-
});
|
|
612
|
-
});
|
|
613
|
-
return [auction, adUnit, bidResponse];
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
function getAuctionByGoogleTagSLot(slot) {
|
|
617
|
-
let slotAdunitCodes = [slot.getSlotElementId(), slot.getAdUnitPath()];
|
|
618
|
-
let slotAuction;
|
|
619
|
-
|
|
620
|
-
_each(auctionMap, auction => {
|
|
621
|
-
if (auction.state === AUCTION_STATES.COMPLETED) {
|
|
622
|
-
return;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
_each(auction.adUnitCodeToAdUnitMap, (bidderRequestIdMap, adUnitCode) => {
|
|
626
|
-
if (includes(slotAdunitCodes, adUnitCode)) {
|
|
627
|
-
slotAuction = auction;
|
|
628
|
-
}
|
|
629
|
-
});
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
return slotAuction;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
function buildAuctionPayload(auction) {
|
|
636
|
-
let {startTime, endTime, state, timeout, auctionOrder, userIds, adUnitCodeToAdUnitMap, id} = auction;
|
|
637
|
-
const auctionId = id;
|
|
638
|
-
let {orgId, publisherPlatformId, publisherAccountId, campaign, testCode, configId, optimizerConfig} = analyticsConfig;
|
|
639
|
-
|
|
640
|
-
return {
|
|
641
|
-
auctionId,
|
|
642
|
-
adapterVersion: ADAPTER_VERSION,
|
|
643
|
-
schemaVersion: SCHEMA_VERSION,
|
|
644
|
-
orgId,
|
|
645
|
-
publisherPlatformId,
|
|
646
|
-
publisherAccountId,
|
|
647
|
-
configId,
|
|
648
|
-
optimizerConfig,
|
|
649
|
-
campaign,
|
|
650
|
-
state,
|
|
651
|
-
startTime,
|
|
652
|
-
endTime,
|
|
653
|
-
timeLimit: timeout,
|
|
654
|
-
auctionOrder,
|
|
655
|
-
deviceType: detectMob() ? 'Mobile' : 'Desktop',
|
|
656
|
-
deviceOSType: detectOS(),
|
|
657
|
-
browser: detectBrowser(),
|
|
658
|
-
testCode: testCode,
|
|
659
|
-
// return an array of module name that have user data
|
|
660
|
-
userIdProviders: buildUserIdProviders(userIds),
|
|
661
|
-
adUnits: buildAdUnitsPayload(adUnitCodeToAdUnitMap),
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
function buildAdUnitsPayload(adUnitCodeToAdUnitMap) {
|
|
665
|
-
return _map(adUnitCodeToAdUnitMap, (adUnit) => {
|
|
666
|
-
let {code, adPosition} = adUnit;
|
|
667
|
-
|
|
668
|
-
return {
|
|
669
|
-
code,
|
|
670
|
-
adPosition,
|
|
671
|
-
bidRequests: buildBidRequestPayload(adUnit.bidRequestsMap)
|
|
672
|
-
};
|
|
673
|
-
|
|
674
|
-
function buildBidRequestPayload(bidRequestsMap) {
|
|
675
|
-
return _map(bidRequestsMap, (bidRequest) => {
|
|
676
|
-
let {bidder, source, bids, mediaTypes, timeLimit, timedOut} = bidRequest;
|
|
677
|
-
return {
|
|
678
|
-
bidder,
|
|
679
|
-
source,
|
|
680
|
-
hasBidderResponded: Object.keys(bids).length > 0,
|
|
681
|
-
availableAdSizes: getMediaTypeSizes(mediaTypes),
|
|
682
|
-
availableMediaTypes: getMediaTypes(mediaTypes),
|
|
683
|
-
timeLimit,
|
|
684
|
-
timedOut,
|
|
685
|
-
bidResponses: _map(bidRequest.bids, (bidderBidResponse) => {
|
|
686
|
-
let {
|
|
687
|
-
adId,
|
|
688
|
-
cpm,
|
|
689
|
-
creativeId,
|
|
690
|
-
ts,
|
|
691
|
-
meta,
|
|
692
|
-
mediaType,
|
|
693
|
-
dealId,
|
|
694
|
-
ttl,
|
|
695
|
-
netRevenue,
|
|
696
|
-
currency,
|
|
697
|
-
width,
|
|
698
|
-
height,
|
|
699
|
-
latency,
|
|
700
|
-
winner,
|
|
701
|
-
rendered,
|
|
702
|
-
renderTime
|
|
703
|
-
} = bidderBidResponse;
|
|
704
|
-
|
|
705
|
-
return {
|
|
706
|
-
bidId: adId,
|
|
707
|
-
microCpm: cpm * 1000000,
|
|
708
|
-
netRevenue,
|
|
709
|
-
currency,
|
|
710
|
-
mediaType,
|
|
711
|
-
height,
|
|
712
|
-
width,
|
|
713
|
-
size: `${width}x${height}`,
|
|
714
|
-
dealId,
|
|
715
|
-
latency,
|
|
716
|
-
ttl,
|
|
717
|
-
winner,
|
|
718
|
-
creativeId,
|
|
719
|
-
ts,
|
|
720
|
-
rendered,
|
|
721
|
-
renderTime,
|
|
722
|
-
meta
|
|
723
|
-
}
|
|
724
|
-
})
|
|
725
|
-
}
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
});
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
function buildUserIdProviders(userIds) {
|
|
732
|
-
return _map(userIds, (userId) => {
|
|
733
|
-
return _map(userId, (id, module) => {
|
|
734
|
-
return hasUserData(module, id) ? module : false
|
|
735
|
-
}).filter(module => module);
|
|
736
|
-
}).reduce(flatten, []).filter(uniques).sort();
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
function hasUserData(module, idOrIdObject) {
|
|
740
|
-
let normalizedId;
|
|
741
|
-
|
|
742
|
-
switch (module) {
|
|
743
|
-
case 'digitrustid':
|
|
744
|
-
normalizedId = deepAccess(idOrIdObject, 'data.id');
|
|
745
|
-
break;
|
|
746
|
-
case 'lipb':
|
|
747
|
-
normalizedId = idOrIdObject.lipbid;
|
|
748
|
-
break;
|
|
749
|
-
default:
|
|
750
|
-
normalizedId = idOrIdObject;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
return !isEmpty(normalizedId);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
function getMediaTypeSizes(mediaTypes) {
|
|
757
|
-
return _map(mediaTypes, (mediaTypeConfig, mediaType) => {
|
|
758
|
-
return parseSizesInput(mediaTypeConfig.sizes)
|
|
759
|
-
.map(size => `${mediaType}_${size}`);
|
|
760
|
-
}).reduce(flatten, []);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
function getMediaTypes(mediaTypes) {
|
|
764
|
-
return _map(mediaTypes, (mediaTypeConfig, mediaType) => mediaType);
|
|
765
|
-
}
|
|
766
27
|
}
|