prebid.js 8.5.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 (174) 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/adsinteractiveBidAdapter.js +1 -1
  9. package/dist/adtrgtmeBidAdapter.js +1 -1
  10. package/dist/adxcgBidAdapter.js +1 -1
  11. package/dist/adyoulikeBidAdapter.js +1 -1
  12. package/dist/ajaBidAdapter.js +1 -1
  13. package/dist/amxBidAdapter.js +1 -1
  14. package/dist/amxIdSystem.js +1 -1
  15. package/dist/appierAnalyticsAdapter.js +1 -1
  16. package/dist/appnexusBidAdapter.js +1 -1
  17. package/dist/asoBidAdapter.js +1 -1
  18. package/dist/axonixBidAdapter.js +1 -1
  19. package/dist/bidglassBidAdapter.js +1 -1
  20. package/dist/big-richmediaBidAdapter.js +1 -1
  21. package/dist/bridBidAdapter.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/connectadBidAdapter.js +1 -1
  28. package/dist/consumableBidAdapter.js +1 -1
  29. package/dist/conversantAnalyticsAdapter.js +1 -1
  30. package/dist/conversantBidAdapter.js +1 -1
  31. package/dist/craftBidAdapter.js +1 -1
  32. package/dist/criteoBidAdapter.js +1 -1
  33. package/dist/cwireBidAdapter.js +1 -1
  34. package/dist/dependencies.json +3 -0
  35. package/dist/dspxBidAdapter.js +1 -1
  36. package/dist/eplanningBidAdapter.js +1 -1
  37. package/dist/euidIdSystem.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/gmosspBidAdapter.js +1 -1
  42. package/dist/goldbachBidAdapter.js +1 -1
  43. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  44. package/dist/greenbidsRtdProvider.js +1 -1
  45. package/dist/gridBidAdapter.js +1 -1
  46. package/dist/growthCodeAnalyticsAdapter.js +1 -1
  47. package/dist/gumgumBidAdapter.js +1 -1
  48. package/dist/h12mediaBidAdapter.js +1 -1
  49. package/dist/hypelabBidAdapter.js +1 -1
  50. package/dist/id5IdSystem.js +1 -1
  51. package/dist/imdsBidAdapter.js +1 -1
  52. package/dist/improvedigitalBidAdapter.js +1 -1
  53. package/dist/insticatorBidAdapter.js +1 -1
  54. package/dist/ixBidAdapter.js +1 -1
  55. package/dist/justpremiumBidAdapter.js +1 -1
  56. package/dist/kargoBidAdapter.js +1 -1
  57. package/dist/konduitAnalyticsAdapter.js +1 -1
  58. package/dist/kueezBidAdapter.js +1 -1
  59. package/dist/kueezRtbBidAdapter.js +1 -1
  60. package/dist/kulturemediaBidAdapter.js +1 -1
  61. package/dist/lassoBidAdapter.js +1 -1
  62. package/dist/lifestreetBidAdapter.js +1 -1
  63. package/dist/logicadBidAdapter.js +1 -1
  64. package/dist/loglyliftBidAdapter.js +1 -1
  65. package/dist/magniteAnalyticsAdapter.js +1 -1
  66. package/dist/malltvAnalyticsAdapter.js +1 -1
  67. package/dist/marsmediaBidAdapter.js +1 -1
  68. package/dist/mediafuseBidAdapter.js +1 -1
  69. package/dist/mediasquareBidAdapter.js +1 -1
  70. package/dist/mgidBidAdapter.js +1 -1
  71. package/dist/minutemediaBidAdapter.js +1 -1
  72. package/dist/minutemediaplusBidAdapter.js +1 -1
  73. package/dist/mspa.js +1 -1
  74. package/dist/newspassidBidAdapter.js +1 -1
  75. package/dist/nexx360BidAdapter.js +1 -1
  76. package/dist/not-for-prod/prebid.js +135 -133
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/optidigitalBidAdapter.js +1 -1
  81. package/dist/outbrainBidAdapter.js +1 -1
  82. package/dist/parrableIdSystem.js +1 -1
  83. package/dist/pixfutureBidAdapter.js +1 -1
  84. package/dist/prebid-core.js +1 -1
  85. package/dist/pubCircleBidAdapter.js +1 -0
  86. package/dist/publinkIdSystem.js +1 -1
  87. package/dist/pubmaticBidAdapter.js +1 -1
  88. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  89. package/dist/pxyzBidAdapter.js +1 -1
  90. package/dist/quantcastBidAdapter.js +1 -1
  91. package/dist/readpeakBidAdapter.js +1 -1
  92. package/dist/relaidoBidAdapter.js +1 -1
  93. package/dist/relevadRtdProvider.js +1 -1
  94. package/dist/retailspotBidAdapter.js +1 -1
  95. package/dist/rhythmoneBidAdapter.js +1 -1
  96. package/dist/riseBidAdapter.js +1 -1
  97. package/dist/rubiconBidAdapter.js +1 -1
  98. package/dist/seedingAllianceBidAdapter.js +1 -1
  99. package/dist/seedtagBidAdapter.js +1 -1
  100. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  101. package/dist/sharethroughBidAdapter.js +1 -1
  102. package/dist/shinezBidAdapter.js +1 -1
  103. package/dist/smaatoBidAdapter.js +1 -1
  104. package/dist/smartadserverBidAdapter.js +1 -1
  105. package/dist/smartxBidAdapter.js +1 -1
  106. package/dist/smilewantedBidAdapter.js +1 -1
  107. package/dist/sonobiBidAdapter.js +1 -1
  108. package/dist/sovrnAnalyticsAdapter.js +1 -1
  109. package/dist/sovrnBidAdapter.js +1 -1
  110. package/dist/ssmasBidAdapter.js +1 -1
  111. package/dist/sspBCBidAdapter.js +1 -1
  112. package/dist/stvBidAdapter.js +1 -1
  113. package/dist/sublimeBidAdapter.js +1 -1
  114. package/dist/tappxBidAdapter.js +1 -1
  115. package/dist/targetVideoBidAdapter.js +1 -1
  116. package/dist/teadsBidAdapter.js +1 -1
  117. package/dist/topicsFpdModule.js +1 -1
  118. package/dist/trionBidAdapter.js +1 -1
  119. package/dist/tripleliftBidAdapter.js +1 -1
  120. package/dist/ttdBidAdapter.js +1 -1
  121. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  122. package/dist/uid2IdSystem.js +1 -1
  123. package/dist/underdogmediaBidAdapter.js +1 -1
  124. package/dist/undertoneBidAdapter.js +1 -1
  125. package/dist/viantOrtbBidAdapter.js +1 -0
  126. package/dist/vidazooBidAdapter.js +1 -1
  127. package/dist/videobyteBidAdapter.js +1 -1
  128. package/dist/videojsVideoProvider.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/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +1 -1
  137. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +1 -1
  138. package/integrationExamples/videoModule/jwplayer/bidsBackHandlerOverride.html +137 -0
  139. package/integrationExamples/videoModule/jwplayer/eventListeners.html +1 -1
  140. package/integrationExamples/videoModule/jwplayer/eventsUI.html +1 -1
  141. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +1 -1
  142. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +1 -1
  143. package/integrationExamples/videoModule/jwplayer/playlist.html +1 -1
  144. package/integrationExamples/videoModule/videojs/bidsBackHandlerOverride.html +164 -0
  145. package/libraries/mspa/activityControls.js +51 -32
  146. package/modules/adgenerationBidAdapter.js +3 -3
  147. package/modules/adsinteractiveBidAdapter.js +2 -2
  148. package/modules/appnexusBidAdapter.js +1 -1
  149. package/modules/criteoBidAdapter.js +18 -0
  150. package/modules/cwireBidAdapter.js +19 -0
  151. package/modules/growthCodeAnalyticsAdapter.js +7 -2
  152. package/modules/newspassid.md +76 -0
  153. package/modules/newspassidBidAdapter.js +44 -18
  154. package/modules/pubCircleBidAdapter.js +231 -0
  155. package/modules/pubCircleBidAdapter.md +79 -0
  156. package/modules/relevadRtdProvider.js +6 -7
  157. package/modules/ssmasBidAdapter.js +2 -2
  158. package/modules/tappxBidAdapter.js +10 -1
  159. package/modules/tappxBidAdapter.md +17 -0
  160. package/modules/topicsFpdModule.js +21 -48
  161. package/modules/viantOrtbBidAdapter.js +113 -0
  162. package/modules/viantOrtbBidAdapter.md +54 -0
  163. package/modules/vidazooBidAdapter.js +9 -2
  164. package/modules/videojsVideoProvider.js +9 -2
  165. package/package.json +1 -1
  166. package/test/spec/libraries/mspa/activityControls_spec.js +145 -212
  167. package/test/spec/modules/adgenerationBidAdapter_spec.js +6 -6
  168. package/test/spec/modules/appnexusBidAdapter_spec.js +12 -1
  169. package/test/spec/modules/criteoBidAdapter_spec.js +31 -3
  170. package/test/spec/modules/cwireBidAdapter_spec.js +47 -0
  171. package/test/spec/modules/newspassidBidAdapter_spec.js +6 -0
  172. package/test/spec/modules/pubCircleBidAdapter_spec.js +399 -0
  173. package/test/spec/modules/topicsFpdModule_spec.js +343 -365
  174. package/test/spec/modules/viantOrtbBidAdapter_spec.js +432 -0
@@ -0,0 +1,54 @@
1
+ # Overview
2
+
3
+ Module Name: VIANT Bidder Adapter
4
+ Module Type: Bidder Adapter
5
+ Maintainer: dist-runtime@viantinc.com
6
+
7
+ # Description
8
+
9
+ An adapter to get a bid from VIANT DSP.
10
+
11
+ # Test Parameters
12
+ ```javascript
13
+ var adUnits = [ // Banner adUnit with only required parameters
14
+ {
15
+ code: 'test-div-minimal',
16
+ mediaTypes: {
17
+ banner: {
18
+ sizes: [[728, 90]]
19
+ }
20
+ },
21
+ bids: [
22
+ {
23
+ bidder: 'viant',
24
+ params: {
25
+ supplySourceId: 'supplier',
26
+ publisherId: '464'
27
+ }
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ code: 'test-div-minimal-video',
33
+ mediaTypes: {
34
+ video: {
35
+ playerSize: [640, 480],
36
+ context: 'outstream'
37
+ }
38
+ },
39
+ bids: [
40
+ {
41
+ bidder: 'viant',
42
+ params: {
43
+ supplySourceId: 'supplier',
44
+ publisherId: '464' // required
45
+ }
46
+ }
47
+ ]
48
+ }
49
+ ];
50
+ ```
51
+
52
+ Where:
53
+
54
+ * placementId - Placement ID of the ad unit (required)
@@ -320,13 +320,20 @@ function interpretResponse(serverResponse, request) {
320
320
  }
321
321
  }
322
322
 
323
- function getUserSyncs(syncOptions, responses, gdprConsent = {}, uspConsent = '') {
323
+ function getUserSyncs(syncOptions, responses, gdprConsent = {}, uspConsent = '', gppConsent = {}) {
324
324
  let syncs = [];
325
325
  const {iframeEnabled, pixelEnabled} = syncOptions;
326
326
  const {gdprApplies, consentString = ''} = gdprConsent;
327
+ const {gppString, applicableSections} = gppConsent;
327
328
 
328
329
  const cidArr = responses.filter(resp => deepAccess(resp, 'body.cid')).map(resp => resp.body.cid).filter(uniques);
329
- const params = `?cid=${encodeURIComponent(cidArr.join(','))}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${encodeURIComponent(consentString || '')}&us_privacy=${encodeURIComponent(uspConsent || '')}`
330
+ let params = `?cid=${encodeURIComponent(cidArr.join(','))}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${encodeURIComponent(consentString || '')}&us_privacy=${encodeURIComponent(uspConsent || '')}`;
331
+
332
+ if (gppString && applicableSections?.length) {
333
+ params += '&gpp=' + encodeURIComponent(gppString);
334
+ params += '&gpp_sid=' + encodeURIComponent(applicableSections.join(','));
335
+ }
336
+
330
337
  if (iframeEnabled) {
331
338
  syncs.push({
332
339
  type: 'iframe',
@@ -201,8 +201,15 @@ export function VideojsProvider(providerConfig, vjs_, adState_, timeState_, call
201
201
  return;
202
202
  }
203
203
 
204
- player.ima.changeAdTag(adTagUrl);
205
- player.ima.requestAds();
204
+ // The VideoJS IMA plugin version 1.11.0 will throw when the ad is empty.
205
+ try {
206
+ player.ima.changeAdTag(adTagUrl);
207
+ player.ima.requestAds();
208
+ } catch (e) {
209
+ /*
210
+ Handling is not required; ad errors are emitted automatically by video.js
211
+ */
212
+ }
206
213
  }
207
214
 
208
215
  function onEvent(type, callback, payload) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "8.5.0",
3
+ "version": "8.6.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -1,220 +1,153 @@
1
- import {mspaRule, setupRules, isTransmitUfpdConsentDenied, isTransmitGeoConsentDenied, isBasicConsentDenied, isSensitiveNoticeMissing, isConsentDenied} from '../../../../libraries/mspa/activityControls.js';
1
+ import {mspaRule, setupRules, isTransmitUfpdConsentDenied, isTransmitGeoConsentDenied, isBasicConsentDenied, sensitiveNoticeIs, isConsentDenied} from '../../../../libraries/mspa/activityControls.js';
2
2
  import {ruleRegistry} from '../../../../src/activities/rules.js';
3
- describe('isBasicConsentDenied', () => {
4
- const cd = {
5
- // not covered, opt in to targeted, sale, and share, all notices given, opt into precise geo
6
- Gpc: 0,
7
- KnownChildSensitiveDataConsents: [0, 0],
8
- MspaCoveredTransaction: 2,
9
- MspaOptOutOptionMode: 0,
10
- MspaServiceProviderMode: 0,
11
- PersonalDataConsents: 0,
12
- SaleOptOut: 2,
13
- SaleOptOutNotice: 1,
14
- SensitiveDataLimitUseNotice: 1,
15
- SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
16
- SensitiveDataProcessingOptOutNotice: 1,
17
- SharingNotice: 1,
18
- SharingOptOut: 2,
19
- SharingOptOutNotice: 1,
20
- TargetedAdvertisingOptOut: 2,
21
- TargetedAdvertisingOptOutNotice: 1,
22
- Version: 1
23
- };
24
- it('should be false (basic consent conditions pass) with variety of notice and opt in', () => {
25
- const result = isBasicConsentDenied(cd);
26
- expect(result).to.equal(false);
27
- });
28
- it('should be true (basic consent conditions do not pass) with personal data consent set to true (invalid state)', () => {
29
- cd.PersonalDataConsents = 2;
30
- const result = isBasicConsentDenied(cd);
31
- expect(result).to.equal(true);
32
- cd.PersonalDataConsents = 0;
33
- });
34
- it('should be true (basic consent conditions do not pass) with sensitive opt in but no notice', () => {
35
- cd.SensitiveDataLimitUseNotice = 0;
36
- const result = isBasicConsentDenied(cd);
37
- expect(result).to.equal(true);
38
- cd.SensitiveDataLimitUseNotice = 1;
39
- });
40
- })
41
- describe('isSensitiveNoticeMissing', () => {
42
- const cd = {
43
- // not covered, opt in to targeted, sale, and share, all notices given, opt into precise geo
44
- Gpc: 0,
45
- KnownChildSensitiveDataConsents: [0, 0],
46
- MspaCoveredTransaction: 2,
47
- MspaOptOutOptionMode: 0,
48
- MspaServiceProviderMode: 0,
49
- PersonalDataConsents: 0,
50
- SaleOptOut: 2,
51
- SaleOptOutNotice: 1,
52
- SensitiveDataLimitUseNotice: 1,
53
- SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
54
- SensitiveDataProcessingOptOutNotice: 1,
55
- SharingNotice: 1,
56
- SharingOptOut: 2,
57
- SharingOptOutNotice: 1,
58
- TargetedAdvertisingOptOut: 2,
59
- TargetedAdvertisingOptOutNotice: 1,
60
- Version: 1
61
- };
62
- it('should be false (sensitive notice is given or not needed) with variety of notice and opt in', () => {
63
- const result = isSensitiveNoticeMissing(cd);
64
- expect(result).to.equal(false);
65
- });
66
- it('should be true (sensitive notice is missing) with variety of notice and opt in', () => {
67
- cd.SensitiveDataLimitUseNotice = 2;
68
- const result = isSensitiveNoticeMissing(cd);
69
- expect(result).to.equal(true);
70
- cd.SensitiveDataLimitUseNotice = 1;
71
- });
72
- })
73
- describe('isConsentDenied', () => {
74
- const cd = {
75
- // not covered, opt in to targeted, sale, and share, all notices given, opt into precise geo
76
- Gpc: 0,
77
- KnownChildSensitiveDataConsents: [0, 0],
78
- MspaCoveredTransaction: 2,
79
- MspaOptOutOptionMode: 0,
80
- MspaServiceProviderMode: 0,
81
- PersonalDataConsents: 0,
82
- SaleOptOut: 2,
83
- SaleOptOutNotice: 1,
84
- SensitiveDataLimitUseNotice: 1,
85
- SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
86
- SensitiveDataProcessingOptOutNotice: 1,
87
- SharingNotice: 1,
88
- SharingOptOut: 2,
89
- SharingOptOutNotice: 1,
90
- TargetedAdvertisingOptOut: 2,
91
- TargetedAdvertisingOptOutNotice: 1,
92
- Version: 1
93
- };
94
- it('should be false (consent given personalized ads / sale / share) with variety of notice and opt in', () => {
95
- const result = isConsentDenied(cd);
96
- expect(result).to.equal(false);
97
- });
98
- it('should be true (no consent) on opt out of targeted ads via TargetedAdvertisingOptOut', () => {
99
- cd.TargetedAdvertisingOptOut = 1;
100
- const result = isConsentDenied(cd);
101
- expect(result).to.equal(true);
102
- cd.TargetedAdvertisingOptOut = 2;
103
- });
104
- it('should be true (no consent) on opt out of targeted ads via no TargetedAdvertisingOptOutNotice', () => {
105
- cd.TargetedAdvertisingOptOutNotice = 2;
106
- const result = isConsentDenied(cd);
107
- expect(result).to.equal(true);
108
- cd.TargetedAdvertisingOptOutNotice = 1;
109
- });
110
- it('should be true (no consent) if TargetedAdvertisingOptOutNotice is 0 and TargetedAdvertisingOptOut is 2', () => {
111
- cd.TargetedAdvertisingOptOutNotice = 0;
112
- const result = isConsentDenied(cd);
113
- expect(result).to.equal(true);
114
- cd.TargetedAdvertisingOptOutNotice = 1;
115
- });
116
- })
117
- describe('isTransmitUfpdConsentDenied', () => {
118
- const cd = {
119
- // not covered, opt in to targeted, sale, and share, all notices given, opt into precise geo
120
- Gpc: 0,
121
- KnownChildSensitiveDataConsents: [0, 0],
122
- MspaCoveredTransaction: 2,
123
- MspaOptOutOptionMode: 0,
124
- MspaServiceProviderMode: 0,
125
- PersonalDataConsents: 0,
126
- SaleOptOut: 2,
127
- SaleOptOutNotice: 1,
128
- SensitiveDataLimitUseNotice: 1,
129
- SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
130
- SensitiveDataProcessingOptOutNotice: 1,
131
- SharingNotice: 1,
132
- SharingOptOut: 2,
133
- SharingOptOutNotice: 1,
134
- TargetedAdvertisingOptOut: 2,
135
- TargetedAdvertisingOptOutNotice: 1,
136
- Version: 1
137
- };
138
- it('should be false (consent given to add ufpd) with variety of notice and opt in', () => {
139
- const result = isTransmitUfpdConsentDenied(cd);
140
- expect(result).to.equal(false);
141
- });
142
- it('should be true (consent denied to add ufpd) if no consent to process health information', () => {
143
- cd.SensitiveDataProcessing[2] = 1;
144
- const result = isTransmitUfpdConsentDenied(cd);
145
- expect(result).to.equal(true);
146
- cd.SensitiveDataProcessing[2] = 0;
147
- });
148
- it('should be true (consent denied to add ufpd) with consent to process biometric data, as this should not be on openrtb', () => {
149
- cd.SensitiveDataProcessing[6] = 1;
150
- const result = isTransmitUfpdConsentDenied(cd);
151
- expect(result).to.equal(true);
152
- cd.SensitiveDataProcessing[6] = 1;
153
- });
154
- it('should be true (consent denied to add ufpd) without sharing notice', () => {
155
- cd.SharingNotice = 2;
156
- const result = isTransmitUfpdConsentDenied(cd);
157
- expect(result).to.equal(true);
158
- cd.SharingNotice = 1;
159
- });
160
- it('should be true (consent denied to add ufpd) with sale opt out', () => {
161
- cd.SaleOptOut = 1;
162
- const result = isTransmitUfpdConsentDenied(cd);
163
- expect(result).to.equal(true);
164
- cd.SaleOptOut = 2;
165
- });
166
- it('should be true (consent denied to add ufpd) without targeted ads opt out', () => {
167
- cd.TargetedAdvertisingOptOut = 1;
168
- const result = isTransmitUfpdConsentDenied(cd);
169
- expect(result).to.equal(true);
170
- cd.TargetedAdvertisingOptOut = 2;
171
- });
172
- it('should be true (consent denied to add ufpd) with missing sensitive data limit notice', () => {
173
- cd.SensitiveDataLimitUseNotice = 2;
174
- const result = isTransmitUfpdConsentDenied(cd);
175
- expect(result).to.equal(true);
176
- cd.SensitiveDataLimitUseNotice = 1;
177
- });
178
- })
179
3
 
180
- describe('isTransmitGeoConsentDenied', () => {
181
- const cd = {
182
- // not covered, opt out of geo
183
- Gpc: 0,
184
- KnownChildSensitiveDataConsents: [0, 0],
185
- MspaCoveredTransaction: 2,
186
- MspaOptOutOptionMode: 0,
187
- MspaServiceProviderMode: 0,
188
- PersonalDataConsents: 0,
189
- SaleOptOut: 2,
190
- SaleOptOutNotice: 1,
191
- SensitiveDataLimitUseNotice: 1,
192
- SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
193
- SensitiveDataProcessingOptOutNotice: 1,
194
- SharingNotice: 1,
195
- SharingOptOut: 2,
196
- SharingOptOutNotice: 1,
197
- TargetedAdvertisingOptOut: 2,
198
- TargetedAdvertisingOptOutNotice: 1,
199
- Version: 1
200
- };
201
- it('should be true (consent denied to add precise geo) -- sensitive flag denied', () => {
202
- const result = isTransmitGeoConsentDenied(cd);
203
- expect(result).to.equal(true);
4
+ describe('Consent interpretation', () => {
5
+ function mkConsent(flags) {
6
+ return Object.assign({
7
+ // not covered, opt in to targeted, sale, and share, all notices given, opt into precise geo
8
+ Gpc: 0,
9
+ KnownChildSensitiveDataConsents: [0, 0],
10
+ MspaCoveredTransaction: 2,
11
+ MspaOptOutOptionMode: 0,
12
+ MspaServiceProviderMode: 0,
13
+ PersonalDataConsents: 0,
14
+ SaleOptOut: 2,
15
+ SaleOptOutNotice: 1,
16
+ SensitiveDataLimitUseNotice: 1,
17
+ SensitiveDataProcessing: [0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0],
18
+ SensitiveDataProcessingOptOutNotice: 1,
19
+ SharingNotice: 1,
20
+ SharingOptOut: 2,
21
+ SharingOptOutNotice: 1,
22
+ TargetedAdvertisingOptOut: 2,
23
+ TargetedAdvertisingOptOutNotice: 1,
24
+ Version: 1
25
+ }, flags)
26
+ }
27
+ describe('isBasicConsentDenied', () => {
28
+ it('should be false (basic consent conditions pass) with variety of notice and opt in', () => {
29
+ const result = isBasicConsentDenied(mkConsent());
30
+ expect(result).to.equal(false);
31
+ });
32
+ it('should be true (basic consent conditions do not pass) with personal data consent set to true (invalid state)', () => {
33
+ const result = isBasicConsentDenied(mkConsent({
34
+ PersonalDataConsents: 2
35
+ }));
36
+ expect(result).to.equal(true);
37
+ });
38
+ it('should not deny when consent for under-13 is null', () => {
39
+ expect(isBasicConsentDenied(mkConsent({
40
+ KnownChildSensitiveDataConsents: [0, null]
41
+ }))).to.be.false;
42
+ })
204
43
  });
205
- it('should be true (consent denied to add precise geo) -- sensitive data limit usage not given', () => {
206
- cd.SensitiveDataLimitUseNotice = 0;
207
- const result = isTransmitGeoConsentDenied(cd);
208
- expect(result).to.equal(true);
209
- cd.SensitiveDataLimitUseNotice = 1;
44
+
45
+ describe('isConsentDenied', () => {
46
+ it('should be false (consent given personalized ads / sale / share) with variety of notice and opt in', () => {
47
+ const result = isConsentDenied(mkConsent());
48
+ expect(result).to.equal(false);
49
+ });
50
+ it('should be true (no consent) on opt out of targeted ads via TargetedAdvertisingOptOut', () => {
51
+ const result = isConsentDenied(mkConsent({
52
+ TargetedAdvertisingOptOut: 1
53
+ }));
54
+ expect(result).to.equal(true);
55
+ });
56
+ it('should be true (no consent) on opt out of targeted ads via no TargetedAdvertisingOptOutNotice', () => {
57
+ const result = isConsentDenied(mkConsent({
58
+ TargetedAdvertisingOptOutNotice: 2
59
+ }));
60
+ expect(result).to.equal(true);
61
+ });
62
+ it('should be true (no consent) if TargetedAdvertisingOptOutNotice is 0 and TargetedAdvertisingOptOut is 2', () => {
63
+ const result = isConsentDenied(mkConsent({
64
+ TargetedAdvertisingOptOutNotice: 0
65
+ }));
66
+ expect(result).to.equal(true);
67
+ });
68
+ it('requires also SharingNotice to accept opt-in for Sharing', () => {
69
+ expect(isConsentDenied(mkConsent({
70
+ SharingNotice: 0
71
+ }))).to.be.true;
72
+ })
210
73
  });
211
- it('should be false (consent given to add precise geo) -- sensitive position 8 (index 7) is true', () => {
212
- cd.SensitiveDataProcessing[7] = 2;
213
- const result = isTransmitGeoConsentDenied(cd);
214
- expect(result).to.equal(false);
215
- cd.SensitiveDataProcessing[7] = 1;
74
+
75
+ describe('isTransmitUfpdConsentDenied', () => {
76
+ it('should be false (consent given to add ufpd) with variety of notice and opt in', () => {
77
+ const result = isTransmitUfpdConsentDenied(mkConsent());
78
+ expect(result).to.equal(false);
79
+ });
80
+ Object.entries({
81
+ 'health information': 2,
82
+ 'biometric data': 6,
83
+ }).forEach(([t, flagNo]) => {
84
+ it(`'should be true (consent denied to add ufpd) if no consent to process ${t}'`, () => {
85
+ const consent = mkConsent();
86
+ consent.SensitiveDataProcessing[flagNo] = 1;
87
+ expect(isTransmitUfpdConsentDenied(consent)).to.be.true;
88
+ })
89
+ });
90
+
91
+ ['SharingNotice', 'SensitiveDataLimitUseNotice'].forEach(flag => {
92
+ it(`should be true (consent denied to add ufpd) without ${flag}`, () => {
93
+ expect(isTransmitUfpdConsentDenied(mkConsent({
94
+ [flag]: 2
95
+ }))).to.be.true;
96
+ })
97
+ });
98
+
99
+ ['SaleOptOut', 'TargetedAdvertisingOptOut'].forEach(flag => {
100
+ it(`should be true (consent denied to add ufpd) with ${flag}`, () => {
101
+ expect(isTransmitUfpdConsentDenied(mkConsent({
102
+ [flag]: 1
103
+ }))).to.be.true;
104
+ })
105
+ });
106
+
107
+ it('should be true (basic consent conditions do not pass) with sensitive opt in but no notice', () => {
108
+ const cd = mkConsent({
109
+ SensitiveDataLimitUseNotice: 0
110
+ });
111
+ cd.SensitiveDataProcessing[0] = 2;
112
+ expect(isTransmitUfpdConsentDenied(cd)).to.be.true;
113
+ });
114
+
115
+ it('should deny when sensitive notice is missing', () => {
116
+ const result = isTransmitUfpdConsentDenied(mkConsent({
117
+ SensitiveDataLimitUseNotice: 2
118
+ }));
119
+ expect(result).to.equal(true);
120
+ });
121
+
122
+ it('should not deny when biometric data opt-out is null', () => {
123
+ const cd = mkConsent();
124
+ cd.SensitiveDataProcessing[6] = null;
125
+ expect(isTransmitUfpdConsentDenied(cd)).to.be.false;
126
+ })
216
127
  });
217
- })
128
+
129
+ describe('isTransmitGeoConsentDenied', () => {
130
+ function geoConsent(geoOptOut, flags) {
131
+ const consent = mkConsent(flags);
132
+ consent.SensitiveDataProcessing[7] = geoOptOut;
133
+ return consent;
134
+ }
135
+ it('should be true (consent denied to add precise geo) -- sensitive flag denied', () => {
136
+ const result = isTransmitGeoConsentDenied(geoConsent(1));
137
+ expect(result).to.equal(true);
138
+ });
139
+ it('should be true (consent denied to add precise geo) -- sensitive data limit usage not given', () => {
140
+ const result = isTransmitGeoConsentDenied(geoConsent(1, {
141
+ SensitiveDataLimitUseNotice: 0
142
+ }));
143
+ expect(result).to.equal(true);
144
+ });
145
+ it('should be false (consent given to add precise geo) -- sensitive position 8 (index 7) is true', () => {
146
+ const result = isTransmitGeoConsentDenied(geoConsent(2));
147
+ expect(result).to.equal(false);
148
+ });
149
+ })
150
+ });
218
151
 
219
152
  describe('mspaRule', () => {
220
153
  it('does not apply if SID is not applicable', () => {
@@ -184,12 +184,12 @@ describe('AdgenerationAdapter', function () {
184
184
  }
185
185
  };
186
186
  const data = {
187
- banner: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&imark=1&tp=https%3A%2F%2Fexample.com`,
188
- bannerUSD: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100&currency=USD&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&imark=1&tp=https%3A%2F%2Fexample.com`,
189
- native: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=1x1&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&tp=https%3A%2F%2Fexample.com`,
190
- bannerWithHyperId: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&imark=1&tp=https%3A%2F%2Fexample.com&hyper_id=novatiqId`,
191
- bannerWithAdgextCriteoId: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&adgext_criteo_id=criteo-id-test-1234567890&imark=1&tp=https%3A%2F%2Fexample.com`,
192
- bannerWithAdgextIds: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.0&adgext_id5_id=id5-id-test-1234567890&adgext_id5_id_link_type=2&adgext_imuid=i.KrAH6ZAZTJOnH5S4N2sogA&adgext_uid2=%5Bobject%20Object%5D&gpid=%252F1111%252Fhomepage%2523300x250&uach=%7B%22source%22%3A2%2C%22platform%22%3A%7B%22brand%22%3A%22macOS%22%7D%2C%22browsers%22%3A%5B%7B%22brand%22%3A%22Chromium%22%2C%22version%22%3A%5B%22112%22%5D%7D%2C%7B%22brand%22%3A%22Google%20Chrome%22%2C%22version%22%3A%5B%22112%22%5D%7D%2C%7B%22brand%22%3A%22Not%3AA-Brand%22%2C%22version%22%3A%5B%2299%22%5D%7D%5D%2C%22mobile%22%3A0%7D&schain=%257B%2522ver%2522%253A%25221.0%2522%252C%2522complete%2522%253A1%252C%2522nodes%2522%253A%255B%257B%2522asi%2522%253A%2522indirectseller.com%2522%252C%2522sid%2522%253A%252200001%2522%252C%2522hp%2522%253A1%257D%255D%257D&imark=1&tp=https%3A%2F%2Fexample.com`,
187
+ banner: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&imark=1&tp=https%3A%2F%2Fexample.com`,
188
+ bannerUSD: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=300x250%2C320x100&currency=USD&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&imark=1&tp=https%3A%2F%2Fexample.com`,
189
+ native: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=1x1&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&tp=https%3A%2F%2Fexample.com`,
190
+ bannerWithHyperId: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&imark=1&tp=https%3A%2F%2Fexample.com&hyper_id=novatiqId`,
191
+ bannerWithAdgextCriteoId: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&adgext_criteo_id=criteo-id-test-1234567890&imark=1&tp=https%3A%2F%2Fexample.com`,
192
+ bannerWithAdgextIds: `posall=SSPLOC&id=58278&sdktype=0&hb=true&t=json3&sizes=320x100&currency=JPY&pbver=${prebid.version}&sdkname=prebidjs&adapterver=1.6.1&adgext_id5_id=id5-id-test-1234567890&adgext_id5_id_link_type=2&adgext_imuid=i.KrAH6ZAZTJOnH5S4N2sogA&adgext_uid2=%5Bobject%20Object%5D&gpid=%2F1111%2Fhomepage%23300x250&uach=%7B%22source%22%3A2%2C%22platform%22%3A%7B%22brand%22%3A%22macOS%22%7D%2C%22browsers%22%3A%5B%7B%22brand%22%3A%22Chromium%22%2C%22version%22%3A%5B%22112%22%5D%7D%2C%7B%22brand%22%3A%22Google%20Chrome%22%2C%22version%22%3A%5B%22112%22%5D%7D%2C%7B%22brand%22%3A%22Not%3AA-Brand%22%2C%22version%22%3A%5B%2299%22%5D%7D%5D%2C%22mobile%22%3A0%7D&schain=%7B%22ver%22%3A%221.0%22%2C%22complete%22%3A1%2C%22nodes%22%3A%5B%7B%22asi%22%3A%22indirectseller.com%22%2C%22sid%22%3A%2200001%22%2C%22hp%22%3A1%7D%5D%7D&imark=1&tp=https%3A%2F%2Fexample.com`,
193
193
  };
194
194
  it('sends bid request to ENDPOINT via GET', function () {
195
195
  const request = spec.buildRequests(bidRequests, bidderRequest)[0];
@@ -1093,7 +1093,18 @@ describe('AppNexusAdapter', function () {
1093
1093
  expect(payload.tags[0].use_pmt_rule).to.equal(true);
1094
1094
  });
1095
1095
 
1096
- it('should add gpid to the request', function () {
1096
+ it('should add preferred gpid to the request', function () {
1097
+ let testGpid = '/12345/my-gpt-tag-0';
1098
+ let bidRequest = deepClone(bidRequests[0]);
1099
+ bidRequest.ortb2Imp = { ext: { gpid: testGpid } };
1100
+
1101
+ const request = spec.buildRequests([bidRequest]);
1102
+ const payload = JSON.parse(request.data);
1103
+
1104
+ expect(payload.tags[0].gpid).to.exist.and.equal(testGpid)
1105
+ });
1106
+
1107
+ it('should add backup gpid to the request', function () {
1097
1108
  let testGpid = '/12345/my-gpt-tag-0';
1098
1109
  let bidRequest = deepClone(bidRequests[0]);
1099
1110
  bidRequest.ortb2Imp = { ext: { data: { pbadslot: testGpid } } };
@@ -9,11 +9,12 @@ import {
9
9
  } from 'modules/criteoBidAdapter.js';
10
10
  import * as utils from 'src/utils.js';
11
11
  import * as refererDetection from 'src/refererDetection.js';
12
+ import * as ajax from 'src/ajax.js';
12
13
  import { config } from '../../../src/config.js';
13
14
  import { BANNER, NATIVE, VIDEO } from '../../../src/mediaTypes.js';
14
15
 
15
16
  describe('The Criteo bidding adapter', function () {
16
- let utilsMock, sandbox;
17
+ let utilsMock, sandbox, ajaxStub;
17
18
 
18
19
  beforeEach(function () {
19
20
  $$PREBID_GLOBAL$$.bidderSettings = {
@@ -26,6 +27,7 @@ describe('The Criteo bidding adapter', function () {
26
27
  utilsMock = sinon.mock(utils);
27
28
 
28
29
  sandbox = sinon.sandbox.create();
30
+ ajaxStub = sandbox.stub(ajax, 'ajax');
29
31
  });
30
32
 
31
33
  afterEach(function () {
@@ -33,6 +35,7 @@ describe('The Criteo bidding adapter', function () {
33
35
  global.Criteo = undefined;
34
36
  utilsMock.restore();
35
37
  sandbox.restore();
38
+ ajaxStub.restore();
36
39
  });
37
40
 
38
41
  describe('getUserSyncs', function () {
@@ -56,7 +59,9 @@ describe('The Criteo bidding adapter', function () {
56
59
  cookiesAreEnabledStub,
57
60
  localStorageIsEnabledStub,
58
61
  getCookieStub,
59
- getDataFromLocalStorageStub;
62
+ setCookieStub,
63
+ getDataFromLocalStorageStub,
64
+ removeDataFromLocalStorageStub;
60
65
 
61
66
  beforeEach(function () {
62
67
  getConfigStub = sinon.stub(config, 'getConfig');
@@ -75,8 +80,10 @@ describe('The Criteo bidding adapter', function () {
75
80
  localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled');
76
81
  localStorageIsEnabledStub.returns(true);
77
82
 
78
- getCookieStub = sinon.stub(storage, 'getCookie')
83
+ getCookieStub = sinon.stub(storage, 'getCookie');
84
+ setCookieStub = sinon.stub(storage, 'setCookie');
79
85
  getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
86
+ removeDataFromLocalStorageStub = sinon.stub(storage, 'removeDataFromLocalStorage');
80
87
  });
81
88
 
82
89
  afterEach(function () {
@@ -86,7 +93,9 @@ describe('The Criteo bidding adapter', function () {
86
93
  cookiesAreEnabledStub.restore();
87
94
  localStorageIsEnabledStub.restore();
88
95
  getCookieStub.restore();
96
+ setCookieStub.restore();
89
97
  getDataFromLocalStorageStub.restore();
98
+ removeDataFromLocalStorageStub.restore();
90
99
  });
91
100
 
92
101
  it('should not trigger sync if publisher is using fast bid', function () {
@@ -198,6 +207,25 @@ describe('The Criteo bidding adapter', function () {
198
207
  url: `https://gum.criteo.com/syncframe?origin=criteoPrebidAdapter&topUrl=www.abc.com&us_privacy=ABC#${JSON.stringify(expectedHash).replace(/"/g, '%22')}`
199
208
  }]);
200
209
  });
210
+
211
+ it('should delete user data when calling onDataDeletionRequest', () => {
212
+ const cookieData = {
213
+ 'cto_bundle': 'a'
214
+ };
215
+ const lsData = {
216
+ 'cto_bundle': 'a'
217
+ }
218
+ getCookieStub.callsFake(cookieName => cookieData[cookieName]);
219
+ setCookieStub.callsFake((cookieName, value, expires) => cookieData[cookieName] = value);
220
+ removeDataFromLocalStorageStub.callsFake(name => lsData[name] = '');
221
+ spec.onDataDeletionRequest([]);
222
+ expect(getCookieStub.calledOnce).to.equal(true);
223
+ expect(setCookieStub.calledOnce).to.equal(true);
224
+ expect(removeDataFromLocalStorageStub.calledOnce).to.equal(true);
225
+ expect(cookieData.cto_bundle).to.equal('');
226
+ expect(lsData.cto_bundle).to.equal('');
227
+ expect(ajaxStub.calledOnce).to.equal(true);
228
+ });
201
229
  });
202
230
 
203
231
  describe('isBidRequestValid', function () {
@@ -293,4 +293,51 @@ describe('C-WIRE bid adapter', () => {
293
293
  expect(bids[0].ad).to.exist;
294
294
  })
295
295
  });
296
+
297
+ describe('add user-syncs', function () {
298
+ it('empty user-syncs if no consent given', function () {
299
+ const userSyncs = spec.getUserSyncs({}, {}, {}, {});
300
+
301
+ expect(userSyncs).to.be.empty
302
+ })
303
+ it('empty user-syncs if no syncOption enabled', function () {
304
+ let gdprConsent = {
305
+ vendorData: {
306
+ purpose: {
307
+ consents: 1
308
+ }
309
+ }};
310
+ const userSyncs = spec.getUserSyncs({}, {}, gdprConsent, {});
311
+
312
+ expect(userSyncs).to.be.empty
313
+ })
314
+
315
+ it('user-syncs with enabled pixel option', function () {
316
+ let gdprConsent = {
317
+ vendorData: {
318
+ purpose: {
319
+ consents: 1
320
+ }
321
+ }};
322
+ let synOptions = {pixelEnabled: true, iframeEnabled: true};
323
+ const userSyncs = spec.getUserSyncs(synOptions, {}, gdprConsent, {});
324
+
325
+ expect(userSyncs[0].type).to.equal('image');
326
+ expect(userSyncs[0].url).to.equal('https://ib.adnxs.com/getuid?https://prebid.cwi.re/v1/cookiesync?xandrId=$UID');
327
+ })
328
+
329
+ it('user-syncs with enabled iframe option', function () {
330
+ let gdprConsent = {
331
+ vendorData: {
332
+ purpose: {
333
+ consents: 1
334
+ }
335
+ }};
336
+ let synOptions = {iframeEnabled: true};
337
+ const userSyncs = spec.getUserSyncs(synOptions, {}, gdprConsent, {});
338
+
339
+ expect(userSyncs[0].type).to.equal('iframe');
340
+ expect(userSyncs[0].url).to.equal('https://ib.adnxs.com/getuid?https://prebid.cwi.re/v1/cookiesync?xandrId=$UID');
341
+ })
342
+ })
296
343
  });
@@ -1667,6 +1667,12 @@ describe('newspassid Adapter', function () {
1667
1667
  expect(result[0]['price']).to.equal(0.9);
1668
1668
  expect(result[0]['adserverTargeting']['np_npappnexus_adId']).to.equal('2899ec066a91ff8-0-np-1');
1669
1669
  });
1670
+ it('should add np_auc_id (response id value)', function () {
1671
+ const request = spec.buildRequests(validBidRequests, validBidderRequest);
1672
+ let validres = JSON.parse(JSON.stringify(validBidResponse1adWith2Bidders));
1673
+ const result = spec.interpretResponse(validres, request);
1674
+ expect(utils.deepAccess(result[0].adserverTargeting, 'np_auc_id')).to.equal(validBidResponse1adWith2Bidders.body.id);
1675
+ });
1670
1676
  it('should correctly process an auction with 2 adunits & multiple bidders one of which bids for both adslots', function() {
1671
1677
  let validres = JSON.parse(JSON.stringify(multiResponse1));
1672
1678
  let request = spec.buildRequests(multiRequest1, multiBidderRequest1.bidderRequest);