prebid.js 7.51.0 → 7.52.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 (199) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.js +1 -1
  6. package/dist/adqueryBidAdapter.js +1 -1
  7. package/dist/adrelevantisBidAdapter.js +1 -1
  8. package/dist/adriverIdSystem.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/allowActivities.js +1 -0
  14. package/dist/amxBidAdapter.js +1 -1
  15. package/dist/amxIdSystem.js +1 -1
  16. package/dist/appierAnalyticsAdapter.js +1 -1
  17. package/dist/appnexusBidAdapter.js +1 -1
  18. package/dist/asoBidAdapter.js +1 -1
  19. package/dist/axonixBidAdapter.js +1 -1
  20. package/dist/bidglassBidAdapter.js +1 -1
  21. package/dist/big-richmediaBidAdapter.js +1 -1
  22. package/dist/bridgewellBidAdapter.js +1 -1
  23. package/dist/brightMountainMediaBidAdapter.js +1 -1
  24. package/dist/carodaBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -1
  26. package/dist/concertBidAdapter.js +1 -1
  27. package/dist/connectIdSystem.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consumableBidAdapter.js +1 -1
  30. package/dist/conversantAnalyticsAdapter.js +1 -1
  31. package/dist/conversantBidAdapter.js +1 -1
  32. package/dist/craftBidAdapter.js +1 -1
  33. package/dist/criteoBidAdapter.js +1 -1
  34. package/dist/cwireBidAdapter.js +1 -1
  35. package/dist/dependencies.json +6 -0
  36. package/dist/dspxBidAdapter.js +1 -1
  37. package/dist/eplanningBidAdapter.js +1 -1
  38. package/dist/feedadBidAdapter.js +1 -1
  39. package/dist/finativeBidAdapter.js +1 -1
  40. package/dist/freewheel-sspBidAdapter.js +1 -1
  41. package/dist/gdprEnforcement.js +1 -1
  42. package/dist/glimpseBidAdapter.js +1 -1
  43. package/dist/gmosspBidAdapter.js +1 -1
  44. package/dist/goldbachBidAdapter.js +1 -1
  45. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  46. package/dist/greenbidsRtdProvider.js +1 -1
  47. package/dist/gridBidAdapter.js +1 -1
  48. package/dist/growthCodeRtdProvider.js +1 -0
  49. package/dist/gumgumBidAdapter.js +1 -1
  50. package/dist/h12mediaBidAdapter.js +1 -1
  51. package/dist/id5IdSystem.js +1 -1
  52. package/dist/improvedigitalBidAdapter.js +1 -1
  53. package/dist/inmarBidAdapter.js +1 -1
  54. package/dist/insticatorBidAdapter.js +1 -1
  55. package/dist/ixBidAdapter.js +1 -1
  56. package/dist/justpremiumBidAdapter.js +1 -1
  57. package/dist/kargoBidAdapter.js +1 -1
  58. package/dist/konduitAnalyticsAdapter.js +1 -1
  59. package/dist/kueezBidAdapter.js +1 -1
  60. package/dist/kueezRtbBidAdapter.js +1 -1
  61. package/dist/kulturemediaBidAdapter.js +1 -1
  62. package/dist/lassoBidAdapter.js +1 -1
  63. package/dist/lifestreetBidAdapter.js +1 -1
  64. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  65. package/dist/logicadBidAdapter.js +1 -1
  66. package/dist/loglyliftBidAdapter.js +1 -1
  67. package/dist/magniteAnalyticsAdapter.js +1 -1
  68. package/dist/malltvAnalyticsAdapter.js +1 -1
  69. package/dist/marsmediaBidAdapter.js +1 -1
  70. package/dist/mediafuseBidAdapter.js +1 -1
  71. package/dist/mediasquareBidAdapter.js +1 -1
  72. package/dist/mgidBidAdapter.js +1 -1
  73. package/dist/minutemediaBidAdapter.js +1 -1
  74. package/dist/minutemediaplusBidAdapter.js +1 -1
  75. package/dist/nexx360BidAdapter.js +1 -1
  76. package/dist/not-for-prod/prebid.js +136 -132
  77. package/dist/objectGuard.js +1 -0
  78. package/dist/oguryBidAdapter.js +1 -1
  79. package/dist/onetagBidAdapter.js +1 -1
  80. package/dist/ooloAnalyticsAdapter.js +1 -1
  81. package/dist/optidigitalBidAdapter.js +1 -1
  82. package/dist/outbrainBidAdapter.js +1 -1
  83. package/dist/oxxionAnalyticsAdapter.js +1 -0
  84. package/dist/pairIdSystem.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/publinkIdSystem.js +1 -1
  89. package/dist/pubmaticBidAdapter.js +1 -1
  90. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  91. package/dist/pxyzBidAdapter.js +1 -1
  92. package/dist/quantcastBidAdapter.js +1 -1
  93. package/dist/readpeakBidAdapter.js +1 -1
  94. package/dist/relaidoBidAdapter.js +1 -1
  95. package/dist/retailspotBidAdapter.js +1 -1
  96. package/dist/rhythmoneBidAdapter.js +1 -1
  97. package/dist/riseBidAdapter.js +1 -1
  98. package/dist/rtdModule.js +1 -1
  99. package/dist/rubiconAnalyticsAdapter.js +1 -1
  100. package/dist/rubiconBidAdapter.js +1 -1
  101. package/dist/seedingAllianceBidAdapter.js +1 -1
  102. package/dist/seedtagBidAdapter.js +1 -1
  103. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  104. package/dist/sharethroughBidAdapter.js +1 -1
  105. package/dist/shinezBidAdapter.js +1 -1
  106. package/dist/smaatoBidAdapter.js +1 -1
  107. package/dist/smartadserverBidAdapter.js +1 -1
  108. package/dist/smartxBidAdapter.js +1 -1
  109. package/dist/smilewantedBidAdapter.js +1 -1
  110. package/dist/sonobiBidAdapter.js +1 -1
  111. package/dist/sovrnAnalyticsAdapter.js +1 -1
  112. package/dist/sovrnBidAdapter.js +1 -1
  113. package/dist/sspBCBidAdapter.js +1 -1
  114. package/dist/stvBidAdapter.js +1 -1
  115. package/dist/sublimeBidAdapter.js +1 -1
  116. package/dist/synacormediaBidAdapter.js +1 -1
  117. package/dist/targetVideoBidAdapter.js +1 -1
  118. package/dist/teadsBidAdapter.js +1 -1
  119. package/dist/trionBidAdapter.js +1 -1
  120. package/dist/tripleliftBidAdapter.js +1 -1
  121. package/dist/ttdBidAdapter.js +1 -1
  122. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  123. package/dist/uid2IdSystem.js +1 -1
  124. package/dist/underdogmediaBidAdapter.js +1 -1
  125. package/dist/undertoneBidAdapter.js +1 -1
  126. package/dist/userId.js +1 -1
  127. package/dist/vidazooBidAdapter.js +1 -1
  128. package/dist/videobyteBidAdapter.js +1 -1
  129. package/dist/visxBidAdapter.js +1 -1
  130. package/dist/vuukleBidAdapter.js +1 -1
  131. package/dist/widespaceBidAdapter.js +1 -1
  132. package/dist/winrBidAdapter.js +1 -1
  133. package/dist/yahoosspBidAdapter.js +1 -1
  134. package/dist/yieldmoBidAdapter.js +1 -1
  135. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  136. package/dist/zeta_global_sspBidAdapter.js +1 -1
  137. package/integrationExamples/gpt/growthcode.html +20 -9
  138. package/libraries/objectGuard/objectGuard.js +108 -0
  139. package/libraries/objectGuard/ortbGuard.js +88 -0
  140. package/modules/adgenerationBidAdapter.js +14 -5
  141. package/modules/adriverIdSystem.js +1 -1
  142. package/modules/allowActivities.js +74 -0
  143. package/modules/connectIdSystem.js +89 -13
  144. package/modules/connectIdSystem.md +4 -7
  145. package/modules/criteoBidAdapter.js +9 -0
  146. package/modules/gdprEnforcement.js +98 -169
  147. package/modules/growthCodeRtdProvider.js +131 -0
  148. package/modules/growthCodeRtdProvider.md +55 -0
  149. package/modules/ixBidAdapter.js +5 -2
  150. package/modules/oxxionAnalyticsAdapter.js +212 -0
  151. package/modules/oxxionAnalyticsAdapter.md +33 -0
  152. package/modules/pairIdSystem.js +6 -6
  153. package/modules/rtdModule/index.js +12 -1
  154. package/modules/sharethroughBidAdapter.js +2 -2
  155. package/modules/smartadserverBidAdapter.js +5 -0
  156. package/modules/stvBidAdapter.js +34 -1
  157. package/modules/undertoneBidAdapter.js +9 -1
  158. package/modules/userId/index.js +69 -41
  159. package/modules/yahoosspBidAdapter.js +45 -3
  160. package/modules/yahoosspBidAdapter.md +1 -1
  161. package/modules/zeta_global_sspBidAdapter.js +1 -0
  162. package/package.json +1 -1
  163. package/src/activities/activities.js +47 -0
  164. package/src/activities/activityParams.js +8 -0
  165. package/src/activities/modules.js +1 -1
  166. package/src/activities/params.js +59 -0
  167. package/src/activities/redactor.js +157 -0
  168. package/src/activities/rules.js +95 -0
  169. package/src/adapterManager.js +45 -8
  170. package/src/fpd/rootDomain.js +1 -1
  171. package/src/prebid.js +1 -1
  172. package/src/storageManager.js +57 -44
  173. package/src/userSync.js +35 -18
  174. package/test/spec/activities/allowActivites_spec.js +138 -0
  175. package/test/spec/activities/objectGuard_spec.js +144 -0
  176. package/test/spec/activities/ortbGuard_spec.js +140 -0
  177. package/test/spec/activities/params_spec.js +25 -0
  178. package/test/spec/activities/redactor_spec.js +296 -0
  179. package/test/spec/activities/rules_spec.js +135 -0
  180. package/test/spec/modules/adgenerationBidAdapter_spec.js +52 -12
  181. package/test/spec/modules/connectIdSystem_spec.js +291 -23
  182. package/test/spec/modules/criteoBidAdapter_spec.js +84 -0
  183. package/test/spec/modules/gdprEnforcement_spec.js +127 -414
  184. package/test/spec/modules/growthCodeRtdProvider_spec.js +127 -0
  185. package/test/spec/modules/ixBidAdapter_spec.js +2 -1
  186. package/test/spec/modules/oxxionAnalyticsAdapter_spec.js +324 -0
  187. package/test/spec/modules/pairIdSystem_spec.js +16 -3
  188. package/test/spec/modules/realTimeDataModule_spec.js +1 -1
  189. package/test/spec/modules/sharethroughBidAdapter_spec.js +1 -1
  190. package/test/spec/modules/smartadserverBidAdapter_spec.js +42 -0
  191. package/test/spec/modules/stvBidAdapter_spec.js +13 -1
  192. package/test/spec/modules/undertoneBidAdapter_spec.js +57 -1
  193. package/test/spec/modules/userId_spec.js +80 -21
  194. package/test/spec/modules/yahoosspBidAdapter_spec.js +103 -51
  195. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +4 -0
  196. package/test/spec/unit/core/adapterManager_spec.js +181 -1
  197. package/test/spec/unit/core/storageManager_spec.js +76 -68
  198. package/test/spec/unit/pbjs_api_spec.js +15 -25
  199. package/test/spec/userSync_spec.js +45 -16
@@ -0,0 +1,131 @@
1
+ /**
2
+ * This module adds GrowthCode HEM and other Data to Bid Requests
3
+ * @module modules/growthCodeRtdProvider
4
+ */
5
+ import { submodule } from '../src/hook.js'
6
+ import { getStorageManager } from '../src/storageManager.js';
7
+ import {
8
+ logMessage, logError, tryAppendQueryString, mergeDeep
9
+ } from '../src/utils.js';
10
+ import * as ajax from '../src/ajax.js';
11
+ import { MODULE_TYPE_RTD } from '../src/activities/modules.js';
12
+
13
+ const MODULE_NAME = 'growthCodeRtd';
14
+ const LOG_PREFIX = 'GrowthCodeRtd: ';
15
+ const ENDPOINT_URL = 'https://p2.gcprivacy.com/v2/rtd?'
16
+ const RTD_EXPIRE_KEY = 'gc_rtd_expires_at'
17
+ const RTD_CACHE_KEY = 'gc_rtd_items'
18
+
19
+ export const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: MODULE_NAME });
20
+ let items
21
+
22
+ export const growthCodeRtdProvider = {
23
+ name: MODULE_NAME,
24
+ init: init,
25
+ getBidRequestData: alterBidRequests,
26
+ addData: addData,
27
+ callServer: callServer
28
+ };
29
+
30
+ /**
31
+ * Parse json if possible, else return null
32
+ * @param data
33
+ * @returns {any|null}
34
+ */
35
+ function tryParse(data) {
36
+ try {
37
+ return JSON.parse(data);
38
+ } catch (err) {
39
+ logError(err);
40
+ return null;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Init The RTD Module
46
+ * @param config
47
+ * @param userConsent
48
+ * @returns {boolean}
49
+ */
50
+ function init(config, userConsent) {
51
+ logMessage(LOG_PREFIX + 'Init RTB');
52
+
53
+ if (config == null) {
54
+ return false
55
+ }
56
+
57
+ const configParams = (config && config.params) || {};
58
+ let expiresAt = parseInt(storage.getDataFromLocalStorage(RTD_EXPIRE_KEY, null));
59
+
60
+ items = tryParse(storage.getDataFromLocalStorage(RTD_CACHE_KEY, null));
61
+
62
+ return callServer(configParams, items, expiresAt, userConsent);
63
+ }
64
+ function callServer(configParams, items, expiresAt, userConsent) {
65
+ // Expire Cache
66
+ let now = Math.trunc(Date.now() / 1000);
67
+ if ((!isNaN(expiresAt)) && (now > expiresAt)) {
68
+ expiresAt = NaN;
69
+ storage.removeDataFromLocalStorage(RTD_CACHE_KEY, null)
70
+ storage.removeDataFromLocalStorage(RTD_EXPIRE_KEY, null)
71
+ }
72
+ if ((items === null) && (isNaN(expiresAt))) {
73
+ let gcid = localStorage.getItem('gcid')
74
+
75
+ let url = configParams.url ? configParams.url : ENDPOINT_URL;
76
+ url = tryAppendQueryString(url, 'pid', configParams.pid);
77
+ url = tryAppendQueryString(url, 'u', window.location.href);
78
+ url = tryAppendQueryString(url, 'gcid', gcid);
79
+ if ((userConsent !== null) && (userConsent.gdpr !== null) && (userConsent.gdpr.consentData.getTCData.tcString)) {
80
+ url = tryAppendQueryString(url, 'tcf', userConsent.gdpr.consentData.getTCData.tcString)
81
+ }
82
+
83
+ ajax.ajaxBuilder()(url, {
84
+ success: response => {
85
+ let respJson = tryParse(response);
86
+ // If response is a valid json and should save is true
87
+ if (respJson && respJson.results >= 1) {
88
+ storage.setDataInLocalStorage(RTD_CACHE_KEY, JSON.stringify(respJson.items), null);
89
+ storage.setDataInLocalStorage(RTD_EXPIRE_KEY, respJson.expires_at, null)
90
+ } else {
91
+ storage.setDataInLocalStorage(RTD_EXPIRE_KEY, respJson.expires_at, null)
92
+ }
93
+ },
94
+ error: error => {
95
+ logError(LOG_PREFIX + 'ID fetch encountered an error', error);
96
+ }
97
+ }, undefined, {method: 'GET', withCredentials: true})
98
+ }
99
+
100
+ return true;
101
+ }
102
+
103
+ function addData(reqBidsConfigObj, items) {
104
+ let merge = false
105
+
106
+ for (let j = 0; j < items.length; j++) {
107
+ let item = items[j]
108
+ let data = JSON.parse(item.parameters);
109
+ if (item['attachment_point'] === 'data') {
110
+ mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, data)
111
+ merge = true
112
+ }
113
+ }
114
+ return merge
115
+ }
116
+
117
+ /**
118
+ * Alter the Bid Request for additional information such as HEM or 3rd Party Ids
119
+ * @param reqBidsConfigObj
120
+ * @param callback
121
+ * @param config
122
+ * @param userConsent
123
+ */
124
+ function alterBidRequests(reqBidsConfigObj, callback, config, userConsent) {
125
+ if (items != null) {
126
+ addData(reqBidsConfigObj, items)
127
+ }
128
+ callback();
129
+ }
130
+
131
+ submodule('realTimeData', growthCodeRtdProvider);
@@ -0,0 +1,55 @@
1
+ ## GrowthCode Real-time Data Submodule
2
+
3
+ The [GrowthCode](https://growthcode.io) real-time data module in Prebid enables publishers to fully
4
+ leverage the potential of their first-party audiences and contextual data.
5
+ With an integrated cookieless GrowthCode identity, this module offers real-time
6
+ contextual and audience segmentation (IAB Taxonomy 2.2, cattax: 6) capabilities, and HEMs that can seamlessly
7
+ integrate into your existing Prebid deployment, making it easy to maximize
8
+ your advertising strategies.
9
+
10
+ ## Building Prebid with GrowthCode Support
11
+
12
+ Compile the GrowthCode RTD module into your Prebid build:
13
+
14
+ `gulp serve --modules=userId,rtdModule,appnexusBidAdapter,growthCodeRtdProvider,sharedIdSystem,criteoBidAdapter`
15
+
16
+ Please visit https://growthcode.io/ for more information.
17
+
18
+ ```
19
+ pbjs.setConfig(
20
+ ...
21
+ realTimeData: {
22
+ auctionDelay: 1000,
23
+ dataProviders: [
24
+ {
25
+ name: 'growthCodeRtd',
26
+ waitForIt: true,
27
+ params: {
28
+ pid: 'TEST01',
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ ...
34
+ }
35
+ ```
36
+
37
+ ### Parameter Descriptions for the GrowthCode Configuration Section
38
+
39
+ | Name | Type | Description | Notes |
40
+ |:---------------------------------|:--------|:--------------------------------------------------------------------------|:----------------------------|
41
+ | name | String | Real time data module name | Always 'growthCodeRtd' |
42
+ | waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false |
43
+ | params | Object | | |
44
+ | params.pid | String | This is the Parter ID value obtained from GrowthCode | `TEST01` |
45
+ | params.url | String | Custom URL for server | Optional |
46
+
47
+ ## Testing
48
+
49
+ To view an example of GrowthCode backends:
50
+
51
+ `gulp serve --modules=userId,rtdModule,appnexusBidAdapter,growthCodeRtdProvider,sharedIdSystem,criteoBidAdapter`
52
+
53
+ and then point your browser at:
54
+
55
+ `http://localhost:9999/integrationExamples/gpt/growthcode.html`
@@ -145,6 +145,7 @@ export const FEATURE_TOGGLES = {
145
145
  let siteID = 0;
146
146
  let gdprConsent = '';
147
147
  let usPrivacy = '';
148
+ let defaultVideoPlacement = false;
148
149
 
149
150
  // Possible values for bidResponse.seatBid[].bid[].mtype which indicates the type of the creative markup so that it can properly be associated with the right sub-object of the BidRequest.Imp.
150
151
  const MEDIA_TYPES = {
@@ -223,7 +224,8 @@ function bidToVideoImp(bid) {
223
224
  if (deepAccess(videoParamRef, 'playerConfig.floatOnScroll')) {
224
225
  imp.video.placement = 5;
225
226
  } else {
226
- imp.video.placement = 4;
227
+ imp.video.placement = 3;
228
+ defaultVideoPlacement = true;
227
229
  }
228
230
  } else {
229
231
  logWarn(`IX Bid Adapter: Video context '${context}' is not supported`);
@@ -1111,7 +1113,8 @@ function buildIXDiag(validBidRequests) {
1111
1113
  ren: false,
1112
1114
  version: '$prebid.version$',
1113
1115
  userIds: _getUserIds(validBidRequests[0]),
1114
- url: window.location.href.split('?')[0]
1116
+ url: window.location.href.split('?')[0],
1117
+ vpd: defaultVideoPlacement
1115
1118
  };
1116
1119
 
1117
1120
  // create ad unit map and collect the required diag properties
@@ -0,0 +1,212 @@
1
+ import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
2
+ import adapterManager from '../src/adapterManager.js';
3
+ import CONSTANTS from '../src/constants.json';
4
+ import { ajax } from '../src/ajax.js';
5
+ import { getRefererInfo } from '../src/refererDetection.js';
6
+
7
+ const analyticsType = 'endpoint';
8
+ const url = 'URL_TO_SERVER_ENDPOINT';
9
+
10
+ const {
11
+ EVENTS: {
12
+ AUCTION_END,
13
+ BID_WON,
14
+ BID_RESPONSE,
15
+ BID_REQUESTED,
16
+ BID_TIMEOUT,
17
+ }
18
+ } = CONSTANTS;
19
+
20
+ let saveEvents = {}
21
+ let allEvents = {}
22
+ let auctionEnd = {}
23
+ let initOptions = {}
24
+ let endpoint = 'https://default'
25
+ let requestsAttributes = ['adUnitCode', 'auctionId', 'bidder', 'bidderCode', 'bidId', 'cpm', 'creativeId', 'currency', 'width', 'height', 'mediaType', 'netRevenue', 'originalCpm', 'originalCurrency', 'requestId', 'size', 'source', 'status', 'timeToRespond', 'transactionId', 'ttl', 'sizes', 'mediaTypes', 'src', 'params', 'userId', 'labelAny', 'bids', 'adId'];
26
+
27
+ function getAdapterNameForAlias(aliasName) {
28
+ return adapterManager.aliasRegistry[aliasName] || aliasName;
29
+ }
30
+
31
+ function filterAttributes(arg, removead) {
32
+ let response = {};
33
+ if (typeof arg == 'object') {
34
+ if (typeof arg['bidderCode'] == 'string') {
35
+ response['originalBidder'] = getAdapterNameForAlias(arg['bidderCode']);
36
+ } else if (typeof arg['bidder'] == 'string') {
37
+ response['originalBidder'] = getAdapterNameForAlias(arg['bidder']);
38
+ }
39
+ if (!removead && typeof arg['ad'] != 'undefined') {
40
+ response['ad'] = arg['ad'];
41
+ }
42
+ if (typeof arg['gdprConsent'] != 'undefined') {
43
+ response['gdprConsent'] = {};
44
+ if (typeof arg['gdprConsent']['consentString'] != 'undefined') { response['gdprConsent']['consentString'] = arg['gdprConsent']['consentString']; }
45
+ }
46
+ if (typeof arg['meta'] == 'object' && typeof arg['meta']['advertiserDomains'] != 'undefined') {
47
+ response['meta'] = {'advertiserDomains': arg['meta']['advertiserDomains']};
48
+ }
49
+ requestsAttributes.forEach((attr) => {
50
+ if (typeof arg[attr] != 'undefined') { response[attr] = arg[attr]; }
51
+ });
52
+ if (typeof response['creativeId'] == 'number') { response['creativeId'] = response['creativeId'].toString(); }
53
+ }
54
+ return response;
55
+ }
56
+
57
+ function cleanAuctionEnd(args) {
58
+ let response = {};
59
+ let filteredObj;
60
+ let objects = ['bidderRequests', 'bidsReceived', 'noBids', 'adUnits'];
61
+ objects.forEach((attr) => {
62
+ if (Array.isArray(args[attr])) {
63
+ response[attr] = [];
64
+ args[attr].forEach((obj) => {
65
+ filteredObj = filterAttributes(obj, true);
66
+ if (typeof obj['bids'] == 'object') {
67
+ filteredObj['bids'] = [];
68
+ obj['bids'].forEach((bid) => {
69
+ filteredObj['bids'].push(filterAttributes(bid, true));
70
+ });
71
+ }
72
+ response[attr].push(filteredObj);
73
+ });
74
+ }
75
+ });
76
+ return response;
77
+ }
78
+
79
+ function cleanCreatives(args) {
80
+ return filterAttributes(args, false);
81
+ }
82
+
83
+ function enhanceMediaType(arg) {
84
+ saveEvents['bidRequested'].forEach((bidRequested) => {
85
+ if (bidRequested['auctionId'] == arg['auctionId'] && Array.isArray(bidRequested['bids'])) {
86
+ bidRequested['bids'].forEach((bid) => {
87
+ if (bid['transactionId'] == arg['transactionId'] && bid['bidId'] == arg['requestId']) { arg['mediaTypes'] = bid['mediaTypes']; }
88
+ });
89
+ }
90
+ });
91
+ return arg;
92
+ }
93
+
94
+ function addBidResponse(args) {
95
+ let eventType = BID_RESPONSE;
96
+ let argsCleaned = cleanCreatives(JSON.parse(JSON.stringify(args))); ;
97
+ if (allEvents[eventType] == undefined) { allEvents[eventType] = [] }
98
+ allEvents[eventType].push(argsCleaned);
99
+ }
100
+
101
+ function addBidRequested(args) {
102
+ let eventType = BID_REQUESTED;
103
+ let argsCleaned = filterAttributes(args, true);
104
+ if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
105
+ saveEvents[eventType].push(argsCleaned);
106
+ }
107
+
108
+ function addTimeout(args) {
109
+ let eventType = BID_TIMEOUT;
110
+ if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
111
+ saveEvents[eventType].push(args);
112
+ let argsCleaned = [];
113
+ let argsDereferenced = JSON.parse(JSON.stringify(args));
114
+ argsDereferenced.forEach((attr) => {
115
+ argsCleaned.push(filterAttributes(JSON.parse(JSON.stringify(attr)), false));
116
+ });
117
+ if (auctionEnd[eventType] == undefined) { auctionEnd[eventType] = [] }
118
+ auctionEnd[eventType].push(argsCleaned);
119
+ }
120
+
121
+ function addAuctionEnd(args) {
122
+ let eventType = AUCTION_END;
123
+ if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
124
+ saveEvents[eventType].push(args);
125
+ let argsCleaned = cleanAuctionEnd(JSON.parse(JSON.stringify(args)));
126
+ if (auctionEnd[eventType] == undefined) { auctionEnd[eventType] = [] }
127
+ auctionEnd[eventType].push(argsCleaned);
128
+ }
129
+
130
+ function handleBidWon(args) {
131
+ args = enhanceMediaType(filterAttributes(JSON.parse(JSON.stringify(args)), true));
132
+ let increment = args['cpm'];
133
+ if (typeof saveEvents['auctionEnd'] == 'object') {
134
+ saveEvents['auctionEnd'].forEach((auction) => {
135
+ if (auction['auctionId'] == args['auctionId'] && typeof auction['bidsReceived'] == 'object') {
136
+ auction['bidsReceived'].forEach((bid) => {
137
+ if (bid['transactionId'] == args['transactionId'] && bid['adId'] != args['adId']) {
138
+ if (args['cpm'] < bid['cpm']) {
139
+ increment = 0;
140
+ } else if (increment > args['cpm'] - bid['cpm']) {
141
+ increment = args['cpm'] - bid['cpm'];
142
+ }
143
+ }
144
+ });
145
+ }
146
+ });
147
+ }
148
+ args['cpmIncrement'] = increment;
149
+ args['referer'] = encodeURIComponent(getRefererInfo().page || getRefererInfo().topmostLocation);
150
+ if (typeof saveEvents.bidRequested == 'object' && saveEvents.bidRequested.length > 0 && saveEvents.bidRequested[0].gdprConsent) { args.gdpr = saveEvents.bidRequested[0].gdprConsent; }
151
+ ajax(endpoint + '.oxxion.io/analytics/bid_won', null, JSON.stringify(args), {method: 'POST', withCredentials: true});
152
+ }
153
+
154
+ function handleAuctionEnd() {
155
+ ajax(endpoint + '.oxxion.io/analytics/auctions', function (data) {
156
+ let list = JSON.parse(data);
157
+ if (Array.isArray(list) && typeof allEvents['bidResponse'] != 'undefined') {
158
+ let alreadyCalled = [];
159
+ allEvents['bidResponse'].forEach((bidResponse) => {
160
+ let tmpId = bidResponse['originalBidder'] + '_' + bidResponse['creativeId'];
161
+ if (list.includes(tmpId) && !alreadyCalled.includes(tmpId)) {
162
+ alreadyCalled.push(tmpId);
163
+ ajax(endpoint + '.oxxion.io/analytics/creatives', null, JSON.stringify(bidResponse), {method: 'POST', withCredentials: true});
164
+ }
165
+ });
166
+ }
167
+ allEvents = {};
168
+ }, JSON.stringify(auctionEnd), {method: 'POST', withCredentials: true});
169
+ auctionEnd = {};
170
+ }
171
+
172
+ let oxxionAnalytics = Object.assign(adapter({url, analyticsType}), {
173
+ track({
174
+ eventType,
175
+ args
176
+ }) {
177
+ switch (eventType) {
178
+ case AUCTION_END:
179
+ addAuctionEnd(args);
180
+ handleAuctionEnd();
181
+ break;
182
+ case BID_WON:
183
+ handleBidWon(args);
184
+ break;
185
+ case BID_RESPONSE:
186
+ addBidResponse(args);
187
+ break;
188
+ case BID_REQUESTED:
189
+ addBidRequested(args);
190
+ break;
191
+ case BID_TIMEOUT:
192
+ addTimeout(args);
193
+ break;
194
+ }
195
+ }});
196
+
197
+ // save the base class function
198
+ oxxionAnalytics.originEnableAnalytics = oxxionAnalytics.enableAnalytics;
199
+
200
+ // override enableAnalytics so we can get access to the config passed in from the page
201
+ oxxionAnalytics.enableAnalytics = function (config) {
202
+ oxxionAnalytics.originEnableAnalytics(config); // call the base class function
203
+ initOptions = config.options;
204
+ if (initOptions.domain) { endpoint = 'https://' + initOptions.domain; }
205
+ };
206
+
207
+ adapterManager.registerAnalyticsAdapter({
208
+ adapter: oxxionAnalytics,
209
+ code: 'oxxion'
210
+ });
211
+
212
+ export default oxxionAnalytics;
@@ -0,0 +1,33 @@
1
+ # Overview
2
+ Module Name: oxxion Analytics Adapter
3
+
4
+ Module Type: Analytics Adapter
5
+
6
+ Maintainer: tech@oxxion.io
7
+
8
+ # Oxxion Analytics Adapter
9
+
10
+ Oxxion helps you to understand how your prebid stack performs.
11
+
12
+ # Integration
13
+
14
+ Add the oxxion analytics adapter module to your prebid configuration :
15
+ ```
16
+ pbjs.enableAnalytics(
17
+ ...
18
+ {
19
+ provider: 'oxxion',
20
+ options : {
21
+ domain: 'test.endpoint'
22
+ }
23
+ }
24
+ ...
25
+ )
26
+ ```
27
+
28
+ # Parameters
29
+
30
+ | Name | Type | Description |
31
+ |:-------------------------------|:---------|:------------------------------------------------------------------------------------------------------------|
32
+ | domain | String | This string identifies yourself in Oxxion's systems and is provided to you by your Oxxion representative. |
33
+
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { submodule } from '../src/hook.js';
9
9
  import {getStorageManager} from '../src/storageManager.js'
10
- import { logError } from '../src/utils.js';
10
+ import { logInfo } from '../src/utils.js';
11
11
  import {MODULE_TYPE_UID} from '../src/activities/modules.js';
12
12
 
13
13
  const MODULE_NAME = 'pairId';
@@ -17,11 +17,11 @@ const DEFAULT_LIVERAMP_PAIR_ID_KEY = '_lr_pairId';
17
17
  export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
18
18
 
19
19
  function pairIdFromLocalStorage(key) {
20
- return storage.localStorageIsEnabled ? storage.getDataFromLocalStorage(key) : null;
20
+ return storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(key) : null;
21
21
  }
22
22
 
23
23
  function pairIdFromCookie(key) {
24
- return storage.cookiesAreEnabled ? storage.getCookie(key) : null;
24
+ return storage.cookiesAreEnabled() ? storage.getCookie(key) : null;
25
25
  }
26
26
 
27
27
  /** @type {Submodule} */
@@ -52,7 +52,7 @@ export const pairIdSubmodule = {
52
52
  try {
53
53
  ids = ids.concat(JSON.parse(atob(pairIdsString)))
54
54
  } catch (error) {
55
- logError(error)
55
+ logInfo(error)
56
56
  }
57
57
  }
58
58
 
@@ -64,12 +64,12 @@ export const pairIdSubmodule = {
64
64
  const obj = JSON.parse(atob(liverampValue));
65
65
  ids = ids.concat(obj.envelope);
66
66
  } catch (error) {
67
- logError(error)
67
+ logInfo(error)
68
68
  }
69
69
  }
70
70
 
71
71
  if (ids.length == 0) {
72
- logError('PairId not found.')
72
+ logInfo('PairId not found.')
73
73
  return undefined;
74
74
  }
75
75
  return {'id': ids};
@@ -168,6 +168,10 @@ import {find} from '../../src/polyfill.js';
168
168
  import {timedAuctionHook} from '../../src/utils/perfMetrics.js';
169
169
  import {GDPR_GVLIDS} from '../../src/consentHandler.js';
170
170
  import {MODULE_TYPE_RTD} from '../../src/activities/modules.js';
171
+ import {guardOrtb2Fragments} from '../../libraries/objectGuard/ortbGuard.js';
172
+ import {activityParamsBuilder} from '../../src/activities/params.js';
173
+
174
+ const activityParams = activityParamsBuilder((al) => adapterManager.resolveAlias(al));
171
175
 
172
176
  /** @type {string} */
173
177
  const MODULE_NAME = 'realTimeData';
@@ -299,6 +303,7 @@ export const setBidRequestsData = timedAuctionHook('rtd', function setBidRequest
299
303
  let callbacksExpected = prioritySubModules.length;
300
304
  let isDone = false;
301
305
  let waitTimeout;
306
+ const verifiers = [];
302
307
 
303
308
  if (!relevantSubModules.length) {
304
309
  return exitHook();
@@ -307,7 +312,12 @@ export const setBidRequestsData = timedAuctionHook('rtd', function setBidRequest
307
312
  waitTimeout = setTimeout(exitHook, shouldDelayAuction ? _moduleConfig.auctionDelay : 0);
308
313
 
309
314
  relevantSubModules.forEach(sm => {
310
- sm.getBidRequestData(reqBidsConfigObj, onGetBidRequestDataCallback.bind(sm), sm.config, _userConsent)
315
+ const fpdGuard = guardOrtb2Fragments(reqBidsConfigObj.ortb2Fragments || {}, activityParams(MODULE_TYPE_RTD, sm.name));
316
+ verifiers.push(fpdGuard.verify);
317
+ sm.getBidRequestData({
318
+ ...reqBidsConfigObj,
319
+ ortb2Fragments: fpdGuard.obj
320
+ }, onGetBidRequestDataCallback.bind(sm), sm.config, _userConsent)
311
321
  });
312
322
 
313
323
  function onGetBidRequestDataCallback() {
@@ -328,6 +338,7 @@ export const setBidRequestsData = timedAuctionHook('rtd', function setBidRequest
328
338
  }
329
339
  isDone = true;
330
340
  clearTimeout(waitTimeout);
341
+ verifiers.forEach(fn => fn());
331
342
  fn.call(this, reqBidsConfigObj);
332
343
  }
333
344
  });
@@ -93,8 +93,8 @@ export const sharethroughAdapterSpec = {
93
93
  if (videoRequest) {
94
94
  // default playerSize, only change this if we know width and height are properly defined in the request
95
95
  let [w, h] = [640, 360];
96
- if (videoRequest.playerSize && videoRequest.playerSize[0] && videoRequest.playerSize[1]) {
97
- [w, h] = videoRequest.playerSize;
96
+ if (videoRequest.playerSize && videoRequest.playerSize[0] && videoRequest.playerSize[0][0] && videoRequest.playerSize[0][1]) {
97
+ [w, h] = videoRequest.playerSize[0];
98
98
  }
99
99
 
100
100
  impression.video = {
@@ -159,6 +159,11 @@ export const spec = {
159
159
  sdc: sellerDefinedContext
160
160
  };
161
161
 
162
+ const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid', deepAccess(bid, 'ortb2Imp.ext.data.pbadslot', ''));
163
+ if (gpid) {
164
+ payload.gpid = gpid;
165
+ }
166
+
162
167
  if (bidderRequest) {
163
168
  if (bidderRequest.gdprConsent) {
164
169
  payload.addtl_consent = bidderRequest.gdprConsent.addtlConsent;
@@ -50,10 +50,16 @@ export const spec = {
50
50
  ref: referrer,
51
51
  bid_id: bidId,
52
52
  pbver: '$prebid.version$',
53
+ schain: '',
53
54
  };
54
55
  if (!isVideoRequest(bidRequest)) {
55
56
  payload._f = 'html';
56
57
  }
58
+ if (bidRequest.schain) {
59
+ payload.schain = serializeSChain(bidRequest.schain);
60
+ } else {
61
+ delete payload.schain;
62
+ }
57
63
 
58
64
  payload.pfilter = { ...params };
59
65
  delete payload.pfilter.placement;
@@ -195,12 +201,39 @@ function objectToQueryString(obj, prefix) {
195
201
  let v = obj[p];
196
202
  str.push((v !== null && typeof v === 'object')
197
203
  ? objectToQueryString(v, k)
198
- : encodeURIComponent(k) + '=' + encodeURIComponent(v));
204
+ : (k == 'schain' ? k + '=' + v : encodeURIComponent(k) + '=' + encodeURIComponent(v)));
199
205
  }
200
206
  }
201
207
  return str.join('&');
202
208
  }
203
209
 
210
+ function serializeSChain(schain) {
211
+ let ret = '';
212
+
213
+ ret += encodeURIComponent(schain.ver);
214
+ ret += ',';
215
+ ret += encodeURIComponent(schain.complete);
216
+
217
+ for (let node of schain.nodes) {
218
+ ret += '!';
219
+ ret += encodeURIComponent(node.asi);
220
+ ret += ',';
221
+ ret += encodeURIComponent(node.sid);
222
+ ret += ',';
223
+ ret += encodeURIComponent(node.hp);
224
+ ret += ',';
225
+ ret += encodeURIComponent(node.rid ?? '');
226
+ ret += ',';
227
+ ret += encodeURIComponent(node.name ?? '');
228
+ ret += ',';
229
+ ret += encodeURIComponent(node.domain ?? '');
230
+ ret += ',';
231
+ ret += encodeURIComponent(node.ext ?? '');
232
+ }
233
+
234
+ return ret;
235
+ }
236
+
204
237
  /**
205
238
  * Check if it's a banner bid request
206
239
  *
@@ -124,6 +124,12 @@ export const spec = {
124
124
  reqUrl += `&ccpa=${bidderRequest.uspConsent}`;
125
125
  }
126
126
 
127
+ if (bidderRequest.gppConsent) {
128
+ const gppString = bidderRequest.gppConsent.gppString ?? '';
129
+ const ggpSid = bidderRequest.gppConsent.applicableSections ?? '';
130
+ reqUrl += `&gpp=${gppString}&gpp_sid=${ggpSid}`;
131
+ }
132
+
127
133
  validBidRequests.map(bidReq => {
128
134
  const bid = {
129
135
  bidRequestId: bidReq.bidId,
@@ -146,7 +152,9 @@ export const spec = {
146
152
  streamType: deepAccess(bidReq, 'mediaTypes.video.context') || null,
147
153
  playbackMethod: deepAccess(bidReq, 'params.video.playbackMethod') || null,
148
154
  maxDuration: deepAccess(bidReq, 'params.video.maxDuration') || null,
149
- skippable: deepAccess(bidReq, 'params.video.skippable') || null
155
+ skippable: deepAccess(bidReq, 'params.video.skippable') || null,
156
+ placement: deepAccess(bidReq, 'mediaTypes.video.placement') || null,
157
+ plcmt: deepAccess(bidReq, 'mediaTypes.video.plcmt') || null
150
158
  };
151
159
  }
152
160
  payload['x-ut-hb-params'].push(bid);