prebid.js 8.4.0 → 8.6.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 (332) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/33acrossIdSystem.js +1 -1
  3. package/dist/a1MediaRtdProvider.js +1 -0
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adfBidAdapter.js +1 -1
  7. package/dist/adgenerationBidAdapter.js +1 -1
  8. package/dist/adkernelAdnBidAdapter.js +1 -1
  9. package/dist/adkernelBidAdapter.js +1 -1
  10. package/dist/admixerIdSystem.js +1 -1
  11. package/dist/adnuntiusBidAdapter.js +1 -1
  12. package/dist/adqueryBidAdapter.js +1 -1
  13. package/dist/adqueryIdSystem.js +1 -1
  14. package/dist/adrelevantisBidAdapter.js +1 -1
  15. package/dist/adsinteractiveBidAdapter.js +1 -1
  16. package/dist/adtelligentIdSystem.js +1 -1
  17. package/dist/adtrgtmeBidAdapter.js +1 -1
  18. package/dist/adxcgBidAdapter.js +1 -1
  19. package/dist/adyoulikeBidAdapter.js +1 -1
  20. package/dist/ajaBidAdapter.js +1 -1
  21. package/dist/amxBidAdapter.js +1 -1
  22. package/dist/amxIdSystem.js +1 -1
  23. package/dist/appierAnalyticsAdapter.js +1 -1
  24. package/dist/appnexusBidAdapter.js +1 -1
  25. package/dist/asoBidAdapter.js +1 -1
  26. package/dist/axonixBidAdapter.js +1 -1
  27. package/dist/beachfrontBidAdapter.js +1 -1
  28. package/dist/bidglassBidAdapter.js +1 -1
  29. package/dist/big-richmediaBidAdapter.js +1 -1
  30. package/dist/bridBidAdapter.js +1 -1
  31. package/dist/bridgewellBidAdapter.js +1 -1
  32. package/dist/brightMountainMediaBidAdapter.js +1 -1
  33. package/dist/britepoolIdSystem.js +1 -1
  34. package/dist/carodaBidAdapter.js +1 -1
  35. package/dist/chtnwBidAdapter.js +1 -1
  36. package/dist/concertBidAdapter.js +1 -1
  37. package/dist/connectIdSystem.js +1 -1
  38. package/dist/connectadBidAdapter.js +1 -1
  39. package/dist/consentManagementGpp.js +1 -1
  40. package/dist/consumableBidAdapter.js +1 -1
  41. package/dist/conversantAnalyticsAdapter.js +1 -1
  42. package/dist/conversantBidAdapter.js +1 -1
  43. package/dist/craftBidAdapter.js +1 -1
  44. package/dist/criteoBidAdapter.js +1 -1
  45. package/dist/criteoIdSystem.js +1 -1
  46. package/dist/cwireBidAdapter.js +1 -1
  47. package/dist/czechAdIdSystem.js +1 -1
  48. package/dist/dacIdSystem.js +1 -1
  49. package/dist/deepintentDpesIdSystem.js +1 -1
  50. package/dist/dependencies.json +6 -0
  51. package/dist/dmdIdSystem.js +1 -1
  52. package/dist/dspxBidAdapter.js +1 -1
  53. package/dist/eplanningBidAdapter.js +1 -1
  54. package/dist/euidIdSystem.js +1 -1
  55. package/dist/fabrickIdSystem.js +1 -1
  56. package/dist/feedadBidAdapter.js +1 -1
  57. package/dist/finativeBidAdapter.js +1 -1
  58. package/dist/freewheel-sspBidAdapter.js +1 -1
  59. package/dist/ftrackIdSystem.js +1 -1
  60. package/dist/geolocationRtdProvider.js +1 -0
  61. package/dist/gmosspBidAdapter.js +1 -1
  62. package/dist/goldbachBidAdapter.js +1 -1
  63. package/dist/gravitoIdSystem.js +1 -1
  64. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  65. package/dist/greenbidsRtdProvider.js +1 -1
  66. package/dist/gridBidAdapter.js +1 -1
  67. package/dist/growthCodeAnalyticsAdapter.js +1 -1
  68. package/dist/growthCodeIdSystem.js +1 -1
  69. package/dist/gumgumBidAdapter.js +1 -1
  70. package/dist/h12mediaBidAdapter.js +1 -1
  71. package/dist/hadronIdSystem.js +1 -1
  72. package/dist/hypelabBidAdapter.js +1 -1
  73. package/dist/id5IdSystem.js +1 -1
  74. package/dist/identityLinkIdSystem.js +1 -1
  75. package/dist/idxIdSystem.js +1 -1
  76. package/dist/imdsBidAdapter.js +1 -1
  77. package/dist/improvedigitalBidAdapter.js +1 -1
  78. package/dist/imuIdSystem.js +1 -1
  79. package/dist/insticatorBidAdapter.js +1 -1
  80. package/dist/intentIqIdSystem.js +1 -1
  81. package/dist/invibesBidAdapter.js +1 -1
  82. package/dist/ixBidAdapter.js +1 -1
  83. package/dist/justIdSystem.js +1 -1
  84. package/dist/justpremiumBidAdapter.js +1 -1
  85. package/dist/kargoBidAdapter.js +1 -1
  86. package/dist/kinessoIdSystem.js +1 -1
  87. package/dist/konduitAnalyticsAdapter.js +1 -1
  88. package/dist/kueezBidAdapter.js +1 -1
  89. package/dist/kueezRtbBidAdapter.js +1 -1
  90. package/dist/kulturemediaBidAdapter.js +1 -1
  91. package/dist/lassoBidAdapter.js +1 -1
  92. package/dist/lifestreetBidAdapter.js +1 -1
  93. package/dist/liveIntentIdSystem.js +1 -1
  94. package/dist/logicadBidAdapter.js +1 -1
  95. package/dist/loglyliftBidAdapter.js +1 -1
  96. package/dist/lotamePanoramaIdSystem.js +1 -1
  97. package/dist/magniteAnalyticsAdapter.js +1 -1
  98. package/dist/malltvAnalyticsAdapter.js +1 -1
  99. package/dist/marsmediaBidAdapter.js +1 -1
  100. package/dist/mediafuseBidAdapter.js +1 -1
  101. package/dist/mediasquareBidAdapter.js +1 -1
  102. package/dist/merkleIdSystem.js +1 -1
  103. package/dist/mgidBidAdapter.js +1 -1
  104. package/dist/minutemediaBidAdapter.js +1 -1
  105. package/dist/minutemediaplusBidAdapter.js +1 -1
  106. package/dist/mspa.js +1 -1
  107. package/dist/mwOpenLinkIdSystem.js +1 -1
  108. package/dist/naveggIdSystem.js +1 -1
  109. package/dist/netIdSystem.js +1 -1
  110. package/dist/newspassidBidAdapter.js +1 -1
  111. package/dist/nexx360BidAdapter.js +1 -1
  112. package/dist/not-for-prod/prebid.js +186 -181
  113. package/dist/novatiqIdSystem.js +1 -1
  114. package/dist/oguryBidAdapter.js +1 -1
  115. package/dist/oneKeyIdSystem.js +1 -1
  116. package/dist/onetagBidAdapter.js +1 -1
  117. package/dist/ooloAnalyticsAdapter.js +1 -1
  118. package/dist/optidigitalBidAdapter.js +1 -1
  119. package/dist/outbrainBidAdapter.js +1 -1
  120. package/dist/ozoneBidAdapter.js +1 -1
  121. package/dist/pairIdSystem.js +1 -1
  122. package/dist/parrableIdSystem.js +1 -1
  123. package/dist/pixfutureBidAdapter.js +1 -1
  124. package/dist/prebid-core.js +1 -1
  125. package/dist/pubCircleBidAdapter.js +1 -0
  126. package/dist/publinkIdSystem.js +1 -1
  127. package/dist/pubmaticBidAdapter.js +1 -1
  128. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  129. package/dist/pxyzBidAdapter.js +1 -1
  130. package/dist/quantcastBidAdapter.js +1 -1
  131. package/dist/quantcastIdSystem.js +1 -1
  132. package/dist/readpeakBidAdapter.js +1 -1
  133. package/dist/relaidoBidAdapter.js +1 -1
  134. package/dist/relevadRtdProvider.js +1 -1
  135. package/dist/retailspotBidAdapter.js +1 -1
  136. package/dist/rhythmoneBidAdapter.js +1 -1
  137. package/dist/riseBidAdapter.js +1 -1
  138. package/dist/rubiconBidAdapter.js +1 -1
  139. package/dist/seedingAllianceBidAdapter.js +1 -1
  140. package/dist/seedtagBidAdapter.js +1 -1
  141. package/dist/sharedIdSystem.js +1 -1
  142. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  143. package/dist/sharethroughBidAdapter.js +1 -1
  144. package/dist/shinezBidAdapter.js +1 -1
  145. package/dist/silverpushBidAdapter.js +1 -1
  146. package/dist/smaatoBidAdapter.js +1 -1
  147. package/dist/smartadserverBidAdapter.js +1 -1
  148. package/dist/smartxBidAdapter.js +1 -1
  149. package/dist/smilewantedBidAdapter.js +1 -1
  150. package/dist/sonobiBidAdapter.js +1 -1
  151. package/dist/sovrnAnalyticsAdapter.js +1 -1
  152. package/dist/sovrnBidAdapter.js +1 -1
  153. package/dist/ssmasBidAdapter.js +1 -0
  154. package/dist/sspBCBidAdapter.js +1 -1
  155. package/dist/stvBidAdapter.js +1 -1
  156. package/dist/sublimeBidAdapter.js +1 -1
  157. package/dist/tapadIdSystem.js +1 -1
  158. package/dist/tappxBidAdapter.js +1 -1
  159. package/dist/targetVideoBidAdapter.js +1 -1
  160. package/dist/teadsBidAdapter.js +1 -1
  161. package/dist/tncIdSystem.js +1 -1
  162. package/dist/topicsFpdModule.js +1 -1
  163. package/dist/trionBidAdapter.js +1 -1
  164. package/dist/tripleliftBidAdapter.js +1 -1
  165. package/dist/ttdBidAdapter.js +1 -1
  166. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  167. package/dist/uid2IdSystem.js +1 -1
  168. package/dist/underdogmediaBidAdapter.js +1 -1
  169. package/dist/undertoneBidAdapter.js +1 -1
  170. package/dist/unifiedIdSystem.js +1 -1
  171. package/dist/userId.js +1 -1
  172. package/dist/utiqSystem.js +1 -1
  173. package/dist/verizonMediaIdSystem.js +1 -1
  174. package/dist/viantOrtbBidAdapter.js +1 -0
  175. package/dist/vidazooBidAdapter.js +1 -1
  176. package/dist/videobyteBidAdapter.js +1 -1
  177. package/dist/videojsVideoProvider.js +1 -1
  178. package/dist/visxBidAdapter.js +1 -1
  179. package/dist/vrtcalBidAdapter.js +1 -1
  180. package/dist/vuukleBidAdapter.js +1 -1
  181. package/dist/widespaceBidAdapter.js +1 -1
  182. package/dist/winrBidAdapter.js +1 -1
  183. package/dist/yahoosspBidAdapter.js +1 -1
  184. package/dist/yieldmoBidAdapter.js +1 -1
  185. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  186. package/dist/zeotapIdPlusIdSystem.js +1 -1
  187. package/integrationExamples/gpt/adUnitFloors.html +0 -1
  188. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +1 -1
  189. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +1 -1
  190. package/integrationExamples/videoModule/jwplayer/bidsBackHandlerOverride.html +137 -0
  191. package/integrationExamples/videoModule/jwplayer/eventListeners.html +1 -1
  192. package/integrationExamples/videoModule/jwplayer/eventsUI.html +1 -1
  193. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +1 -1
  194. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +1 -1
  195. package/integrationExamples/videoModule/jwplayer/playlist.html +1 -1
  196. package/integrationExamples/videoModule/videojs/bidsBackHandlerOverride.html +164 -0
  197. package/libraries/mspa/activityControls.js +51 -32
  198. package/modules/.submodules.json +1 -0
  199. package/modules/33acrossIdSystem.js +9 -0
  200. package/modules/a1MediaRtdProvider.js +92 -0
  201. package/modules/a1MediaRtdProvider.md +46 -0
  202. package/modules/adfBidAdapter.js +4 -1
  203. package/modules/adgenerationBidAdapter.js +3 -3
  204. package/modules/adkernelAdnBidAdapter.js +1 -1
  205. package/modules/adkernelBidAdapter.js +10 -3
  206. package/modules/admixerIdSystem.js +6 -0
  207. package/modules/adnuntiusBidAdapter.js +5 -13
  208. package/modules/adqueryIdSystem.js +6 -0
  209. package/modules/adsinteractiveBidAdapter.js +2 -2
  210. package/modules/adtelligentIdSystem.js +6 -0
  211. package/modules/adyoulikeBidAdapter.js +6 -3
  212. package/modules/amxIdSystem.js +6 -0
  213. package/modules/appnexusBidAdapter.js +1 -1
  214. package/modules/beachfrontBidAdapter.js +32 -6
  215. package/modules/britepoolIdSystem.js +6 -0
  216. package/modules/connectIdSystem.js +6 -0
  217. package/modules/consentManagementGpp.js +10 -1
  218. package/modules/consumableBidAdapter.js +9 -1
  219. package/modules/criteoBidAdapter.js +18 -0
  220. package/modules/criteoIdSystem.js +6 -0
  221. package/modules/cwireBidAdapter.js +19 -0
  222. package/modules/czechAdIdSystem.js +6 -0
  223. package/modules/dacIdSystem.js +6 -0
  224. package/modules/deepintentDpesIdSystem.js +7 -2
  225. package/modules/dmdIdSystem.js +6 -0
  226. package/modules/euidIdSystem.js +9 -0
  227. package/modules/fabrickIdSystem.js +6 -0
  228. package/modules/ftrackIdSystem.js +16 -0
  229. package/modules/geolocationRtdProvider.js +65 -0
  230. package/modules/gravitoIdSystem.js +6 -0
  231. package/modules/greenbidsRtdProvider.js +1 -1
  232. package/modules/growthCodeAnalyticsAdapter.js +7 -2
  233. package/modules/growthCodeIdSystem.js +20 -1
  234. package/modules/hadronIdSystem.js +6 -0
  235. package/modules/id5IdSystem.js +34 -8
  236. package/modules/identityLinkIdSystem.js +6 -0
  237. package/modules/idxIdSystem.js +6 -0
  238. package/modules/imdsBidAdapter.js +38 -14
  239. package/modules/imuIdSystem.js +10 -0
  240. package/modules/intentIqIdSystem.js +6 -0
  241. package/modules/invibesBidAdapter.js +5 -5
  242. package/modules/ixBidAdapter.js +16 -0
  243. package/modules/justIdSystem.js +6 -0
  244. package/modules/kinessoIdSystem.js +7 -2
  245. package/modules/liveIntentIdSystem.js +53 -0
  246. package/modules/lotamePanoramaIdSystem.js +6 -0
  247. package/modules/merkleIdSystem.js +24 -0
  248. package/modules/mwOpenLinkIdSystem.js +6 -0
  249. package/modules/naveggIdSystem.js +6 -0
  250. package/modules/netIdSystem.js +6 -0
  251. package/modules/newspassid.md +76 -0
  252. package/modules/newspassidBidAdapter.js +44 -18
  253. package/modules/novatiqIdSystem.js +12 -0
  254. package/modules/oneKeyIdSystem.js +26 -0
  255. package/modules/ozoneBidAdapter.js +65 -18
  256. package/modules/ozoneBidAdapter.md +3 -1
  257. package/modules/pairIdSystem.js +6 -0
  258. package/modules/parrableIdSystem.js +38 -2
  259. package/modules/pubCircleBidAdapter.js +231 -0
  260. package/modules/pubCircleBidAdapter.md +79 -0
  261. package/modules/publinkIdSystem.js +7 -1
  262. package/modules/quantcastIdSystem.js +6 -0
  263. package/modules/relevadRtdProvider.js +6 -7
  264. package/modules/rubiconBidAdapter.js +9 -0
  265. package/modules/sharedIdSystem.js +6 -0
  266. package/modules/silverpushBidAdapter.js +2 -2
  267. package/modules/ssmasBidAdapter.js +126 -0
  268. package/modules/ssmasBidAdapter.md +35 -0
  269. package/modules/sspBCBidAdapter.js +36 -13
  270. package/modules/tapadIdSystem.js +6 -0
  271. package/modules/tappxBidAdapter.js +10 -1
  272. package/modules/tappxBidAdapter.md +17 -0
  273. package/modules/tncIdSystem.js +6 -0
  274. package/modules/topicsFpdModule.js +21 -48
  275. package/modules/tripleliftBidAdapter.js +5 -0
  276. package/modules/uid2IdSystem.js +14 -0
  277. package/modules/unifiedIdSystem.js +11 -0
  278. package/modules/userId/eids.js +6 -445
  279. package/modules/userId/index.js +36 -24
  280. package/modules/utiqSystem.js +9 -0
  281. package/modules/verizonMediaIdSystem.js +6 -0
  282. package/modules/viantOrtbBidAdapter.js +113 -0
  283. package/modules/viantOrtbBidAdapter.md +54 -0
  284. package/modules/vidazooBidAdapter.js +9 -2
  285. package/modules/videojsVideoProvider.js +9 -2
  286. package/modules/vrtcalBidAdapter.js +10 -6
  287. package/modules/zeotapIdPlusIdSystem.js +6 -0
  288. package/package.json +1 -1
  289. package/src/adapters/bidderFactory.js +15 -6
  290. package/src/adloader.js +2 -1
  291. package/test/spec/libraries/mspa/activityControls_spec.js +145 -212
  292. package/test/spec/modules/a1MediaRtdProvider_spec.js +105 -0
  293. package/test/spec/modules/adfBidAdapter_spec.js +47 -0
  294. package/test/spec/modules/adgenerationBidAdapter_spec.js +6 -6
  295. package/test/spec/modules/adkernelAdnBidAdapter_spec.js +1 -2
  296. package/test/spec/modules/adkernelBidAdapter_spec.js +7 -2
  297. package/test/spec/modules/adnuntiusBidAdapter_spec.js +116 -64
  298. package/test/spec/modules/adyoulikeBidAdapter_spec.js +13 -24
  299. package/test/spec/modules/appnexusBidAdapter_spec.js +12 -1
  300. package/test/spec/modules/beachfrontBidAdapter_spec.js +35 -2
  301. package/test/spec/modules/consentManagementGpp_spec.js +16 -0
  302. package/test/spec/modules/consumableBidAdapter_spec.js +15 -0
  303. package/test/spec/modules/criteoBidAdapter_spec.js +31 -3
  304. package/test/spec/modules/cwireBidAdapter_spec.js +47 -0
  305. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +5 -5
  306. package/test/spec/modules/geolocationRtdProvider_spec.js +119 -0
  307. package/test/spec/modules/greenbidsRtdProvider_spec.js +1 -1
  308. package/test/spec/modules/id5IdSystem_spec.js +18 -0
  309. package/test/spec/modules/imdsBidAdapter_spec.js +98 -17
  310. package/test/spec/modules/invibesBidAdapter_spec.js +123 -32
  311. package/test/spec/modules/ixBidAdapter_spec.js +23 -5
  312. package/test/spec/modules/medianetBidAdapter_spec.js +117 -0
  313. package/test/spec/modules/newspassidBidAdapter_spec.js +6 -0
  314. package/test/spec/modules/outbrainBidAdapter_spec.js +3 -5
  315. package/test/spec/modules/ozoneBidAdapter_spec.js +27 -1
  316. package/test/spec/modules/prebidServerBidAdapter_spec.js +2 -20
  317. package/test/spec/modules/priceFloors_spec.js +14 -0
  318. package/test/spec/modules/pubCircleBidAdapter_spec.js +399 -0
  319. package/test/spec/modules/pubmaticBidAdapter_spec.js +6 -373
  320. package/test/spec/modules/rubiconBidAdapter_spec.js +220 -9
  321. package/test/spec/modules/smaatoBidAdapter_spec.js +4 -6
  322. package/test/spec/modules/ssmasBidAdapter_spec.js +244 -0
  323. package/test/spec/modules/sspBCBidAdapter_spec.js +18 -19
  324. package/test/spec/modules/topicsFpdModule_spec.js +343 -365
  325. package/test/spec/modules/tripleliftBidAdapter_spec.js +40 -0
  326. package/test/spec/modules/userId_spec.js +116 -7
  327. package/test/spec/modules/viantOrtbBidAdapter_spec.js +432 -0
  328. package/test/spec/modules/vrtcalBidAdapter_spec.js +12 -4
  329. package/test/spec/modules/xeBidAdapter_spec.js +366 -368
  330. package/test/spec/modules/yahoosspBidAdapter_spec.js +5 -18
  331. package/test/spec/unit/core/bidderFactory_spec.js +61 -14
  332. package/integrationExamples/gpt/pbjs_video_adUnit.html +0 -109
@@ -1,312 +1,313 @@
1
1
  import {
2
+ getCachedTopics,
2
3
  getTopics,
3
4
  getTopicsData,
5
+ loadTopicsForBidders,
4
6
  processFpd,
5
- hasGDPRConsent,
6
- getCachedTopics,
7
7
  receiveMessage,
8
+ reset,
8
9
  topicStorageName
9
10
  } from '../../../modules/topicsFpdModule.js';
10
11
  import {deepClone, safeJSONParse} from '../../../src/utils.js';
11
- import {gdprDataHandler} from 'src/adapterManager.js';
12
12
  import {getCoreStorageManager} from 'src/storageManager.js';
13
+ import {config} from 'src/config.js';
14
+ import * as activities from '../../../src/activities/rules.js';
15
+ import {ACTIVITY_ENRICH_UFPD} from '../../../src/activities/activities.js';
13
16
 
14
- describe('getTopicsData', () => {
15
- function makeTopic(topic, modelv, taxv = '1') {
16
- return {
17
- topic,
18
- taxonomyVersion: taxv,
19
- modelVersion: modelv
20
- };
21
- }
17
+ describe('topics', () => {
18
+ beforeEach(() => {
19
+ reset();
20
+ });
22
21
 
23
- function byTaxClass(segments) {
24
- return segments.reduce((memo, segment) => {
25
- memo[`${segment.ext.segtax}:${segment.ext.segclass}`] = segment;
26
- return memo;
27
- }, {});
28
- }
22
+ describe('getTopicsData', () => {
23
+ function makeTopic(topic, modelv, taxv = '1') {
24
+ return {
25
+ topic,
26
+ taxonomyVersion: taxv,
27
+ modelVersion: modelv
28
+ };
29
+ }
29
30
 
30
- [
31
- {
32
- t: 'no topics',
33
- topics: [],
34
- expected: []
35
- },
36
- {
37
- t: 'single topic',
38
- topics: [makeTopic(123, 'm1')],
39
- expected: [
40
- {
41
- ext: {
42
- segtax: 600,
43
- segclass: 'm1'
44
- },
45
- segment: [
46
- {id: '123'}
47
- ]
48
- }
49
- ]
50
- },
51
- {
52
- t: 'multiple topics with the same model version',
53
- topics: [makeTopic(123, 'm1'), makeTopic(321, 'm1')],
54
- expected: [
55
- {
56
- ext: {
57
- segtax: 600,
58
- segclass: 'm1'
59
- },
60
- segment: [
61
- {id: '123'},
62
- {id: '321'}
63
- ]
64
- }
65
- ]
66
- },
67
- {
68
- t: 'multiple topics with different model versions',
69
- topics: [makeTopic(1, 'm1'), makeTopic(2, 'm1'), makeTopic(3, 'm2')],
70
- expected: [
71
- {
72
- ext: {
73
- segtax: 600,
74
- segclass: 'm1'
75
- },
76
- segment: [
77
- {id: '1'},
78
- {id: '2'}
79
- ]
80
- },
81
- {
82
- ext: {
83
- segtax: 600,
84
- segclass: 'm2'
85
- },
86
- segment: [
87
- {id: '3'}
88
- ]
89
- }
90
- ]
91
- },
92
- {
93
- t: 'multiple topics, some with a taxonomy version other than "1"',
94
- topics: [makeTopic(123, 'm1'), makeTopic(321, 'm1', 'other')],
95
- expected: [
96
- {
97
- ext: {
98
- segtax: 600,
99
- segclass: 'm1'
100
- },
101
- segment: [
102
- {id: '123'}
103
- ]
104
- }
105
- ]
106
- },
107
- {
108
- t: 'multiple topics in multiple taxonomies',
109
- taxonomies: {
110
- '1': 600,
111
- '2': 601
31
+ function byTaxClass(segments) {
32
+ return segments.reduce((memo, segment) => {
33
+ memo[`${segment.ext.segtax}:${segment.ext.segclass}`] = segment;
34
+ return memo;
35
+ }, {});
36
+ }
37
+
38
+ [
39
+ {
40
+ t: 'no topics',
41
+ topics: [],
42
+ expected: []
43
+ },
44
+ {
45
+ t: 'single topic',
46
+ topics: [makeTopic(123, 'm1')],
47
+ expected: [
48
+ {
49
+ ext: {
50
+ segtax: 600,
51
+ segclass: 'm1'
52
+ },
53
+ segment: [
54
+ {id: '123'}
55
+ ]
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ t: 'multiple topics with the same model version',
61
+ topics: [makeTopic(123, 'm1'), makeTopic(321, 'm1')],
62
+ expected: [
63
+ {
64
+ ext: {
65
+ segtax: 600,
66
+ segclass: 'm1'
67
+ },
68
+ segment: [
69
+ {id: '123'},
70
+ {id: '321'}
71
+ ]
72
+ }
73
+ ]
112
74
  },
113
- topics: [
114
- makeTopic(123, 'm1', '1'),
115
- makeTopic(321, 'm1', '2'),
116
- makeTopic(213, 'm2', '1'),
117
- ],
118
- expected: [
119
- {
120
- ext: {
121
- segtax: 600,
122
- segclass: 'm1'
75
+ {
76
+ t: 'multiple topics with different model versions',
77
+ topics: [makeTopic(1, 'm1'), makeTopic(2, 'm1'), makeTopic(3, 'm2')],
78
+ expected: [
79
+ {
80
+ ext: {
81
+ segtax: 600,
82
+ segclass: 'm1'
83
+ },
84
+ segment: [
85
+ {id: '1'},
86
+ {id: '2'}
87
+ ]
123
88
  },
124
- segment: [
125
- {id: '123'}
126
- ]
89
+ {
90
+ ext: {
91
+ segtax: 600,
92
+ segclass: 'm2'
93
+ },
94
+ segment: [
95
+ {id: '3'}
96
+ ]
97
+ }
98
+ ]
99
+ },
100
+ {
101
+ t: 'multiple topics, some with a taxonomy version other than "1"',
102
+ topics: [makeTopic(123, 'm1'), makeTopic(321, 'm1', 'other')],
103
+ expected: [
104
+ {
105
+ ext: {
106
+ segtax: 600,
107
+ segclass: 'm1'
108
+ },
109
+ segment: [
110
+ {id: '123'}
111
+ ]
112
+ }
113
+ ]
114
+ },
115
+ {
116
+ t: 'multiple topics in multiple taxonomies',
117
+ taxonomies: {
118
+ '1': 600,
119
+ '2': 601
127
120
  },
128
- {
129
- ext: {
130
- segtax: 601,
131
- segclass: 'm1',
121
+ topics: [
122
+ makeTopic(123, 'm1', '1'),
123
+ makeTopic(321, 'm1', '2'),
124
+ makeTopic(213, 'm2', '1'),
125
+ ],
126
+ expected: [
127
+ {
128
+ ext: {
129
+ segtax: 600,
130
+ segclass: 'm1'
131
+ },
132
+ segment: [
133
+ {id: '123'}
134
+ ]
132
135
  },
133
- segment: [
134
- {id: '321'}
135
- ]
136
- },
137
- {
138
- ext: {
139
- segtax: 600,
140
- segclass: 'm2'
136
+ {
137
+ ext: {
138
+ segtax: 601,
139
+ segclass: 'm1',
140
+ },
141
+ segment: [
142
+ {id: '321'}
143
+ ]
141
144
  },
142
- segment: [
143
- {id: '213'}
144
- ]
145
- }
146
- ]
147
- }
148
- ].forEach(({t, topics, expected, taxonomies}) => {
149
- describe(`on ${t}`, () => {
150
- it('should convert topics to user.data segments correctly', () => {
151
- const actual = getTopicsData('mockName', topics, taxonomies);
152
- expect(actual.length).to.eql(expected.length);
153
- expected = byTaxClass(expected);
154
- Object.entries(byTaxClass(actual)).forEach(([key, datum]) => {
155
- sinon.assert.match(datum, expected[key]);
156
- expect(datum.name).to.equal('mockName');
145
+ {
146
+ ext: {
147
+ segtax: 600,
148
+ segclass: 'm2'
149
+ },
150
+ segment: [
151
+ {id: '213'}
152
+ ]
153
+ }
154
+ ]
155
+ }
156
+ ].forEach(({t, topics, expected, taxonomies}) => {
157
+ describe(`on ${t}`, () => {
158
+ it('should convert topics to user.data segments correctly', () => {
159
+ const actual = getTopicsData('mockName', topics, taxonomies);
160
+ expect(actual.length).to.eql(expected.length);
161
+ expected = byTaxClass(expected);
162
+ Object.entries(byTaxClass(actual)).forEach(([key, datum]) => {
163
+ sinon.assert.match(datum, expected[key]);
164
+ expect(datum.name).to.equal('mockName');
165
+ });
157
166
  });
158
- });
159
167
 
160
- it('should not set name if null', () => {
161
- getTopicsData(null, topics).forEach((data) => {
162
- expect(data.hasOwnProperty('name')).to.be.false;
168
+ it('should not set name if null', () => {
169
+ getTopicsData(null, topics).forEach((data) => {
170
+ expect(data.hasOwnProperty('name')).to.be.false;
171
+ });
163
172
  });
164
173
  });
165
174
  });
166
175
  });
167
- });
168
176
 
169
- describe('getTopics', () => {
170
- Object.entries({
171
- 'document with no browsingTopics': {},
172
- 'document that disallows topics': {
173
- featurePolicy: {
174
- allowsFeature: sinon.stub().returns(false)
175
- }
176
- },
177
- 'document that throws on featurePolicy': {
178
- browsingTopics: sinon.stub(),
179
- get featurePolicy() {
180
- throw new Error();
181
- }
182
- },
183
- 'document that throws on browsingTopics': {
184
- browsingTopics: sinon.stub().callsFake(() => {
185
- throw new Error();
186
- }),
187
- featurePolicy: {
188
- allowsFeature: sinon.stub().returns(true)
189
- }
190
- },
191
- }).forEach(([t, doc]) => {
192
- it(`should resolve to an empty list on ${t}`, () => {
193
- return getTopics(doc).then((topics) => {
194
- expect(topics).to.eql([]);
177
+ describe('getTopics', () => {
178
+ Object.entries({
179
+ 'document with no browsingTopics': {},
180
+ 'document that disallows topics': {
181
+ featurePolicy: {
182
+ allowsFeature: sinon.stub().returns(false)
183
+ }
184
+ },
185
+ 'document that throws on featurePolicy': {
186
+ browsingTopics: sinon.stub(),
187
+ get featurePolicy() {
188
+ throw new Error();
189
+ }
190
+ },
191
+ 'document that throws on browsingTopics': {
192
+ browsingTopics: sinon.stub().callsFake(() => {
193
+ throw new Error();
194
+ }),
195
+ featurePolicy: {
196
+ allowsFeature: sinon.stub().returns(true)
197
+ }
198
+ },
199
+ }).forEach(([t, doc]) => {
200
+ it(`should resolve to an empty list on ${t}`, () => {
201
+ return getTopics(doc).then((topics) => {
202
+ expect(topics).to.eql([]);
203
+ });
195
204
  });
196
205
  });
197
- });
198
206
 
199
- it('should call `document.browsingTopics` when allowed', () => {
200
- const topics = ['t1', 't2'];
201
- return getTopics({
202
- browsingTopics: sinon.stub().returns(Promise.resolve(topics)),
203
- featurePolicy: {
204
- allowsFeature: sinon.stub().returns(true)
205
- }
206
- }).then((actual) => {
207
- expect(actual).to.eql(topics);
208
- });
209
- });
210
- });
211
-
212
- describe('processFpd', () => {
213
- const mockData = [
214
- {
215
- name: 'domain',
216
- segment: [{id: 123}]
217
- },
218
- {
219
- name: 'domain',
220
- segment: [{id: 321}]
221
- }
222
- ];
223
-
224
- it('should add topics data', () => {
225
- return processFpd({}, {global: {}}, {data: Promise.resolve(mockData)})
226
- .then(({global}) => {
227
- expect(global.user.data).to.eql(mockData);
207
+ it('should call `document.browsingTopics` when allowed', () => {
208
+ const topics = ['t1', 't2'];
209
+ return getTopics({
210
+ browsingTopics: sinon.stub().returns(Promise.resolve(topics)),
211
+ featurePolicy: {
212
+ allowsFeature: sinon.stub().returns(true)
213
+ }
214
+ }).then((actual) => {
215
+ expect(actual).to.eql(topics);
228
216
  });
217
+ });
229
218
  });
230
219
 
231
- it('should apppend to existing user.data', () => {
232
- const global = {
233
- user: {
234
- data: [
235
- {name: 'preexisting'},
236
- ]
220
+ describe('processFpd', () => {
221
+ const mockData = [
222
+ {
223
+ name: 'domain',
224
+ segment: [{id: 123}]
225
+ },
226
+ {
227
+ name: 'domain',
228
+ segment: [{id: 321}]
237
229
  }
238
- };
239
- return processFpd({}, {global: deepClone(global)}, {data: Promise.resolve(mockData)})
240
- .then((data) => {
241
- expect(data.global.user.data).to.eql(global.user.data.concat(mockData));
242
- });
243
- });
244
-
245
- it('should not modify fpd when there is no data', () => {
246
- return processFpd({}, {global: {}}, {data: Promise.resolve([])})
247
- .then((data) => {
248
- expect(data.global).to.eql({});
249
- });
250
- });
251
- });
230
+ ];
252
231
 
253
- describe('Topics Module GDPR consent check', () => {
254
- let gdprDataHdlrStub;
255
- beforeEach(() => {
256
- gdprDataHdlrStub = sinon.stub(gdprDataHandler, 'getConsentData');
257
- });
258
-
259
- afterEach(() => {
260
- gdprDataHdlrStub.restore();
261
- });
262
-
263
- it('should return false when GDPR is applied but consent string is not present', () => {
264
- const consentString = '';
265
- const consentConfig = {
266
- consentString: consentString,
267
- gdprApplies: true,
268
- vendorData: {}
269
- };
270
- gdprDataHdlrStub.returns(consentConfig);
271
- expect(hasGDPRConsent()).to.equal(false);
272
- });
232
+ it('should add topics data', () => {
233
+ return processFpd({}, {global: {}}, {data: Promise.resolve(mockData)})
234
+ .then(({global}) => {
235
+ expect(global.user.data).to.eql(mockData);
236
+ });
237
+ });
273
238
 
274
- it('should return true when GDPR doesn\'t apply', () => {
275
- const consentString = 'CPi8wgAPi8wgAADABBENCrCsAP_AAH_AAAAAISNB7D==';
276
- const consentConfig = {
277
- consentString: consentString,
278
- gdprApplies: false,
279
- vendorData: {}
280
- };
239
+ it('should apppend to existing user.data', () => {
240
+ const global = {
241
+ user: {
242
+ data: [
243
+ {name: 'preexisting'},
244
+ ]
245
+ }
246
+ };
247
+ return processFpd({}, {global: deepClone(global)}, {data: Promise.resolve(mockData)})
248
+ .then((data) => {
249
+ expect(data.global.user.data).to.eql(global.user.data.concat(mockData));
250
+ });
251
+ });
281
252
 
282
- gdprDataHdlrStub.returns(consentConfig);
283
- expect(hasGDPRConsent()).to.equal(true);
253
+ it('should not modify fpd when there is no data', () => {
254
+ return processFpd({}, {global: {}}, {data: Promise.resolve([])})
255
+ .then((data) => {
256
+ expect(data.global).to.eql({});
257
+ });
258
+ });
284
259
  });
285
260
 
286
- it('should return true when GDPR is applied and purpose consent is true for all purpose[1,2,3,4]', () => {
287
- const consentString = 'CPi8wgAPi8wgAADABBENCrCsAP_AAH_AAAAAISNB7D==';
288
- const consentConfig = {
289
- consentString: consentString,
290
- gdprApplies: true,
291
- vendorData: {
292
- metadata: consentString,
293
- gdprApplies: true,
294
- purpose: {
295
- consents: {
296
- 1: true,
297
- 2: true,
298
- 3: true,
299
- 4: true
261
+ describe('loadTopicsForBidders', () => {
262
+ beforeEach(() => {
263
+ config.setConfig({
264
+ userSync: {
265
+ topics: {
266
+ bidders: [{
267
+ bidder: 'mockBidder',
268
+ iframeURL: 'https://mock.iframe'
269
+ }]
300
270
  }
301
271
  }
302
- }
303
- };
272
+ })
273
+ });
274
+ afterEach(() => {
275
+ config.resetConfig();
276
+ })
304
277
 
305
- gdprDataHdlrStub.returns(consentConfig);
306
- expect(hasGDPRConsent()).to.equal(true);
278
+ Object.entries({
279
+ 'support': {},
280
+ 'allow': {
281
+ browsingTopics: true,
282
+ featurePolicy: {
283
+ allowsFeature(feature) {
284
+ return feature !== 'browsing-topics';
285
+ }
286
+ }
287
+ },
288
+ }).forEach(([t, doc]) => {
289
+ it(`does not attempt to load frames if browser does not ${t} topics`, () => {
290
+ doc.createElement = sinon.stub();
291
+ loadTopicsForBidders(doc);
292
+ sinon.assert.notCalled(doc.createElement);
293
+ });
294
+ });
307
295
  });
308
296
 
309
- it('should return false when GDPR is applied and purpose consent is false for one of the purpose[1,2,3,4]', () => {
297
+ describe('getCachedTopics()', () => {
298
+ const storage = getCoreStorageManager('topicsFpd');
299
+ const expected = [{
300
+ ext: {
301
+ segtax: 600,
302
+ segclass: '2206021246'
303
+ },
304
+ segment: [{
305
+ 'id': '243'
306
+ }, {
307
+ 'id': '265'
308
+ }],
309
+ name: 'ads.pubmatic.com'
310
+ }];
310
311
  const consentString = 'CPi8wgAPi8wgAADABBENCrCsAP_AAH_AAAAAISNB7D==';
311
312
  const consentConfig = {
312
313
  consentString: consentString,
@@ -319,120 +320,97 @@ describe('Topics Module GDPR consent check', () => {
319
320
  1: true,
320
321
  2: true,
321
322
  3: true,
322
- 4: false
323
+ 4: true
323
324
  }
324
325
  }
325
326
  }
326
327
  };
327
-
328
- gdprDataHdlrStub.returns(consentConfig);
329
- expect(hasGDPRConsent()).to.equal(false);
330
- });
331
- });
332
-
333
- describe('getCachedTopics()', () => {
334
- const storage = getCoreStorageManager('topicsFpd');
335
- const expected = [{
336
- ext: {
337
- segtax: 600,
338
- segclass: '2206021246'
339
- },
340
- segment: [{
341
- 'id': '243'
342
- }, {
343
- 'id': '265'
344
- }],
345
- name: 'ads.pubmatic.com'
346
- }];
347
- const consentString = 'CPi8wgAPi8wgAADABBENCrCsAP_AAH_AAAAAISNB7D==';
348
- const consentConfig = {
349
- consentString: consentString,
350
- gdprApplies: true,
351
- vendorData: {
352
- metadata: consentString,
353
- gdprApplies: true,
354
- purpose: {
355
- consents: {
356
- 1: true,
357
- 2: true,
358
- 3: true,
359
- 4: true
360
- }
328
+ const mockData = [
329
+ {
330
+ name: 'domain',
331
+ segment: [{id: 123}]
332
+ },
333
+ {
334
+ name: 'domain',
335
+ segment: [{id: 321}],
361
336
  }
362
- }
363
- };
364
- const mockData = [
365
- {
366
- name: 'domain',
367
- segment: [{id: 123}]
368
- },
369
- {
370
- name: 'domain',
371
- segment: [{id: 321}],
372
- }
373
- ];
337
+ ];
374
338
 
375
- const evt_pm = {
376
- data: '{"segment":{"domain":"ads.pubmatic.com","topics":[{"configVersion":"chrome.1","modelVersion":"2206021246","taxonomyVersion":"1","topic":165,"version":"chrome.1:1:2206021246"}],"bidder":"pubmatic"},"date":1669743901858}',
377
- origin: 'https://ads.pubmatic.com'
378
- };
339
+ const evt = {
340
+ data: '{"segment":{"domain":"ads.pubmatic.com","topics":[{"configVersion":"chrome.1","modelVersion":"2206021246","taxonomyVersion":"1","topic":165,"version":"chrome.1:1:2206021246"}],"bidder":"pubmatic"},"date":1669743901858}',
341
+ origin: 'https://ads.pubmatic.com'
342
+ };
379
343
 
380
- const evt_rh = {
381
- data: '{"segment":{"domain":"topics.authorizedvault.com","topics":[{"configVersion":"chrome.1","modelVersion":"2206021246","taxonomyVersion":"1","topic":165,"version":"chrome.1:1:2206021246"}],"bidder":"rtbhouse"},"date":1669743901858}',
382
- origin: 'https://topics.authorizedvault.com'
383
- };
344
+ afterEach(() => {
345
+ storage.removeDataFromLocalStorage(topicStorageName);
346
+ });
384
347
 
385
- let gdprDataHdlrStub;
386
- beforeEach(() => {
387
- gdprDataHdlrStub = sinon.stub(gdprDataHandler, 'getConsentData');
388
- });
348
+ describe('when cached data is available and not expired', () => {
349
+ let sandbox;
350
+ beforeEach(() => {
351
+ sandbox = sinon.sandbox.create();
352
+ const storedSegments = JSON.stringify(
353
+ [['pubmatic', {
354
+ '2206021246': {
355
+ 'ext': {'segtax': 600, 'segclass': '2206021246'},
356
+ 'segment': [{'id': '243'}, {'id': '265'}],
357
+ 'name': 'ads.pubmatic.com'
358
+ },
359
+ 'lastUpdated': new Date().getTime()
360
+ }]]
361
+ );
362
+ storage.setDataInLocalStorage(topicStorageName, storedSegments);
363
+ });
364
+ afterEach(() => {
365
+ sandbox.restore();
366
+ });
389
367
 
390
- afterEach(() => {
391
- storage.removeDataFromLocalStorage(topicStorageName);
392
- gdprDataHdlrStub.restore();
393
- });
368
+ it('should return segments for bidder if transmitUfpd is allowed', () => {
369
+ assert.deepEqual(getCachedTopics(), expected);
370
+ });
394
371
 
395
- it('should return segments for bidder if GDPR consent is true and there is cached segments stored which is not expired', () => {
396
- const storedSegments = JSON.stringify(
397
- [['pubmatic', {
398
- '2206021246': {
399
- 'ext': {'segtax': 600, 'segclass': '2206021246'},
400
- 'segment': [{'id': '243'}, {'id': '265'}],
401
- 'name': 'ads.pubmatic.com'
402
- },
403
- 'lastUpdated': new Date().getTime()
404
- }]]
405
- );
406
- storage.setDataInLocalStorage(topicStorageName, storedSegments);
407
- gdprDataHdlrStub.returns(consentConfig);
408
- assert.deepEqual(getCachedTopics(), expected);
409
- });
372
+ it('should NOT return segments for bidder if enrichUfpd is NOT allowed', () => {
373
+ sandbox.stub(activities, 'isActivityAllowed').callsFake((activity, params) => {
374
+ return !(activity === ACTIVITY_ENRICH_UFPD && params.component === 'bidder.pubmatic');
375
+ });
376
+ expect(getCachedTopics()).to.eql([]);
377
+ });
378
+ })
410
379
 
411
- it('should return empty segments for bidder if GDPR consent is true and there is cached segments stored which is expired', () => {
412
- let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":10}]]';
413
- storage.setDataInLocalStorage(topicStorageName, storedSegments);
414
- gdprDataHdlrStub.returns(consentConfig);
415
- assert.deepEqual(getCachedTopics(), []);
416
- });
380
+ it('should return empty segments for bidder if there is cached segments stored which is expired', () => {
381
+ let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":10}]]';
382
+ storage.setDataInLocalStorage(topicStorageName, storedSegments);
383
+ assert.deepEqual(getCachedTopics(), []);
384
+ });
417
385
 
418
- it('should stored segments if receiveMessage event is triggerred with segment data', () => {
419
- return processFpd({}, {global: {}}, {data: Promise.resolve(mockData)})
420
- .then(({global}) => {
421
- receiveMessage(evt_pm);
422
- receiveMessage(evt_rh);
386
+ describe('cross-frame messages', () => {
387
+ beforeEach(() => {
388
+ // init iframe logic so that the receiveMessage origin check passes
389
+ loadTopicsForBidders({
390
+ browsingTopics: true,
391
+ featurePolicy: {
392
+ allowsFeature() { return true }
393
+ },
394
+ createElement: sinon.stub().callsFake(() => ({style: {}})),
395
+ documentElement: {
396
+ appendChild() {}
397
+ }
398
+ });
399
+ });
400
+
401
+ it('should store segments if receiveMessage event is triggered with segment data', () => {
402
+ receiveMessage(evt);
423
403
  let segments = new Map(safeJSONParse(storage.getDataFromLocalStorage(topicStorageName)));
424
- expect(segments.has('pubmatic') || segments.has('rtbhouse')).to.equal(true);
404
+ expect(segments.has('pubmatic')).to.equal(true);
425
405
  });
426
- });
427
406
 
428
- it('should update stored segments if receiveMessage event is triggerred with segment data', () => {
429
- let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":1669719242027}]]';
430
- storage.setDataInLocalStorage(topicStorageName, storedSegments);
431
- return processFpd({}, {global: {}}, {data: Promise.resolve(mockData)})
432
- .then(({global}) => {
433
- receiveMessage(evt_pm);
407
+ it('should update stored segments if receiveMessage event is triggerred with segment data', () => {
408
+ let storedSegments = '[["pubmatic",{"2206021246":{"ext":{"segtax":600,"segclass":"2206021246"},"segment":[{"id":"243"},{"id":"265"}],"name":"ads.pubmatic.com"},"lastUpdated":1669719242027}]]';
409
+ storage.setDataInLocalStorage(topicStorageName, storedSegments);
410
+ receiveMessage(evt);
434
411
  let segments = new Map(safeJSONParse(storage.getDataFromLocalStorage(topicStorageName)));
435
412
  expect(segments.get('pubmatic')[2206021246].segment.length).to.equal(1);
436
413
  });
414
+ });
437
415
  });
438
416
  });