prebid.js 7.17.0 → 7.19.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.
Files changed (220) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/adagioBidAdapter.js +1 -1
  3. package/dist/adbookpspBidAdapter.js +1 -1
  4. package/dist/adfBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adqueryBidAdapter.js +1 -1
  7. package/dist/adqueryIdSystem.js +1 -1
  8. package/dist/adrelevantisBidAdapter.js +1 -1
  9. package/dist/adtrgtmeBidAdapter.js +1 -1
  10. package/dist/adxcgBidAdapter.js +1 -1
  11. package/dist/adyoulikeBidAdapter.js +1 -1
  12. package/dist/ajaBidAdapter.js +1 -1
  13. package/dist/amxBidAdapter.js +1 -1
  14. package/dist/amxIdSystem.js +1 -1
  15. package/dist/appierAnalyticsAdapter.js +1 -1
  16. package/dist/appnexusBidAdapter.js +1 -1
  17. package/dist/asoBidAdapter.js +1 -1
  18. package/dist/audiencerunBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.js +1 -1
  20. package/dist/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +1 -1
  21. package/dist/bidglassBidAdapter.js +1 -1
  22. package/dist/bidwatchAnalyticsAdapter.js +1 -1
  23. package/dist/big-richmediaBidAdapter.js +1 -1
  24. package/dist/bluebillywigBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/carodaBidAdapter.js +1 -1
  28. package/dist/cleanioRtdProvider.js +1 -1
  29. package/dist/colossussspBidAdapter.js +1 -1
  30. package/dist/concertBidAdapter.js +1 -1
  31. package/dist/connectadBidAdapter.js +1 -1
  32. package/dist/consumableBidAdapter.js +1 -1
  33. package/dist/conversantAnalyticsAdapter.js +1 -0
  34. package/dist/conversantBidAdapter.js +1 -1
  35. package/dist/craftBidAdapter.js +1 -1
  36. package/dist/criteoBidAdapter.js +1 -1
  37. package/dist/debugging-standalone.js +1 -1
  38. package/dist/debugging.js +1 -1
  39. package/dist/dependencies.json +6 -0
  40. package/dist/dgkeywordRtdProvider.js +1 -1
  41. package/dist/dianomiBidAdapter.js +1 -1
  42. package/dist/dspxBidAdapter.js +1 -1
  43. package/dist/enrichmentFpdModule.js +1 -1
  44. package/dist/eplanningBidAdapter.js +1 -1
  45. package/dist/finativeBidAdapter.js +1 -1
  46. package/dist/fpd.js +1 -0
  47. package/dist/glimpseBidAdapter.js +1 -1
  48. package/dist/gmosspBidAdapter.js +1 -1
  49. package/dist/goldbachBidAdapter.js +1 -1
  50. package/dist/gridBidAdapter.js +1 -1
  51. package/dist/gridNMBidAdapter.js +1 -1
  52. package/dist/growthCodeIdSystem.js +1 -0
  53. package/dist/gumgumBidAdapter.js +1 -1
  54. package/dist/h12mediaBidAdapter.js +1 -1
  55. package/dist/id5IdSystem.js +1 -1
  56. package/dist/impactifyBidAdapter.js +1 -1
  57. package/dist/improvedigitalBidAdapter.js +1 -1
  58. package/dist/inmarBidAdapter.js +1 -1
  59. package/dist/insticatorBidAdapter.js +1 -1
  60. package/dist/ixBidAdapter.js +1 -1
  61. package/dist/jixieBidAdapter.js +1 -1
  62. package/dist/justpremiumBidAdapter.js +1 -1
  63. package/dist/konduitAnalyticsAdapter.js +1 -1
  64. package/dist/kueezBidAdapter.js +1 -1
  65. package/dist/lassoBidAdapter.js +1 -1
  66. package/dist/lifestreetBidAdapter.js +1 -1
  67. package/dist/liveIntentIdSystem.js +1 -1
  68. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  69. package/dist/logicadBidAdapter.js +1 -1
  70. package/dist/loglyliftBidAdapter.js +1 -1
  71. package/dist/malltvAnalyticsAdapter.js +1 -1
  72. package/dist/marsmediaBidAdapter.js +1 -1
  73. package/dist/mediafuseBidAdapter.js +1 -1
  74. package/dist/mediakeysBidAdapter.js +1 -1
  75. package/dist/mediasquareBidAdapter.js +1 -1
  76. package/dist/mgidBidAdapter.js +1 -1
  77. package/dist/minutemediaBidAdapter.js +1 -1
  78. package/dist/nativoBidAdapter.js +1 -1
  79. package/dist/nextMillenniumBidAdapter.js +1 -1
  80. package/dist/not-for-prod/prebid.js +133 -130
  81. package/dist/oguryBidAdapter.js +1 -1
  82. package/dist/onetagBidAdapter.js +1 -1
  83. package/dist/ooloAnalyticsAdapter.js +1 -1
  84. package/dist/outbrainBidAdapter.js +1 -1
  85. package/dist/parrableIdSystem.js +1 -1
  86. package/dist/pixfutureBidAdapter.js +1 -1
  87. package/dist/prebid-core.js +1 -1
  88. package/dist/prebidServerBidAdapter.js +1 -1
  89. package/dist/publinkIdSystem.js +1 -1
  90. package/dist/pubmaticBidAdapter.js +1 -1
  91. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  92. package/dist/pxyzBidAdapter.js +1 -1
  93. package/dist/quantcastBidAdapter.js +1 -1
  94. package/dist/readpeakBidAdapter.js +1 -1
  95. package/dist/relaidoBidAdapter.js +1 -1
  96. package/dist/rhythmoneBidAdapter.js +1 -1
  97. package/dist/riseBidAdapter.js +1 -1
  98. package/dist/rubiconAnalyticsAdapter.js +1 -1
  99. package/dist/rubiconBidAdapter.js +1 -1
  100. package/dist/seedingAllianceBidAdapter.js +1 -1
  101. package/dist/seedtagBidAdapter.js +1 -1
  102. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  103. package/dist/sharethroughBidAdapter.js +1 -1
  104. package/dist/shinezBidAdapter.js +1 -1
  105. package/dist/smaatoBidAdapter.js +1 -1
  106. package/dist/smartadserverBidAdapter.js +1 -1
  107. package/dist/smartxBidAdapter.js +1 -1
  108. package/dist/smilewantedBidAdapter.js +1 -1
  109. package/dist/sonobiBidAdapter.js +1 -1
  110. package/dist/sovrnAnalyticsAdapter.js +1 -1
  111. package/dist/sovrnBidAdapter.js +1 -1
  112. package/dist/sspBCBidAdapter.js +1 -1
  113. package/dist/sublimeBidAdapter.js +1 -1
  114. package/dist/synacormediaBidAdapter.js +1 -1
  115. package/dist/taboolaBidAdapter.js +1 -1
  116. package/dist/targetVideoBidAdapter.js +1 -1
  117. package/dist/teadsBidAdapter.js +1 -1
  118. package/dist/trionBidAdapter.js +1 -1
  119. package/dist/tripleliftBidAdapter.js +1 -1
  120. package/dist/ttdBidAdapter.js +1 -1
  121. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  122. package/dist/underdogmediaBidAdapter.js +1 -1
  123. package/dist/undertoneBidAdapter.js +1 -1
  124. package/dist/userId.js +1 -1
  125. package/dist/vidazooBidAdapter.js +1 -1
  126. package/dist/videobyteBidAdapter.js +1 -1
  127. package/dist/visxBidAdapter.js +1 -1
  128. package/dist/vuukleBidAdapter.js +1 -1
  129. package/dist/widespaceBidAdapter.js +1 -1
  130. package/dist/winrBidAdapter.js +1 -1
  131. package/dist/yahoosspBidAdapter.js +1 -1
  132. package/dist/yandexBidAdapter.js +1 -1
  133. package/dist/yieldmoBidAdapter.js +1 -1
  134. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  135. package/libraries/fpd/sua.js +98 -0
  136. package/modules/adagioBidAdapter.js +2 -1
  137. package/modules/adfBidAdapter.js +1 -1
  138. package/modules/adkernelAdnBidAdapter.js +1 -0
  139. package/modules/adqueryBidAdapter.js +4 -2
  140. package/modules/adqueryIdSystem.js +8 -8
  141. package/modules/adxcgBidAdapter.js +1 -1
  142. package/modules/amxBidAdapter.js +1 -1
  143. package/modules/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +0 -0
  144. package/modules/{andBeyondMediaBidAdapter.md → beyondmediaBidAdapter.md} +1 -1
  145. package/modules/bidwatchAnalyticsAdapter.js +1 -1
  146. package/modules/cleanioRtdProvider.js +3 -4
  147. package/modules/colossussspBidAdapter.js +2 -1
  148. package/modules/conversantAnalyticsAdapter.js +560 -0
  149. package/modules/conversantAnalyticsAdapter.md +47 -0
  150. package/modules/criteoBidAdapter.js +1 -1
  151. package/modules/debugging/bidInterceptor.js +2 -2
  152. package/modules/debugging/debugging.js +10 -2
  153. package/modules/dgkeywordRtdProvider.js +21 -3
  154. package/modules/dianomiBidAdapter.js +1 -1
  155. package/modules/enrichmentFpdModule.js +33 -14
  156. package/modules/finativeBidAdapter.js +1 -1
  157. package/modules/gridBidAdapter.js +188 -118
  158. package/modules/growthCodeIdSystem.js +164 -0
  159. package/modules/growthCodeIdSystem.md +37 -0
  160. package/modules/improvedigitalBidAdapter.js +2 -2
  161. package/modules/ixBidAdapter.js +94 -23
  162. package/modules/liveIntentIdSystem.js +39 -5
  163. package/modules/mediakeysBidAdapter.js +6 -1
  164. package/modules/mediakeysBidAdapter.md +50 -40
  165. package/modules/nativoBidAdapter.js +3 -2
  166. package/modules/nextMillenniumBidAdapter.js +34 -11
  167. package/modules/prebidServerBidAdapter/index.js +44 -13
  168. package/modules/readpeakBidAdapter.js +1 -1
  169. package/modules/rubiconBidAdapter.js +2 -3
  170. package/modules/seedingAllianceBidAdapter.js +1 -1
  171. package/modules/seedtagBidAdapter.js +4 -0
  172. package/modules/sharethroughBidAdapter.js +1 -1
  173. package/modules/taboolaBidAdapter.js +4 -8
  174. package/modules/talkadsBidAdapter.js +1 -0
  175. package/modules/truereachBidAdapter.js +1 -0
  176. package/modules/ttdBidAdapter.js +1 -1
  177. package/modules/userId/eids.js +19 -0
  178. package/modules/vidazooBidAdapter.js +1 -1
  179. package/modules/vuukleBidAdapter.js +34 -3
  180. package/modules/yahoosspBidAdapter.js +3 -1
  181. package/modules/yandexBidAdapter.js +31 -8
  182. package/package.json +2 -2
  183. package/src/adapterManager.js +2 -4
  184. package/src/cpmBucketManager.js +22 -3
  185. package/src/native.js +1 -5
  186. package/src/prebid.js +3 -3
  187. package/test/spec/cpmBucketManager_spec.js +239 -177
  188. package/test/spec/fpd/sua_spec.js +244 -0
  189. package/test/spec/modules/adagioBidAdapter_spec.js +23 -0
  190. package/test/spec/modules/adfBidAdapter_spec.js +2 -3
  191. package/test/spec/modules/adqueryBidAdapter_spec.js +11 -0
  192. package/test/spec/modules/adqueryIdSystem_spec.js +0 -2
  193. package/test/spec/modules/adxcgBidAdapter_spec.js +2 -3
  194. package/test/spec/modules/amxBidAdapter_spec.js +3 -2
  195. package/test/spec/modules/{andBeyondMediaBidAdapter_spec.js → beyondmediaBidAdapter_spec.js} +1 -1
  196. package/test/spec/modules/bidwatchAnalyticsAdapter_spec.js +2 -0
  197. package/test/spec/modules/colossussspBidAdapter_spec.js +4 -2
  198. package/test/spec/modules/conversantAnalyticsAdapter_spec.js +963 -0
  199. package/test/spec/modules/debugging_mod_spec.js +9 -0
  200. package/test/spec/modules/dgkeywordRtdProvider_spec.js +83 -1
  201. package/test/spec/modules/dianomiBidAdapter_spec.js +2 -3
  202. package/test/spec/modules/enrichmentFpdModule_spec.js +50 -7
  203. package/test/spec/modules/fpdModule_spec.js +9 -0
  204. package/test/spec/modules/gridBidAdapter_spec.js +87 -31
  205. package/test/spec/modules/growthCodeIdSystem_spec.js +83 -0
  206. package/test/spec/modules/ixBidAdapter_spec.js +221 -2
  207. package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +62 -8
  208. package/test/spec/modules/liveIntentIdSystem_spec.js +62 -8
  209. package/test/spec/modules/mediakeysBidAdapter_spec.js +20 -3
  210. package/test/spec/modules/nativoBidAdapter_spec.js +13 -2
  211. package/test/spec/modules/prebidServerBidAdapter_spec.js +171 -4
  212. package/test/spec/modules/seedtagBidAdapter_spec.js +42 -0
  213. package/test/spec/modules/sharethroughBidAdapter_spec.js +2 -1
  214. package/test/spec/modules/taboolaBidAdapter_spec.js +2 -2
  215. package/test/spec/modules/ttdBidAdapter_spec.js +3 -3
  216. package/test/spec/modules/vuukleBidAdapter_spec.js +87 -0
  217. package/test/spec/modules/yahoosspBidAdapter_spec.js +3 -1
  218. package/test/spec/modules/yandexBidAdapter_spec.js +8 -5
  219. package/test/spec/native_spec.js +5 -0
  220. package/test/spec/unit/pbjs_api_spec.js +44 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * This module adds GrowthCodeId to the User ID module
3
+ * The {@link module:modules/userId} module is required
4
+ * @module modules/growthCodeIdSystem
5
+ * @requires module:modules/userId
6
+ */
7
+
8
+ import {logError, logInfo, tryAppendQueryString} from '../src/utils.js';
9
+ import {ajax} from '../src/ajax.js';
10
+ import { submodule } from '../src/hook.js'
11
+ import { getStorageManager } from '../src/storageManager.js';
12
+
13
+ const GCID_EXPIRY = 45;
14
+ const MODULE_NAME = 'growthCodeId';
15
+ const GC_DATA_KEY = '_gc_data';
16
+ const ENDPOINT_URL = 'https://p2.gcprivacy.com/v1/pb?'
17
+
18
+ export const storage = getStorageManager({ gvlid: undefined, moduleName: MODULE_NAME });
19
+
20
+ /**
21
+ * Read GrowthCode data from cookie or local storage
22
+ * @param key
23
+ * @return {string}
24
+ */
25
+ export function readData(key) {
26
+ try {
27
+ if (storage.hasLocalStorage()) {
28
+ return storage.getDataFromLocalStorage(key);
29
+ }
30
+ if (storage.cookiesAreEnabled()) {
31
+ return storage.getCookie(key);
32
+ }
33
+ } catch (error) {
34
+ logError(error);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Store GrowthCode data in either cookie or local storage
40
+ * expiration date: 45 days
41
+ * @param key
42
+ * @param {string} value
43
+ */
44
+ function storeData(key, value) {
45
+ try {
46
+ logInfo(MODULE_NAME + ': storing data: key=' + key + ' value=' + value);
47
+
48
+ if (value) {
49
+ if (storage.hasLocalStorage()) {
50
+ storage.setDataInLocalStorage(key, value);
51
+ }
52
+ const expiresStr = (new Date(Date.now() + (GCID_EXPIRY * (60 * 60 * 24 * 1000)))).toUTCString();
53
+ if (storage.cookiesAreEnabled()) {
54
+ storage.setCookie(key, value, expiresStr, 'LAX');
55
+ }
56
+ }
57
+ } catch (error) {
58
+ logError(error);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Parse json if possible, else return null
64
+ * @param data
65
+ * @param {object|null}
66
+ */
67
+ function tryParse(data) {
68
+ try {
69
+ return JSON.parse(data);
70
+ } catch (err) {
71
+ logError(err);
72
+ return null;
73
+ }
74
+ }
75
+
76
+ /** @type {Submodule} */
77
+ export const growthCodeIdSubmodule = {
78
+ /**
79
+ * used to link submodule with config
80
+ * @type {string}
81
+ */
82
+ name: MODULE_NAME,
83
+ /**
84
+ * decode the stored id value for passing to bid requests
85
+ * @function
86
+ * @param {{string}} value
87
+ * @returns {{growthCodeId: {string}}|undefined}
88
+ */
89
+ decode(value) {
90
+ return value && value !== '' ? { 'growthCodeId': value } : undefined;
91
+ },
92
+ /**
93
+ * performs action to obtain id and return a value in the callback's response argument
94
+ * @function
95
+ * @param {SubmoduleConfig} [config]
96
+ * @returns {IdResponse|undefined}
97
+ */
98
+ getId(config, consentData) {
99
+ const configParams = (config && config.params) || {};
100
+ if (!configParams || typeof configParams.pid !== 'string') {
101
+ logError('User ID - GrowthCodeID submodule requires a valid Partner ID to be defined');
102
+ return;
103
+ }
104
+
105
+ const gdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0;
106
+ const consentString = gdpr ? consentData.consentString : '';
107
+ if (gdpr && !consentString) {
108
+ logInfo('Consent string is required to call GrowthCode id.');
109
+ return;
110
+ }
111
+
112
+ let publisherId = configParams.publisher_id ? configParams.publisher_id : '_sharedID';
113
+
114
+ let sharedId;
115
+ if (configParams.publisher_id_storage === 'html5') {
116
+ sharedId = storage.getDataFromLocalStorage(publisherId, null) ? (storage.getDataFromLocalStorage(publisherId, null)) : null;
117
+ } else {
118
+ sharedId = storage.getCookie(publisherId, null) ? (storage.getCookie(publisherId, null)) : null;
119
+ }
120
+ if (!sharedId) {
121
+ logError('User ID - Publisher ID is not correctly setup.');
122
+ }
123
+
124
+ const resp = function(callback) {
125
+ let gcData = tryParse(readData(GC_DATA_KEY));
126
+ if (gcData) {
127
+ callback(gcData);
128
+ } else {
129
+ let segment = window.location.pathname.substr(1).replace(/\/+$/, '');
130
+ if (segment === '') {
131
+ segment = 'home';
132
+ }
133
+
134
+ let url = configParams.url ? configParams.url : ENDPOINT_URL;
135
+ url = tryAppendQueryString(url, 'pid', configParams.pid);
136
+ url = tryAppendQueryString(url, 'uid', sharedId);
137
+ url = tryAppendQueryString(url, 'u', window.location.href);
138
+ url = tryAppendQueryString(url, 'h', window.location.hostname);
139
+ url = tryAppendQueryString(url, 's', segment);
140
+ url = tryAppendQueryString(url, 'r', document.referrer);
141
+
142
+ ajax(url, {
143
+ success: response => {
144
+ let respJson = tryParse(response);
145
+ // If response is a valid json and should save is true
146
+ if (respJson) {
147
+ storeData(GC_DATA_KEY, JSON.stringify(respJson))
148
+ callback(respJson);
149
+ } else {
150
+ callback();
151
+ }
152
+ },
153
+ error: error => {
154
+ logError(MODULE_NAME + ': ID fetch encountered an error', error);
155
+ callback();
156
+ }
157
+ }, undefined, {method: 'GET', withCredentials: true})
158
+ }
159
+ };
160
+ return { callback: resp };
161
+ }
162
+ };
163
+
164
+ submodule('userId', growthCodeIdSubmodule);
@@ -0,0 +1,37 @@
1
+ ## GrowthCode User ID Submodule
2
+
3
+ GrowthCode provides Id Enrichment for requests.
4
+
5
+ ## Building Prebid with GrowthCode Support
6
+
7
+ First, make sure to add the GrowthCode submodule to your Prebid.js package with:
8
+
9
+ ```
10
+ gulp build --modules=growthCodeIdSystem,userId
11
+ ```
12
+
13
+ The following configuration parameters are available:
14
+
15
+ ```javascript
16
+ pbjs.setConfig({
17
+ userSync: {
18
+ userIds: [{
19
+ name: 'growthCodeId',
20
+ params: {
21
+ pid: 'TEST01', // Set your Partner ID here for production (obtained from Growthcode)
22
+ publisher_id: '_sharedID',
23
+ publisher_id_storage: 'html5'
24
+ }
25
+ }]
26
+ }
27
+ });
28
+ ```
29
+
30
+ | Param under userSync.userIds[] | Scope | Type | Description | Example |
31
+ |--------------------------------|----------|--------| --- |-----------------|
32
+ | name | Required | String | The name of this module. | `"growthCodeId"` |
33
+ | params | Required | Object | Details of module params. | |
34
+ | params.pid | Required | String | This is the Parter ID value obtained from GrowthCode | `"TEST01"` |
35
+ | params.url | Optional | String | Custom URL for server | |
36
+ | params.publisher_id | Optional | String | Name if the variable that holds your publisher ID | `"_sharedID"` |
37
+ | params.publisher_id_storage | Optional | String | Publisher ID storage (cookie, html5) | `"html5"` |
@@ -307,10 +307,10 @@ const ID_REQUEST = {
307
307
  }
308
308
  // In the single request mode, split imps between those going to the ad server and those going to extend server
309
309
  if (extendImps.length) {
310
- requests.push(formatRequest(extendImps, null, true));
310
+ requests.push(formatRequest(extendImps, bidderRequest.auctionId, true));
311
311
  }
312
312
  if (adServerImps.length) {
313
- requests.push(formatRequest(adServerImps, null, false));
313
+ requests.push(formatRequest(adServerImps, bidderRequest.auctionId, false));
314
314
  }
315
315
 
316
316
  return requests;
@@ -13,7 +13,8 @@ import {
13
13
  logError,
14
14
  logWarn,
15
15
  mergeDeep,
16
- parseQueryStringParameters
16
+ parseQueryStringParameters,
17
+ safeJSONParse
17
18
  } from '../src/utils.js';
18
19
  import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js';
19
20
  import {config} from '../src/config.js';
@@ -99,8 +100,46 @@ const VIDEO_PARAMS_ALLOW_LIST = [
99
100
  'playerSize', 'w', 'h'
100
101
  ];
101
102
  const LOCAL_STORAGE_KEY = 'ixdiag';
103
+ export const LOCAL_STORAGE_FEATURE_TOGGLES_KEY = `${BIDDER_CODE}_features`;
102
104
  let hasRegisteredHandler = false;
103
105
  export const storage = getStorageManager({gvlid: GLOBAL_VENDOR_ID, bidderCode: BIDDER_CODE});
106
+ export const FEATURE_TOGGLES = {
107
+ featureToggles: {},
108
+ isFeatureEnabled: function(ft) {
109
+ return deepAccess(this.featureToggles, `features.${ft}.activated`)
110
+ },
111
+ getFeatureToggles: function() {
112
+ if (storage.localStorageIsEnabled()) {
113
+ const parsedToggles = safeJSONParse(storage.getDataFromLocalStorage(LOCAL_STORAGE_FEATURE_TOGGLES_KEY));
114
+ if (deepAccess(parsedToggles, 'expiry') && parsedToggles.expiry >= new Date().getTime()) {
115
+ this.featureToggles = parsedToggles
116
+ } else {
117
+ this.clearFeatureToggles();
118
+ }
119
+ }
120
+ },
121
+ setFeatureToggles: function(serverResponse) {
122
+ const responseBody = serverResponse.body;
123
+ const expiryTime = new Date();
124
+ const toggles = deepAccess(responseBody, 'ext.features');
125
+
126
+ if (toggles) {
127
+ this.featureToggles = {
128
+ expiry: expiryTime.setHours(expiryTime.getHours() + 1),
129
+ features: toggles
130
+ }
131
+ if (storage.localStorageIsEnabled()) {
132
+ storage.setDataInLocalStorage(LOCAL_STORAGE_FEATURE_TOGGLES_KEY, JSON.stringify(this.featureToggles));
133
+ }
134
+ }
135
+ },
136
+ clearFeatureToggles: function() {
137
+ this.featureToggles = {};
138
+ if (storage.localStorageIsEnabled()) {
139
+ storage.removeDataFromLocalStorage(LOCAL_STORAGE_FEATURE_TOGGLES_KEY);
140
+ }
141
+ }
142
+ };
104
143
  let siteID = 0;
105
144
  let gdprConsent = '';
106
145
  let usPrivacy = '';
@@ -578,6 +617,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
578
617
  r.ext = {};
579
618
  r.ext.source = 'prebid';
580
619
  r.ext.ixdiag = {};
620
+ r.ext.ixdiag.ls = storage.localStorageIsEnabled();
581
621
  r.imp = [];
582
622
  r.at = 1;
583
623
 
@@ -602,13 +642,15 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
602
642
  r.ext.ixdiag.err = cachedErrors;
603
643
  }
604
644
 
645
+ // set source.tid to auctionId for outgoing request to Exchange.
646
+ r.source = {
647
+ tid: validBidRequests[0].auctionId,
648
+ }
649
+
605
650
  // if an schain is provided, send it along
606
651
  if (validBidRequests[0].schain) {
607
- r.source = {
608
- ext: {
609
- schain: validBidRequests[0].schain
610
- }
611
- };
652
+ r.source.ext = {};
653
+ r.source.ext.schain = validBidRequests[0].schain;
612
654
  }
613
655
 
614
656
  if (userEids.length > 0) {
@@ -665,14 +707,17 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
665
707
  // Use the siteId in the first bid request as the main siteId.
666
708
  siteID = validBidRequests[0].params.siteId;
667
709
  payload.s = siteID;
668
- if (version) {
669
- payload.v = version;
670
- }
671
- payload.ac = 'j';
672
- payload.sd = 1;
673
710
 
674
- if (version === VIDEO_ENDPOINT_VERSION) {
675
- payload.nf = 1;
711
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_enable_post')) {
712
+ if (version) {
713
+ payload.v = version;
714
+ }
715
+ payload.ac = 'j';
716
+ payload.sd = 1;
717
+
718
+ if (version === VIDEO_ENDPOINT_VERSION) {
719
+ payload.nf = 1;
720
+ }
676
721
  }
677
722
 
678
723
  // Parse additional runtime configs.
@@ -718,9 +763,11 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
718
763
  }
719
764
  }
720
765
 
721
- // Create t in payload if timeout is configured.
722
- if (typeof otherIxConfig.timeout === 'number') {
723
- payload.t = otherIxConfig.timeout;
766
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_enable_post')) {
767
+ // Create t in payload if timeout is configured.
768
+ if (typeof otherIxConfig.timeout === 'number') {
769
+ payload.t = otherIxConfig.timeout;
770
+ }
724
771
  }
725
772
  }
726
773
 
@@ -866,12 +913,27 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
866
913
  requestSequenceNumber++;
867
914
  clonedPayload.r = JSON.stringify(r);
868
915
 
869
- requests.push({
870
- method: 'GET',
871
- url: baseUrl,
872
- data: clonedPayload,
873
- validBidRequests
874
- });
916
+ let requestData;
917
+
918
+ if (FEATURE_TOGGLES.isFeatureEnabled('pbjs_enable_post')) {
919
+ requestData = {
920
+ method: 'POST',
921
+ url: baseUrl + '?s=' + payload.s,
922
+ data: deepClone(r),
923
+ option: {
924
+ contentType: 'text/plain',
925
+ },
926
+ validBidRequests
927
+ }
928
+ } else {
929
+ requestData = {
930
+ method: 'GET',
931
+ url: baseUrl,
932
+ data: clonedPayload,
933
+ validBidRequests
934
+ }
935
+ }
936
+ requests.push(requestData);
875
937
 
876
938
  currentRequestSize = baseRequestSize;
877
939
  r.imp = [];
@@ -1381,6 +1443,7 @@ export const spec = {
1381
1443
  const videoImps = {}; // Stores created video impressions
1382
1444
  const nativeImps = {}; // Stores created native impressions
1383
1445
  const missingBannerSizes = {}; // To capture the missing sizes i.e not configured for ix
1446
+ FEATURE_TOGGLES.getFeatureToggles();
1384
1447
 
1385
1448
  // Step 1: Create impresssions from IX params
1386
1449
  validBidRequests.forEach((validBidRequest) => {
@@ -1451,6 +1514,7 @@ export const spec = {
1451
1514
  let bid = null;
1452
1515
 
1453
1516
  if (!serverResponse.hasOwnProperty('body') || !serverResponse.body.hasOwnProperty('seatbid')) {
1517
+ FEATURE_TOGGLES.setFeatureToggles(serverResponse);
1454
1518
  return bids;
1455
1519
  }
1456
1520
 
@@ -1463,7 +1527,13 @@ export const spec = {
1463
1527
 
1464
1528
  // Transform rawBid in bid response to the format that will be accepted by prebid.
1465
1529
  const innerBids = seatbid[i].bid;
1466
- let requestBid = JSON.parse(bidderRequest.data.r);
1530
+ let requestBid;
1531
+
1532
+ if (FEATURE_TOGGLES.isFeatureEnabled('pbjs_enable_post')) {
1533
+ requestBid = bidderRequest.data;
1534
+ } else {
1535
+ requestBid = safeJSONParse(bidderRequest.data.r);
1536
+ }
1467
1537
 
1468
1538
  for (let j = 0; j < innerBids.length; j++) {
1469
1539
  const bidRequest = getBidRequest(innerBids[j].impid, requestBid.imp, bidderRequest.validBidRequests);
@@ -1491,6 +1561,7 @@ export const spec = {
1491
1561
  }
1492
1562
  }
1493
1563
 
1564
+ FEATURE_TOGGLES.setFeatureToggles(serverResponse);
1494
1565
  return bids;
1495
1566
  },
1496
1567
 
@@ -14,6 +14,7 @@ import { MinimalLiveConnect } from 'live-connect-js/esm/minimal-live-connect.js'
14
14
 
15
15
  const MODULE_NAME = 'liveIntentId';
16
16
  export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME});
17
+ const defaultRequestedAttributes = {'nonId': true}
17
18
  const calls = {
18
19
  ajaxGet: (url, onSuccess, onError, timeout) => {
19
20
  ajaxBuilder(timeout)(
@@ -57,6 +58,23 @@ function parseLiveIntentCollectorConfig(collectConfig) {
57
58
  return config;
58
59
  }
59
60
 
61
+ /**
62
+ * Create requestedAttributes array to pass to liveconnect
63
+ * @function
64
+ * @param {Object} overrides - object with boolean values that will override defaults { 'foo': true, 'bar': false }
65
+ * @returns {Array}
66
+ */
67
+ function parseRequestedAttributes(overrides) {
68
+ function createParameterArray(config) {
69
+ return Object.entries(config).flatMap(([k, v]) => (typeof v === 'boolean' && v) ? [k] : []);
70
+ }
71
+ if (typeof overrides === 'object') {
72
+ return createParameterArray({...defaultRequestedAttributes, ...overrides})
73
+ } else {
74
+ return createParameterArray(defaultRequestedAttributes);
75
+ }
76
+ }
77
+
60
78
  function initializeLiveConnect(configParams) {
61
79
  configParams = configParams || {};
62
80
  if (liveConnect) {
@@ -66,7 +84,8 @@ function initializeLiveConnect(configParams) {
66
84
  const publisherId = configParams.publisherId || 'any';
67
85
  const identityResolutionConfig = {
68
86
  source: 'prebid',
69
- publisherId: publisherId
87
+ publisherId: publisherId,
88
+ requestedAttributes: parseRequestedAttributes(configParams.requestedAttributesOverrides)
70
89
  };
71
90
  if (configParams.url) {
72
91
  identityResolutionConfig.url = configParams.url
@@ -136,9 +155,24 @@ export const liveIntentIdSubmodule = {
136
155
  decode(value, config) {
137
156
  const configParams = (config && config.params) || {};
138
157
  function composeIdObject(value) {
139
- const base = { 'lipbid': value.unifiedId };
140
- delete value.unifiedId;
141
- return { 'lipb': { ...base, ...value } };
158
+ const result = {};
159
+
160
+ // old versions stored lipbid in unifiedId. Ensure that we can still read the data.
161
+ const lipbid = value.nonId || value.unifiedId
162
+ if (lipbid) {
163
+ value.lipbid = lipbid
164
+ delete value.unifiedId
165
+ result.lipb = value
166
+ }
167
+
168
+ // Lift usage of uid2 by exposing uid2 if we were asked to resolve it.
169
+ // As adapters are applied in lexicographical order, we will always
170
+ // be overwritten by the 'proper' uid2 module if it is present.
171
+ if (value.uid2) {
172
+ result.uid2 = { 'id': value.uid2 }
173
+ }
174
+
175
+ return result
142
176
  }
143
177
 
144
178
  if (!liveConnect) {
@@ -146,7 +180,7 @@ export const liveIntentIdSubmodule = {
146
180
  }
147
181
  tryFireEvent();
148
182
 
149
- return (value && typeof value['unifiedId'] === 'string') ? composeIdObject(value) : undefined;
183
+ return composeIdObject(value);
150
184
  },
151
185
 
152
186
  /**
@@ -572,7 +572,12 @@ function nativeBidResponseHandler(bid) {
572
572
  native.impressionTrackers.push(tracker.url);
573
573
  break;
574
574
  case 2:
575
- native.javascriptTrackers = `<script src=\"${tracker.url}\"></script>`;
575
+ const script = `<script async src=\"${tracker.url}\"></script>`;
576
+ if (!native.javascriptTrackers) {
577
+ native.javascriptTrackers = script;
578
+ } else {
579
+ native.javascriptTrackers += `\n${script}`;
580
+ }
576
581
  break;
577
582
  }
578
583
  });
@@ -14,9 +14,10 @@ Connects to Mediakeys demand source to fetch bids.
14
14
 
15
15
  ## Banner only Ad Unit
16
16
 
17
- ```
18
- var adUnits = [
19
- {
17
+ The Mediakeys adapter accepts any valid OpenRTB Spec 2.5 property.
18
+
19
+ ```javascript
20
+ var adUnits = [{
20
21
  code: 'test',
21
22
  mediaTypes: {
22
23
  banner: {
@@ -27,20 +28,26 @@ var adUnits = [
27
28
  bidder: 'mediakeys',
28
29
  params: {} // no params required.
29
30
  }]
30
- },
31
+ }]
31
32
  ```
32
33
 
33
34
  ## Native only Ad Unit
34
35
 
35
36
  The Mediakeys adapter accepts two optional params for native requests. Please see the [OpenRTB Native Ads Specification](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) for valid values.
36
37
 
37
- ```
38
- var adUnits = [
39
- {
38
+ ```javascript
39
+ var adUnits = [{
40
40
  code: 'test',
41
41
  mediaTypes: {
42
42
  native: {
43
- type: 'image',
43
+ title: {
44
+ required: true,
45
+ len: 120
46
+ },
47
+ image: {
48
+ required: true,
49
+ sizes: [300, 250]
50
+ }
44
51
  }
45
52
  },
46
53
  bids: [{
@@ -52,7 +59,7 @@ var adUnits = [
52
59
  }
53
60
  }
54
61
  }]
55
- },
62
+ }]
56
63
  ```
57
64
 
58
65
  ## Video only Ad Unit
@@ -61,63 +68,65 @@ The Mediakeys adapter accepts any valid openRTB 2.5 video property. Properties c
61
68
 
62
69
  ### Outstream context
63
70
 
64
- ```
65
- var adUnits = [
66
- {
71
+ ```javascript
72
+ var adUnits = [{
67
73
  code: 'test',
68
74
  mediaTypes: {
69
75
  video: {
70
76
  context: 'outstream',
71
- playerSize: [300, 250],
77
+ playerSize: [1280, 720],
72
78
  // additional OpenRTB video params
73
79
  // placement: 2,
74
80
  // api: [1],
75
81
  // …
82
+ mimes: ['video/mp4'],
83
+ protocols: [2, 3],
84
+ skip: 0
76
85
  }
77
86
  },
78
87
  renderer: {
79
88
  url: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js',
89
+ // the render method must fetch the vast xml document before displaying video
80
90
  render: function (bid) {
81
- var bidReqConfig = pbjs.adUnits.find(bidReq => bidReq.bidId === bid.impid);
82
-
83
- if (bidReqConfig && bidReqConfig.mediaTypes && bidReqConfig.mediaTypes.video && bidReqConfig.mediaTypes.video.context === 'outstream') {
84
- var adResponse = fetch(bid.vastUrl).then(resp => resp.text()).then(text => ({
85
- ad: {
86
- video: {
87
- content: text,
88
- player_width: bid.width || bidReqConfig.mediaTypes.video.playerSize[0],
89
- player_height: bid.height || bidReqConfig.mediaTypes.video.playerSize[1],
90
- }
91
+ var adResponse = fetch(bid.vastUrl).then(resp => resp.text()).then(text => ({
92
+ ad: {
93
+ video: {
94
+ content: text,
95
+ player_height: bid.playerHeight,
96
+ player_width: bid.playerWidth
91
97
  }
92
- }))
93
-
94
- adResponse.then((ad) => {
95
- bid.renderer.push(() => {
96
- ANOutstreamVideo.renderAd({
97
- targetId: bid.adUnitCode,
98
- adResponse: ad
99
- });
98
+ }
99
+ }))
100
+
101
+ adResponse.then((content) => {
102
+ bid.renderer.push(() => {
103
+ ANOutstreamVideo.renderAd({
104
+ targetId: bid.adUnitCode,
105
+ adResponse: content
100
106
  });
101
- })
102
- }
107
+ });
108
+ })
103
109
  }
104
110
  },
105
111
  bids: [{
106
112
  bidder: 'mediakeys',
107
113
  params: {
108
114
  video: {
109
- // additional OpenRTB video params. Will be merged with params defined at mediaTypes level
115
+ // additional OpenRTB video params.
116
+ // will be merged with params defined at mediaTypes level
117
+ api: [1]
110
118
  }
111
119
  }
112
120
  }]
113
- },
121
+ }]
114
122
  ```
115
123
 
116
124
  ### Instream context
117
125
 
118
- ```
119
- var adUnits = [
120
- {
126
+ For Instream Video, you have to enable the Instream Tracking Module to have Prebid emit the onBidWon required event.
127
+
128
+ ```javascript
129
+ var adUnits = [{
121
130
  code: 'test',
122
131
  mediaTypes: {
123
132
  video: {
@@ -132,8 +141,9 @@ var adUnits = [
132
141
  bids: [{
133
142
  bidder: 'mediakeys',
134
143
  params: {
135
- // additional OpenRTB video params. Will be merged with params defined at mediaTypes level
144
+ // additional OpenRTB video params.
145
+ // will be merged with params defined at mediaTypes level
136
146
  }
137
147
  }]
138
- },
148
+ }]
139
149
  ```
@@ -145,7 +145,7 @@ export const spec = {
145
145
  'params.url',
146
146
  )
147
147
  if (pageUrl == undefined || pageUrl === '') {
148
- pageUrl = bidderRequest.refererInfo.page
148
+ pageUrl = bidderRequest.refererInfo.location
149
149
  }
150
150
 
151
151
  placementId = deepAccess(bidRequest, 'params.placementId')
@@ -465,8 +465,9 @@ export function parseFloorPriceData(bidRequest) {
465
465
  // Setup price floor data per media type
466
466
  let mediaTypeData = bidMediaTypes[mediaType]
467
467
  let mediaTypeFloorPriceData = {}
468
+ let mediaTypeSizes = mediaTypeData.sizes || mediaTypeData.playerSize || [];
468
469
  // Step through each size of the media type so we can get floor data for each size per media type
469
- mediaTypeData.sizes.forEach((size) => {
470
+ mediaTypeSizes.forEach((size) => {
470
471
  // Get floor price data per the getFloor method and respective media type / size combination
471
472
  const priceFloorData = bidRequest.getFloor({
472
473
  currency: FLOOR_PRICE_CURRENCY,