prebid.js 7.51.0 → 7.53.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 (277) hide show
  1. package/dist/1plusXRtdProvider.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/adkernelBidAdapter.js +1 -1
  8. package/dist/adqueryBidAdapter.js +1 -1
  9. package/dist/adrelevantisBidAdapter.js +1 -1
  10. package/dist/adriverIdSystem.js +1 -1
  11. package/dist/adtrgtmeBidAdapter.js +1 -1
  12. package/dist/adxcgBidAdapter.js +1 -1
  13. package/dist/adyoulikeBidAdapter.js +1 -1
  14. package/dist/airgridRtdProvider.js +1 -1
  15. package/dist/ajaBidAdapter.js +1 -1
  16. package/dist/allowActivities.js +1 -0
  17. package/dist/amxBidAdapter.js +1 -1
  18. package/dist/amxIdSystem.js +1 -1
  19. package/dist/appierAnalyticsAdapter.js +1 -1
  20. package/dist/appnexusBidAdapter.js +1 -1
  21. package/dist/asoBidAdapter.js +1 -1
  22. package/dist/axonixBidAdapter.js +1 -1
  23. package/dist/beopBidAdapter.js +1 -1
  24. package/dist/bidglassBidAdapter.js +1 -1
  25. package/dist/big-richmediaBidAdapter.js +1 -1
  26. package/dist/bridgewellBidAdapter.js +1 -1
  27. package/dist/brightMountainMediaBidAdapter.js +1 -1
  28. package/dist/carodaBidAdapter.js +1 -1
  29. package/dist/chtnwBidAdapter.js +1 -1
  30. package/dist/conceptxBidAdapter.js +1 -0
  31. package/dist/concertBidAdapter.js +1 -1
  32. package/dist/connectIdSystem.js +1 -1
  33. package/dist/connectadBidAdapter.js +1 -1
  34. package/dist/consumableBidAdapter.js +1 -1
  35. package/dist/conversantAnalyticsAdapter.js +1 -1
  36. package/dist/conversantBidAdapter.js +1 -1
  37. package/dist/craftBidAdapter.js +1 -1
  38. package/dist/criteoBidAdapter.js +1 -1
  39. package/dist/cwireBidAdapter.js +1 -1
  40. package/dist/dependencies.json +6 -0
  41. package/dist/dspxBidAdapter.js +1 -1
  42. package/dist/eplanningBidAdapter.js +1 -1
  43. package/dist/eskimiBidAdapter.js +1 -1
  44. package/dist/euidIdSystem.js +1 -0
  45. package/dist/feedadBidAdapter.js +1 -1
  46. package/dist/finativeBidAdapter.js +1 -1
  47. package/dist/freepassIdSystem.js +1 -0
  48. package/dist/freewheel-sspBidAdapter.js +1 -1
  49. package/dist/gdprEnforcement.js +1 -1
  50. package/dist/glimpseBidAdapter.js +1 -1
  51. package/dist/gmosspBidAdapter.js +1 -1
  52. package/dist/goldbachBidAdapter.js +1 -1
  53. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  54. package/dist/greenbidsRtdProvider.js +1 -1
  55. package/dist/gridBidAdapter.js +1 -1
  56. package/dist/growthCodeRtdProvider.js +1 -0
  57. package/dist/gumgumBidAdapter.js +1 -1
  58. package/dist/h12mediaBidAdapter.js +1 -1
  59. package/dist/id5IdSystem.js +1 -1
  60. package/dist/improvedigitalBidAdapter.js +1 -1
  61. package/dist/inmarBidAdapter.js +1 -1
  62. package/dist/insticatorBidAdapter.js +1 -1
  63. package/dist/ixBidAdapter.js +1 -1
  64. package/dist/justpremiumBidAdapter.js +1 -1
  65. package/dist/kargoBidAdapter.js +1 -1
  66. package/dist/konduitAnalyticsAdapter.js +1 -1
  67. package/dist/kueezBidAdapter.js +1 -1
  68. package/dist/kueezRtbBidAdapter.js +1 -1
  69. package/dist/kulturemediaBidAdapter.js +1 -1
  70. package/dist/lassoBidAdapter.js +1 -1
  71. package/dist/lifestreetBidAdapter.js +1 -1
  72. package/dist/limelightDigitalBidAdapter.js +1 -1
  73. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  74. package/dist/logicadBidAdapter.js +1 -1
  75. package/dist/loglyliftBidAdapter.js +1 -1
  76. package/dist/magniteAnalyticsAdapter.js +1 -1
  77. package/dist/malltvAnalyticsAdapter.js +1 -1
  78. package/dist/marsmediaBidAdapter.js +1 -1
  79. package/dist/mediafuseBidAdapter.js +1 -1
  80. package/dist/mediasquareBidAdapter.js +1 -1
  81. package/dist/mgidBidAdapter.js +1 -1
  82. package/dist/minutemediaBidAdapter.js +1 -1
  83. package/dist/minutemediaplusBidAdapter.js +1 -1
  84. package/dist/nexx360BidAdapter.js +1 -1
  85. package/dist/not-for-prod/prebid.js +154 -146
  86. package/dist/objectGuard.js +1 -0
  87. package/dist/oguryBidAdapter.js +1 -1
  88. package/dist/onetagBidAdapter.js +1 -1
  89. package/dist/ooloAnalyticsAdapter.js +1 -1
  90. package/dist/optidigitalBidAdapter.js +1 -1
  91. package/dist/outbrainBidAdapter.js +1 -1
  92. package/dist/oxxionAnalyticsAdapter.js +1 -0
  93. package/dist/pairIdSystem.js +1 -1
  94. package/dist/parrableIdSystem.js +1 -1
  95. package/dist/pixfutureBidAdapter.js +1 -1
  96. package/dist/prebid-core.js +1 -1
  97. package/dist/proxistoreBidAdapter.js +1 -1
  98. package/dist/publinkIdSystem.js +1 -1
  99. package/dist/pubmaticBidAdapter.js +1 -1
  100. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  101. package/dist/pxyzBidAdapter.js +1 -1
  102. package/dist/quantcastBidAdapter.js +1 -1
  103. package/dist/readpeakBidAdapter.js +1 -1
  104. package/dist/relaidoBidAdapter.js +1 -1
  105. package/dist/retailspotBidAdapter.js +1 -1
  106. package/dist/rhythmoneBidAdapter.js +1 -1
  107. package/dist/richaudienceBidAdapter.js +1 -1
  108. package/dist/riseBidAdapter.js +1 -1
  109. package/dist/rtdModule.js +1 -1
  110. package/dist/rubiconAnalyticsAdapter.js +1 -1
  111. package/dist/rubiconBidAdapter.js +1 -1
  112. package/dist/schain.js +1 -1
  113. package/dist/seedingAllianceBidAdapter.js +1 -1
  114. package/dist/seedtagBidAdapter.js +1 -1
  115. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  116. package/dist/sharethroughBidAdapter.js +1 -1
  117. package/dist/shinezBidAdapter.js +1 -1
  118. package/dist/sirdataRtdProvider.js +1 -1
  119. package/dist/smaatoBidAdapter.js +1 -1
  120. package/dist/smartadserverBidAdapter.js +1 -1
  121. package/dist/smartxBidAdapter.js +1 -1
  122. package/dist/smilewantedBidAdapter.js +1 -1
  123. package/dist/sonobiBidAdapter.js +1 -1
  124. package/dist/sovrnAnalyticsAdapter.js +1 -1
  125. package/dist/sovrnBidAdapter.js +1 -1
  126. package/dist/sspBCBidAdapter.js +1 -1
  127. package/dist/stroeerCoreBidAdapter.js +1 -1
  128. package/dist/stvBidAdapter.js +1 -1
  129. package/dist/sublimeBidAdapter.js +1 -1
  130. package/dist/synacormediaBidAdapter.js +1 -1
  131. package/dist/targetVideoBidAdapter.js +1 -1
  132. package/dist/teadsBidAdapter.js +1 -1
  133. package/dist/trionBidAdapter.js +1 -1
  134. package/dist/tripleliftBidAdapter.js +1 -1
  135. package/dist/ttdBidAdapter.js +1 -1
  136. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  137. package/dist/uid2IdSystem.js +1 -1
  138. package/dist/uid2IdSystem_shared.js +1 -0
  139. package/dist/underdogmediaBidAdapter.js +1 -1
  140. package/dist/undertoneBidAdapter.js +1 -1
  141. package/dist/userId.js +1 -1
  142. package/dist/vidazooBidAdapter.js +1 -1
  143. package/dist/videobyteBidAdapter.js +1 -1
  144. package/dist/viouslyBidAdapter.js +1 -1
  145. package/dist/visxBidAdapter.js +1 -1
  146. package/dist/vuukleBidAdapter.js +1 -1
  147. package/dist/weboramaRtdProvider.js +1 -1
  148. package/dist/widespaceBidAdapter.js +1 -1
  149. package/dist/winrBidAdapter.js +1 -1
  150. package/dist/yahoosspBidAdapter.js +1 -1
  151. package/dist/yieldlabBidAdapter.js +1 -1
  152. package/dist/yieldmoBidAdapter.js +1 -1
  153. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  154. package/dist/zeta_global_sspBidAdapter.js +1 -1
  155. package/integrationExamples/gpt/growthcode.html +20 -9
  156. package/integrationExamples/gpt/userId_example.html +20 -6
  157. package/libraries/objectGuard/objectGuard.js +108 -0
  158. package/libraries/objectGuard/ortbGuard.js +88 -0
  159. package/modules/.submodules.json +3 -1
  160. package/modules/1plusXRtdProvider.js +31 -60
  161. package/modules/adagioBidAdapter.js +86 -24
  162. package/modules/adgenerationBidAdapter.js +14 -5
  163. package/modules/adkernelBidAdapter.js +2 -2
  164. package/modules/adriverIdSystem.js +1 -1
  165. package/modules/airgridRtdProvider.js +11 -12
  166. package/modules/allowActivities.js +74 -0
  167. package/modules/asoBidAdapter.js +2 -1
  168. package/modules/beopBidAdapter.js +6 -0
  169. package/modules/conceptxBidAdapter.js +70 -0
  170. package/modules/conceptxBidAdapter.md +36 -0
  171. package/modules/connectIdSystem.js +89 -13
  172. package/modules/connectIdSystem.md +4 -7
  173. package/modules/criteoBidAdapter.js +18 -2
  174. package/modules/eskimiBidAdapter.js +171 -41
  175. package/modules/eskimiBidAdapter.md +35 -16
  176. package/modules/euidIdSystem.js +121 -0
  177. package/modules/euidIdSystem.md +131 -0
  178. package/modules/freepassIdSystem.js +61 -0
  179. package/modules/freepassIdSystem.md +47 -0
  180. package/modules/gdprEnforcement.js +98 -169
  181. package/modules/greenbidsAnalyticsAdapter.js +1 -1
  182. package/modules/growthCodeRtdProvider.js +131 -0
  183. package/modules/growthCodeRtdProvider.md +55 -0
  184. package/modules/id5IdSystem.js +3 -5
  185. package/modules/ixBidAdapter.js +17 -3
  186. package/modules/limelightDigitalBidAdapter.js +1 -1
  187. package/modules/logicadBidAdapter.js +14 -1
  188. package/modules/mediasquareBidAdapter.js +13 -5
  189. package/modules/nexx360BidAdapter.js +1 -0
  190. package/modules/oxxionAnalyticsAdapter.js +212 -0
  191. package/modules/oxxionAnalyticsAdapter.md +33 -0
  192. package/modules/pairIdSystem.js +16 -11
  193. package/modules/proxistoreBidAdapter.js +11 -14
  194. package/modules/richaudienceBidAdapter.js +10 -1
  195. package/modules/riseBidAdapter.js +1 -1
  196. package/modules/rtdModule/index.js +12 -1
  197. package/modules/schain.js +2 -2
  198. package/modules/sharethroughBidAdapter.js +2 -2
  199. package/modules/sirdataRtdProvider.js +73 -146
  200. package/modules/smartadserverBidAdapter.js +5 -0
  201. package/modules/sovrnBidAdapter.js +4 -1
  202. package/modules/stroeerCoreBidAdapter.js +55 -6
  203. package/modules/stvBidAdapter.js +34 -1
  204. package/modules/uid2IdSystem.js +27 -210
  205. package/modules/uid2IdSystem.md +104 -23
  206. package/modules/uid2IdSystem_shared.js +232 -0
  207. package/modules/undertoneBidAdapter.js +9 -1
  208. package/modules/userId/eids.js +8 -0
  209. package/modules/userId/index.js +69 -41
  210. package/modules/userId/userId.md +2 -1
  211. package/modules/viouslyBidAdapter.js +2 -2
  212. package/modules/weboramaRtdProvider.js +25 -95
  213. package/modules/weboramaRtdProvider.md +4 -4
  214. package/modules/yahoosspBidAdapter.js +45 -3
  215. package/modules/yahoosspBidAdapter.md +1 -1
  216. package/modules/yieldlabBidAdapter.js +23 -14
  217. package/modules/zeta_global_sspBidAdapter.js +28 -22
  218. package/package.json +1 -1
  219. package/src/activities/activities.js +47 -0
  220. package/src/activities/activityParams.js +8 -0
  221. package/src/activities/modules.js +1 -1
  222. package/src/activities/params.js +59 -0
  223. package/src/activities/redactor.js +157 -0
  224. package/src/activities/rules.js +95 -0
  225. package/src/adapterManager.js +45 -8
  226. package/src/adloader.js +1 -0
  227. package/src/fpd/rootDomain.js +1 -1
  228. package/src/prebid.js +1 -1
  229. package/src/storageManager.js +57 -44
  230. package/src/userSync.js +35 -18
  231. package/test/spec/activities/allowActivites_spec.js +138 -0
  232. package/test/spec/activities/objectGuard_spec.js +144 -0
  233. package/test/spec/activities/ortbGuard_spec.js +140 -0
  234. package/test/spec/activities/params_spec.js +25 -0
  235. package/test/spec/activities/redactor_spec.js +296 -0
  236. package/test/spec/activities/rules_spec.js +135 -0
  237. package/test/spec/modules/1plusXRtdProvider_spec.js +98 -149
  238. package/test/spec/modules/adagioBidAdapter_spec.js +46 -17
  239. package/test/spec/modules/adgenerationBidAdapter_spec.js +52 -12
  240. package/test/spec/modules/airgridRtdProvider_spec.js +2 -0
  241. package/test/spec/modules/beopBidAdapter_spec.js +24 -0
  242. package/test/spec/modules/conceptxBidAdapter_spec.js +136 -0
  243. package/test/spec/modules/connectIdSystem_spec.js +291 -23
  244. package/test/spec/modules/criteoBidAdapter_spec.js +85 -1
  245. package/test/spec/modules/eids_spec.js +15 -0
  246. package/test/spec/modules/eskimiBidAdapter_spec.js +264 -112
  247. package/test/spec/modules/euidIdSystem_spec.js +130 -0
  248. package/test/spec/modules/freepassIdSystem_spec.js +186 -0
  249. package/test/spec/modules/gdprEnforcement_spec.js +127 -414
  250. package/test/spec/modules/growthCodeRtdProvider_spec.js +127 -0
  251. package/test/spec/modules/id5IdSystem_spec.js +10 -3
  252. package/test/spec/modules/ixBidAdapter_spec.js +32 -1
  253. package/test/spec/modules/logicadBidAdapter_spec.js +122 -2
  254. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -0
  255. package/test/spec/modules/oxxionAnalyticsAdapter_spec.js +324 -0
  256. package/test/spec/modules/pairIdSystem_spec.js +16 -3
  257. package/test/spec/modules/realTimeDataModule_spec.js +1 -1
  258. package/test/spec/modules/richaudienceBidAdapter_spec.js +44 -0
  259. package/test/spec/modules/schain_spec.js +9 -0
  260. package/test/spec/modules/sharethroughBidAdapter_spec.js +1 -1
  261. package/test/spec/modules/sirdataRtdProvider_spec.js +110 -17
  262. package/test/spec/modules/smartadserverBidAdapter_spec.js +42 -0
  263. package/test/spec/modules/sovrnBidAdapter_spec.js +13 -0
  264. package/test/spec/modules/stroeerCoreBidAdapter_spec.js +151 -6
  265. package/test/spec/modules/stvBidAdapter_spec.js +13 -1
  266. package/test/spec/modules/uid2IdSystem_helpers.js +70 -0
  267. package/test/spec/modules/uid2IdSystem_spec.js +131 -86
  268. package/test/spec/modules/undertoneBidAdapter_spec.js +57 -1
  269. package/test/spec/modules/userId_spec.js +96 -33
  270. package/test/spec/modules/weboramaRtdProvider_spec.js +331 -205
  271. package/test/spec/modules/yahoosspBidAdapter_spec.js +103 -51
  272. package/test/spec/modules/yieldlabBidAdapter_spec.js +42 -2
  273. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +204 -4
  274. package/test/spec/unit/core/adapterManager_spec.js +181 -1
  275. package/test/spec/unit/core/storageManager_spec.js +76 -68
  276. package/test/spec/unit/pbjs_api_spec.js +15 -25
  277. package/test/spec/userSync_spec.js +45 -16
@@ -0,0 +1,232 @@
1
+ /* eslint-disable no-console */
2
+ export const Uid2CodeVersion = '1.1';
3
+
4
+ function isValidIdentity(identity) {
5
+ return !!(typeof identity === 'object' && identity !== null && identity.advertising_token && identity.identity_expires && identity.refresh_from && identity.refresh_token && identity.refresh_expires);
6
+ }
7
+
8
+ // This is extracted from an in-progress API client. Once it's available via NPM, this class should be replaced with the NPM package.
9
+ export class Uid2ApiClient {
10
+ constructor(opts, clientId, logInfo, logWarn) {
11
+ this._baseUrl = opts.baseUrl;
12
+ this._clientVersion = clientId;
13
+ this._logInfo = logInfo;
14
+ this._logWarn = logWarn;
15
+ }
16
+ createArrayBuffer(text) {
17
+ const arrayBuffer = new Uint8Array(text.length);
18
+ for (let i = 0; i < text.length; i++) {
19
+ arrayBuffer[i] = text.charCodeAt(i);
20
+ }
21
+ return arrayBuffer;
22
+ }
23
+ hasStatusResponse(response) {
24
+ return typeof (response) === 'object' && response && response.status;
25
+ }
26
+ isValidRefreshResponse(response) {
27
+ return this.hasStatusResponse(response) && (
28
+ response.status === 'optout' || response.status === 'expired_token' || (response.status === 'success' && response.body && isValidIdentity(response.body))
29
+ );
30
+ }
31
+ ResponseToRefreshResult(response) {
32
+ if (this.isValidRefreshResponse(response)) {
33
+ if (response.status === 'success') { return { status: response.status, identity: response.body }; }
34
+ return response;
35
+ } else { return `Response didn't contain a valid status`; }
36
+ }
37
+ callRefreshApi(refreshDetails) {
38
+ const url = this._baseUrl + '/v2/token/refresh';
39
+ const req = new XMLHttpRequest();
40
+ req.overrideMimeType('text/plain');
41
+ req.open('POST', url, true);
42
+ req.setRequestHeader('X-UID2-Client-Version', this._clientVersion);
43
+ let resolvePromise;
44
+ let rejectPromise;
45
+ const promise = new Promise((resolve, reject) => {
46
+ resolvePromise = resolve;
47
+ rejectPromise = reject;
48
+ });
49
+ req.onreadystatechange = () => {
50
+ if (req.readyState !== req.DONE) { return; }
51
+ try {
52
+ if (!refreshDetails.refresh_response_key || req.status !== 200) {
53
+ this._logInfo('Error status OR no response decryption key available, assuming unencrypted JSON');
54
+ const response = JSON.parse(req.responseText);
55
+ const result = this.ResponseToRefreshResult(response);
56
+ if (typeof result === 'string') { rejectPromise(result); } else { resolvePromise(result); }
57
+ } else {
58
+ this._logInfo('Decrypting refresh API response');
59
+ const encodeResp = this.createArrayBuffer(atob(req.responseText));
60
+ window.crypto.subtle.importKey('raw', this.createArrayBuffer(atob(refreshDetails.refresh_response_key)), { name: 'AES-GCM' }, false, ['decrypt']).then((key) => {
61
+ this._logInfo('Imported decryption key')
62
+ // returns the symmetric key
63
+ window.crypto.subtle.decrypt({
64
+ name: 'AES-GCM',
65
+ iv: encodeResp.slice(0, 12),
66
+ tagLength: 128, // The tagLength you used to encrypt (if any)
67
+ }, key, encodeResp.slice(12)).then((decrypted) => {
68
+ const decryptedResponse = String.fromCharCode(...new Uint8Array(decrypted));
69
+ this._logInfo('Decrypted to:', decryptedResponse);
70
+ const response = JSON.parse(decryptedResponse);
71
+ const result = this.ResponseToRefreshResult(response);
72
+ if (typeof result === 'string') { rejectPromise(result); } else { resolvePromise(result); }
73
+ }, (reason) => this._logWarn(`Call to UID2 API failed`, reason));
74
+ }, (reason) => this._logWarn(`Call to UID2 API failed`, reason));
75
+ }
76
+ } catch (err) {
77
+ rejectPromise(err);
78
+ }
79
+ };
80
+ this._logInfo('Sending refresh request', refreshDetails);
81
+ req.send(refreshDetails.refresh_token);
82
+ return promise;
83
+ }
84
+ }
85
+ export class Uid2StorageManager {
86
+ constructor(storage, preferLocalStorage, storageName, logInfo) {
87
+ this._storage = storage;
88
+ this._preferLocalStorage = preferLocalStorage;
89
+ this._storageName = storageName;
90
+ this._logInfo = logInfo;
91
+ }
92
+ readCookie(cookieName) {
93
+ return this._storage.cookiesAreEnabled() ? this._storage.getCookie(cookieName) : null;
94
+ }
95
+ readLocalStorage(key) {
96
+ return this._storage.localStorageIsEnabled() ? this._storage.getDataFromLocalStorage(key) : null;
97
+ }
98
+ readModuleCookie() {
99
+ return this.parseIfContainsBraces(this.readCookie(this._storageName));
100
+ }
101
+ writeModuleCookie(value) {
102
+ this._storage.setCookie(this._storageName, JSON.stringify(value), Date.now() + 60 * 60 * 24 * 1000);
103
+ }
104
+ readModuleStorage() {
105
+ return this.parseIfContainsBraces(this.readLocalStorage(this._storageName));
106
+ }
107
+ writeModuleStorage(value) {
108
+ this._storage.setDataInLocalStorage(this._storageName, JSON.stringify(value));
109
+ }
110
+ readProvidedCookie(cookieName) {
111
+ return JSON.parse(this.readCookie(cookieName));
112
+ }
113
+ parseIfContainsBraces(value) {
114
+ return (value?.includes('{')) ? JSON.parse(value) : value;
115
+ }
116
+ storeValue(value) {
117
+ if (this._preferLocalStorage) {
118
+ this.writeModuleStorage(value);
119
+ } else {
120
+ this.writeModuleCookie(value);
121
+ }
122
+ }
123
+
124
+ getStoredValueWithFallback() {
125
+ const preferredStorageLabel = this._preferLocalStorage ? 'local storage' : 'cookie';
126
+ const preferredStorageGet = (this._preferLocalStorage ? this.readModuleStorage : this.readModuleCookie).bind(this);
127
+ const preferredStorageSet = (this._preferLocalStorage ? this.writeModuleStorage : this.writeModuleCookie).bind(this);
128
+ const fallbackStorageGet = (this._preferLocalStorage ? this.readModuleCookie : this.readModuleStorage).bind(this);
129
+
130
+ const storedValue = preferredStorageGet();
131
+
132
+ if (!storedValue) {
133
+ const fallbackValue = fallbackStorageGet();
134
+ if (fallbackValue) {
135
+ this._logInfo(`${preferredStorageLabel} was empty, but found a fallback value.`)
136
+ if (typeof fallbackValue === 'object') {
137
+ this._logInfo(`Copying the fallback value to ${preferredStorageLabel}.`);
138
+ preferredStorageSet(fallbackValue);
139
+ }
140
+ return fallbackValue;
141
+ }
142
+ } else if (typeof storedValue === 'string') {
143
+ const fallbackValue = fallbackStorageGet();
144
+ if (fallbackValue && typeof fallbackValue === 'object') {
145
+ this._logInfo(`${preferredStorageLabel} contained a basic token, but found a refreshable token fallback. Copying the fallback value to ${preferredStorageLabel}.`);
146
+ preferredStorageSet(fallbackValue);
147
+ return fallbackValue;
148
+ }
149
+ }
150
+ return storedValue;
151
+ }
152
+ }
153
+
154
+ function refreshTokenAndStore(baseUrl, token, clientId, storageManager, _logInfo, _logWarn) {
155
+ _logInfo('UID2 base url provided: ', baseUrl);
156
+ const client = new Uid2ApiClient({baseUrl}, clientId, _logInfo, _logWarn);
157
+ return client.callRefreshApi(token).then((response) => {
158
+ _logInfo('Refresh endpoint responded with:', response);
159
+ const tokens = {
160
+ originalToken: token,
161
+ latestToken: response.identity,
162
+ };
163
+ storageManager.storeValue(tokens);
164
+ return tokens;
165
+ });
166
+ }
167
+
168
+ export function Uid2GetId(config, prebidStorageManager, _logInfo, _logWarn) {
169
+ let suppliedToken = null;
170
+ const preferLocalStorage = (config.storage !== 'cookie');
171
+ const storageManager = new Uid2StorageManager(prebidStorageManager, preferLocalStorage, config.internalStorage, _logInfo);
172
+ _logInfo(`Module is using ${preferLocalStorage ? 'local storage' : 'cookies'} for internal storage.`);
173
+
174
+ if (config.paramToken) {
175
+ suppliedToken = config.paramToken;
176
+ _logInfo('Read token from params', suppliedToken);
177
+ } else if (config.serverCookieName) {
178
+ suppliedToken = storageManager.readProvidedCookie(config.serverCookieName);
179
+ _logInfo('Read token from server-supplied cookie', suppliedToken);
180
+ }
181
+ let storedTokens = storageManager.getStoredValueWithFallback();
182
+ _logInfo('Loaded module-stored tokens:', storedTokens);
183
+
184
+ if (storedTokens && typeof storedTokens === 'string') {
185
+ // Stored value is a plain token - if no token is supplied, just use the stored value.
186
+
187
+ if (!suppliedToken) {
188
+ _logInfo('Returning legacy cookie value.');
189
+ return { id: storedTokens };
190
+ }
191
+ // Otherwise, ignore the legacy value - it should get over-written later anyway.
192
+ _logInfo('Discarding superseded legacy cookie.');
193
+ storedTokens = null;
194
+ }
195
+
196
+ if (suppliedToken && storedTokens) {
197
+ if (storedTokens.originalToken?.advertising_token !== suppliedToken.advertising_token) {
198
+ _logInfo('Server supplied new token - ignoring stored value.', storedTokens.originalToken?.advertising_token, suppliedToken.advertising_token);
199
+ // Stored token wasn't originally sourced from the provided token - ignore the stored value. A new user has logged in?
200
+ storedTokens = null;
201
+ }
202
+ }
203
+ // At this point, any legacy values or superseded stored tokens have been nulled out.
204
+ const useSuppliedToken = !(storedTokens?.latestToken) || (suppliedToken && suppliedToken.identity_expires > storedTokens.latestToken.identity_expires);
205
+ const newestAvailableToken = useSuppliedToken ? suppliedToken : storedTokens.latestToken;
206
+ _logInfo('UID2 module selected latest token', useSuppliedToken, newestAvailableToken);
207
+ if (!newestAvailableToken || Date.now() > newestAvailableToken.refresh_expires) {
208
+ _logInfo('Newest available token is expired and not refreshable.');
209
+ return { id: null };
210
+ }
211
+ if (Date.now() > newestAvailableToken.identity_expires) {
212
+ const promise = refreshTokenAndStore(config.apiBaseUrl, newestAvailableToken, config.clientId, storageManager, _logInfo, _logWarn);
213
+ _logInfo('Token is expired but can be refreshed, attempting refresh.');
214
+ return { callback: (cb) => {
215
+ promise.then((result) => {
216
+ _logInfo('Refresh reponded, passing the updated token on.', result);
217
+ cb(result);
218
+ });
219
+ } };
220
+ }
221
+ // If should refresh (but don't need to), refresh in the background.
222
+ if (Date.now() > newestAvailableToken.refresh_from) {
223
+ _logInfo(`Refreshing token in background with low priority.`);
224
+ refreshTokenAndStore(config.apiBaseUrl, newestAvailableToken, config.clientId, storageManager, _logInfo, _logWarn);
225
+ }
226
+ const tokens = {
227
+ originalToken: suppliedToken ?? storedTokens?.originalToken,
228
+ latestToken: newestAvailableToken,
229
+ };
230
+ storageManager.storeValue(tokens);
231
+ return { id: tokens };
232
+ }
@@ -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);
@@ -291,6 +291,14 @@ export const USER_IDS_CONFIG = {
291
291
  }
292
292
  },
293
293
 
294
+ 'euid': {
295
+ source: 'euid.eu',
296
+ atype: 3,
297
+ getValue: function(data) {
298
+ return data.id;
299
+ }
300
+ },
301
+
294
302
  'deepintentId': {
295
303
  source: 'deepintent.com',
296
304
  atype: 3
@@ -110,6 +110,7 @@
110
110
  * @property {SubmoduleConfig} config
111
111
  * @property {(Object|undefined)} idObj - cache decoded id value (this is copied to every adUnit bid)
112
112
  * @property {(function|undefined)} callback - holds reference to submodule.getId() result if it returned a function. Will be set to undefined after callback executes
113
+ * @property {StorageManager} storageMgr
113
114
  */
114
115
 
115
116
  /**
@@ -133,7 +134,12 @@ import adapterManager, {gdprDataHandler} from '../../src/adapterManager.js';
133
134
  import CONSTANTS from '../../src/constants.json';
134
135
  import {hook, module, ready as hooksReady} from '../../src/hook.js';
135
136
  import {buildEidPermissions, createEidsArray, USER_IDS_CONFIG} from './eids.js';
136
- import {getCoreStorageManager, STORAGE_TYPE_COOKIES, STORAGE_TYPE_LOCALSTORAGE} from '../../src/storageManager.js';
137
+ import {
138
+ getCoreStorageManager,
139
+ getStorageManager,
140
+ STORAGE_TYPE_COOKIES,
141
+ STORAGE_TYPE_LOCALSTORAGE
142
+ } from '../../src/storageManager.js';
137
143
  import {
138
144
  cyrb53Hash,
139
145
  deepAccess,
@@ -159,6 +165,9 @@ import {newMetrics, timedAuctionHook, useMetrics} from '../../src/utils/perfMetr
159
165
  import {findRootDomain} from '../../src/fpd/rootDomain.js';
160
166
  import {GDPR_GVLIDS} from '../../src/consentHandler.js';
161
167
  import {MODULE_TYPE_UID} from '../../src/activities/modules.js';
168
+ import {isActivityAllowed} from '../../src/activities/rules.js';
169
+ import {ACTIVITY_ENRICH_EIDS} from '../../src/activities/activities.js';
170
+ import {activityParams} from '../../src/activities/activityParams.js';
162
171
 
163
172
  const MODULE_NAME = 'User ID';
164
173
  const COOKIE = STORAGE_TYPE_COOKIES;
@@ -170,7 +179,10 @@ const CONSENT_DATA_COOKIE_STORAGE_CONFIG = {
170
179
  expires: 30 // 30 days expiration, which should match how often consent is refreshed by CMPs
171
180
  };
172
181
  export const PBJS_USER_ID_OPTOUT_NAME = '_pbjs_id_optout';
173
- export const coreStorage = getCoreStorageManager('userid');
182
+ export const coreStorage = getCoreStorageManager('userId');
183
+ export const dep = {
184
+ isAllowed: isActivityAllowed
185
+ }
174
186
 
175
187
  /** @type {boolean} */
176
188
  let addedUserIdHook = false;
@@ -220,11 +232,12 @@ export function setSubmoduleRegistry(submodules) {
220
232
  submoduleRegistry = submodules;
221
233
  }
222
234
 
223
- function cookieSetter(submodule) {
235
+ function cookieSetter(submodule, storageMgr) {
236
+ storageMgr = storageMgr || submodule.storageMgr;
224
237
  const domainOverride = (typeof submodule.submodule.domainOverride === 'function') ? submodule.submodule.domainOverride() : null;
225
238
  const name = submodule.config.storage.name;
226
239
  return function setCookie(suffix, value, expiration) {
227
- coreStorage.setCookie(name + (suffix || ''), value, expiration, 'Lax', domainOverride);
240
+ storageMgr.setCookie(name + (suffix || ''), value, expiration, 'Lax', domainOverride);
228
241
  }
229
242
  }
230
243
 
@@ -237,6 +250,7 @@ export function setStoredValue(submodule, value) {
237
250
  * @type {SubmoduleStorage}
238
251
  */
239
252
  const storage = submodule.config.storage;
253
+ const mgr = submodule.storageMgr;
240
254
 
241
255
  try {
242
256
  const expiresStr = (new Date(Date.now() + (storage.expires * (60 * 60 * 24 * 1000)))).toUTCString();
@@ -248,10 +262,10 @@ export function setStoredValue(submodule, value) {
248
262
  setCookie('_last', new Date().toUTCString(), expiresStr);
249
263
  }
250
264
  } else if (storage.type === LOCAL_STORAGE) {
251
- coreStorage.setDataInLocalStorage(`${storage.name}_exp`, expiresStr);
252
- coreStorage.setDataInLocalStorage(storage.name, encodeURIComponent(valueStr));
265
+ mgr.setDataInLocalStorage(`${storage.name}_exp`, expiresStr);
266
+ mgr.setDataInLocalStorage(storage.name, encodeURIComponent(valueStr));
253
267
  if (typeof storage.refreshInSeconds === 'number') {
254
- coreStorage.setDataInLocalStorage(`${storage.name}_last`, new Date().toUTCString());
268
+ mgr.setDataInLocalStorage(`${storage.name}_last`, new Date().toUTCString());
255
269
  }
256
270
  }
257
271
  } catch (error) {
@@ -263,7 +277,7 @@ export function deleteStoredValue(submodule) {
263
277
  let deleter, suffixes;
264
278
  switch (submodule.config?.storage?.type) {
265
279
  case COOKIE:
266
- const setCookie = cookieSetter(submodule);
280
+ const setCookie = cookieSetter(submodule, coreStorage);
267
281
  const expiry = (new Date(Date.now() - 1000 * 60 * 60 * 24)).toUTCString();
268
282
  deleter = (suffix) => setCookie(suffix, '', expiry)
269
283
  suffixes = ['', '_last'];
@@ -292,25 +306,26 @@ function setPrebidServerEidPermissions(initializedSubmodules) {
292
306
  }
293
307
 
294
308
  /**
295
- /**
296
- * @param {SubmoduleStorage} storage
309
+ * @param {SubmoduleContainer} submodule
297
310
  * @param {String|undefined} key optional key of the value
298
311
  * @returns {string}
299
312
  */
300
- function getStoredValue(storage, key = undefined) {
313
+ function getStoredValue(submodule, key = undefined) {
314
+ const mgr = submodule.storageMgr;
315
+ const storage = submodule.config.storage;
301
316
  const storedKey = key ? `${storage.name}_${key}` : storage.name;
302
317
  let storedValue;
303
318
  try {
304
319
  if (storage.type === COOKIE) {
305
- storedValue = coreStorage.getCookie(storedKey);
320
+ storedValue = mgr.getCookie(storedKey);
306
321
  } else if (storage.type === LOCAL_STORAGE) {
307
- const storedValueExp = coreStorage.getDataFromLocalStorage(`${storage.name}_exp`);
322
+ const storedValueExp = mgr.getDataFromLocalStorage(`${storage.name}_exp`);
308
323
  // empty string means no expiration set
309
324
  if (storedValueExp === '') {
310
- storedValue = coreStorage.getDataFromLocalStorage(storedKey);
325
+ storedValue = mgr.getDataFromLocalStorage(storedKey);
311
326
  } else if (storedValueExp) {
312
327
  if ((new Date(storedValueExp)).getTime() - Date.now() > 0) {
313
- storedValue = decodeURIComponent(coreStorage.getDataFromLocalStorage(storedKey));
328
+ storedValue = decodeURIComponent(mgr.getDataFromLocalStorage(storedKey));
314
329
  }
315
330
  }
316
331
  }
@@ -415,7 +430,7 @@ function processSubmoduleCallbacks(submodules, cb) {
415
430
  moduleDone();
416
431
  }
417
432
  try {
418
- submodule.callback(callbackCompleted, getStoredValue.bind(null, submodule.config?.storage));
433
+ submodule.callback(callbackCompleted, getStoredValue.bind(null, submodule));
419
434
  } catch (e) {
420
435
  logError(`Error in userID module '${submodule.submodule.name}':`, e);
421
436
  moduleDone();
@@ -773,6 +788,8 @@ function getUserIdsAsync() {
773
788
  * This hook returns updated list of submodules which are allowed to do get user id based on TCF 2 enforcement rules configured
774
789
  */
775
790
  export const validateGdprEnforcement = hook('sync', function (submodules, consentData) {
791
+ // TODO: remove the `hasValidated` check in v8. Enforcement should be OFF by default.
792
+ // https://github.com/prebid/Prebid.js/issues/9766
776
793
  return { userIdModules: submodules, hasValidated: consentData && consentData.hasValidated };
777
794
  }, 'validateGdprEnforcement');
778
795
 
@@ -781,12 +798,12 @@ function populateSubmoduleId(submodule, consentData, storedConsentData, forceRef
781
798
  // 1. storage: retrieve user id data from cookie/html storage or with the submodule's getId method
782
799
  // 2. value: pass directly to bids
783
800
  if (submodule.config.storage) {
784
- let storedId = getStoredValue(submodule.config.storage);
801
+ let storedId = getStoredValue(submodule);
785
802
  let response;
786
803
 
787
804
  let refreshNeeded = false;
788
805
  if (typeof submodule.config.storage.refreshInSeconds === 'number') {
789
- const storedDate = new Date(getStoredValue(submodule.config.storage, 'last'));
806
+ const storedDate = new Date(getStoredValue(submodule, 'last'));
790
807
  refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000);
791
808
  }
792
809
 
@@ -849,17 +866,23 @@ function initSubmodules(dest, submodules, consentData, forceRefresh = false) {
849
866
  return uidMetrics().fork().measureTime('userId.init.modules', function () {
850
867
  if (!submodules.length) return []; // to simplify log messages from here on
851
868
 
852
- // filter out submodules whose storage type is not enabled
853
- // this needs to be done here (after consent data has loaded) so that enforcement may disable storage globally
854
- const storageTypes = getActiveStorageTypes();
855
- submodules = submodules.filter((submod) => !submod.config.storage || storageTypes.has(submod.config.storage.type));
869
+ /**
870
+ * filter out submodules that:
871
+ *
872
+ * - cannot use the storage they've been set up with (storage not available / not allowed / disabled)
873
+ * - are not allowed to perform the `enrichEids` activity
874
+ */
875
+ submodules = submodules.filter((submod) => {
876
+ return (!submod.config.storage || canUseStorage(submod)) &&
877
+ dep.isAllowed(ACTIVITY_ENRICH_EIDS, activityParams(MODULE_TYPE_UID, submod.config.name));
878
+ });
856
879
 
857
880
  if (!submodules.length) {
858
- logWarn(`${MODULE_NAME} - no ID module is configured for one of the available storage types:`, Array.from(storageTypes));
881
+ logWarn(`${MODULE_NAME} - no ID module configured`);
859
882
  return [];
860
883
  }
861
884
 
862
- // another consent check, this time each module is checked for consent with its own gvlid
885
+ // TODO: remove this check in v8 (https://github.com/prebid/Prebid.js/issues/9766)
863
886
  let { userIdModules, hasValidated } = validateGdprEnforcement(submodules, consentData);
864
887
  if (!hasValidated && !hasPurpose1Consent(consentData)) {
865
888
  logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`);
@@ -940,24 +963,28 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry) {
940
963
 
941
964
  const ALL_STORAGE_TYPES = new Set([LOCAL_STORAGE, COOKIE]);
942
965
 
943
- function getActiveStorageTypes() {
944
- const storageTypes = [];
945
- let disabled = false;
946
- if (coreStorage.localStorageIsEnabled()) {
947
- storageTypes.push(LOCAL_STORAGE);
948
- if (coreStorage.getDataFromLocalStorage(PBJS_USER_ID_OPTOUT_NAME)) {
949
- logInfo(`${MODULE_NAME} - opt-out localStorage found, storage disabled`);
950
- disabled = true;
951
- }
952
- }
953
- if (coreStorage.cookiesAreEnabled()) {
954
- storageTypes.push(COOKIE);
955
- if (coreStorage.getCookie(PBJS_USER_ID_OPTOUT_NAME)) {
956
- logInfo(`${MODULE_NAME} - opt-out cookie found, storage disabled`);
957
- disabled = true;
958
- }
966
+ function canUseStorage(submodule) {
967
+ switch (submodule.config?.storage?.type) {
968
+ case LOCAL_STORAGE:
969
+ if (submodule.storageMgr.localStorageIsEnabled()) {
970
+ if (coreStorage.getDataFromLocalStorage(PBJS_USER_ID_OPTOUT_NAME)) {
971
+ logInfo(`${MODULE_NAME} - opt-out localStorage found, storage disabled`);
972
+ return false
973
+ }
974
+ return true;
975
+ }
976
+ break;
977
+ case COOKIE:
978
+ if (submodule.storageMgr.cookiesAreEnabled()) {
979
+ if (coreStorage.getCookie(PBJS_USER_ID_OPTOUT_NAME)) {
980
+ logInfo(`${MODULE_NAME} - opt-out cookie found, storage disabled`);
981
+ return false;
982
+ }
983
+ return true
984
+ }
985
+ break;
959
986
  }
960
- return new Set(disabled ? [] : storageTypes)
987
+ return false;
961
988
  }
962
989
 
963
990
  /**
@@ -985,6 +1012,7 @@ function updateSubmodules() {
985
1012
  config: submoduleConfig,
986
1013
  callback: undefined,
987
1014
  idObj: undefined,
1015
+ storageMgr: getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: submoduleConfig.name}),
988
1016
  } : null;
989
1017
  }).filter(submodule => submodule !== null)
990
1018
  .forEach((sm) => submodules.push(sm));
@@ -126,7 +126,8 @@ pbjs.setConfig({
126
126
  }
127
127
  },{
128
128
  name: 'uid2'
129
- }
129
+ }, {
130
+ name: 'euid'
130
131
  }, {
131
132
  name: 'admixerId',
132
133
  params: {
@@ -5,7 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js';
5
5
  import find from 'core-js-pure/features/array/find.js'; // eslint-disable-line prebid/validate-imports
6
6
 
7
7
  const BIDDER_CODE = 'viously';
8
- // const GVLID = 1028;
8
+ const GVLID = 1028;
9
9
  const CURRENCY = 'EUR';
10
10
  const TTL = 60;
11
11
  const HTTP_METHOD = 'POST';
@@ -15,7 +15,7 @@ const REQUIRED_VIOUSLY_PARAMS = ['pid'];
15
15
 
16
16
  export const spec = {
17
17
  code: BIDDER_CODE,
18
- // gvlid: GVLID,
18
+ gvlid: GVLID,
19
19
  supportedMediaTypes: [BANNER, VIDEO],
20
20
 
21
21
  /**