prebid.js 7.20.0 → 7.22.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 (189) hide show
  1. package/dist/1plusXRtdProvider.js +1 -1
  2. package/dist/33acrossBidAdapter.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/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adtrgtmeBidAdapter.js +1 -1
  8. package/dist/adxcgBidAdapter.js +1 -1
  9. package/dist/adyoulikeBidAdapter.js +1 -1
  10. package/dist/ajaBidAdapter.js +1 -1
  11. package/dist/amxBidAdapter.js +1 -1
  12. package/dist/amxIdSystem.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/audiencerunBidAdapter.js +1 -1
  17. package/dist/axonixBidAdapter.js +1 -1
  18. package/dist/bidglassBidAdapter.js +1 -1
  19. package/dist/big-richmediaBidAdapter.js +1 -1
  20. package/dist/bluebillywigBidAdapter.js +1 -1
  21. package/dist/bridgewellBidAdapter.js +1 -1
  22. package/dist/brightMountainMediaBidAdapter.js +1 -1
  23. package/dist/brightcomBidAdapter.js +1 -1
  24. package/dist/carodaBidAdapter.js +1 -1
  25. package/dist/concertBidAdapter.js +1 -1
  26. package/dist/connectadBidAdapter.js +1 -1
  27. package/dist/consumableBidAdapter.js +1 -1
  28. package/dist/conversantBidAdapter.js +1 -1
  29. package/dist/craftBidAdapter.js +1 -1
  30. package/dist/criteoBidAdapter.js +1 -1
  31. package/dist/dacIdSystem.js +1 -1
  32. package/dist/dspxBidAdapter.js +1 -1
  33. package/dist/eplanningBidAdapter.js +1 -1
  34. package/dist/finativeBidAdapter.js +1 -1
  35. package/dist/freewheel-sspBidAdapter.js +1 -1
  36. package/dist/ftrackIdSystem.js +1 -1
  37. package/dist/glimpseBidAdapter.js +1 -1
  38. package/dist/gmosspBidAdapter.js +1 -1
  39. package/dist/goldbachBidAdapter.js +1 -1
  40. package/dist/gridBidAdapter.js +1 -1
  41. package/dist/gridNMBidAdapter.js +1 -1
  42. package/dist/gumgumBidAdapter.js +1 -1
  43. package/dist/h12mediaBidAdapter.js +1 -1
  44. package/dist/iasRtdProvider.js +1 -1
  45. package/dist/id5IdSystem.js +1 -1
  46. package/dist/impactifyBidAdapter.js +1 -1
  47. package/dist/improvedigitalBidAdapter.js +1 -1
  48. package/dist/inmarBidAdapter.js +1 -1
  49. package/dist/insticatorBidAdapter.js +1 -1
  50. package/dist/ixBidAdapter.js +1 -1
  51. package/dist/jixieBidAdapter.js +1 -1
  52. package/dist/justpremiumBidAdapter.js +1 -1
  53. package/dist/konduitAnalyticsAdapter.js +1 -1
  54. package/dist/kueezBidAdapter.js +1 -1
  55. package/dist/lassoBidAdapter.js +1 -1
  56. package/dist/lifestreetBidAdapter.js +1 -1
  57. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  58. package/dist/logicadBidAdapter.js +1 -1
  59. package/dist/loglyliftBidAdapter.js +1 -1
  60. package/dist/magniteAnalyticsAdapter.js +1 -1
  61. package/dist/malltvAnalyticsAdapter.js +1 -1
  62. package/dist/marsmediaBidAdapter.js +1 -1
  63. package/dist/mediafuseBidAdapter.js +1 -1
  64. package/dist/mediakeysBidAdapter.js +1 -1
  65. package/dist/medianetAnalyticsAdapter.js +1 -1
  66. package/dist/medianetBidAdapter.js +1 -1
  67. package/dist/mediasquareBidAdapter.js +1 -1
  68. package/dist/mgidBidAdapter.js +1 -1
  69. package/dist/minutemediaBidAdapter.js +1 -1
  70. package/dist/not-for-prod/prebid.js +127 -127
  71. package/dist/oguryBidAdapter.js +1 -1
  72. package/dist/onetagBidAdapter.js +1 -1
  73. package/dist/ooloAnalyticsAdapter.js +1 -1
  74. package/dist/outbrainBidAdapter.js +1 -1
  75. package/dist/parrableIdSystem.js +1 -1
  76. package/dist/pixfutureBidAdapter.js +1 -1
  77. package/dist/prebid-core.js +1 -1
  78. package/dist/prebidServerBidAdapter.js +1 -1
  79. package/dist/publinkIdSystem.js +1 -1
  80. package/dist/pubmaticBidAdapter.js +1 -1
  81. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  82. package/dist/pubwiseBidAdapter.js +1 -1
  83. package/dist/pulsepointBidAdapter.js +1 -1
  84. package/dist/pxyzBidAdapter.js +1 -1
  85. package/dist/quantcastBidAdapter.js +1 -1
  86. package/dist/readpeakBidAdapter.js +1 -1
  87. package/dist/relaidoBidAdapter.js +1 -1
  88. package/dist/rhythmoneBidAdapter.js +1 -1
  89. package/dist/riseBidAdapter.js +1 -1
  90. package/dist/rubiconAnalyticsAdapter.js +1 -1
  91. package/dist/rubiconBidAdapter.js +1 -1
  92. package/dist/seedingAllianceBidAdapter.js +1 -1
  93. package/dist/seedtagBidAdapter.js +1 -1
  94. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  95. package/dist/sharethroughBidAdapter.js +1 -1
  96. package/dist/shinezBidAdapter.js +1 -1
  97. package/dist/smaatoBidAdapter.js +1 -1
  98. package/dist/smartadserverBidAdapter.js +1 -1
  99. package/dist/smartxBidAdapter.js +1 -1
  100. package/dist/smilewantedBidAdapter.js +1 -1
  101. package/dist/sonobiBidAdapter.js +1 -1
  102. package/dist/sovrnAnalyticsAdapter.js +1 -1
  103. package/dist/sovrnBidAdapter.js +1 -1
  104. package/dist/sspBCBidAdapter.js +1 -1
  105. package/dist/sublimeBidAdapter.js +1 -1
  106. package/dist/synacormediaBidAdapter.js +1 -1
  107. package/dist/targetVideoBidAdapter.js +1 -1
  108. package/dist/teadsBidAdapter.js +1 -1
  109. package/dist/trionBidAdapter.js +1 -1
  110. package/dist/tripleliftBidAdapter.js +1 -1
  111. package/dist/ttdBidAdapter.js +1 -1
  112. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  113. package/dist/underdogmediaBidAdapter.js +1 -1
  114. package/dist/undertoneBidAdapter.js +1 -1
  115. package/dist/userId.js +1 -1
  116. package/dist/vidazooBidAdapter.js +1 -1
  117. package/dist/videobyteBidAdapter.js +1 -1
  118. package/dist/visxBidAdapter.js +1 -1
  119. package/dist/vuukleBidAdapter.js +1 -1
  120. package/dist/weboramaRtdProvider.js +1 -1
  121. package/dist/widespaceBidAdapter.js +1 -1
  122. package/dist/winrBidAdapter.js +1 -1
  123. package/dist/yahoosspBidAdapter.js +1 -1
  124. package/dist/yieldmoBidAdapter.js +1 -1
  125. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  126. package/dist/yieldoneBidAdapter.js +1 -1
  127. package/integrationExamples/gpt/weboramaRtdProvider_example.html +10 -51
  128. package/modules/1plusXRtdProvider.js +32 -5
  129. package/modules/33acrossBidAdapter.js +18 -11
  130. package/modules/adyoulikeBidAdapter.js +12 -6
  131. package/modules/asoBidAdapter.js +11 -6
  132. package/modules/asoBidAdapter.md +5 -6
  133. package/modules/brightcomBidAdapter.js +30 -10
  134. package/modules/dacIdSystem.js +145 -27
  135. package/modules/dacIdSystem.md +7 -2
  136. package/modules/fledgeForGpt.md +101 -23
  137. package/modules/freewheel-sspBidAdapter.js +48 -7
  138. package/modules/freewheel-sspBidAdapter.md +1 -1
  139. package/modules/ftrackIdSystem.js +28 -9
  140. package/modules/gridBidAdapter.js +1 -0
  141. package/modules/iasRtdProvider.js +21 -6
  142. package/modules/iasRtdProvider.md +1 -1
  143. package/modules/ixBidAdapter.js +9 -4
  144. package/modules/medianetAnalyticsAdapter.js +26 -22
  145. package/modules/medianetBidAdapter.js +5 -1
  146. package/modules/mediasquareBidAdapter.js +42 -3
  147. package/modules/mgidBidAdapter.js +8 -1
  148. package/modules/oguryBidAdapter.js +6 -2
  149. package/modules/prebidServerBidAdapter/index.js +1 -1
  150. package/modules/pubmaticBidAdapter.js +27 -3
  151. package/modules/pubwiseBidAdapter.js +14 -12
  152. package/modules/pulsepointBidAdapter.js +11 -6
  153. package/modules/smaatoBidAdapter.js +54 -5
  154. package/modules/smaatoBidAdapter.md +78 -0
  155. package/modules/teadsBidAdapter.js +26 -8
  156. package/modules/ttdBidAdapter.js +8 -0
  157. package/modules/userId/eids.js +7 -11
  158. package/modules/weboramaRtdProvider.js +800 -643
  159. package/modules/weboramaRtdProvider.md +32 -0
  160. package/modules/yieldoneBidAdapter.js +7 -4
  161. package/package.json +3 -3
  162. package/src/adapters/bidderFactory.js +11 -9
  163. package/src/auction.js +3 -3
  164. package/test/spec/auctionmanager_spec.js +29 -20
  165. package/test/spec/modules/1plusXRtdProvider_spec.js +30 -14
  166. package/test/spec/modules/33acrossBidAdapter_spec.js +44 -1
  167. package/test/spec/modules/adyoulikeBidAdapter_spec.js +1 -1
  168. package/test/spec/modules/asoBidAdapter_spec.js +2 -2
  169. package/test/spec/modules/brightcomBidAdapter_spec.js +94 -1
  170. package/test/spec/modules/dacIdSystem_spec.js +93 -11
  171. package/test/spec/modules/eids_spec.js +11 -7
  172. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +25 -4
  173. package/test/spec/modules/ftrackIdSystem_spec.js +200 -90
  174. package/test/spec/modules/iasRtdProvider_spec.js +57 -1
  175. package/test/spec/modules/ixBidAdapter_spec.js +12 -0
  176. package/test/spec/modules/medianetAnalyticsAdapter_spec.js +50 -8
  177. package/test/spec/modules/medianetBidAdapter_spec.js +76 -0
  178. package/test/spec/modules/mediasquareBidAdapter_spec.js +4 -2
  179. package/test/spec/modules/mgidBidAdapter_spec.js +50 -0
  180. package/test/spec/modules/oguryBidAdapter_spec.js +33 -17
  181. package/test/spec/modules/prebidServerBidAdapter_spec.js +24 -0
  182. package/test/spec/modules/pubmaticBidAdapter_spec.js +60 -5
  183. package/test/spec/modules/pubwiseBidAdapter_spec.js +6 -4
  184. package/test/spec/modules/pulsepointBidAdapter_spec.js +123 -0
  185. package/test/spec/modules/smaatoBidAdapter_spec.js +307 -36
  186. package/test/spec/modules/teadsBidAdapter_spec.js +119 -6
  187. package/test/spec/modules/weboramaRtdProvider_spec.js +382 -0
  188. package/test/spec/modules/yieldoneBidAdapter_spec.js +2 -3
  189. package/test/spec/unit/core/bidderFactory_spec.js +0 -4
@@ -7,83 +7,98 @@
7
7
  * @requires module:modules/realTimeData
8
8
  */
9
9
 
10
- /**
10
+ /** profile metadata
11
11
  * @typedef dataCallbackMetadata
12
- * @property {Boolean} user if true it is user-centric data
13
- * @property {String} source describe the source of data, if "contextual" or "wam"
14
- * @property {Boolean} isDefault if true it the default profile defined in the configuration
12
+ * @property {boolean} user if true it is user-centric data
13
+ * @property {string} source describe the source of data, if 'contextual' or 'wam'
14
+ * @property {boolean} isDefault if true it the default profile defined in the configuration
15
+ */
16
+
17
+ /** profile from contextual, wam or sfbx
18
+ * @typedef {Object.<string,string[]>} Profile
15
19
  */
16
20
 
17
21
  /** onData callback type
18
22
  * @callback dataCallback
19
- * @param {Object} data profile data
23
+ * @param {Profile} data profile data
20
24
  * @param {dataCallbackMetadata} meta metadata
21
25
  * @returns {void}
22
26
  */
23
27
 
24
28
  /** setPrebidTargeting callback type
25
29
  * @callback setPrebidTargetingCallback
26
- * @param {String} adUnitCode
27
- * @param {Object} data
30
+ * @param {string} adUnitCode
31
+ * @param {Profile} data
28
32
  * @param {dataCallbackMetadata} metadata
29
- * @returns {Boolean}
33
+ * @returns {boolean}
30
34
  */
31
35
 
32
36
  /** sendToBidders callback type
33
37
  * @callback sendToBiddersCallback
34
38
  * @param {Object} bid
35
- * @param {String} adUnitCode
36
- * @param {Object} data
39
+ * @param {string} adUnitCode
40
+ * @param {Profile} data
37
41
  * @param {dataCallbackMetadata} metadata
38
- * @returns {Boolean}
42
+ * @returns {boolean}
39
43
  */
40
44
 
41
45
  /**
42
46
  * @typedef {Object} ModuleParams
43
- * @property {?setPrebidTargetingCallback|?Boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
44
- * @property {?sendToBiddersCallback|?Boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
47
+ * @property {?setPrebidTargetingCallback|?boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
48
+ * @property {?sendToBiddersCallback|?boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
45
49
  * @property {?dataCallback} onData callback
46
50
  * @property {?WeboCtxConf} weboCtxConf site-centric contextual configuration
47
51
  * @property {?WeboUserDataConf} weboUserDataConf user-centric wam configuration
48
52
  * @property {?SfbxLiteDataConf} sfbxLiteDataConf site-centric lite configuration
49
53
  */
50
54
 
55
+ /**
56
+ * @callback assetIDcallback
57
+ * @returns {string} should return asset identifier using the form datasource:docId
58
+ */
51
59
  /**
52
60
  * @typedef {Object} WeboCtxConf
53
61
  * @property {string} token required token to be used on bigsea contextual API requests
54
62
  * @property {?string} targetURL specify the target url instead use the referer
55
- * @property {?setPrebidTargetingCallback|?Boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
56
- * @property {?sendToBiddersCallback|?Boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
63
+ * @property {?assetIDcallback|?string} assetID specifies the assert identifier using the form datasource:docId or via callback
64
+ * @property {?setPrebidTargetingCallback|?boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
65
+ * @property {?sendToBiddersCallback|?boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
57
66
  * @property {?dataCallback} onData callback
58
- * @property {?object} defaultProfile to be used if the profile is not found
59
- * @property {?Boolean} enabled if false, will ignore this configuration
67
+ * @property {?Profile} defaultProfile to be used if the profile is not found
68
+ * @property {?boolean} enabled if false, will ignore this configuration
60
69
  * @property {?string} baseURLProfileAPI to be used to point to a different domain than ctx.weborama.com
61
70
  */
62
71
 
63
72
  /**
64
73
  * @typedef {Object} WeboUserDataConf
65
74
  * @property {?number} accountId wam account id
66
- * @property {?setPrebidTargetingCallback|?Boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
67
- * @property {?sendToBiddersCallback|?Boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
68
- * @property {?object} defaultProfile to be used if the profile is not found
75
+ * @property {?setPrebidTargetingCallback|?boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
76
+ * @property {?sendToBiddersCallback|?boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
77
+ * @property {?Profile} defaultProfile to be used if the profile is not found
69
78
  * @property {?dataCallback} onData callback
70
79
  * @property {?string} localStorageProfileKey can be used to customize the local storage key (default is 'webo_wam2gam_entry')
71
- * @property {?Boolean} enabled if false, will ignore this configuration
80
+ * @property {?boolean} enabled if false, will ignore this configuration
72
81
  */
73
82
 
74
83
  /**
75
84
  * @typedef {Object} SfbxLiteDataConf
76
- * @property {?setPrebidTargetingCallback|?Boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
77
- * @property {?sendToBiddersCallback|?Boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
78
- * @property {?object} defaultProfile to be used if the profile is not found
85
+ * @property {?setPrebidTargetingCallback|?boolean|?Object} setPrebidTargeting if true, will set the GAM targeting (default undefined)
86
+ * @property {?sendToBiddersCallback|?boolean|?Object} sendToBidders if true, will send the contextual profile to all bidders, else expects a list of allowed bidders (default undefined)
87
+ * @property {?Profile} defaultProfile to be used if the profile is not found
79
88
  * @property {?dataCallback} onData callback
80
89
  * @property {?string} localStorageProfileKey can be used to customize the local storage key (default is '_lite')
81
- * @property {?Boolean} enabled if false, will ignore this configuration
90
+ * @property {?boolean} enabled if false, will ignore this configuration
82
91
  */
92
+
93
+ /** common configuration between contextual, wam and sfbx
94
+ * @typedef {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} CommonConf
95
+ */
96
+
83
97
  import {
84
98
  getGlobal
85
99
  } from '../src/prebidGlobal.js';
86
100
  import {
101
+ deepClone,
87
102
  deepSetValue,
88
103
  isEmpty,
89
104
  isFn,
@@ -93,8 +108,9 @@ import {
93
108
  isStr,
94
109
  isBoolean,
95
110
  isPlainObject,
96
- deepClone,
97
- tryAppendQueryString, mergeDeep, logWarn
111
+ logWarn,
112
+ mergeDeep,
113
+ tryAppendQueryString
98
114
  } from '../src/utils.js';
99
115
  import {
100
116
  submodule
@@ -127,431 +143,869 @@ const WEBO_CTX_CONF_SECTION = 'weboCtxConf';
127
143
  const WEBO_USER_DATA_CONF_SECTION = 'weboUserDataConf';
128
144
  /** @type {string} */
129
145
  const SFBX_LITE_DATA_CONF_SECTION = 'sfbxLiteDataConf';
130
-
146
+ /** @type {string} */
147
+ const WEBO_CTX_SOURCE_LABEL = 'contextual';
148
+ /** @type {string} */
149
+ const WEBO_USER_DATA_SOURCE_LABEL = 'wam';
150
+ /** @type {string} */
151
+ const SFBX_LITE_DATA_SOURCE_LABEL = 'lite';
131
152
  /** @type {number} */
132
153
  const GVLID = 284;
133
- /** @type {?Object} */
154
+
134
155
  export const storage = getStorageManager({
135
156
  gvlid: GVLID,
136
157
  moduleName: SUBMODULE_NAME
137
158
  });
138
159
 
139
- /** @type {null|Object} */
140
- let _weboContextualProfile = null;
160
+ /**
161
+ * @typedef {Object} Component
162
+ * @property {boolean} initialized
163
+ * @property {?Profile} data
164
+ * @property {boolean} user if true it is user-centric data
165
+ * @property {string} source describe the source of data, if 'contextual' or 'wam'
166
+ * @property {buildProfileHandlerCallbackBuilder} callbackBuilder
167
+ */
168
+
169
+ /**
170
+ * @typedef {Object} Components
171
+ * @property {Component} WeboCtx
172
+ * @property {Component} WeboUserData
173
+ * @property {Component} SfbxLiteData
174
+ */
141
175
 
142
- /** @type {Boolean} */
143
- let _weboCtxInitialized = false;
176
+ /**
177
+ * @classdesc Weborama Real Time Data Provider
178
+ * @class
179
+ */
180
+ class WeboramaRtdProvider {
181
+ #components;
182
+ name = SUBMODULE_NAME;
183
+ /**
184
+ * @param {Components} components
185
+ */
186
+ constructor(components) {
187
+ this.#components = components;
188
+ }
189
+ /** Initialize module
190
+ * @method
191
+ * @param {Object} moduleConfig
192
+ * @param {?ModuleParams} moduleConfig.params
193
+ * @return {boolean} true if module was initialized with success
194
+ */
195
+ init(moduleConfig) {
196
+ /** @type {Object} */
197
+ const globalDefaults = {
198
+ setPrebidTargeting: true,
199
+ sendToBidders: true,
200
+ onData: () => {
201
+ /* do nothing */
202
+ }
203
+ };
204
+ /** @type {ModuleParams} */
205
+ const moduleParams = Object.assign({}, globalDefaults, moduleConfig?.params || {});
144
206
 
145
- /** @type {?Object} */
146
- let _weboUserDataUserProfile = null;
207
+ // reset profiles
147
208
 
148
- /** @type {Boolean} */
149
- let _weboUserDataInitialized = false;
209
+ this.#components.WeboCtx.data = null;
210
+ this.#components.WeboUserData.data = null;
211
+ this.#components.SfbxLiteData.data = null;
150
212
 
151
- /** @type {?Object} */
152
- let _sfbxLiteDataProfile = null;
213
+ this.#components.WeboCtx.initialized = this.#initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, 'token');
214
+ this.#components.WeboUserData.initialized = this.#initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION);
215
+ this.#components.SfbxLiteData.initialized = this.#initSubSection(moduleParams, SFBX_LITE_DATA_CONF_SECTION);
153
216
 
154
- /** @type {Boolean} */
155
- let _sfbxLiteDataInitialized = false;
217
+ return Object.values(this.#components).some((c) => c.initialized);
218
+ }
156
219
 
157
- /** Initialize module
158
- * @param {object} moduleConfig
159
- * @return {Boolean} true if module was initialized with success
160
- */
161
- function init(moduleConfig) {
162
- const moduleParams = moduleConfig?.params || {};
220
+ /** function that will allow RTD sub-modules to modify the AdUnit object for each auction
221
+ * @method
222
+ * @param {Object} reqBidsConfigObj
223
+ * @param {doneCallback} onDone
224
+ * @param {Object} moduleConfig
225
+ * @param {?ModuleParams} moduleConfig.params
226
+ * @returns {void}
227
+ */
228
+ getBidRequestData(reqBidsConfigObj, onDone, moduleConfig) {
229
+ /** @type {ModuleParams} */
230
+ const moduleParams = moduleConfig?.params || {};
231
+
232
+ if (!this.#components.WeboCtx.initialized) {
233
+ this.#handleBidRequestData(reqBidsConfigObj, moduleParams);
163
234
 
164
- _weboContextualProfile = null;
165
- _weboUserDataUserProfile = null;
166
- _sfbxLiteDataProfile = null;
235
+ onDone();
167
236
 
168
- _weboCtxInitialized = initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, 'token');
169
- _weboUserDataInitialized = initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION);
170
- _sfbxLiteDataInitialized = initSubSection(moduleParams, SFBX_LITE_DATA_CONF_SECTION);
237
+ return;
238
+ }
171
239
 
172
- return _weboCtxInitialized || _weboUserDataInitialized || _sfbxLiteDataInitialized;
173
- }
240
+ /** @type {WeboCtxConf} */
241
+ const weboCtxConf = moduleParams.weboCtxConf || {};
174
242
 
175
- /** Initialize subsection module
176
- * @param {Object} moduleParams
177
- * @param {string} subSection subsection name to initialize
178
- * @param {[]string} requiredFields
179
- * @return {Boolean} true if module subsection was initialized with success
180
- */
181
- function initSubSection(moduleParams, subSection, ...requiredFields) {
182
- const weboSectionConf = moduleParams[subSection] || {enabled: false};
243
+ this.#fetchContextualProfile(weboCtxConf, (data) => {
244
+ logMessage('fetchContextualProfile on getBidRequestData is done');
183
245
 
184
- if (weboSectionConf.enabled === false) {
185
- delete moduleParams[subSection];
246
+ this.#setWeboContextualProfile(data);
247
+ }, () => {
248
+ this.#handleBidRequestData(reqBidsConfigObj, moduleParams);
186
249
 
187
- return false;
250
+ onDone();
251
+ });
188
252
  }
189
253
 
190
- requiredFields ||= [];
254
+ /** function that provides ad server targeting data to RTD-core
255
+ * @method
256
+ * @param {string[]} adUnitsCodes
257
+ * @param {Object} moduleConfig
258
+ * @param {?ModuleParams} moduleConfig.params
259
+ * @returns {Object} target data
260
+ */
261
+ getTargetingData(adUnitsCodes, moduleConfig) {
262
+ /** @type {ModuleParams} */
263
+ const moduleParams = moduleConfig?.params || {};
264
+
265
+ const profileHandlers = this.#buildProfileHandlers(moduleParams);
266
+
267
+ if (isEmpty(profileHandlers)) {
268
+ logMessage('no data to set targeting');
269
+ return {};
270
+ }
191
271
 
192
- try {
193
- normalizeConf(moduleParams, weboSectionConf);
272
+ try {
273
+ return adUnitsCodes.reduce((data, adUnitCode) => {
274
+ data[adUnitCode] = profileHandlers.reduce((targeting, ph) => {
275
+ // logMessage(`check if should set targeting for adunit '${adUnitCode}'`);
276
+ const [data, metadata] = this.#copyDataAndMetadata(ph);
277
+ if (ph.setTargeting(adUnitCode, data, metadata)) {
278
+ // logMessage(`set targeting for adunit '${adUnitCode}', source '${metadata.source}'`);
279
+
280
+ mergeDeep(targeting, data);
281
+ }
194
282
 
195
- requiredFields.forEach(field => {
196
- if (!weboSectionConf[field]) {
197
- throw `missing required field "{field}" on {section}`;
198
- }
199
- });
200
- } catch (e) {
201
- logError(`unable to initialize: error on ${subSection} configuration: ${e}`);
202
- return false;
203
- }
283
+ return targeting;
284
+ }, {});
204
285
 
205
- logMessage(`weborama ${subSection} initialized with success`);
286
+ return data;
287
+ }, {});
288
+ } catch (e) {
289
+ logError(`unable to format weborama rtd targeting data:`, e);
206
290
 
207
- return true;
208
- }
291
+ return {};
292
+ }
293
+ }
209
294
 
210
- /** @type {Object} */
211
- const globalDefaults = {
212
- setPrebidTargeting: true,
213
- sendToBidders: true,
214
- onData: () => {
215
- /* do nothing */ },
216
- };
295
+ /** Initialize subsection module
296
+ * @method
297
+ * @private
298
+ * @param {ModuleParams} moduleParams
299
+ * @param {string} subSection subsection name to initialize
300
+ * @param {string[]} requiredFields
301
+ * @return {boolean} true if module subsection was initialized with success
302
+ */
303
+ #initSubSection(moduleParams, subSection, ...requiredFields) {
304
+ /** @type {CommonConf} */
305
+ const weboSectionConf = moduleParams[subSection] || { enabled: false };
306
+
307
+ if (weboSectionConf.enabled === false) {
308
+ delete moduleParams[subSection];
217
309
 
218
- /** normalize submodule configuration
219
- * @param {ModuleParams} moduleParams
220
- * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
221
- * @return {void}
222
- */
223
- function normalizeConf(moduleParams, submoduleParams) {
224
- // handle defaults
225
- Object.entries(globalDefaults).forEach(([propertyName, globalDefaultValue]) => {
226
- if (!submoduleParams.hasOwnProperty(propertyName)) {
227
- const hasModuleParam = moduleParams.hasOwnProperty(propertyName);
228
- submoduleParams[propertyName] = (hasModuleParam) ? moduleParams[propertyName] : globalDefaultValue;
310
+ return false;
229
311
  }
230
- })
231
312
 
232
- // handle setPrebidTargeting
233
- coerceSetPrebidTargeting(submoduleParams)
313
+ try {
314
+ this.#normalizeConf(moduleParams, weboSectionConf);
234
315
 
235
- // handle sendToBidders
236
- coerceSendToBidders(submoduleParams)
316
+ requiredFields.forEach(field => {
317
+ if (!(field in weboSectionConf)) {
318
+ throw `missing required field '${field}''`;
319
+ }
320
+ });
321
+ } catch (e) {
322
+ logError(`unable to initialize: error on ${subSection} configuration:`, e);
323
+ return false;
324
+ }
325
+
326
+ logMessage(`weborama ${subSection} initialized with success`);
237
327
 
238
- if (!isFn(submoduleParams.onData)) {
239
- throw 'onData parameter should be a callback';
328
+ return true;
240
329
  }
241
330
 
242
- submoduleParams.defaultProfile = submoduleParams.defaultProfile || {};
331
+ /** normalize submodule configuration
332
+ * @method
333
+ * @private
334
+ * @param {ModuleParams} moduleParams
335
+ * @param {CommonConf} submoduleParams
336
+ * @return {void}
337
+ * @throws will throw an error in case of invalid configuration
338
+ */
339
+ // eslint-disable-next-line no-dupe-class-members
340
+ #normalizeConf(moduleParams, submoduleParams) {
341
+ submoduleParams.defaultProfile = submoduleParams.defaultProfile || {};
243
342
 
244
- if (!isValidProfile(submoduleParams.defaultProfile)) {
245
- throw 'defaultProfile is not valid';
246
- }
247
- }
343
+ const { setPrebidTargeting, sendToBidders, onData } = moduleParams;
248
344
 
249
- /** coerce set prebid targeting to function
250
- * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
251
- * @return {void}
252
- */
253
- function coerceSetPrebidTargeting(submoduleParams) {
254
- const setPrebidTargeting = submoduleParams.setPrebidTargeting;
345
+ submoduleParams.setPrebidTargeting ??= setPrebidTargeting;
346
+ submoduleParams.sendToBidders ??= sendToBidders;
347
+ submoduleParams.onData ??= onData;
255
348
 
256
- if (isFn(setPrebidTargeting)) {
257
- return
258
- }
349
+ // handle setPrebidTargeting
350
+ this.#coerceSetPrebidTargeting(submoduleParams);
259
351
 
260
- if (isBoolean(setPrebidTargeting)) {
261
- const shouldSetPrebidTargeting = setPrebidTargeting;
352
+ // handle sendToBidders
353
+ this.#coerceSendToBidders(submoduleParams);
262
354
 
263
- submoduleParams.setPrebidTargeting = () => shouldSetPrebidTargeting;
355
+ if (!isFn(submoduleParams.onData)) {
356
+ throw 'onData parameter should be a callback';
357
+ }
264
358
 
265
- return
359
+ if (!isValidProfile(submoduleParams.defaultProfile)) {
360
+ throw 'defaultProfile is not valid';
361
+ }
266
362
  }
267
363
 
268
- if (isStr(setPrebidTargeting)) {
269
- const allowedAdUnitCode = setPrebidTargeting;
364
+ /** coerce setPrebidTargeting to a callback
365
+ * @method
366
+ * @private
367
+ * @param {CommonConf} submoduleParams
368
+ * @return {void}
369
+ * @throws will throw an error in case of invalid configuration
370
+ */
371
+ // eslint-disable-next-line no-dupe-class-members
372
+ #coerceSetPrebidTargeting(submoduleParams) {
373
+ try {
374
+ submoduleParams.setPrebidTargeting = this.#wrapValidatorCallback(submoduleParams.setPrebidTargeting);
375
+ } catch (e) {
376
+ throw `invalid setPrebidTargeting: ${e}`;
377
+ }
378
+ }
270
379
 
271
- submoduleParams.setPrebidTargeting = (adUnitCode) => allowedAdUnitCode == adUnitCode;
380
+ /** coerce sendToBidders to a callback
381
+ * @method
382
+ * @private
383
+ * @param {CommonConf} submoduleParams
384
+ * @return {void}
385
+ * @throws will throw an error in case of invalid configuration
386
+ */
387
+ // eslint-disable-next-line no-dupe-class-members
388
+ #coerceSendToBidders(submoduleParams) {
389
+ let sendToBidders = submoduleParams.sendToBidders;
390
+
391
+ if (isPlainObject(sendToBidders)) {
392
+ const sendToBiddersMap = Object.entries(sendToBidders).reduce((map, [key, value]) => {
393
+ map[key] = this.#wrapValidatorCallback(value);
394
+ return map;
395
+ }, {});
272
396
 
273
- return
274
- }
397
+ submoduleParams.sendToBidders = (bid, adUnitCode) => {
398
+ const bidder = bid.bidder;
399
+ if (!(bidder in sendToBiddersMap)) {
400
+ return false;
401
+ }
275
402
 
276
- if (isArray(setPrebidTargeting)) {
277
- const allowedAdUnitCodes = setPrebidTargeting;
403
+ const validatorCallback = sendToBiddersMap[bidder];
278
404
 
279
- submoduleParams.setPrebidTargeting = (adUnitCode) => allowedAdUnitCodes.includes(adUnitCode);
405
+ try {
406
+ return validatorCallback(adUnitCode);
407
+ } catch (e) {
408
+ throw `invalid sendToBidders[${bidder}]: ${e}`;
409
+ }
410
+ };
280
411
 
281
- return
412
+ return;
413
+ }
414
+
415
+ try {
416
+ submoduleParams.sendToBidders = this.#wrapValidatorCallback(submoduleParams.sendToBidders,
417
+ (bid) => bid.bidder);
418
+ } catch (e) {
419
+ throw `invalid sendToBidders: ${e}`;
420
+ }
282
421
  }
283
422
 
284
- throw `unexpected format for setPrebidTargeting: ${typeof setPrebidTargeting}`;
285
- }
423
+ /**
424
+ * @typedef {Object} AdUnit
425
+ * @property {Object[]} bids
426
+ */
427
+ /** function that handles bid request data
428
+ * @method
429
+ * @private
430
+ * @param {Object} reqBidsConfigObj
431
+ * @param {AdUnit[]} reqBidsConfigObj.adUnits
432
+ * @param {Object} reqBidsConfigObj.ortb2Fragments
433
+ * @param {Object} reqBidsConfigObj.ortb2Fragments.bidder
434
+ * @param {ModuleParams} moduleParams
435
+ * @returns {void}
436
+ */
437
+ // eslint-disable-next-line no-dupe-class-members
438
+ #handleBidRequestData(reqBidsConfigObj, moduleParams) {
439
+ const profileHandlers = this.#buildProfileHandlers(moduleParams);
440
+
441
+ if (isEmpty(profileHandlers)) {
442
+ logMessage('no data to send to bidders');
443
+ return;
444
+ }
286
445
 
287
- /** coerce send to bidders to function
288
- * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
289
- * @return {void}
290
- */
291
- function coerceSendToBidders(submoduleParams) {
292
- const sendToBidders = submoduleParams.sendToBidders;
446
+ const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits;
447
+
448
+ try {
449
+ adUnits.forEach(
450
+ adUnit => adUnit.bids?.forEach(
451
+ bid => profileHandlers.forEach(ph => {
452
+ // logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`);
453
+
454
+ const [data, metadata] = this.#copyDataAndMetadata(ph);
455
+ if (ph.sendToBidders(bid, adUnit.code, data, metadata)) {
456
+ // logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`);
457
+
458
+ this.#handleBid(reqBidsConfigObj, bid, data, ph.metadata);
459
+ }
460
+ })
461
+ )
462
+ );
463
+ } catch (e) {
464
+ logError('unable to send data to bidders:', e);
465
+ }
293
466
 
294
- if (isFn(sendToBidders)) {
295
- return
467
+ profileHandlers.forEach(ph => {
468
+ try {
469
+ const [data, metadata] = this.#copyDataAndMetadata(ph);
470
+ ph.onData(data, metadata);
471
+ } catch (e) {
472
+ logError(`error while execute onData callback with ${ph.metadata.source}-based data:`, e);
473
+ }
474
+ });
296
475
  }
297
476
 
298
- if (isBoolean(sendToBidders)) {
299
- const shouldSendToBidders = sendToBidders;
477
+ /** onSuccess callback type
478
+ * @callback successCallback
479
+ * @param {?Object} data
480
+ * @returns {void}
481
+ */
482
+
483
+ /** onDone callback type
484
+ * @callback doneCallback
485
+ * @returns {void}
486
+ */
487
+
488
+ /** Fetch Bigsea Contextual Profile
489
+ * @method
490
+ * @private
491
+ * @param {WeboCtxConf} weboCtxConf
492
+ * @param {successCallback} onSuccess callback
493
+ * @param {doneCallback} onDone callback
494
+ * @returns {void}
495
+ */
496
+ // eslint-disable-next-line no-dupe-class-members
497
+ #fetchContextualProfile(weboCtxConf, onSuccess, onDone) {
498
+ const token = weboCtxConf.token;
499
+ const baseURLProfileAPI = weboCtxConf.baseURLProfileAPI || BASE_URL_CONTEXTUAL_PROFILE_API;
500
+
501
+ let path = '/profile';
502
+ let queryString = '';
503
+ queryString = tryAppendQueryString(queryString, 'token', token);
504
+
505
+ if (weboCtxConf.assetID) {
506
+ path = '/document-profile';
507
+
508
+ let assetID = weboCtxConf.assetID;
509
+ if (isFn(assetID)) {
510
+ try {
511
+ assetID = weboCtxConf.assetID();
512
+ } catch (e) {
513
+ logError('unexpected error while fetching asset id from callback', e);
300
514
 
301
- submoduleParams.sendToBidders = () => shouldSendToBidders;
515
+ onDone();
302
516
 
303
- return
304
- }
517
+ return;
518
+ }
519
+ }
305
520
 
306
- if (isStr(sendToBidders)) {
307
- const allowedBidder = sendToBidders;
521
+ if (!assetID) {
522
+ logError('missing asset id');
308
523
 
309
- submoduleParams.sendToBidders = (bid) => allowedBidder == bid.bidder;
524
+ onDone();
310
525
 
311
- return
312
- }
526
+ return;
527
+ }
313
528
 
314
- if (isArray(sendToBidders)) {
315
- const allowedBidders = sendToBidders;
529
+ queryString = tryAppendQueryString(queryString, 'assetId', assetID);
530
+ }
316
531
 
317
- submoduleParams.sendToBidders = (bid) => allowedBidders.includes(bid.bidder);
532
+ const targetURL = weboCtxConf.targetURL || document.URL;
533
+ queryString = tryAppendQueryString(queryString, 'url', targetURL);
318
534
 
319
- return
320
- }
535
+ const urlProfileAPI = `https://${baseURLProfileAPI}/api${path}?${queryString}`;
321
536
 
322
- if (isPlainObject(sendToBidders)) {
323
- const sendToBiddersMap = sendToBidders;
324
- submoduleParams.sendToBidders = (bid, adUnitCode) => {
325
- const bidder = bid.bidder;
326
- if (!sendToBiddersMap.hasOwnProperty(bidder)) {
327
- return false
537
+ const success = (response, req) => {
538
+ if (req.status === 200) {
539
+ const data = JSON.parse(response);
540
+ onSuccess(data);
541
+ } else {
542
+ throw `unexpected http status response ${req.status} with response ${response}`;
328
543
  }
329
544
 
330
- const value = sendToBiddersMap[bidder];
545
+ onDone();
546
+ };
331
547
 
332
- if (isBoolean(value)) {
333
- return value
334
- }
548
+ const error = (e, req) => {
549
+ logError(`unable to get weborama data`, e, req);
335
550
 
336
- if (isStr(value)) {
337
- return value == adUnitCode
338
- }
551
+ onDone();
552
+ };
339
553
 
340
- if (isArray(value)) {
341
- return value.includes(adUnitCode)
342
- }
554
+ const callback = {
555
+ success,
556
+ error,
557
+ };
343
558
 
344
- throw `unexpected format for sendToBidders[${bidder}]: ${typeof value}`;
559
+ const options = {
560
+ method: 'GET',
561
+ withCredentials: false,
345
562
  };
346
563
 
347
- return
564
+ ajax(urlProfileAPI, callback, null, options);
348
565
  }
349
566
 
350
- throw `unexpected format for sendToBidders: ${typeof sendToBidders}`;
351
- }
352
- /**
353
- * check if profile is valid
354
- * @param {*} profile
355
- * @returns {Boolean}
356
- */
357
- function isValidProfile(profile) {
358
- if (!isPlainObject(profile)) {
359
- return false;
567
+ /** set bigsea contextual profile on module state
568
+ * @method
569
+ * @private
570
+ * @param {?Object} data
571
+ * @returns {void}
572
+ */
573
+ // eslint-disable-next-line no-dupe-class-members
574
+ #setWeboContextualProfile(data) {
575
+ if (data && isPlainObject(data) && isValidProfile(data) && !isEmpty(data)) {
576
+ this.#components.WeboCtx.data = data;
577
+ }
360
578
  }
361
579
 
362
- const keys = Object.keys(profile);
580
+ /** function that provides data handlers based on the configuration
581
+ * @method
582
+ * @private
583
+ * @param {ModuleParams} moduleParams
584
+ * @returns {ProfileHandler[]}
585
+ */
586
+ // eslint-disable-next-line no-dupe-class-members
587
+ #buildProfileHandlers(moduleParams) {
588
+ const steps = [{
589
+ component: this.#components.WeboCtx,
590
+ conf: moduleParams?.weboCtxConf,
591
+ }, {
592
+ component: this.#components.WeboUserData,
593
+ conf: moduleParams?.weboUserDataConf,
594
+ }, {
595
+ component: this.#components.SfbxLiteData,
596
+ conf: moduleParams?.sfbxLiteDataConf,
597
+ }];
598
+
599
+ return steps.filter(step => step.component.initialized).reduce((ph, { component, conf }) => {
600
+ const user = component.user;
601
+ const source = component.source;
602
+ const callback = component.callbackBuilder(component /* equivalent to this */);
603
+ const profileHandler = this.#buildProfileHandler(conf, callback, user, source);
604
+ if (profileHandler) {
605
+ ph.push(profileHandler);
606
+ } else {
607
+ logMessage(`skip ${source} profile: no data`);
608
+ }
363
609
 
364
- for (var i in keys) {
365
- const key = keys[i];
366
- const value = profile[key];
367
- if (!isArray(value)) {
368
- return false;
610
+ return ph;
611
+ }, []);
612
+ }
613
+
614
+ /**
615
+ * @typedef {Object} ProfileHandler
616
+ * @property {Profile} data
617
+ * @property {dataCallbackMetadata} metadata
618
+ * @property {setPrebidTargetingCallback} setTargeting
619
+ * @property {sendToBiddersCallback} sendToBidders
620
+ * @property {dataCallback} onData
621
+ */
622
+
623
+ /**
624
+ * @callback buildProfileHandlerCallbackBuilder
625
+ * @param {Component} component
626
+ * @returns {buildProfileHandlerCallback}
627
+ */
628
+
629
+ /**
630
+ * @callback buildProfileHandlerCallback
631
+ * @param {CommonConf} dataConf
632
+ * @returns {[Profile,boolean]} profile + is default flag
633
+ */
634
+
635
+ /**
636
+ * return specific profile handler
637
+ * @method
638
+ * @private
639
+ * @param {CommonConf} dataConf
640
+ * @param {buildProfileHandlerCallback} callback
641
+ * @param {boolean} user
642
+ * @param {string} source
643
+ * @returns {ProfileHandler}
644
+ */
645
+ // eslint-disable-next-line no-dupe-class-members
646
+ #buildProfileHandler(dataConf, callback, user, source) {
647
+ if (!dataConf) {
648
+ return;
369
649
  }
370
650
 
371
- for (var j in value) {
372
- const elem = value[j]
373
- if (!isStr(elem)) {
374
- return false;
375
- }
651
+ const [data, isDefault] = callback(dataConf);
652
+ if (isEmpty(data)) {
653
+ return;
654
+ }
655
+
656
+ return {
657
+ data: data,
658
+ metadata: {
659
+ user: user,
660
+ source: source,
661
+ isDefault: !!isDefault,
662
+ },
663
+ setTargeting: dataConf.setPrebidTargeting,
664
+ sendToBidders: dataConf.sendToBidders,
665
+ onData: dataConf.onData,
666
+ };
667
+ }
668
+ /** handle individual bid
669
+ * @method
670
+ * @private
671
+ * @param {Object} reqBidsConfigObj
672
+ * @param {Object} reqBidsConfigObj.ortb2Fragments
673
+ * @param {Object} reqBidsConfigObj.ortb2Fragments.bidder
674
+ * @param {Object} bid
675
+ * @param {string} bid.bidder
676
+ * @param {Profile} profile
677
+ * @param {dataCallbackMetadata} metadata
678
+ * @returns {void}
679
+ */
680
+ // eslint-disable-next-line no-dupe-class-members
681
+ #handleBid(reqBidsConfigObj, bid, profile, metadata) {
682
+ this.#handleBidViaORTB2(reqBidsConfigObj, bid.bidder, profile, metadata);
683
+
684
+ /** @type {Object.<string,string>} */
685
+ const bidderAliasRegistry = adapterManager.aliasRegistry || {};
686
+
687
+ /** @type {string} */
688
+ const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder;
689
+
690
+ switch (bidder) {
691
+ case 'appnexus':
692
+ this.#handleAppnexusBid(bid, profile);
693
+ break;
694
+ case 'pubmatic':
695
+ this.#handlePubmaticBid(bid, profile);
696
+ break;
697
+ case 'smartadserver':
698
+ this.#handleSmartadserverBid(bid, profile);
699
+ break;
700
+ case 'rubicon':
701
+ this.#handleRubiconBid(bid, profile, metadata);
702
+ break;
376
703
  }
377
704
  }
378
705
 
379
- return true;
380
- }
706
+ /** function that handles bid request data
707
+ * @method
708
+ * @private
709
+ * @param {ProfileHandler} ph profile handler
710
+ * @returns {[Profile,dataCallbackMetadata]} deeply copy data + metadata
711
+ */
712
+ // eslint-disable-next-line no-dupe-class-members
713
+ #copyDataAndMetadata(ph) {
714
+ return [deepClone(ph.data), deepClone(ph.metadata)];
715
+ }
381
716
 
382
- /** function that provides ad server targeting data to RTD-core
383
- * @param {Array} adUnitsCodes
384
- * @param {Object} moduleConfig
385
- * @returns {Object} target data
386
- */
387
- function getTargetingData(adUnitsCodes, moduleConfig) {
388
- const moduleParams = moduleConfig?.params || {};
717
+ /** handle appnexus/xandr bid
718
+ * @method
719
+ * @private
720
+ * @param {Object} bid
721
+ * @param {Object} bid.params
722
+ * @param {Object} bid.params.keyword
723
+ * @param {Profile} profile
724
+ * @returns {void}
725
+ */
726
+ // eslint-disable-next-line no-dupe-class-members
727
+ #handleAppnexusBid(bid, profile) {
728
+ const base = 'params.keywords';
729
+ this.#assignProfileToObject(bid, base, profile);
730
+ }
389
731
 
390
- const profileHandlers = buildProfileHandlers(moduleParams);
732
+ /** handle pubmatic bid
733
+ * @method
734
+ * @private
735
+ * @param {Object} bid
736
+ * @param {Object} bid.params
737
+ * @param {string} bid.params.dctr
738
+ * @param {Profile} profile
739
+ * @returns {void}
740
+ */
741
+ // eslint-disable-next-line no-dupe-class-members
742
+ #handlePubmaticBid(bid, profile) {
743
+ const sep = '|';
744
+ const subsep = ',';
745
+
746
+ bid.params ||= {};
747
+
748
+ const data = bid.params.dctr || '';
749
+ const target = new Set(data.split(sep).filter((x) => x.length > 0));
750
+
751
+ Object.entries(profile).forEach(([key, values]) => {
752
+ const value = values.join(subsep);
753
+ const keyword = `${key}=${value}`;
754
+ target.add(keyword);
755
+ });
391
756
 
392
- if (isEmpty(profileHandlers)) {
393
- logMessage('no data to set targeting');
394
- return {};
757
+ bid.params.dctr = Array.from(target).join(sep);
395
758
  }
396
759
 
397
- try {
398
- const td = adUnitsCodes.reduce((data, adUnitCode) => {
399
- data[adUnitCode] = profileHandlers.reduce((targeting, ph) => {
400
- // logMessage(`check if should set targeting for adunit '${adUnitCode}'`);
401
- const cph = copyProfileHandler(ph);
402
- if (ph.setTargeting(adUnitCode, cph.data, cph.metadata)) {
403
- // logMessage(`set targeting for adunit '${adUnitCode}', source '${ph.metadata.source}'`);
404
-
405
- mergeDeep(targeting, cph.data);
406
- }
407
- return targeting;
408
- }, {});
409
- return data;
410
- }, {});
760
+ /** handle smartadserver bid
761
+ * @method
762
+ * @private
763
+ * @param {Object} bid
764
+ * @param {Object} bid.params
765
+ * @param {string} bid.params.target
766
+ * @param {Profile} profile
767
+ * @returns {void}
768
+ */
769
+ // eslint-disable-next-line no-dupe-class-members
770
+ #handleSmartadserverBid(bid, profile) {
771
+ const sep = ';';
772
+
773
+ bid.params ||= {};
774
+
775
+ const data = bid.params.target || '';
776
+ const target = new Set(data.split(sep).filter((x) => x.length > 0));
777
+
778
+ Object.entries(profile).forEach(([key, values]) => {
779
+ values.forEach(value => {
780
+ const keyword = `${key}=${value}`;
781
+ target.add(keyword);
782
+ })
783
+ });
411
784
 
412
- return td;
413
- } catch (e) {
414
- logError('unable to format weborama rtd targeting data', e);
415
- return {};
785
+ bid.params.target = Array.from(target).join(sep);
416
786
  }
417
- }
418
787
 
419
- /** function that provides data handlers based on the configuration
420
- * @param {ModuleParams} moduleParams
421
- * @returns {Array<Object>} handlers
422
- */
423
- function buildProfileHandlers(moduleParams) {
424
- const profileHandlers = [];
425
-
426
- if (_weboCtxInitialized && moduleParams?.weboCtxConf) {
427
- const weboCtxConf = moduleParams.weboCtxConf;
428
- const [data, isDefault] = getContextualProfile(weboCtxConf);
429
- if (!isEmpty(data)) {
430
- profileHandlers.push({
431
- data: data,
432
- metadata: {
433
- user: false,
434
- source: 'contextual',
435
- isDefault: !!isDefault,
436
- },
437
- setTargeting: weboCtxConf.setPrebidTargeting,
438
- sendToBidders: weboCtxConf.sendToBidders,
439
- onData: weboCtxConf.onData,
440
- })
788
+ /** handle rubicon bid
789
+ * @method
790
+ * @private
791
+ * @param {Object} bid
792
+ * @param {string} bid.bidder
793
+ * @param {Profile} profile
794
+ * @param {dataCallbackMetadata} metadata
795
+ * @returns {void}
796
+ */
797
+ // eslint-disable-next-line no-dupe-class-members
798
+ #handleRubiconBid(bid, profile, metadata) {
799
+ if (isBoolean(metadata.user)) {
800
+ const section = metadata.user ? 'visitor' : 'inventory';
801
+ const base = `params.${section}`;
802
+ this.#assignProfileToObject(bid, base, profile);
441
803
  } else {
442
- logMessage('skip contextual profile: no data');
804
+ logMessage(`SKIP bidder '${bid.bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
443
805
  }
444
806
  }
445
807
 
446
- if (_weboUserDataInitialized && moduleParams?.weboUserDataConf) {
447
- const weboUserDataConf = moduleParams.weboUserDataConf;
448
- const [data, isDefault] = getWeboUserDataProfile(weboUserDataConf);
449
- if (!isEmpty(data)) {
450
- profileHandlers.push({
451
- data: data,
452
- metadata: {
453
- user: true,
454
- source: 'wam',
455
- isDefault: !!isDefault,
456
- },
457
- setTargeting: weboUserDataConf.setPrebidTargeting,
458
- sendToBidders: weboUserDataConf.sendToBidders,
459
- onData: weboUserDataConf.onData,
460
- })
808
+ /** handle generic bid via ortb2 arbitrary data
809
+ * @method
810
+ * @private
811
+ * @param {Object} reqBidsConfigObj
812
+ * @param {Object} reqBidsConfigObj.ortb2Fragments
813
+ * @param {Object} reqBidsConfigObj.ortb2Fragments.bidder
814
+ * @param {string} bidder
815
+ * @param {Profile} profile
816
+ * @param {dataCallbackMetadata} metadata
817
+ * @returns {void}
818
+ */
819
+ // eslint-disable-next-line no-dupe-class-members
820
+ #handleBidViaORTB2(reqBidsConfigObj, bidder, profile, metadata) {
821
+ if (isBoolean(metadata.user)) {
822
+ logMessage(`bidder '${bidder}' is not directly supported, trying set data via bidder ortb2 fpd`);
823
+ const section = metadata.user ? 'user' : 'site';
824
+ const base = `${bidder}.${section}.ext.data`;
825
+
826
+ this.#assignProfileToObject(reqBidsConfigObj.ortb2Fragments?.bidder, base, profile);
461
827
  } else {
462
- logMessage('skip wam profile: no data');
828
+ logMessage(`SKIP unsupported bidder '${bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
463
829
  }
464
830
  }
465
831
 
466
- if (_sfbxLiteDataInitialized && moduleParams?.sfbxLiteDataConf) {
467
- const sfbxLiteDataConf = moduleParams.sfbxLiteDataConf;
468
- const [data, isDefault] = getSfbxLiteDataProfile(sfbxLiteDataConf);
469
- if (!isEmpty(data)) {
470
- profileHandlers.push({
471
- data: data,
472
- metadata: {
473
- user: false,
474
- source: 'lite',
475
- isDefault: !!isDefault,
476
- },
477
- setTargeting: sfbxLiteDataConf.setPrebidTargeting,
478
- sendToBidders: sfbxLiteDataConf.sendToBidders,
479
- onData: sfbxLiteDataConf.onData,
480
- })
481
- } else {
482
- logMessage('skip sfbx lite profile: no data');
483
- }
832
+ /**
833
+ * assign profile to object
834
+ * @method
835
+ * @private
836
+ * @param {Object} destination
837
+ * @param {string} base
838
+ * @param {Profile} profile
839
+ * @returns {void}
840
+ */
841
+ // eslint-disable-next-line no-dupe-class-members
842
+ #assignProfileToObject(destination, base, profile) {
843
+ Object.entries(profile).forEach(([key, values]) => {
844
+ const path = `${base}.${key}`;
845
+ deepSetValue(destination, path, values);
846
+ })
484
847
  }
485
848
 
486
- return profileHandlers;
849
+ /**
850
+ * @callback validatorCallback
851
+ * @param {string} target
852
+ * @returns {boolean}
853
+ */
854
+
855
+ /**
856
+ * @callback coerceCallback
857
+ * @param {*} input
858
+ * @returns {*}
859
+ */
860
+
861
+ /**
862
+ * wrap value into validator
863
+ * @method
864
+ * @private
865
+ * @param {*} value
866
+ * @param {coerceCallback} coerce
867
+ * @returns {validatorCallback}
868
+ * @throws will throw an error in case of unsupported type
869
+ */
870
+ // eslint-disable-next-line no-dupe-class-members
871
+ #wrapValidatorCallback(value, coerce = (x) => x) {
872
+ if (isFn(value)) {
873
+ return value;
874
+ }
875
+
876
+ if (isBoolean(value)) {
877
+ return (_) => value;
878
+ }
879
+
880
+ if (isStr(value)) {
881
+ return (target) => {
882
+ return value == coerce(target);
883
+ };
884
+ }
885
+
886
+ if (isArray(value)) {
887
+ return (target) => {
888
+ return value.includes(coerce(target));
889
+ };
890
+ }
891
+
892
+ throw `unexpected format: ${typeof value} (expects function, boolean, string or array)`;
893
+ }
487
894
  }
488
895
 
489
- /** return contextual profile
490
- * @param {WeboCtxConf} weboCtxConf
491
- * @returns {Array} contextual profile + isDefault boolean flag
896
+ /**
897
+ * check if profile is valid
898
+ * @param {*} profile
899
+ * @returns {boolean}
492
900
  */
493
- function getContextualProfile(weboCtxConf) {
494
- if (_weboContextualProfile) {
495
- return [_weboContextualProfile, false];
901
+ export function isValidProfile(profile) {
902
+ if (!isPlainObject(profile)) {
903
+ return false;
496
904
  }
497
905
 
498
- const defaultContextualProfile = weboCtxConf.defaultProfile || {};
906
+ return Object.values(profile).every((field) => isArray(field) && field.every(isStr));
907
+ }
908
+
909
+ /**
910
+ * bind callback with component
911
+ * @param {Component} component
912
+ * @returns {buildProfileHandlerCallback}
913
+ */
914
+ function getContextualProfile(component /* equivalent to this */) {
915
+ /** return contextual profile
916
+ * @param {WeboCtxConf} weboCtxConf
917
+ * @returns {[Profile,boolean]} contextual profile + isDefault boolean flag
918
+ */
919
+ return function (weboCtxConf) {
920
+ if (component.data) {
921
+ return [component.data, false];
922
+ }
499
923
 
500
- return [defaultContextualProfile, true];
924
+ const defaultContextualProfile = weboCtxConf.defaultProfile || {};
925
+
926
+ return [defaultContextualProfile, true];
927
+ }
501
928
  }
502
929
 
503
- /** return weboUserData profile
504
- * @param {WeboUserDataConf} weboUserDataConf
505
- * @returns {Array} weboUserData profile + isDefault boolean flag
930
+ /**
931
+ * bind callback with component
932
+ * @param {Component} component
933
+ * @returns {buildProfileHandlerCallback}
506
934
  */
507
- function getWeboUserDataProfile(weboUserDataConf) {
508
- return getDataFromLocalStorage(weboUserDataConf,
509
- () => _weboUserDataUserProfile,
510
- (data) => _weboUserDataUserProfile = data,
511
- DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY,
512
- LOCAL_STORAGE_USER_TARGETING_SECTION,
513
- 'wam');
935
+ function getWeboUserDataProfile(component /* equivalent to this */) {
936
+ /** return weboUserData profile
937
+ * @param {WeboUserDataConf} weboUserDataConf
938
+ * @returns {[Profile,boolean]} weboUserData profile + isDefault boolean flag
939
+ */
940
+ return function (weboUserDataConf) {
941
+ return getDataFromLocalStorage(weboUserDataConf,
942
+ () => component.data,
943
+ (data) => component.data = data,
944
+ DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY,
945
+ LOCAL_STORAGE_USER_TARGETING_SECTION,
946
+ WEBO_USER_DATA_SOURCE_LABEL);
947
+ }
514
948
  }
515
949
 
516
- /** return weboUserData profile
517
- * @param {SfbxLiteDataConf} sfbxLiteDataConf
518
- * @returns {Array} sfbxLiteData profile + isDefault boolean flag
950
+ /**
951
+ * bind callback with component
952
+ * @param {Component} component
953
+ * @returns {buildProfileHandlerCallback}
519
954
  */
520
- function getSfbxLiteDataProfile(sfbxLiteDataConf) {
521
- return getDataFromLocalStorage(sfbxLiteDataConf,
522
- () => _sfbxLiteDataProfile,
523
- (data) => _sfbxLiteDataProfile = data,
524
- DEFAULT_LOCAL_STORAGE_LITE_PROFILE_KEY,
525
- LOCAL_STORAGE_LITE_TARGETING_SECTION,
526
- 'lite');
955
+ function getSfbxLiteDataProfile(component /* equivalent to this */) {
956
+ /** return weboUserData profile
957
+ * @param {SfbxLiteDataConf} sfbxLiteDataConf
958
+ * @returns {[Profile,boolean]} sfbxLiteData profile + isDefault boolean flag
959
+ */
960
+ return function getSfbxLiteDataProfile(sfbxLiteDataConf) {
961
+ return getDataFromLocalStorage(sfbxLiteDataConf,
962
+ () => component.data,
963
+ (data) => component.data = data,
964
+ DEFAULT_LOCAL_STORAGE_LITE_PROFILE_KEY,
965
+ LOCAL_STORAGE_LITE_TARGETING_SECTION,
966
+ SFBX_LITE_DATA_SOURCE_LABEL);
967
+ }
527
968
  }
528
969
 
970
+ /**
971
+ * @callback cacheGetCallback
972
+ * @returns {Profile}
973
+ */
974
+ /**
975
+ * @callback cacheSetCallback
976
+ * @param {Profile} profile
977
+ * @returns {void}
978
+ */
979
+
529
980
  /** return generic webo data profile
530
981
  * @param {WeboUserDataConf|SfbxLiteDataConf} weboDataConf
531
982
  * @param {cacheGetCallback} cacheGet
532
983
  * @param {cacheSetCallback} cacheSet
533
- * @param {String} defaultLocalStorageProfileKey
534
- * @param {String} targetingSection
535
- * @param {String} source
536
- * @returns {Array} webo (user|lite) data profile + isDefault boolean flag
984
+ * @param {string} defaultLocalStorageProfileKey
985
+ * @param {string} targetingSection
986
+ * @param {string} source
987
+ * @returns {[Profile,boolean]} webo (user|lite) data profile + isDefault boolean flag
537
988
  */
538
989
  function getDataFromLocalStorage(weboDataConf, cacheGet, cacheSet, defaultLocalStorageProfileKey, targetingSection, source) {
539
990
  const defaultProfile = weboDataConf.defaultProfile || {};
540
991
 
541
- if (storage.localStorageIsEnabled() && !cacheGet()) {
992
+ if (storage.hasLocalStorage() && storage.localStorageIsEnabled() && !cacheGet()) {
542
993
  const localStorageProfileKey = weboDataConf.localStorageProfileKey || defaultLocalStorageProfileKey;
543
994
 
544
995
  const entry = storage.getDataFromLocalStorage(localStorageProfileKey);
545
996
  if (entry) {
546
997
  const data = JSON.parse(entry);
547
- if (data && isPlainObject(data) && data.hasOwnProperty(targetingSection)) {
998
+ if (data && isPlainObject(data) && targetingSection in data) {
999
+ /** @type {profile} */
548
1000
  const profile = data[targetingSection];
549
1001
  const valid = isValidProfile(profile);
550
1002
  if (!valid) {
551
1003
  logWarn(`found invalid ${source} profile on local storage key ${localStorageProfileKey}, section ${targetingSection}`);
1004
+
1005
+ return;
552
1006
  }
553
1007
 
554
- if (valid && !isEmpty(data)) {
1008
+ if (!isEmpty(data)) {
555
1009
  cacheSet(profile);
556
1010
  }
557
1011
  }
@@ -566,328 +1020,31 @@ function getDataFromLocalStorage(weboDataConf, cacheGet, cacheSet, defaultLocalS
566
1020
 
567
1021
  return [defaultProfile, true];
568
1022
  }
569
-
570
- /** function that will allow RTD sub-modules to modify the AdUnit object for each auction
571
- * @param {Object} reqBidsConfigObj
572
- * @param {doneCallback} onDone
573
- * @param {Object} moduleConfig
574
- * @returns {void}
575
- */
576
- export function getBidRequestData(reqBidsConfigObj, onDone, moduleConfig) {
577
- const moduleParams = moduleConfig?.params || {};
578
-
579
- if (!_weboCtxInitialized) {
580
- handleBidRequestData(reqBidsConfigObj, moduleParams);
581
-
582
- onDone();
583
-
584
- return;
585
- }
586
-
587
- const weboCtxConf = moduleParams.weboCtxConf || {};
588
-
589
- fetchContextualProfile(weboCtxConf, (data) => {
590
- logMessage('fetchContextualProfile on getBidRequestData is done');
591
-
592
- setWeboContextualProfile(data);
593
- }, () => {
594
- handleBidRequestData(reqBidsConfigObj, moduleParams);
595
-
596
- onDone();
597
- });
598
- }
599
-
600
- /** function that handles bid request data
601
- * @param {Object} reqBids
602
- * @param {ModuleParams} moduleParams
603
- * @returns {void}
604
- */
605
- function handleBidRequestData(reqBids, moduleParams) {
606
- const profileHandlers = buildProfileHandlers(moduleParams);
607
-
608
- if (isEmpty(profileHandlers)) {
609
- logMessage('no data to send to bidders');
610
- return;
611
- }
612
-
613
- const adUnits = reqBids.adUnits || getGlobal().adUnits;
614
-
615
- try {
616
- adUnits.filter(
617
- adUnit => adUnit.hasOwnProperty('bids')
618
- ).forEach(
619
- adUnit => adUnit.bids.forEach(
620
- bid => profileHandlers.forEach(ph => {
621
- // logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`);
622
-
623
- const cph = copyProfileHandler(ph);
624
- if (ph.sendToBidders(bid, adUnit.code, cph.data, cph.metadata)) {
625
- // logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`);
626
-
627
- handleBid(reqBids, bid, cph.data, ph.metadata);
628
- }
629
- })
630
- )
631
- );
632
- } catch (e) {
633
- logError('unable to send data to bidders:', e);
634
- }
635
-
636
- profileHandlers.forEach(ph => {
637
- try {
638
- const cph = copyProfileHandler(ph);
639
- ph.onData(cph.data, cph.metadata);
640
- } catch (e) {
641
- logError(`error while executure onData callback with ${ph.metadata.source}-based data:`, e);
642
- }
643
- });
644
- }
645
- /** function that handles bid request data
646
- * @param {Object} ph profile handler
647
- *@returns {Object} of deeply copy data and metadata
648
- */
649
- function copyProfileHandler(ph) {
650
- return {
651
- data: deepClone(ph.data),
652
- metadata: deepClone(ph.metadata),
653
- };
654
- }
655
-
656
- /** @type {string} */
657
- const APPNEXUS = 'appnexus';
658
-
659
- /** @type {string} */
660
- const PUBMATIC = 'pubmatic';
661
-
662
- /** @type {string} */
663
- const RUBICON = 'rubicon';
664
-
665
- /** @type {string} */
666
- const SMARTADSERVER = 'smartadserver';
667
-
668
- /** @type {Object} */
669
- const bidderAliasRegistry = adapterManager.aliasRegistry || {};
670
-
671
- /** handle individual bid
672
- * @param reqBids
673
- * @param {Object} bid
674
- * @param {Object} profile
675
- * @param {Object} metadata
676
- * @returns {void}
677
- */
678
- function handleBid(reqBids, bid, profile, metadata) {
679
- const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder;
680
-
681
- switch (bidder) {
682
- // TODO: these special cases should not be necessary - all adapters should look into FPD, not just their params
683
- case APPNEXUS:
684
- handleAppnexusBid(bid, profile);
685
-
686
- break;
687
-
688
- case PUBMATIC:
689
- handlePubmaticBid(bid, profile);
690
-
691
- break;
692
-
693
- case SMARTADSERVER:
694
- handleSmartadserverBid(bid, profile);
695
-
696
- break;
697
- case RUBICON:
698
- handleRubiconBid(bid, profile, metadata);
699
-
700
- break;
701
- default:
702
- handleBidViaORTB2(reqBids, bid, profile, metadata);
703
- }
704
- }
705
-
706
- /** handle appnexus/xandr bid
707
- * @param {Object} bid
708
- * @param {Object} profile
709
- * @returns {void}
710
- */
711
- function handleAppnexusBid(bid, profile) {
712
- const base = 'params.keywords';
713
- assignProfileToObject(bid, base, profile);
714
- }
715
-
716
- /** handle pubmatic bid
717
- * @param {Object} bid
718
- * @param {Object} profile
719
- * @returns {void}
720
- */
721
- function handlePubmaticBid(bid, profile) {
722
- const sep = '|';
723
- const subsep = ',';
724
- const target = [];
725
-
726
- bid.params ||= {};
727
-
728
- const data = bid.params.dctr;
729
- if (data) {
730
- data.split(sep).forEach(t => target.push(t));
731
- }
732
-
733
- Object.keys(profile).forEach(key => {
734
- const value = profile[key].join(subsep);
735
- const keyword = `${key}=${value}`;
736
- if (target.indexOf(keyword) === -1) {
737
- target.push(keyword);
738
- }
739
- });
740
-
741
- bid.params.dctr = target.join(sep);
742
- }
743
-
744
- /** handle smartadserver bid
745
- * @param {Object} bid
746
- * @param {Object} profile
747
- * @returns {void}
748
- */
749
- function handleSmartadserverBid(bid, profile) {
750
- const sep = ';';
751
- const target = [];
752
-
753
- bid.params ||= {};
754
-
755
- const data = bid.params.target;
756
- if (data) {
757
- data.split(sep).forEach(t => target.push(t));
758
- }
759
-
760
- Object.keys(profile).forEach(key => {
761
- profile[key].forEach(value => {
762
- const keyword = `${key}=${value}`;
763
- if (target.indexOf(keyword) === -1) {
764
- target.push(keyword);
765
- }
766
- });
767
- });
768
-
769
- bid.params.target = target.join(sep);
770
- }
771
-
772
- /** handle rubicon bid
773
- * @param {Object} bid
774
- * @param {Object} profile
775
- * @param {Object} metadata
776
- * @returns {void}
777
- */
778
- function handleRubiconBid(bid, profile, metadata) {
779
- if (isBoolean(metadata.user)) {
780
- const section = (metadata.user) ? 'visitor' : 'inventory';
781
- const base = `params.${section}`;
782
- assignProfileToObject(bid, base, profile);
783
- } else {
784
- logMessage(`SKIP bidder '${bid.bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
785
- }
786
- }
787
-
788
- /** handle generic bid via ortb2 arbitrary data
789
- * @param reqBids
790
- * @param {Object} bid
791
- * @param {Object} profile
792
- * @param {Object} metadata
793
- * @returns {void}
794
- */
795
- function handleBidViaORTB2(reqBids, bid, profile, metadata) {
796
- if (isBoolean(metadata.user)) {
797
- logMessage(`bidder '${bid.bidder}' is not directly supported, trying set data via bidder ortb2 fpd`);
798
- const section = ((metadata.user) ? 'user' : 'site');
799
- const base = `${bid.bidder}.${section}.ext.data`;
800
-
801
- assignProfileToObject(reqBids.ortb2Fragments?.bidder, base, profile);
802
- } else {
803
- logMessage(`SKIP unsupported bidder '${bid.bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
804
- }
805
- }
806
-
807
- /**
808
- * assign profile to object
809
- * @param {Object} destination
810
- * @param {string} base
811
- * @param {Object} profile
812
- * @returns {void}
813
- */
814
- function assignProfileToObject(destination, base, profile) {
815
- Object.keys(profile).forEach(key => {
816
- const path = `${base}.${key}`;
817
- deepSetValue(destination, path, profile[key])
818
- })
819
- }
820
-
821
- /** set bigsea contextual profile on module state
822
- * @param {null|Object} data
823
- * @returns {void}
824
- */
825
- export function setWeboContextualProfile(data) {
826
- if (data && isPlainObject(data) && isValidProfile(data) && !isEmpty(data)) {
827
- _weboContextualProfile = data;
828
- }
829
- }
830
-
831
- /** onSuccess callback type
832
- * @callback successCallback
833
- * @param {null|Object} data
834
- * @returns {void}
835
- */
836
-
837
- /** onDone callback type
838
- * @callback doneCallback
839
- * @returns {void}
840
- */
841
-
842
- /** Fetch Bigsea Contextual Profile
843
- * @param {WeboCtxConf} weboCtxConf
844
- * @param {successCallback} onSuccess callback
845
- * @param {doneCallback} onDone callback
846
- * @returns {void}
847
- */
848
- function fetchContextualProfile(weboCtxConf, onSuccess, onDone) {
849
- const targetURL = weboCtxConf.targetURL || document.URL;
850
- const token = weboCtxConf.token;
851
- const baseURLProfileAPI = weboCtxConf.baseURLProfileAPI || BASE_URL_CONTEXTUAL_PROFILE_API;
852
-
853
- let queryString = '';
854
- queryString = tryAppendQueryString(queryString, 'token', token);
855
- queryString = tryAppendQueryString(queryString, 'url', targetURL);
856
-
857
- const urlProfileAPI = `https://${baseURLProfileAPI}/api/profile?${queryString}`;
858
-
859
- ajax(urlProfileAPI, {
860
- success: (response, req) => {
861
- if (req.status === 200) {
862
- try {
863
- const data = JSON.parse(response);
864
- onSuccess(data);
865
- onDone();
866
- } catch (e) {
867
- onDone();
868
- logError('unable to parse weborama data', e);
869
- throw e;
870
- }
871
- } else if (req.status === 204) {
872
- onDone();
873
- }
874
- },
875
- error: () => {
876
- onDone();
877
- logError('unable to get weborama data');
878
- }
1023
+ /** @type {Components} */
1024
+ const components = {
1025
+ WeboCtx: {
1026
+ initialized: false,
1027
+ data: null,
1028
+ user: false,
1029
+ source: WEBO_CTX_SOURCE_LABEL,
1030
+ callbackBuilder: getContextualProfile,
1031
+ },
1032
+ WeboUserData: {
1033
+ initialized: false,
1034
+ data: null,
1035
+ user: true,
1036
+ source: WEBO_USER_DATA_SOURCE_LABEL,
1037
+ callbackBuilder: getWeboUserDataProfile,
1038
+ },
1039
+ SfbxLiteData: {
1040
+ initialized: false,
1041
+ data: null,
1042
+ user: false,
1043
+ source: SFBX_LITE_DATA_SOURCE_LABEL,
1044
+ callbackBuilder: getSfbxLiteDataProfile,
879
1045
  },
880
- null, {
881
- method: 'GET',
882
- withCredentials: false,
883
- });
884
- }
885
-
886
- export const weboramaSubmodule = {
887
- name: SUBMODULE_NAME,
888
- init: init,
889
- getTargetingData: getTargetingData,
890
- getBidRequestData: getBidRequestData,
891
1046
  };
892
1047
 
1048
+ export const weboramaSubmodule = new WeboramaRtdProvider(components);
1049
+
893
1050
  submodule(MODULE_NAME, weboramaSubmodule);