@@ -2,6 +2,7 @@ import { getValue, logError, deepAccess, parseSizesInput, getBidIdParameter, log
2
2
import { registerBidder } from '../src/adapters/bidderFactory.js' ;
3
3
import { getStorageManager } from '../src/storageManager.js' ;
4
4
import { getDM , getHC , getHLen } from '../libraries/navigatorData/navigatorData.js' ;
5
+ import { getTimeToFirstByte } from '../libraries/timeToFirstBytesUtils/timeToFirstBytesUtils.js' ;
5
6
6
7
/**
7
8
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest } BidRequest
@@ -10,7 +11,7 @@ import { getDM, getHC, getHLen } from '../libraries/navigatorData/navigatorData.
10
11
11
12
const BIDDER_CODE = 'greenbids' ;
12
13
const GVL_ID = 1232 ;
13
- const ENDPOINT_URL = 'https://d .greenbids.ai/hb/bid-request ' ;
14
+ const ENDPOINT_URL = 'https://hb .greenbids.ai' ;
14
15
export const storage = getStorageManager ( { bidderCode : BIDDER_CODE } ) ;
15
16
16
17
export const spec = {
@@ -40,7 +41,18 @@ export const spec = {
40
41
* @return ServerRequest Info describing the request to the server.
41
42
*/
42
43
buildRequests : function ( validBidRequests , bidderRequest ) {
43
- const bids = validBidRequests . map ( cleanBidsInfo ) ;
44
+ const bids = validBidRequests . map ( bids => {
45
+ const reqObj = { } ;
46
+ let placementId = getValue ( bids . params , 'placementId' ) ;
47
+ const gpid = deepAccess ( bids , 'ortb2Imp.ext.gpid' ) ;
48
+ reqObj . sizes = getSizes ( bids ) ;
49
+ reqObj . bidId = getBidIdParameter ( 'bidId' , bids ) ;
50
+ reqObj . bidderRequestId = getBidIdParameter ( 'bidderRequestId' , bids ) ;
51
+ reqObj . placementId = parseInt ( placementId , 10 ) ;
52
+ reqObj . adUnitCode = getBidIdParameter ( 'adUnitCode' , bids ) ;
53
+ reqObj . transactionId = bids . ortb2Imp ?. ext ?. tid || '' ;
54
+ if ( gpid ) { reqObj . gpid = gpid ; }
55
+ } ) ;
44
56
const topWindow = window . top ;
45
57
46
58
const payload = {
@@ -70,8 +82,8 @@ export const spec = {
70
82
payload . schain = firstBidRequest . schain ;
71
83
}
72
84
73
- hydratePayloadWithGppData ( payload , bidderRequest . gppConsent ) ;
74
- hydratePayloadWithGdprData ( payload , bidderRequest . gdprConsent ) ;
85
+ hydratePayloadWithGppConsentData ( payload , bidderRequest . gppConsent ) ;
86
+ hydratePayloadWithGdprConsentData ( payload , bidderRequest . gdprConsent ) ;
75
87
hydratePayloadWithUspConsentData ( payload , bidderRequest . uspConsent ) ;
76
88
77
89
const userAgentClientHints = deepAccess ( firstBidRequest , 'ortb2.device.sua' ) ;
@@ -133,6 +145,15 @@ export const spec = {
133
145
registerBidder ( spec ) ;
134
146
135
147
// Page info retrival
148
+
149
+ /**
150
+ * Retrieves the referrer information from the bidder request.
151
+ *
152
+ * @param {Object } bidderRequest - The bidder request object.
153
+ * @param {Object } [bidderRequest.refererInfo] - The referer information object.
154
+ * @param {string } [bidderRequest.refererInfo.page] - The page URL of the referer.
155
+ * @returns {string } The referrer URL if available, otherwise an empty string.
156
+ */
136
157
function getReferrerInfo ( bidderRequest ) {
137
158
let ref = '' ;
138
159
if ( bidderRequest && bidderRequest . refererInfo && bidderRequest . refererInfo . page ) {
@@ -141,6 +162,15 @@ function getReferrerInfo(bidderRequest) {
141
162
return ref ;
142
163
}
143
164
165
+ /**
166
+ * Retrieves the title of the current web page.
167
+ *
168
+ * This function attempts to get the title from the top-level window's document.
169
+ * If an error occurs (e.g., due to cross-origin restrictions), it falls back to the current document.
170
+ * It first tries to get the title from the `og:title` meta tag, and if that is not available, it uses the document's title.
171
+ *
172
+ * @returns {string } The title of the current web page, or an empty string if no title is found.
173
+ */
144
174
function getPageTitle ( ) {
145
175
try {
146
176
const ogTitle = window . top . document . querySelector ( 'meta[property="og:title"]' ) ;
@@ -151,6 +181,15 @@ function getPageTitle() {
151
181
}
152
182
}
153
183
184
+ /**
185
+ * Retrieves the content of the page description meta tag.
186
+ *
187
+ * This function attempts to get the description from the top-level window's document.
188
+ * If it fails (e.g., due to cross-origin restrictions), it falls back to the current document.
189
+ * It looks for meta tags with either the name "description" or the property "og:description".
190
+ *
191
+ * @returns {string } The content of the description meta tag, or an empty string if not found.
192
+ */
154
193
function getPageDescription ( ) {
155
194
try {
156
195
const element = window . top . document . querySelector ( 'meta[name="description"]' ) ||
@@ -163,73 +202,60 @@ function getPageDescription() {
163
202
}
164
203
}
165
204
205
+ /**
206
+ * Retrieves the downlink speed of the user's network connection.
207
+ *
208
+ * @param {object } nav - The navigator object, typically `window.navigator`.
209
+ * @returns {string } The downlink speed as a string if available, otherwise an empty string.
210
+ */
166
211
function getConnectionDownLink ( nav ) {
167
212
return nav && nav . connection && nav . connection . downlink >= 0 ? nav . connection . downlink . toString ( ) : '' ;
168
213
}
169
214
170
- function getTimeToFirstByte ( win ) {
171
- const performance = win . performance || win . webkitPerformance || win . msPerformance || win . mozPerformance ;
172
-
173
- const ttfbWithTimingV2 = performance &&
174
- typeof performance . getEntriesByType === 'function' &&
175
- Object . prototype . toString . call ( performance . getEntriesByType ) === '[object Function]' &&
176
- performance . getEntriesByType ( 'navigation' ) [ 0 ] &&
177
- performance . getEntriesByType ( 'navigation' ) [ 0 ] . responseStart &&
178
- performance . getEntriesByType ( 'navigation' ) [ 0 ] . requestStart &&
179
- performance . getEntriesByType ( 'navigation' ) [ 0 ] . responseStart > 0 &&
180
- performance . getEntriesByType ( 'navigation' ) [ 0 ] . requestStart > 0 &&
181
- Math . round (
182
- performance . getEntriesByType ( 'navigation' ) [ 0 ] . responseStart - performance . getEntriesByType ( 'navigation' ) [ 0 ] . requestStart
183
- ) ;
184
-
185
- if ( ttfbWithTimingV2 ) {
186
- return ttfbWithTimingV2 . toString ( ) ;
187
- }
188
-
189
- const ttfbWithTimingV1 = performance &&
190
- performance . timing . responseStart &&
191
- performance . timing . requestStart &&
192
- performance . timing . responseStart > 0 &&
193
- performance . timing . requestStart > 0 &&
194
- performance . timing . responseStart - performance . timing . requestStart ;
195
-
196
- return ttfbWithTimingV1 ? ttfbWithTimingV1 . toString ( ) : '' ;
197
- }
198
-
199
- function cleanBidsInfo ( bids ) {
200
- const reqObj = { } ;
201
- let placementId = getValue ( bids . params , 'placementId' ) ;
202
- const gpid = deepAccess ( bids , 'ortb2Imp.ext.gpid' ) ;
203
- reqObj . sizes = getSizes ( bids ) ;
204
- reqObj . bidId = getBidIdParameter ( 'bidId' , bids ) ;
205
- reqObj . bidderRequestId = getBidIdParameter ( 'bidderRequestId' , bids ) ;
206
- reqObj . placementId = parseInt ( placementId , 10 ) ;
207
- reqObj . adUnitCode = getBidIdParameter ( 'adUnitCode' , bids ) ;
208
- reqObj . transactionId = bids . ortb2Imp ?. ext ?. tid || '' ;
209
- if ( gpid ) { reqObj . gpid = gpid ; }
210
- return reqObj ;
211
- }
212
-
215
+ /**
216
+ * Converts the sizes from the bid object to the required format.
217
+ *
218
+ * @param {Object } bid - The bid object containing size information.
219
+ * @param {Array } bid.sizes - The sizes array from the bid object.
220
+ * @returns {Array } - The parsed sizes in the required format.
221
+ */
213
222
function getSizes ( bid ) {
214
223
return parseSizesInput ( bid . sizes ) ;
215
224
}
216
225
217
226
// Privacy handling
218
227
219
- export function hydratePayloadWithGppData ( payload , gppData ) {
220
- if ( gppData ) {
221
- let isValidConsentString = typeof gppData . gppString === 'string' ;
222
- let validateApplicableSections =
228
+ /**
229
+ * Hydrates the given payload with GPP consent data if available.
230
+ *
231
+ * @param {Object } payload - The payload object to be hydrated.
232
+ * @param {Object } gppData - The GPP consent data object.
233
+ * @param {string } gppData.gppString - The GPP consent string.
234
+ * @param {number[] } gppData.applicableSections - An array of applicable section IDs.
235
+ */
236
+ function hydratePayloadWithGppConsentData ( payload , gppData ) {
237
+ if ( ! gppData ) { return ; }
238
+ let isValidConsentString = typeof gppData . gppString === 'string' ;
239
+ let validateApplicableSections =
223
240
Array . isArray ( gppData . applicableSections ) &&
224
241
gppData . applicableSections . every ( ( section ) => typeof ( section ) === 'number' )
225
- payload . gpp = {
226
- consentString : isValidConsentString ? gppData . gppString : '' ,
227
- applicableSectionIds : validateApplicableSections ? gppData . applicableSections : [ ] ,
228
- } ;
229
- }
242
+ payload . gpp = {
243
+ consentString : isValidConsentString ? gppData . gppString : '' ,
244
+ applicableSectionIds : validateApplicableSections ? gppData . applicableSections : [ ] ,
245
+ } ;
230
246
}
231
247
232
- export function hydratePayloadWithGdprData ( payload , gdprData ) {
248
+ /**
249
+ * Hydrates the given payload with GDPR consent data if available.
250
+ *
251
+ * @param {Object } payload - The payload object to be hydrated with GDPR consent data.
252
+ * @param {Object } gdprData - The GDPR data object containing consent information.
253
+ * @param {boolean } gdprData.gdprApplies - Indicates if GDPR applies.
254
+ * @param {string } gdprData.consentString - The GDPR consent string.
255
+ * @param {number } gdprData.apiVersion - The version of the GDPR API being used.
256
+ * @param {Object } gdprData.vendorData - Additional vendor data related to GDPR.
257
+ */
258
+ function hydratePayloadWithGdprConsentData ( payload , gdprData ) {
233
259
if ( ! gdprData ) { return ; }
234
260
let isCmp = typeof gdprData . gdprApplies === 'boolean' ;
235
261
let isConsentString = typeof gdprData . consentString === 'string' ;
@@ -243,10 +269,15 @@ export function hydratePayloadWithGdprData(payload, gdprData) {
243
269
} ;
244
270
}
245
271
246
- export function hydratePayloadWithUspConsentData ( payload , uspConsentData ) {
247
- if ( uspConsentData ) {
248
- payload . us_privacy = uspConsentData ;
249
- }
272
+ /**
273
+ * Adds USP (CCPA) consent data to the payload if available.
274
+ *
275
+ * @param {Object } payload - The payload object to be hydrated with USP consent data.
276
+ * @param {string } uspConsentData - The USP consent string to be added to the payload.
277
+ */
278
+ function hydratePayloadWithUspConsentData ( payload , uspConsentData ) {
279
+ if ( ! uspConsentData ) { return ; }
280
+ payload . us_privacy = uspConsentData ;
250
281
}
251
282
252
283
const gdprStatus = {
@@ -256,6 +287,14 @@ const gdprStatus = {
256
287
CMP_NOT_FOUND_OR_ERROR : 22
257
288
} ;
258
289
290
+ /**
291
+ * Determines the GDPR status based on whether GDPR applies and the provided GDPR data.
292
+ *
293
+ * @param {boolean } gdprApplies - Indicates if GDPR applies.
294
+ * @param {Object } gdprData - The GDPR data object.
295
+ * @param {boolean } gdprData.isServiceSpecific - Indicates if the GDPR data is service-specific.
296
+ * @returns {string } The GDPR status.
297
+ */
259
298
function findGdprStatus ( gdprApplies , gdprData ) {
260
299
let status = gdprStatus . GDPR_APPLIES_PUBLISHER ;
261
300
if ( gdprApplies ) {
0 commit comments