prebid.js 6.24.0 → 6.26.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 (178) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/adagioBidAdapter.js +1 -1
  3. package/dist/adbookpspBidAdapter.js +1 -1
  4. package/dist/adgenerationBidAdapter.js +1 -1
  5. package/dist/adrelevantisBidAdapter.js +1 -1
  6. package/dist/adtelligentBidAdapter.js +1 -1
  7. package/dist/adxcgBidAdapter.js +1 -1
  8. package/dist/adyoulikeBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/appierAnalyticsAdapter.js +1 -1
  13. package/dist/appnexusBidAdapter.js +1 -1
  14. package/dist/asoBidAdapter.js +1 -1
  15. package/dist/audiencerunBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/beopBidAdapter.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/concertBidAdapter.js +1 -1
  24. package/dist/connectadBidAdapter.js +1 -1
  25. package/dist/consumableBidAdapter.js +1 -1
  26. package/dist/conversantBidAdapter.js +1 -1
  27. package/dist/cpexIdSystem.js +1 -1
  28. package/dist/craftBidAdapter.js +1 -1
  29. package/dist/criteoBidAdapter.js +1 -1
  30. package/dist/currency.js +1 -1
  31. package/dist/dfpAdServerVideo.js +1 -1
  32. package/dist/dspxBidAdapter.js +1 -1
  33. package/dist/eplanningBidAdapter.js +1 -1
  34. package/dist/glimpseBidAdapter.js +1 -1
  35. package/dist/gmosspBidAdapter.js +1 -1
  36. package/dist/goldbachBidAdapter.js +1 -1
  37. package/dist/gravitoIdSystem.js +1 -0
  38. package/dist/gridBidAdapter.js +1 -1
  39. package/dist/gridNMBidAdapter.js +1 -1
  40. package/dist/gumgumBidAdapter.js +1 -1
  41. package/dist/h12mediaBidAdapter.js +1 -1
  42. package/dist/id5IdSystem.js +1 -1
  43. package/dist/impactifyBidAdapter.js +1 -1
  44. package/dist/improvedigitalBidAdapter.js +1 -1
  45. package/dist/inmarBidAdapter.js +1 -1
  46. package/dist/insticatorBidAdapter.js +1 -1
  47. package/dist/invibesBidAdapter.js +1 -1
  48. package/dist/ixBidAdapter.js +1 -1
  49. package/dist/jixieBidAdapter.js +1 -1
  50. package/dist/justpremiumBidAdapter.js +1 -1
  51. package/dist/kargoBidAdapter.js +1 -1
  52. package/dist/konduitAnalyticsAdapter.js +1 -1
  53. package/dist/liveIntentIdSystem.js +1 -1
  54. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  55. package/dist/logicadBidAdapter.js +1 -1
  56. package/dist/loglyliftBidAdapter.js +1 -1
  57. package/dist/malltvAnalyticsAdapter.js +1 -1
  58. package/dist/marsmediaBidAdapter.js +1 -1
  59. package/dist/mediafuseBidAdapter.js +1 -1
  60. package/dist/mediakeysBidAdapter.js +1 -1
  61. package/dist/mediasquareBidAdapter.js +1 -1
  62. package/dist/mgidBidAdapter.js +1 -1
  63. package/dist/minutemediaBidAdapter.js +1 -1
  64. package/dist/not-for-prod/prebid.js +123 -121
  65. package/dist/oguryBidAdapter.js +1 -1
  66. package/dist/oneVideoBidAdapter.js +1 -1
  67. package/dist/onetagBidAdapter.js +1 -1
  68. package/dist/ooloAnalyticsAdapter.js +1 -1
  69. package/dist/outbrainBidAdapter.js +1 -1
  70. package/dist/parrableIdSystem.js +1 -1
  71. package/dist/pixfutureBidAdapter.js +1 -1
  72. package/dist/prebid-core.js +3 -3
  73. package/dist/publinkIdSystem.js +1 -1
  74. package/dist/pubmaticBidAdapter.js +1 -1
  75. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  76. package/dist/pxyzBidAdapter.js +1 -1
  77. package/dist/quantcastBidAdapter.js +1 -1
  78. package/dist/readpeakBidAdapter.js +1 -1
  79. package/dist/relaidoBidAdapter.js +1 -1
  80. package/dist/rhythmoneBidAdapter.js +1 -1
  81. package/dist/riseBidAdapter.js +1 -1
  82. package/dist/rubiconAnalyticsAdapter.js +1 -1
  83. package/dist/rubiconBidAdapter.js +1 -1
  84. package/dist/seedingAllianceBidAdapter.js +1 -1
  85. package/dist/seedtagBidAdapter.js +1 -1
  86. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  87. package/dist/sharethroughBidAdapter.js +1 -1
  88. package/dist/smaatoBidAdapter.js +1 -1
  89. package/dist/smartadserverBidAdapter.js +1 -1
  90. package/dist/smartxBidAdapter.js +1 -1
  91. package/dist/smilewantedBidAdapter.js +1 -1
  92. package/dist/sonobiBidAdapter.js +1 -1
  93. package/dist/sortableBidAdapter.js +1 -1
  94. package/dist/sovrnAnalyticsAdapter.js +1 -1
  95. package/dist/sovrnBidAdapter.js +1 -1
  96. package/dist/sspBCBidAdapter.js +1 -1
  97. package/dist/sublimeBidAdapter.js +1 -1
  98. package/dist/synacormediaBidAdapter.js +1 -1
  99. package/dist/targetVideoBidAdapter.js +1 -1
  100. package/dist/teadsBidAdapter.js +1 -1
  101. package/dist/trionBidAdapter.js +1 -1
  102. package/dist/tripleliftBidAdapter.js +1 -1
  103. package/dist/trustpidSystem.js +1 -1
  104. package/dist/trustxBidAdapter.js +1 -1
  105. package/dist/ttdBidAdapter.js +1 -1
  106. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  107. package/dist/underdogmediaBidAdapter.js +1 -1
  108. package/dist/undertoneBidAdapter.js +1 -1
  109. package/dist/userId.js +1 -1
  110. package/dist/vidazooBidAdapter.js +1 -1
  111. package/dist/videobyteBidAdapter.js +1 -1
  112. package/dist/videoheroesBidAdapter.js +1 -0
  113. package/dist/vidoomyBidAdapter.js +1 -1
  114. package/dist/visxBidAdapter.js +1 -1
  115. package/dist/vuukleBidAdapter.js +1 -1
  116. package/dist/weboramaRtdProvider.js +1 -1
  117. package/dist/widespaceBidAdapter.js +1 -1
  118. package/dist/winrBidAdapter.js +1 -1
  119. package/dist/yahoosspBidAdapter.js +1 -1
  120. package/dist/yieldmoBidAdapter.js +1 -1
  121. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  122. package/dist/zeta_global_sspBidAdapter.js +1 -1
  123. package/integrationExamples/gpt/userId_example.html +3 -0
  124. package/integrationExamples/gpt/weboramaRtdProvider_example.html +65 -11
  125. package/modules/.submodules.json +2 -1
  126. package/modules/adagioBidAdapter.js +2 -0
  127. package/modules/adtelligentBidAdapter.js +3 -1
  128. package/modules/alkimiBidAdapter.md +10 -4
  129. package/modules/appnexusBidAdapter.js +13 -2
  130. package/modules/beopBidAdapter.js +51 -6
  131. package/modules/cpexIdSystem.js +1 -2
  132. package/modules/currency.js +4 -13
  133. package/modules/dacIdSystem.md +4 -4
  134. package/modules/dfpAdServerVideo.js +8 -0
  135. package/modules/gravitoIdSystem.js +57 -0
  136. package/modules/gravitoIdSystem.md +28 -0
  137. package/modules/improvedigitalBidAdapter.js +100 -43
  138. package/modules/invibesBidAdapter.js +55 -34
  139. package/modules/ixBidAdapter.js +62 -26
  140. package/modules/ixBidAdapter.md +42 -42
  141. package/modules/jixieBidAdapter.js +2 -0
  142. package/modules/kargoBidAdapter.js +23 -8
  143. package/modules/oguryBidAdapter.js +27 -1
  144. package/modules/trustpidSystem.js +9 -28
  145. package/modules/trustpidSystem.md +11 -34
  146. package/modules/userId/eids.js +6 -0
  147. package/modules/userId/index.js +30 -55
  148. package/modules/userId/userId.md +3 -11
  149. package/modules/videoheroesBidAdapter.js +267 -0
  150. package/modules/videoheroesBidAdapter.md +134 -0
  151. package/modules/vidoomyBidAdapter.js +2 -6
  152. package/modules/weboramaRtdProvider.js +515 -241
  153. package/modules/weboramaRtdProvider.md +488 -51
  154. package/modules/zeta_global_sspBidAdapter.js +1 -1
  155. package/package.json +4 -4
  156. package/src/adserver.js +7 -0
  157. package/src/hook.js +19 -1
  158. package/src/utils/promise.js +36 -0
  159. package/test/spec/modules/adtelligentBidAdapter_spec.js +1 -0
  160. package/test/spec/modules/appnexusBidAdapter_spec.js +37 -10
  161. package/test/spec/modules/beopBidAdapter_spec.js +15 -2
  162. package/test/spec/modules/dfpAdServerVideo_spec.js +45 -0
  163. package/test/spec/modules/gravitoIdSystem_spec.js +51 -0
  164. package/test/spec/modules/improvedigitalBidAdapter_spec.js +289 -72
  165. package/test/spec/modules/invibesBidAdapter_spec.js +98 -7
  166. package/test/spec/modules/ixBidAdapter_spec.js +132 -26
  167. package/test/spec/modules/jixieBidAdapter_spec.js +17 -0
  168. package/test/spec/modules/kargoBidAdapter_spec.js +45 -3
  169. package/test/spec/modules/liveIntentIdSystem_spec.js +2 -2
  170. package/test/spec/modules/loglyliftBidAdapter_spec.js +8 -0
  171. package/test/spec/modules/oguryBidAdapter_spec.js +181 -3
  172. package/test/spec/modules/trustpidSystem_spec.js +42 -19
  173. package/test/spec/modules/userId_spec.js +18 -0
  174. package/test/spec/modules/videoheroesBidAdapter_spec.js +363 -0
  175. package/test/spec/modules/weboramaRtdProvider_spec.js +2333 -266
  176. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +37 -24
  177. package/test/spec/unit/utils/promise_spec.js +49 -0
  178. package/test/spec/modules/medianetRtdProvider_spec.js +0 -146
@@ -7,57 +7,96 @@
7
7
  * @requires module:modules/realTimeData
8
8
  */
9
9
 
10
+ /**
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
15
+ */
16
+
10
17
  /** onData callback type
11
18
  * @callback dataCallback
12
19
  * @param {Object} data profile data
13
- * @param {Boolean} site true if site, else it is user
20
+ * @param {dataCallbackMetadata} meta metadata
14
21
  * @returns {void}
15
22
  */
16
23
 
24
+ /** setPrebidTargeting callback type
25
+ * @callback setPrebidTargetingCallback
26
+ * @param {String} adUnitCode
27
+ * @param {Object} data
28
+ * @param {dataCallbackMetadata} metadata
29
+ * @returns {Boolean}
30
+ */
31
+
32
+ /** sendToBidders callback type
33
+ * @callback sendToBiddersCallback
34
+ * @param {Object} bid
35
+ * @param {String} adUnitCode
36
+ * @param {Object} data
37
+ * @param {dataCallbackMetadata} metadata
38
+ * @returns {Boolean}
39
+ */
40
+
17
41
  /**
18
42
  * @typedef {Object} ModuleParams
19
- * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default undefined)
20
- * @property {?Boolean} sendToBidders if true, will send the contextual profile to all bidders (default undefined)
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)
21
45
  * @property {?dataCallback} onData callback
22
- * @property {?WeboCtxConf} weboCtxConf
23
- * @property {?WeboUserDataConf} weboUserDataConf
46
+ * @property {?WeboCtxConf} weboCtxConf site-centric contextual configuration
47
+ * @property {?WeboUserDataConf} weboUserDataConf user-centric wam configuration
48
+ * @property {?SfbxLiteDataConf} sfbxLiteDataConf site-centric lite configuration
24
49
  */
25
50
 
26
51
  /**
27
52
  * @typedef {Object} WeboCtxConf
28
53
  * @property {string} token required token to be used on bigsea contextual API requests
29
54
  * @property {?string} targetURL specify the target url instead use the referer
30
- * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default params.setPrebidTargeting or true)
31
- * @property {?Boolean} sendToBidders if true, will send the contextual profile to all bidders (default params.sendToBidders or true)
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)
32
57
  * @property {?dataCallback} onData callback
33
58
  * @property {?object} defaultProfile to be used if the profile is not found
34
59
  * @property {?Boolean} enabled if false, will ignore this configuration
60
+ * @property {?string} baseURLProfileAPI to be used to point to a different domain than ctx.weborama.com
35
61
  */
36
62
 
37
63
  /**
38
64
  * @typedef {Object} WeboUserDataConf
39
65
  * @property {?number} accountId wam account id
40
- * @property {?Boolean} setPrebidTargeting if true, will set the GAM targeting (default params.setPrebidTargeting or true)
41
- * @property {?Boolean} sendToBidders if true, will send the user-centric profile to all bidders (default params.sendToBidders or true)
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)
42
68
  * @property {?object} defaultProfile to be used if the profile is not found
43
69
  * @property {?dataCallback} onData callback
44
70
  * @property {?string} localStorageProfileKey can be used to customize the local storage key (default is 'webo_wam2gam_entry')
45
71
  * @property {?Boolean} enabled if false, will ignore this configuration
46
72
  */
47
73
 
74
+ /**
75
+ * @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
79
+ * @property {?dataCallback} onData callback
80
+ * @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
82
+ */
48
83
  import {
49
84
  getGlobal
50
85
  } from '../src/prebidGlobal.js';
51
86
  import {
52
87
  deepSetValue,
53
- deepAccess,
54
88
  isEmpty,
55
89
  mergeDeep,
56
90
  logError,
57
91
  logWarn,
58
92
  tryAppendQueryString,
59
93
  logMessage,
60
- isFn
94
+ isFn,
95
+ isArray,
96
+ isStr,
97
+ isBoolean,
98
+ isPlainObject,
99
+ deepClone,
61
100
  } from '../src/utils.js';
62
101
  import {
63
102
  submodule
@@ -75,13 +114,29 @@ const MODULE_NAME = 'realTimeData';
75
114
  /** @type {string} */
76
115
  const SUBMODULE_NAME = 'weborama';
77
116
  /** @type {string} */
117
+ const BASE_URL_CONTEXTUAL_PROFILE_API = 'ctx.weborama.com';
118
+ /** @type {string} */
78
119
  export const DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY = 'webo_wam2gam_entry';
79
120
  /** @type {string} */
80
121
  const LOCAL_STORAGE_USER_TARGETING_SECTION = 'targeting';
122
+ /** @type {string} */
123
+ export const DEFAULT_LOCAL_STORAGE_LITE_PROFILE_KEY = '_lite';
124
+ /** @type {string} */
125
+ const LOCAL_STORAGE_LITE_TARGETING_SECTION = 'webo';
126
+ /** @type {string} */
127
+ const WEBO_CTX_CONF_SECTION = 'weboCtxConf';
128
+ /** @type {string} */
129
+ const WEBO_USER_DATA_CONF_SECTION = 'weboUserDataConf';
130
+ /** @type {string} */
131
+ const SFBX_LITE_DATA_CONF_SECTION = 'sfbxLiteDataConf';
132
+
81
133
  /** @type {number} */
82
134
  const GVLID = 284;
83
- /** @type {object} */
84
- export const storage = getStorageManager({gvlid: GVLID, moduleName: SUBMODULE_NAME});
135
+ /** @type {?Object} */
136
+ export const storage = getStorageManager({
137
+ gvlid: GVLID,
138
+ moduleName: SUBMODULE_NAME
139
+ });
85
140
 
86
141
  /** @type {null|Object} */
87
142
  let _weboContextualProfile = null;
@@ -89,78 +144,67 @@ let _weboContextualProfile = null;
89
144
  /** @type {Boolean} */
90
145
  let _weboCtxInitialized = false;
91
146
 
92
- /** @type {null|Object} */
147
+ /** @type {?Object} */
93
148
  let _weboUserDataUserProfile = null;
94
149
 
95
150
  /** @type {Boolean} */
96
151
  let _weboUserDataInitialized = false;
97
152
 
153
+ /** @type {?Object} */
154
+ let _sfbxLiteDataProfile = null;
155
+
156
+ /** @type {Boolean} */
157
+ let _sfbxLiteDataInitialized = false;
158
+
98
159
  /** Initialize module
99
160
  * @param {object} moduleConfig
100
161
  * @return {Boolean} true if module was initialized with success
101
162
  */
102
163
  function init(moduleConfig) {
103
- moduleConfig = moduleConfig || {};
104
- const moduleParams = moduleConfig.params || {};
105
- const weboCtxConf = moduleParams.weboCtxConf;
106
- const weboUserDataConf = moduleParams.weboUserDataConf;
164
+ const moduleParams = moduleConfig?.params || {};
107
165
 
108
- _weboCtxInitialized = initWeboCtx(moduleParams, weboCtxConf);
109
- _weboUserDataInitialized = initWeboUserData(moduleParams, weboUserDataConf);
110
-
111
- return _weboCtxInitialized || _weboUserDataInitialized;
112
- }
113
-
114
- /** Initialize contextual sub module
115
- * @param {ModuleParams} moduleParams
116
- * @param {WeboCtxConf} weboCtxConf
117
- * @return {Boolean} true if sub module was initialized with success
118
- */
119
- function initWeboCtx(moduleParams, weboCtxConf) {
120
- if (!weboCtxConf || weboCtxConf.enabled === false) {
121
- moduleParams.weboCtxConf = null;
122
-
123
- return false
124
- }
125
-
126
- normalizeConf(moduleParams, weboCtxConf);
127
-
128
- _weboCtxInitialized = false;
129
166
  _weboContextualProfile = null;
167
+ _weboUserDataUserProfile = null;
168
+ _sfbxLiteDataProfile = null;
130
169
 
131
- if (!weboCtxConf.token) {
132
- logWarn('missing param "token" for weborama contextual sub module initialization');
133
- return false;
134
- }
135
-
136
- logMessage('weborama contextual intialized with success');
170
+ _weboCtxInitialized = initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, 'token');
171
+ _weboUserDataInitialized = initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION);
172
+ _sfbxLiteDataInitialized = initSubSection(moduleParams, SFBX_LITE_DATA_CONF_SECTION);
137
173
 
138
- return true;
174
+ return _weboCtxInitialized || _weboUserDataInitialized || _sfbxLiteDataInitialized;
139
175
  }
140
176
 
141
- /** Initialize weboUserData sub module
142
- * @param {ModuleParams} moduleParams
143
- * @param {WeboUserDataConf} weboUserDataConf
144
- * @return {Boolean} true if sub module was initialized with success
177
+ /** Initialize subsection module
178
+ * @param {Object} moduleParams
179
+ * @param {string} subSection subsection name to initialize
180
+ * @param {[]string} requiredFields
181
+ * @return {Boolean} true if module subsection was initialized with success
145
182
  */
146
- function initWeboUserData(moduleParams, weboUserDataConf) {
147
- if (!weboUserDataConf || weboUserDataConf.enabled === false) {
148
- moduleParams.weboUserDataConf = null;
183
+ function initSubSection(moduleParams, subSection, ...requiredFields) {
184
+ const weboSectionConf = moduleParams[subSection] || {enabled: false};
185
+
186
+ if (weboSectionConf.enabled === false) {
187
+ delete moduleParams[subSection];
149
188
 
150
189
  return false;
151
190
  }
152
191
 
153
- normalizeConf(moduleParams, weboUserDataConf);
192
+ requiredFields ||= [];
154
193
 
155
- _weboUserDataInitialized = false;
156
- _weboUserDataUserProfile = null;
194
+ try {
195
+ normalizeConf(moduleParams, weboSectionConf);
157
196
 
158
- let message = 'weborama user-centric intialized with success';
159
- if (weboUserDataConf.hasOwnProperty('accountId')) {
160
- message = `weborama user-centric intialized with success for account: ${weboUserDataConf.accountId}`;
197
+ requiredFields.forEach(field => {
198
+ if (!weboSectionConf[field]) {
199
+ throw `missing required field "{field}" on {section}`;
200
+ }
201
+ });
202
+ } catch (e) {
203
+ logError(`unable to initialize: error on ${subSection} configuration: ${e}`);
204
+ return false
161
205
  }
162
206
 
163
- logMessage(message);
207
+ logMessage(`weborama ${subSection} initialized with success`);
164
208
 
165
209
  return true;
166
210
  }
@@ -169,21 +213,172 @@ function initWeboUserData(moduleParams, weboUserDataConf) {
169
213
  const globalDefaults = {
170
214
  setPrebidTargeting: true,
171
215
  sendToBidders: true,
172
- onData: (data, kind, def) => logMessage('onData(data,kind,default)', data, kind, def),
216
+ onData: () => {
217
+ /* do nothing */ },
173
218
  }
174
219
 
175
220
  /** normalize submodule configuration
176
221
  * @param {ModuleParams} moduleParams
177
- * @param {WeboCtxConf|WeboUserDataConf} submoduleParams
222
+ * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
178
223
  * @return {void}
179
224
  */
180
225
  function normalizeConf(moduleParams, submoduleParams) {
226
+ // handle defaults
181
227
  Object.entries(globalDefaults).forEach(([propertyName, globalDefaultValue]) => {
182
228
  if (!submoduleParams.hasOwnProperty(propertyName)) {
183
229
  const hasModuleParam = moduleParams.hasOwnProperty(propertyName);
184
230
  submoduleParams[propertyName] = (hasModuleParam) ? moduleParams[propertyName] : globalDefaultValue;
185
231
  }
186
232
  })
233
+
234
+ // handle setPrebidTargeting
235
+ coerceSetPrebidTargeting(submoduleParams)
236
+
237
+ // handle sendToBidders
238
+ coerceSendToBidders(submoduleParams)
239
+
240
+ if (!isFn(submoduleParams.onData)) {
241
+ throw 'onData parameter should be a callback';
242
+ }
243
+
244
+ submoduleParams.defaultProfile = submoduleParams.defaultProfile || {};
245
+
246
+ if (!isValidProfile(submoduleParams.defaultProfile)) {
247
+ throw 'defaultProfile is not valid';
248
+ }
249
+ }
250
+
251
+ /** coerce set prebid targeting to function
252
+ * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
253
+ * @return {void}
254
+ */
255
+ function coerceSetPrebidTargeting(submoduleParams) {
256
+ const setPrebidTargeting = submoduleParams.setPrebidTargeting;
257
+
258
+ if (isFn(setPrebidTargeting)) {
259
+ return
260
+ }
261
+
262
+ if (isBoolean(setPrebidTargeting)) {
263
+ const shouldSetPrebidTargeting = setPrebidTargeting;
264
+
265
+ submoduleParams.setPrebidTargeting = () => shouldSetPrebidTargeting;
266
+
267
+ return
268
+ }
269
+
270
+ if (isStr(setPrebidTargeting)) {
271
+ const allowedAdUnitCode = setPrebidTargeting;
272
+
273
+ submoduleParams.setPrebidTargeting = (adUnitCode) => allowedAdUnitCode == adUnitCode;
274
+
275
+ return
276
+ }
277
+
278
+ if (isArray(setPrebidTargeting)) {
279
+ const allowedAdUnitCodes = setPrebidTargeting;
280
+
281
+ submoduleParams.setPrebidTargeting = (adUnitCode) => allowedAdUnitCodes.includes(adUnitCode);
282
+
283
+ return
284
+ }
285
+
286
+ throw `unexpected format for setPrebidTargeting: ${typeof setPrebidTargeting}`;
287
+ }
288
+
289
+ /** coerce send to bidders to function
290
+ * @param {WeboCtxConf|WeboUserDataConf|SfbxLiteDataConf} submoduleParams
291
+ * @return {void}
292
+ */
293
+ function coerceSendToBidders(submoduleParams) {
294
+ const sendToBidders = submoduleParams.sendToBidders;
295
+
296
+ if (isFn(sendToBidders)) {
297
+ return
298
+ }
299
+
300
+ if (isBoolean(sendToBidders)) {
301
+ const shouldSendToBidders = sendToBidders;
302
+
303
+ submoduleParams.sendToBidders = () => shouldSendToBidders;
304
+
305
+ return
306
+ }
307
+
308
+ if (isStr(sendToBidders)) {
309
+ const allowedBidder = sendToBidders;
310
+
311
+ submoduleParams.sendToBidders = (bid) => allowedBidder == bid.bidder;
312
+
313
+ return
314
+ }
315
+
316
+ if (isArray(sendToBidders)) {
317
+ const allowedBidders = sendToBidders;
318
+
319
+ submoduleParams.sendToBidders = (bid) => allowedBidders.includes(bid.bidder);
320
+
321
+ return
322
+ }
323
+
324
+ if (isPlainObject(sendToBidders)) {
325
+ const sendToBiddersMap = sendToBidders;
326
+ submoduleParams.sendToBidders = (bid, adUnitCode) => {
327
+ const bidder = bid.bidder;
328
+ if (!sendToBiddersMap.hasOwnProperty(bidder)) {
329
+ return false
330
+ }
331
+
332
+ const value = sendToBiddersMap[bidder];
333
+
334
+ if (isBoolean(value)) {
335
+ return value
336
+ }
337
+
338
+ if (isStr(value)) {
339
+ return value == adUnitCode
340
+ }
341
+
342
+ if (isArray(value)) {
343
+ return value.includes(adUnitCode)
344
+ }
345
+
346
+ throw `unexpected format for sendToBidders[${bidder}]: ${typeof value}`;
347
+ };
348
+
349
+ return
350
+ }
351
+
352
+ throw `unexpected format for sendToBidders: ${typeof sendToBidders}`;
353
+ }
354
+ /**
355
+ * check if profile is valid
356
+ * @param {*} profile
357
+ * @returns {Boolean}
358
+ */
359
+ function isValidProfile(profile) {
360
+ if (!isPlainObject(profile)) {
361
+ return false;
362
+ }
363
+
364
+ const keys = Object.keys(profile);
365
+
366
+ for (var i in keys) {
367
+ const key = keys[i];
368
+ const value = profile[key];
369
+ if (!isArray(value)) {
370
+ return false;
371
+ }
372
+
373
+ for (var j in value) {
374
+ const elem = value[j]
375
+ if (!isStr(elem)) {
376
+ return false;
377
+ }
378
+ }
379
+ }
380
+
381
+ return true;
187
382
  }
188
383
 
189
384
  /** function that provides ad server targeting data to RTD-core
@@ -192,24 +387,27 @@ function normalizeConf(moduleParams, submoduleParams) {
192
387
  * @returns {Object} target data
193
388
  */
194
389
  function getTargetingData(adUnitsCodes, moduleConfig) {
195
- moduleConfig = moduleConfig || {};
196
- const moduleParams = moduleConfig.params || {};
197
- const weboCtxConf = moduleParams.weboCtxConf || {};
198
- const weboUserDataConf = moduleParams.weboUserDataConf || {};
199
- const weboCtxConfTargeting = weboCtxConf.setPrebidTargeting;
200
- const weboUserDataConfTargeting = weboUserDataConf.setPrebidTargeting;
390
+ const moduleParams = moduleConfig?.params || {};
201
391
 
202
- try {
203
- const profile = getCompleteProfile(moduleParams, weboCtxConfTargeting, weboUserDataConfTargeting);
392
+ const profileHandlers = buildProfileHandlers(moduleParams);
204
393
 
205
- if (isEmpty(profile)) {
206
- return {};
207
- }
394
+ if (isEmpty(profileHandlers)) {
395
+ logMessage('no data to set targeting');
396
+ return {};
397
+ }
208
398
 
399
+ try {
209
400
  const td = adUnitsCodes.reduce((data, adUnitCode) => {
210
- if (adUnitCode) {
211
- data[adUnitCode] = profile;
212
- }
401
+ data[adUnitCode] = profileHandlers.reduce((targeting, ph) => {
402
+ // logMessage(`check if should set targeting for adunit '${adUnitCode}'`);
403
+ const cph = copyProfileHandler(ph);
404
+ if (ph.setTargeting(adUnitCode, cph.data, cph.metadata)) {
405
+ // logMessage(`set targeting for adunit '${adUnitCode}', source '${ph.metadata.source}'`);
406
+
407
+ mergeDeep(targeting, cph.data);
408
+ }
409
+ return targeting;
410
+ }, {});
213
411
  return data;
214
412
  }, {});
215
413
 
@@ -220,57 +418,155 @@ function getTargetingData(adUnitsCodes, moduleConfig) {
220
418
  }
221
419
  }
222
420
 
223
- /** function that provides complete profile formatted to be used
421
+ /** function that provides data handlers based on the configuration
224
422
  * @param {ModuleParams} moduleParams
225
- * @param {Boolean} weboCtxConfTargeting
226
- * @param {Boolean} weboUserDataConfTargeting
227
- * @returns {Object} complete profile
423
+ * @returns {Array<Object>} handlers
228
424
  */
229
- function getCompleteProfile(moduleParams, weboCtxConfTargeting, weboUserDataConfTargeting) {
230
- const profile = {};
425
+ function buildProfileHandlers(moduleParams) {
426
+ const profileHandlers = [];
427
+
428
+ if (_weboCtxInitialized && moduleParams?.weboCtxConf) {
429
+ const weboCtxConf = moduleParams.weboCtxConf;
430
+ const [data, isDefault] = getContextualProfile(weboCtxConf);
431
+ if (!isEmpty(data)) {
432
+ profileHandlers.push({
433
+ data: data,
434
+ metadata: {
435
+ user: false,
436
+ source: 'contextual',
437
+ isDefault: !!isDefault,
438
+ },
439
+ setTargeting: weboCtxConf.setPrebidTargeting,
440
+ sendToBidders: weboCtxConf.sendToBidders,
441
+ onData: weboCtxConf.onData,
442
+ })
443
+ } else {
444
+ logMessage('skip contextual profile: no data');
445
+ }
446
+ }
231
447
 
232
- if (weboCtxConfTargeting) {
233
- const contextualProfile = getContextualProfile(moduleParams.weboCtxConf || {});
234
- mergeDeep(profile, contextualProfile);
448
+ if (_weboUserDataInitialized && moduleParams?.weboUserDataConf) {
449
+ const weboUserDataConf = moduleParams.weboUserDataConf;
450
+ const [data, isDefault] = getWeboUserDataProfile(weboUserDataConf);
451
+ if (!isEmpty(data)) {
452
+ profileHandlers.push({
453
+ data: data,
454
+ metadata: {
455
+ user: true,
456
+ source: 'wam',
457
+ isDefault: !!isDefault,
458
+ },
459
+ setTargeting: weboUserDataConf.setPrebidTargeting,
460
+ sendToBidders: weboUserDataConf.sendToBidders,
461
+ onData: weboUserDataConf.onData,
462
+ })
463
+ } else {
464
+ logMessage('skip wam profile: no data');
465
+ }
235
466
  }
236
467
 
237
- if (weboUserDataConfTargeting) {
238
- const weboUserDataProfile = getWeboUserDataProfile(moduleParams.weboUserDataConf || {});
239
- mergeDeep(profile, weboUserDataProfile);
468
+ if (_sfbxLiteDataInitialized && moduleParams?.sfbxLiteDataConf) {
469
+ const sfbxLiteDataConf = moduleParams.sfbxLiteDataConf;
470
+ const [data, isDefault] = getSfbxLiteDataProfile(sfbxLiteDataConf);
471
+ if (!isEmpty(data)) {
472
+ profileHandlers.push({
473
+ data: data,
474
+ metadata: {
475
+ user: false,
476
+ source: 'lite',
477
+ isDefault: !!isDefault,
478
+ },
479
+ setTargeting: sfbxLiteDataConf.setPrebidTargeting,
480
+ sendToBidders: sfbxLiteDataConf.sendToBidders,
481
+ onData: sfbxLiteDataConf.onData,
482
+ })
483
+ } else {
484
+ logMessage('skip sfbx lite profile: no data');
485
+ }
240
486
  }
241
487
 
242
- return profile;
488
+ return profileHandlers;
243
489
  }
244
490
 
245
491
  /** return contextual profile
246
492
  * @param {WeboCtxConf} weboCtxConf
247
- * @returns {Object} contextual profile
493
+ * @returns {Array} contextual profile + isDefault boolean flag
248
494
  */
249
495
  function getContextualProfile(weboCtxConf) {
496
+ if (_weboContextualProfile) {
497
+ return [_weboContextualProfile, false];
498
+ }
499
+
250
500
  const defaultContextualProfile = weboCtxConf.defaultProfile || {};
251
- return _weboContextualProfile || defaultContextualProfile;
501
+
502
+ return [defaultContextualProfile, true];
252
503
  }
253
504
 
254
505
  /** return weboUserData profile
255
506
  * @param {WeboUserDataConf} weboUserDataConf
256
- * @returns {Object} weboUserData profile
507
+ * @returns {Array} weboUserData profile + isDefault boolean flag
257
508
  */
258
509
  function getWeboUserDataProfile(weboUserDataConf) {
259
- const weboUserDataDefaultUserProfile = weboUserDataConf.defaultProfile || {};
510
+ return getDataFromLocalStorage(weboUserDataConf,
511
+ () => _weboUserDataUserProfile,
512
+ (data) => _weboUserDataUserProfile = data,
513
+ DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY,
514
+ LOCAL_STORAGE_USER_TARGETING_SECTION,
515
+ 'wam');
516
+ }
260
517
 
261
- if (storage.localStorageIsEnabled() && !_weboUserDataUserProfile) {
262
- const localStorageProfileKey = weboUserDataConf.localStorageProfileKey || DEFAULT_LOCAL_STORAGE_USER_PROFILE_KEY;
518
+ /** return weboUserData profile
519
+ * @param {SfbxLiteDataConf} sfbxLiteDataConf
520
+ * @returns {Array} sfbxLiteData profile + isDefault boolean flag
521
+ */
522
+ function getSfbxLiteDataProfile(sfbxLiteDataConf) {
523
+ return getDataFromLocalStorage(sfbxLiteDataConf,
524
+ () => _sfbxLiteDataProfile,
525
+ (data) => _sfbxLiteDataProfile = data,
526
+ DEFAULT_LOCAL_STORAGE_LITE_PROFILE_KEY,
527
+ LOCAL_STORAGE_LITE_TARGETING_SECTION,
528
+ 'lite');
529
+ }
530
+
531
+ /** return generic webo data profile
532
+ * @param {WeboUserDataConf|SfbxLiteDataConf} weboDataConf
533
+ * @param {cacheGetCallback} cacheGet
534
+ * @param {cacheSetCallback} cacheSet
535
+ * @param {String} defaultLocalStorageProfileKey
536
+ * @param {String} targetingSection
537
+ * @param {String} source
538
+ * @returns {Array} webo (user|lite) data profile + isDefault boolean flag
539
+ */
540
+ function getDataFromLocalStorage(weboDataConf, cacheGet, cacheSet, defaultLocalStorageProfileKey, targetingSection, source) {
541
+ const defaultProfile = weboDataConf.defaultProfile || {};
542
+
543
+ if (storage.localStorageIsEnabled() && !cacheGet()) {
544
+ const localStorageProfileKey = weboDataConf.localStorageProfileKey || defaultLocalStorageProfileKey;
263
545
 
264
546
  const entry = storage.getDataFromLocalStorage(localStorageProfileKey);
265
547
  if (entry) {
266
548
  const data = JSON.parse(entry);
267
- if (data && Object.keys(data).length > 0) {
268
- _weboUserDataUserProfile = data[LOCAL_STORAGE_USER_TARGETING_SECTION];
549
+ if (data && isPlainObject(data) && data.hasOwnProperty(targetingSection)) {
550
+ const profile = data[targetingSection];
551
+ const valid = isValidProfile(profile);
552
+ if (!valid) {
553
+ logWarn(`found invalid ${source} profile on local storage key ${localStorageProfileKey}, section ${targetingSection}`);
554
+ }
555
+
556
+ if (valid && !isEmpty(data)) {
557
+ cacheSet(profile);
558
+ }
269
559
  }
270
560
  }
271
561
  }
272
562
 
273
- return _weboUserDataUserProfile || weboUserDataDefaultUserProfile;
563
+ const profile = cacheGet()
564
+
565
+ if (profile) {
566
+ return [profile, false];
567
+ }
568
+
569
+ return [defaultProfile, true];
274
570
  }
275
571
 
276
572
  /** function that will allow RTD sub-modules to modify the AdUnit object for each auction
@@ -280,102 +576,83 @@ function getWeboUserDataProfile(weboUserDataConf) {
280
576
  * @returns {void}
281
577
  */
282
578
  export function getBidRequestData(reqBidsConfigObj, onDone, moduleConfig) {
283
- moduleConfig = moduleConfig || {};
284
- const moduleParams = moduleConfig.params || {};
285
- const weboCtxConf = moduleParams.weboCtxConf || {};
286
-
287
- const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits;
579
+ const moduleParams = moduleConfig?.params || {};
288
580
 
289
581
  if (!_weboCtxInitialized) {
290
- handleBidRequestData(adUnits, moduleParams);
582
+ handleBidRequestData(reqBidsConfigObj, moduleParams);
291
583
 
292
584
  onDone();
293
585
 
294
586
  return;
295
587
  }
296
588
 
589
+ const weboCtxConf = moduleParams.weboCtxConf || {};
590
+
297
591
  fetchContextualProfile(weboCtxConf, (data) => {
298
592
  logMessage('fetchContextualProfile on getBidRequestData is done');
299
593
 
300
594
  setWeboContextualProfile(data);
301
595
  }, () => {
302
- handleBidRequestData(adUnits, moduleParams);
596
+ handleBidRequestData(reqBidsConfigObj, moduleParams);
303
597
 
304
598
  onDone();
305
599
  });
306
600
  }
307
601
 
308
602
  /** function that handles bid request data
309
- * @param {Object[]} adUnits
603
+ * @param {Object} reqBids
310
604
  * @param {ModuleParams} moduleParams
311
605
  * @returns {void}
312
606
  */
607
+ function handleBidRequestData(reqBids, moduleParams) {
608
+ const profileHandlers = buildProfileHandlers(moduleParams);
313
609
 
314
- function handleBidRequestData(adUnits, moduleParams) {
315
- const weboCtxConf = moduleParams.weboCtxConf || {};
316
- const weboUserDataConf = moduleParams.weboUserDataConf || {};
317
- const weboCtxConfTargeting = weboCtxConf.sendToBidders;
318
- const weboUserDataConfTargeting = weboUserDataConf.sendToBidders;
319
-
320
- if (weboCtxConfTargeting) {
321
- const contextualProfile = getContextualProfile(weboCtxConf);
322
- if (!isEmpty(contextualProfile)) {
323
- setBidRequestProfile(adUnits, contextualProfile, true);
324
- }
325
- }
326
-
327
- if (weboUserDataConfTargeting) {
328
- const weboUserDataProfile = getWeboUserDataProfile(weboUserDataConf);
329
- if (!isEmpty(weboUserDataProfile)) {
330
- setBidRequestProfile(adUnits, weboUserDataProfile, false);
331
- }
610
+ if (isEmpty(profileHandlers)) {
611
+ logMessage('no data to send to bidders');
612
+ return;
332
613
  }
333
614
 
334
- handleOnData(weboCtxConf, weboUserDataConf);
335
- }
336
-
337
- /** function that handle with onData callbacks
338
- * @param {WeboCtxConf} weboCtxConf
339
- * @param {WeboUserDataConf} weboUserDataConf
340
- */
615
+ const adUnits = reqBids.adUnits || getGlobal().adUnits;
341
616
 
342
- function handleOnData(weboCtxConf, weboUserDataConf) {
343
- const callbacks = [{
344
- onData: weboCtxConf.onData,
345
- fetchData: () => getContextualProfile(weboCtxConf),
346
- site: true,
347
- }, {
348
- onData: weboUserDataConf.onData,
349
- fetchData: () => getWeboUserDataProfile(weboUserDataConf),
350
- site: false,
351
- }];
617
+ try {
618
+ adUnits.filter(
619
+ adUnit => adUnit.hasOwnProperty('bids')
620
+ ).forEach(
621
+ adUnit => adUnit.bids.forEach(
622
+ bid => profileHandlers.forEach(ph => {
623
+ // logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`);
624
+
625
+ const cph = copyProfileHandler(ph);
626
+ if (ph.sendToBidders(bid, adUnit.code, cph.data, cph.metadata)) {
627
+ // logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`);
628
+
629
+ handleBid(bid, cph.data, ph.metadata);
630
+ }
631
+ })
632
+ )
633
+ );
634
+ } catch (e) {
635
+ logError('unable to send data to bidders:', e);
636
+ }
352
637
 
353
- callbacks.filter(obj => isFn(obj.onData)).forEach(obj => {
638
+ profileHandlers.forEach(ph => {
354
639
  try {
355
- const data = obj.fetchData();
356
- obj.onData(data, obj.site);
640
+ const cph = copyProfileHandler(ph);
641
+ ph.onData(cph.data, cph.metadata);
357
642
  } catch (e) {
358
- const kind = (obj.site) ? 'site' : 'user';
359
- logError(`error while executure onData callback with ${kind}-based data:`, e);
643
+ logError(`error while executure onData callback with ${ph.metadata.source}-based data:`, e);
360
644
  }
361
645
  });
362
646
  }
363
-
364
- /** function that set bid request data on each segment (site or user centric)
365
- * @param {Object[]} adUnits
366
- * @param {Object} profile
367
- * @param {Boolean} site true if site centric, else it is user centric
368
- * @returns {void}
647
+ /** function that handles bid request data
648
+ * @param {Object} ph profile handler
649
+ *@returns {Object} of deeply copy data and metadata
369
650
  */
370
- function setBidRequestProfile(adUnits, profile, site) {
371
- setGlobalOrtb2(profile, site);
372
-
373
- adUnits.forEach(adUnit => {
374
- if (adUnit.hasOwnProperty('bids')) {
375
- const adUnitCode = adUnit.code || 'no code';
376
- adUnit.bids.forEach(bid => handleBid(adUnitCode, profile, site, bid));
377
- }
378
- });
651
+ function copyProfileHandler(ph) {
652
+ return {
653
+ data: deepClone(ph.data),
654
+ metadata: deepClone(ph.metadata),
655
+ };
379
656
  }
380
657
 
381
658
  /** @type {string} */
@@ -394,115 +671,61 @@ const SMARTADSERVER = 'smartadserver';
394
671
  const bidderAliasRegistry = adapterManager.aliasRegistry || {};
395
672
 
396
673
  /** handle individual bid
397
- * @param {string} adUnitCode
398
- * @param {Object} profile
399
- * @param {Boolean} site true if site centric, else it is user centric
400
674
  * @param {Object} bid
675
+ * @param {Object} profile
676
+ * @param {Object} metadata
401
677
  * @returns {void}
402
678
  */
403
- function handleBid(adUnitCode, profile, site, bid) {
679
+ function handleBid(bid, profile, metadata) {
404
680
  const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder;
405
681
 
406
- logMessage(`handling on adunit '${adUnitCode}', bidder '${bidder}' and bid`, bid);
407
-
408
682
  switch (bidder) {
409
683
  case APPNEXUS:
410
- handleAppnexusBid(profile, bid);
684
+ handleAppnexusBid(bid, profile);
411
685
 
412
686
  break;
413
687
 
414
688
  case PUBMATIC:
415
- handlePubmaticBid(profile, bid);
689
+ handlePubmaticBid(bid, profile);
416
690
 
417
691
  break;
418
692
 
419
693
  case SMARTADSERVER:
420
- handleSmartadserverBid(profile, bid);
694
+ handleSmartadserverBid(bid, profile);
421
695
 
422
696
  break;
423
697
  case RUBICON:
424
- handleRubiconBid(profile, site, bid);
698
+ handleRubiconBid(bid, profile, metadata);
425
699
 
426
700
  break;
427
701
  default:
428
- logMessage(`unsupported bidder '${bidder}', trying via bidder ortb2 fpd`);
429
- const section = ((site) ? 'site' : 'user');
430
- const base = `ortb2.${section}.ext.data`;
431
-
432
- assignProfileToObject(bid, base, profile);
433
- }
434
- }
435
-
436
- /**
437
- * set ortb2 global data
438
- * @param {Object} profile
439
- * @param {Boolean} site
440
- * @returns {void}
441
- */
442
- function setGlobalOrtb2(profile, site) {
443
- const section = ((site) ? 'site' : 'user');
444
- const base = `${section}.ext.data`;
445
- const addOrtb2 = {};
446
-
447
- assignProfileToObject(addOrtb2, base, profile);
448
-
449
- if (!isEmpty(addOrtb2)) {
450
- const testGlobal = getGlobal().getConfig('ortb2') || {};
451
- const ortb2 = {
452
- ortb2: mergeDeep({}, testGlobal, addOrtb2)
453
- };
454
- getGlobal().setConfig(ortb2);
702
+ handleBidViaORTB2(bid, profile, metadata);
455
703
  }
456
704
  }
457
705
 
458
- /**
459
- * assign profile to object
460
- * @param {Object} destination
461
- * @param {string} base
462
- * @param {Object} profile
463
- * @returns {void}
464
- */
465
- function assignProfileToObject(destination, base, profile) {
466
- Object.keys(profile).forEach(key => {
467
- const path = `${base}.${key}`;
468
- deepSetValue(destination, path, profile[key])
469
- })
470
- }
471
-
472
- /** handle rubicon bid
473
- * @param {Object} profile
474
- * @param {Boolean} site
475
- * @param {Object} bid
476
- * @returns {void}
477
- */
478
- function handleRubiconBid(profile, site, bid) {
479
- const section = (site) ? 'inventory' : 'visitor';
480
- const base = `params.${section}`;
481
- assignProfileToObject(bid, base, profile);
482
- }
483
-
484
706
  /** handle appnexus/xandr bid
485
- * @param {Object} profile
486
707
  * @param {Object} bid
708
+ * @param {Object} profile
487
709
  * @returns {void}
488
710
  */
489
- function handleAppnexusBid(profile, bid) {
711
+ function handleAppnexusBid(bid, profile) {
490
712
  const base = 'params.keywords';
491
713
  assignProfileToObject(bid, base, profile);
492
714
  }
493
715
 
494
716
  /** handle pubmatic bid
495
- * @param {Object} profile
496
717
  * @param {Object} bid
718
+ * @param {Object} profile
497
719
  * @returns {void}
498
720
  */
499
- function handlePubmaticBid(profile, bid) {
721
+ function handlePubmaticBid(bid, profile) {
500
722
  const sep = '|';
501
723
  const subsep = ',';
502
- const bidKey = 'params.dctr';
503
724
  const target = [];
504
725
 
505
- const data = deepAccess(bid, bidKey);
726
+ bid.params ||= {};
727
+
728
+ const data = bid.params.dctr;
506
729
  if (data) {
507
730
  data.split(sep).forEach(t => target.push(t));
508
731
  }
@@ -515,20 +738,21 @@ function handlePubmaticBid(profile, bid) {
515
738
  }
516
739
  });
517
740
 
518
- deepSetValue(bid, bidKey, target.join(sep));
741
+ bid.params.dctr = target.join(sep);
519
742
  }
520
743
 
521
744
  /** handle smartadserver bid
522
- * @param {Object} profile
523
745
  * @param {Object} bid
746
+ * @param {Object} profile
524
747
  * @returns {void}
525
748
  */
526
- function handleSmartadserverBid(profile, bid) {
749
+ function handleSmartadserverBid(bid, profile) {
527
750
  const sep = ';';
528
- const bidKey = 'params.target';
529
751
  const target = [];
530
752
 
531
- const data = deepAccess(bid, bidKey);
753
+ bid.params ||= {};
754
+
755
+ const data = bid.params.target;
532
756
  if (data) {
533
757
  data.split(sep).forEach(t => target.push(t));
534
758
  }
@@ -541,7 +765,56 @@ function handleSmartadserverBid(profile, bid) {
541
765
  }
542
766
  });
543
767
  });
544
- deepSetValue(bid, bidKey, target.join(sep));
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 {Object} bid
790
+ * @param {Object} profile
791
+ * @param {Object} metadata
792
+ * @returns {void}
793
+ */
794
+ function handleBidViaORTB2(bid, profile, metadata) {
795
+ if (isBoolean(metadata.user)) {
796
+ logMessage(`bidder '${bid.bidder}' is not directly supported, trying set data via bidder ortb2 fpd`);
797
+ const section = ((metadata.user) ? 'user' : 'site');
798
+ const base = `ortb2.${section}.ext.data`;
799
+
800
+ assignProfileToObject(bid, base, profile);
801
+ } else {
802
+ logMessage(`SKIP unsupported bidder '${bid.bidder}', data from '${metadata.source}' is not defined as user or site-centric`);
803
+ }
804
+ }
805
+
806
+ /**
807
+ * assign profile to object
808
+ * @param {Object} destination
809
+ * @param {string} base
810
+ * @param {Object} profile
811
+ * @returns {void}
812
+ */
813
+ function assignProfileToObject(destination, base, profile) {
814
+ Object.keys(profile).forEach(key => {
815
+ const path = `${base}.${key}`;
816
+ deepSetValue(destination, path, profile[key])
817
+ })
545
818
  }
546
819
 
547
820
  /** set bigsea contextual profile on module state
@@ -549,7 +822,7 @@ function handleSmartadserverBid(profile, bid) {
549
822
  * @returns {void}
550
823
  */
551
824
  export function setWeboContextualProfile(data) {
552
- if (data && Object.keys(data).length > 0) {
825
+ if (data && isPlainObject(data) && isValidProfile(data) && !isEmpty(data)) {
553
826
  _weboContextualProfile = data;
554
827
  }
555
828
  }
@@ -574,15 +847,16 @@ export function setWeboContextualProfile(data) {
574
847
  function fetchContextualProfile(weboCtxConf, onSuccess, onDone) {
575
848
  const targetURL = weboCtxConf.targetURL || document.URL;
576
849
  const token = weboCtxConf.token;
850
+ const baseURLProfileAPI = weboCtxConf.baseURLProfileAPI || BASE_URL_CONTEXTUAL_PROFILE_API;
577
851
 
578
852
  let queryString = '';
579
853
  queryString = tryAppendQueryString(queryString, 'token', token);
580
854
  queryString = tryAppendQueryString(queryString, 'url', targetURL);
581
855
 
582
- const url = `https://ctx.weborama.com/api/profile?${queryString}`;
856
+ const urlProfileAPI = `https://${baseURLProfileAPI}/api/profile?${queryString}`;
583
857
 
584
- ajax(url, {
585
- success: function(response, req) {
858
+ ajax(urlProfileAPI, {
859
+ success: (response, req) => {
586
860
  if (req.status === 200) {
587
861
  try {
588
862
  const data = JSON.parse(response);
@@ -597,7 +871,7 @@ function fetchContextualProfile(weboCtxConf, onSuccess, onDone) {
597
871
  onDone();
598
872
  }
599
873
  },
600
- error: function() {
874
+ error: () => {
601
875
  onDone();
602
876
  logError('unable to get weborama data');
603
877
  }