From 17451f86f29d5fa1abdb7637d4d936b9f065df2c Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Wed, 26 Jun 2024 16:56:09 +0530 Subject: [PATCH 01/12] Preciso : Added new library to remove code duplication in bid adapter --- integrationExamples/gpt/precisoExample.html | 166 +++++++++++++ libraries/precisoUtils/precisoUtils.js | 161 ++++++++++++ modules/precisoBidAdapter.js | 230 ++++-------------- .../precisoUtils/precisoUtils_spec.js | 155 ++++++++++++ test/spec/modules/precisoBidAdapter_spec.js | 73 +++--- 5 files changed, 562 insertions(+), 223 deletions(-) create mode 100644 integrationExamples/gpt/precisoExample.html create mode 100644 libraries/precisoUtils/precisoUtils.js create mode 100644 test/spec/libraries/precisoUtils/precisoUtils_spec.js diff --git a/integrationExamples/gpt/precisoExample.html b/integrationExamples/gpt/precisoExample.html new file mode 100644 index 00000000000..1d7680256f4 --- /dev/null +++ b/integrationExamples/gpt/precisoExample.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + +

Basic Prebid.js Example with Preciso Bidder

+

Adslot-1

+
+ +
+ +
+

Adslot-2

+ +
+ + + + diff --git a/libraries/precisoUtils/precisoUtils.js b/libraries/precisoUtils/precisoUtils.js new file mode 100644 index 00000000000..54315d847b8 --- /dev/null +++ b/libraries/precisoUtils/precisoUtils.js @@ -0,0 +1,161 @@ +import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; +import { isFn, deepAccess, replaceAuctionPrice } from '../../src/utils.js'; +import { ajax } from '../../src/ajax.js'; + +export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest) => { + // convert Native ORTB definition to old-style prebid native definition + validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); + var city = Intl.DateTimeFormat().resolvedOptions().timeZone; + let req = { + // bidRequest: bidderRequest, + id: validBidRequests[0].auctionId, + cur: validBidRequests[0].params.currency || ['USD'], + imp: validBidRequests.map(req => { + const { bidId, sizes } = req + const impValue = { + id: bidId, + bidFloor: getBidFloorPrice(req), + bidfloorcur: req.params.currency + } + if (req.mediaTypes.banner) { + impValue.banner = { + format: (req.mediaTypes.banner.sizes || sizes).map(size => { + return { w: size[0], h: size[1] } + }), + + } + } + return impValue + }), + user: { + id: validBidRequests[0].userId.pubcid || '', + buyeruid: window.localStorage.getItem('_pre|id'), + geo: { + country: validBidRequests[0].params.region || city, + }, + + }, + device: validBidRequests[0].ortb2.device, + site: validBidRequests[0].ortb2.site, + source: validBidRequests[0].ortb2.source, + bcat: validBidRequests[0].ortb2.bcat || validBidRequests[0].params.bcat, + badv: validBidRequests[0].ortb2.badv || validBidRequests[0].params.badv, + wlang: validBidRequests[0].ortb2.wlang || validBidRequests[0].params.wlang, + }; + req.site.publisher = { + publisherId: validBidRequests[0].params.publisherId + }; + + // req.language.indexOf('-') != -1 && (req.language = req.language.split('-')[0]) + if (bidderRequest) { + if (bidderRequest.uspConsent) { + req.ccpa = bidderRequest.uspConsent; + } + if (bidderRequest.gdprConsent) { + req.gdpr = bidderRequest.gdprConsent + } + if (bidderRequest.gppConsent) { + req.gpp = bidderRequest.gppConsent; + } + } + + return { + method: 'POST', + url: endpoint, + data: req, + + }; +} + +export function interpretResponse(serverResponse) { + const bidsValue = [] + const bidResponse = serverResponse.body + bidResponse.seatbid.forEach(seat => { + seat.bid.forEach(bid => { + bidsValue.push({ + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + creativeId: bid.crid, + ad: macroReplace(bid.adm, bid.price), + currency: 'USD', + netRevenue: true, + ttl: 300, + meta: { + advertiserDomains: bid.adomain || '', + }, + }) + }) + }) + return bidsValue +} + +export const getUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { + let userId = 'NA'; + // let userId = readFromAllStorages(strId, storage); + let syncs = []; + let syncUrl = `${syncEndpoint}id=${userId}` + + if (gdprConsent) { + syncUrl = syncUrl + `&gdpr=${Number(gdprConsent.gdprApplies && 1)}&gdpr_consent=${encodeURIComponent(gdprConsent.consentString || '')}`; + } else { + syncUrl = syncUrl + `&gdpr=0&gdpr_consent=` + } + if (uspConsent) { + syncUrl = syncUrl + `&us_privacy=${uspConsent}` + } else { + syncUrl = syncUrl + `&us_privacy=` + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: syncUrl + `&t=4` + }); + } else { + syncs.push({ + type: 'image', + url: syncUrl + `&t=2` + }); + } + + return syncs +} + +export function onBidWon(bid) { + if (bid.nurl) { + const resolvedNurl = replaceAuctionPrice(bid.nurl, bid.price); + ajax(resolvedNurl); + } +} + +function getBidFloorPrice(bid) { + if (!isFn(bid.getFloor)) { + return deepAccess(bid, 'params.bidFloor', 0); + } + + try { + const bidFloorPrice = bid.getFloor({ + currency: 'USD', + mediaType: '*', + size: '*', + }); + return bidFloorPrice.floor; + } catch (_) { + return 0 + } +} + +/* replacing auction_price macro from adm */ +function macroReplace(adm, cpm) { + let replacedadm = replaceAuctionPrice(adm, cpm); + return replacedadm; +} + +export function readFromAllStorages(name, storage) { + const fromCookie = storage.getCookie(name); + const fromLocalStorage = storage.getDataFromLocalStorage(name); + + return fromCookie || fromLocalStorage || 'NA'; +} diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index b4f1b665d91..d1dd93921c6 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -1,205 +1,69 @@ -import { isFn, deepAccess, logInfo } from '../src/utils.js'; +import { logInfo } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; - -const BIDDER_CODE = 'preciso'; -const AD_URL = 'https://ssp-bidder.mndtrk.com/bid_request/openrtb'; -const URL_SYNC = 'https://ck.2trk.info/rtb/user/usersync.aspx?'; -const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE, VIDEO]; +import { BANNER } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { MODULE_TYPE_UID } from '../src/activities/modules.js'; +import { getUserSyncs, buildRequests, interpretResponse, onBidWon, readFromAllStorages } from '../libraries/precisoUtils/precisoUtils.js'; + +const BIDDER__CODE = 'preciso'; +const strId = '_sharedid'; +const SUPPORTED_MEDIA_TYPES = [BANNER]; const GVLID = 874; -let userId = 'NA'; +let precisoId = 'NA'; +let sharedId = 'NA' +const endpoint = 'https://ssp-bidder.mndtrk.com/bid_request/openrtb'; +const syncEndpoint = 'https://ck.2trk.info/rtb/user/usersync.aspx?'; +// const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId='; + +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); +export const storage2 = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); export const spec = { - code: BIDDER_CODE, + code: BIDDER__CODE, supportedMediaTypes: SUPPORTED_MEDIA_TYPES, gvlid: GVLID, isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && !isNaN(bid.params.publisherId) && bid.params.host == 'prebid'); - }, - - buildRequests: (validBidRequests = [], bidderRequest) => { - // convert Native ORTB definition to old-style prebid native definition - validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); - // userId = validBidRequests[0].userId.pubcid; - let winTop = window; - let location; - var offset = new Date().getTimezoneOffset(); - logInfo('timezone ' + offset); - var city = Intl.DateTimeFormat().resolvedOptions().timeZone; - logInfo('location test' + city) - - const countryCode = getCountryCodeByTimezone(city); - logInfo(`The country code for ${city} is ${countryCode}`); - - location = bidderRequest?.refererInfo ?? null; - - let request = { - id: validBidRequests[0].bidderRequestId, - - imp: validBidRequests.map(request => { - const { bidId, sizes, mediaType, ortb2 } = request - const item = { - id: bidId, - region: request.params.region, - traffic: mediaType, - bidFloor: getBidFloor(request), - ortb2: ortb2 - - } - - if (request.mediaTypes.banner) { - item.banner = { - format: (request.mediaTypes.banner.sizes || sizes).map(size => { - return { w: size[0], h: size[1] } - }), - } - } - - if (request.schain) { - item.schain = request.schain; - } - - if (request.floorData) { - item.bidFloor = request.floorData.floorMin; - } - return item - }), - auctionId: validBidRequests[0].auctionId, - 'deviceWidth': winTop.screen.width, - 'deviceHeight': winTop.screen.height, - 'language': (navigator && navigator.language) ? navigator.language : '', - geo: navigator.geolocation.getCurrentPosition(position => { - const { latitude, longitude } = position.coords; - return { - latitude: latitude, - longitude: longitude - } - // Show a map centered at latitude / longitude. - }) || { utcoffset: new Date().getTimezoneOffset() }, - city: city, - 'host': location?.domain ?? '', - 'page': location?.page ?? '', - 'coppa': config.getConfig('coppa') === true ? 1 : 0 - // userId: validBidRequests[0].userId - }; - - request.language.indexOf('-') != -1 && (request.language = request.language.split('-')[0]) - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent - } - if (bidderRequest.gppConsent) { - request.gpp = bidderRequest.gppConsent; + sharedId = readFromAllStorages(strId, storage); + let precisoBid = true; + const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId=' + sharedId; + precisoId = window.localStorage.getItem('_pre|id'); + + if (Object.is(precisoId, 'NA') || Object.is(precisoId, null) || Object.is(precisoId, undefined)) { + if (!bid.precisoBid) { + precisoBid = false; + getapi(preCall); } } - return { - method: 'POST', - url: AD_URL, - data: request, - - }; - }, - - interpretResponse: function (serverResponse) { - const response = serverResponse.body - - const bids = [] - - response.seatbid.forEach(seat => { - seat.bid.forEach(bid => { - bids.push({ - requestId: bid.impid, - cpm: bid.price, - width: bid.w, - height: bid.h, - creativeId: bid.crid, - ad: bid.adm, - currency: 'USD', - netRevenue: true, - ttl: 300, - meta: { - advertiserDomains: bid.adomain || [], - }, - }) - }) - }) - - return bids + return Boolean(bid.bidId && bid.params && bid.params.publisherId && precisoBid); }, + buildRequests: buildRequests(endpoint), + interpretResponse, + onBidWon, + getUserSyncs: getUserSyncs(syncEndpoint) +}; - getUserSyncs: (syncOptions, serverResponses = [], gdprConsent = {}, uspConsent = '', gppConsent = '') => { - let syncs = []; - let { gdprApplies, consentString = '' } = gdprConsent; +registerBidder(spec); - if (serverResponses.length > 0) { - logInfo('preciso bidadapter getusersync serverResponses:' + serverResponses.toString); - } - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: `${URL_SYNC}id=${userId}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${consentString}&us_privacy=${uspConsent}&t=4` - }); - } else { - syncs.push({ - type: 'image', - url: `${URL_SYNC}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${consentString}&us_privacy=${uspConsent}&t=2` - }); - } +async function getapi(url) { + try { + // Storing response + const response = await fetch(url); - return syncs - } + // Storing data in form of JSON + var data = await response.json(); -}; + const dataMap = new Map(Object.entries(data)); -function getCountryCodeByTimezone(city) { - try { - const now = new Date(); - const options = { - timeZone: city, - timeZoneName: 'long', - }; - const [timeZoneName] = new Intl.DateTimeFormat('en-US', options) - .formatToParts(now) - .filter((part) => part.type === 'timeZoneName'); + const uuidValue = dataMap.get('UUID'); - if (timeZoneName) { - // Extract the country code from the timezone name - const parts = timeZoneName.value.split('-'); - if (parts.length >= 2) { - return parts[1]; - } + if (!Object.is(uuidValue, null) && !Object.is(uuidValue, undefined)) { + storage2.setDataInLocalStorage('_pre|id', uuidValue); + logInfo('DEBUG nonNull uuidValue:' + uuidValue); } + return data; } catch (error) { - // Handle errors, such as an invalid timezone city - logInfo(error); + logInfo('Error in preciso precall' + error); } - - // Handle the case where the city is not found or an error occurred - return 'Unknown'; } - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidFloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} - -registerBidder(spec); diff --git a/test/spec/libraries/precisoUtils/precisoUtils_spec.js b/test/spec/libraries/precisoUtils/precisoUtils_spec.js new file mode 100644 index 00000000000..34826bf9477 --- /dev/null +++ b/test/spec/libraries/precisoUtils/precisoUtils_spec.js @@ -0,0 +1,155 @@ + +import { expect } from 'chai'; +import { buildRequests, interpretResponse, getUserSyncs } from '../../../../libraries/precisoUtils/precisoUtils.js'; +import { getStorageManager } from '../../../../src/storageManager.js'; +import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; + +const DEFAULT_PRICE = 1 +const DEFAULT_CURRENCY = 'USD' +const DEFAULT_BANNER_WIDTH = 300 +const DEFAULT_BANNER_HEIGHT = 250 +const BIDDER_CODE = 'bidder'; +const TESTDOMAIN = 'test.org' +const cookieName = 'test'; + +const bidEndPoint = `https://${TESTDOMAIN}/bid_request/openrtb`; +const syncEndPoint = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?`; +const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE }); + +describe('bidderOperations', function () { + let bid = { + bidId: '23fhj33i987f', + bidder: BIDDER_CODE, + mediaTypes: { + banner: { + sizes: [[DEFAULT_BANNER_WIDTH, DEFAULT_BANNER_HEIGHT]] + } + }, + params: { + host: 'prebid', + sourceid: '0', + publisherId: '0', + mediaType: 'banner', + region: 'IND' + + }, + userId: { + pubcid: '12355454test' + + }, + user: { + geo: { + region: 'IND', + } + }, + ortb2: { + device: { + w: 1920, + h: 166, + dnt: 0, + }, + site: { + domain: 'localHost' + }, + source: { + tid: 'eaff09b-a1ab-4ec6-a81e-c5a75bc1dde3' + } + + } + + }; + + const spec = { + // isBidRequestValid: isBidRequestValid(), + buildRequests: buildRequests(bidEndPoint), + interpretResponse, + getUserSyncs: getUserSyncs(syncEndPoint, cookieName, storage) + }; + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', function () { + expect(serverRequest.url).to.equal(`https://${TESTDOMAIN}/bid_request/openrtb`); + }); + it('Returns valid data if array of bids is valid', function () { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data.device).to.be.a('object'); + expect(data.user).to.be.a('object'); + expect(data.source).to.be.a('object'); + expect(data.site).to.be.a('object'); + }); + it('Returns data.device is undefined if no valid device object is passed', function () { + delete bid.ortb2.device; + serverRequest = spec.buildRequests([bid]); + let data = serverRequest.data; + expect(data.device).to.be.undefined; + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response', function () { + let response = { + bidderRequestId: 'f6adb85f-4e19-45a0-b41e-2a5b9a48f23a', + seatbid: [ + { + bid: [ + { + id: '123', + impid: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', + price: DEFAULT_PRICE, + adm: 'hi', + cid: 'test_cid', + crid: 'test_banner_crid', + w: DEFAULT_BANNER_WIDTH, + h: DEFAULT_BANNER_HEIGHT, + adomain: [], + } + ], + seat: BIDDER_CODE + } + ], + } + let expectedResponse = [ + { + requestId: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', + cpm: DEFAULT_PRICE, + width: DEFAULT_BANNER_WIDTH, + height: DEFAULT_BANNER_HEIGHT, + creativeId: 'test_banner_crid', + ad: 'hi', + currency: DEFAULT_CURRENCY, + netRevenue: true, + ttl: 300, + meta: { advertiserDomains: [] }, + } + ] + let result = spec.interpretResponse({ body: response }) + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])) + }) + }); + describe('getUserSyncs', function () { + const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4`; + const syncOptions = { + iframeEnabled: true + }; + let userSync = spec.getUserSyncs(syncOptions); + it('Returns valid URL and type', function () { + expect(userSync).to.be.an('array').with.lengthOf(1); + expect(userSync[0].type).to.exist; + expect(userSync[0].url).to.exist; + expect(userSync).to.deep.equal([ + { type: 'iframe', url: syncUrl } + ]); + }); + }); +}); diff --git a/test/spec/modules/precisoBidAdapter_spec.js b/test/spec/modules/precisoBidAdapter_spec.js index 78a1615a02e..4ac1c479bb9 100644 --- a/test/spec/modules/precisoBidAdapter_spec.js +++ b/test/spec/modules/precisoBidAdapter_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { spec } from '../../../modules/precisoBidAdapter.js'; -import { config } from '../../../src/config.js'; +// simport { config } from '../../../src/config.js'; const DEFAULT_PRICE = 1 const DEFAULT_CURRENCY = 'USD' @@ -10,6 +10,7 @@ const BIDDER_CODE = 'preciso'; describe('PrecisoAdapter', function () { let bid = { + precisoBid: true, bidId: '23fhj33i987f', bidder: 'preciso', mediaTypes: { @@ -22,15 +23,33 @@ describe('PrecisoAdapter', function () { sourceid: '0', publisherId: '0', mediaType: 'banner', - region: 'prebid-eu' + region: 'IND' }, userId: { pubcid: '12355454test' }, - geo: 'NA', - city: 'Asia,delhi' + user: { + geo: { + region: 'IND', + } + }, + ortb2: { + device: { + w: 1920, + h: 166, + dnt: 0, + }, + site: { + domain: 'localHost' + }, + source: { + tid: 'eaff09b-a1ab-4ec6-a81e-c5a75bc1dde3' + } + + } + }; describe('isBidRequestValid', function () { @@ -59,43 +78,17 @@ describe('PrecisoAdapter', function () { }); it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; - // expect(data).to.be.an('object'); - - // expect(data).to.have.all.keys('bidId', 'imp', 'site', 'deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'coppa'); - - expect(data.deviceWidth).to.be.a('number'); - expect(data.deviceHeight).to.be.a('number'); - expect(data.coppa).to.be.a('number'); - expect(data.language).to.be.a('string'); - // expect(data.secure).to.be.within(0, 1); - expect(data.host).to.be.a('string'); - expect(data.page).to.be.a('string'); - - expect(data.city).to.be.a('string'); - expect(data.geo).to.be.a('object'); - // expect(data.userId).to.be.a('string'); - // expect(data.imp).to.be.a('object'); - }); - // it('Returns empty data if no valid requests are passed', function () { - /// serverRequest = spec.buildRequests([]); - // let data = serverRequest.data; - // expect(data.imp).to.be.an('array').that.is.empty; - // }); - }); - - describe('with COPPA', function () { - beforeEach(function () { - sinon.stub(config, 'getConfig') - .withArgs('coppa') - .returns(true); + expect(data).to.be.an('object'); + expect(data.device).to.be.a('object'); + expect(data.user).to.be.a('object'); + expect(data.source).to.be.a('object'); + expect(data.site).to.be.a('object'); }); - afterEach(function () { - config.getConfig.restore(); - }); - - it('should send the Coppa "required" flag set to "1" in the request', function () { - let serverRequest = spec.buildRequests([bid]); - expect(serverRequest.data.coppa).to.equal(1); + it('Returns empty data if no valid requests are passed', function () { + delete bid.ortb2.device; + serverRequest = spec.buildRequests([bid]); + let data = serverRequest.data; + expect(data.device).to.be.undefined; }); }); From 23731e602e471e8679c664412ae886bf523daa5e Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 27 Jun 2024 11:43:12 +0530 Subject: [PATCH 02/12] modified bidfloor mapping logic --- integrationExamples/gpt/precisoExample.html | 4 +++- libraries/precisoUtils/precisoUtils.js | 26 ++++++--------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/integrationExamples/gpt/precisoExample.html b/integrationExamples/gpt/precisoExample.html index 1d7680256f4..f354f0eaf5c 100644 --- a/integrationExamples/gpt/precisoExample.html +++ b/integrationExamples/gpt/precisoExample.html @@ -34,6 +34,7 @@ publisherId: 'PRECISO_TEST00001', traffic: 'banner', bidFloor: 0.12, + currency: 'USD' } }] }, @@ -50,7 +51,8 @@ publisherId: 'PRECISO_TEST00001', host: 'prebid', traffic: 'banner', - bidFloor: 0.28 + bidFloor: 0.28, + currency: 'INR' } }] } diff --git a/libraries/precisoUtils/precisoUtils.js b/libraries/precisoUtils/precisoUtils.js index 54315d847b8..5bd854a8e5b 100644 --- a/libraries/precisoUtils/precisoUtils.js +++ b/libraries/precisoUtils/precisoUtils.js @@ -1,5 +1,5 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; -import { isFn, deepAccess, replaceAuctionPrice } from '../../src/utils.js'; +import { replaceAuctionPrice } from '../../src/utils.js'; import { ajax } from '../../src/ajax.js'; export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest) => { @@ -14,7 +14,7 @@ export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest const { bidId, sizes } = req const impValue = { id: bidId, - bidFloor: getBidFloorPrice(req), + bidfloor: req.params.bidFloor, bidfloorcur: req.params.currency } if (req.mediaTypes.banner) { @@ -42,6 +42,11 @@ export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest badv: validBidRequests[0].ortb2.badv || validBidRequests[0].params.badv, wlang: validBidRequests[0].ortb2.wlang || validBidRequests[0].params.wlang, }; + if (req.device && req.device != 'undefined') { + req.device.geo = { + country: req.user.geo.country + }; + }; req.site.publisher = { publisherId: validBidRequests[0].params.publisherId }; @@ -130,23 +135,6 @@ export function onBidWon(bid) { } } -function getBidFloorPrice(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidFloor', 0); - } - - try { - const bidFloorPrice = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloorPrice.floor; - } catch (_) { - return 0 - } -} - /* replacing auction_price macro from adm */ function macroReplace(adm, cpm) { let replacedadm = replaceAuctionPrice(adm, cpm); From 1e51330afc926bce6b254afbcc9060bacd1b3a08 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Wed, 24 Jul 2024 17:20:57 +0530 Subject: [PATCH 03/12] error fix --- libraries/precisoUtils/precisoUtils.js | 4 ++-- modules/precisoBidAdapter.js | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/precisoUtils/precisoUtils.js b/libraries/precisoUtils/precisoUtils.js index 5bd854a8e5b..a19584bd7c3 100644 --- a/libraries/precisoUtils/precisoUtils.js +++ b/libraries/precisoUtils/precisoUtils.js @@ -2,7 +2,7 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; import { replaceAuctionPrice } from '../../src/utils.js'; import { ajax } from '../../src/ajax.js'; -export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest) => { +export const buildRequests = (endpoint,storage2,buyerKey) => (validBidRequests = [], bidderRequest) => { // convert Native ORTB definition to old-style prebid native definition validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); var city = Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -29,7 +29,7 @@ export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest }), user: { id: validBidRequests[0].userId.pubcid || '', - buyeruid: window.localStorage.getItem('_pre|id'), + buyeruid: readFromAllStorages (buyerKey,storage2), geo: { country: validBidRequests[0].params.region || city, }, diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index d1dd93921c6..6c3817c8920 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -7,10 +7,12 @@ import { getUserSyncs, buildRequests, interpretResponse, onBidWon, readFromAllSt const BIDDER__CODE = 'preciso'; const strId = '_sharedid'; +const buyerKey = '_pre|id'; const SUPPORTED_MEDIA_TYPES = [BANNER]; const GVLID = 874; let precisoId = 'NA'; let sharedId = 'NA' + const endpoint = 'https://ssp-bidder.mndtrk.com/bid_request/openrtb'; const syncEndpoint = 'https://ck.2trk.info/rtb/user/usersync.aspx?'; // const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId='; @@ -27,7 +29,7 @@ export const spec = { sharedId = readFromAllStorages(strId, storage); let precisoBid = true; const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId=' + sharedId; - precisoId = window.localStorage.getItem('_pre|id'); + precisoId = readFromAllStorages(buyerKey, storage); if (Object.is(precisoId, 'NA') || Object.is(precisoId, null) || Object.is(precisoId, undefined)) { if (!bid.precisoBid) { @@ -38,7 +40,7 @@ export const spec = { return Boolean(bid.bidId && bid.params && bid.params.publisherId && precisoBid); }, - buildRequests: buildRequests(endpoint), + buildRequests: buildRequests(endpoint,storage2,buyerKey), interpretResponse, onBidWon, getUserSyncs: getUserSyncs(syncEndpoint) From 702eba7242561253b3ec88f98f06a8916ae4a2ff Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Wed, 24 Jul 2024 18:26:43 +0530 Subject: [PATCH 04/12] error fix --- libraries/precisoUtils/precisoUtils.js | 4 ++-- modules/precisoBidAdapter.js | 2 +- test/spec/libraries/precisoUtils/precisoUtils_spec.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/precisoUtils/precisoUtils.js b/libraries/precisoUtils/precisoUtils.js index a19584bd7c3..171d0f9fa57 100644 --- a/libraries/precisoUtils/precisoUtils.js +++ b/libraries/precisoUtils/precisoUtils.js @@ -2,7 +2,7 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; import { replaceAuctionPrice } from '../../src/utils.js'; import { ajax } from '../../src/ajax.js'; -export const buildRequests = (endpoint,storage2,buyerKey) => (validBidRequests = [], bidderRequest) => { +export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests = [], bidderRequest) => { // convert Native ORTB definition to old-style prebid native definition validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); var city = Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -29,7 +29,7 @@ export const buildRequests = (endpoint,storage2,buyerKey) => (validBidRequests = }), user: { id: validBidRequests[0].userId.pubcid || '', - buyeruid: readFromAllStorages (buyerKey,storage2), + buyeruid: readFromAllStorages(buyerKey, storage2), geo: { country: validBidRequests[0].params.region || city, }, diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index 6c3817c8920..2a833142500 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -40,7 +40,7 @@ export const spec = { return Boolean(bid.bidId && bid.params && bid.params.publisherId && precisoBid); }, - buildRequests: buildRequests(endpoint,storage2,buyerKey), + buildRequests: buildRequests(endpoint, storage2, buyerKey), interpretResponse, onBidWon, getUserSyncs: getUserSyncs(syncEndpoint) diff --git a/test/spec/libraries/precisoUtils/precisoUtils_spec.js b/test/spec/libraries/precisoUtils/precisoUtils_spec.js index 34826bf9477..3c4493a3033 100644 --- a/test/spec/libraries/precisoUtils/precisoUtils_spec.js +++ b/test/spec/libraries/precisoUtils/precisoUtils_spec.js @@ -61,7 +61,7 @@ describe('bidderOperations', function () { const spec = { // isBidRequestValid: isBidRequestValid(), - buildRequests: buildRequests(bidEndPoint), + buildRequests: buildRequests(bidEndPoint, storage, cookieName), interpretResponse, getUserSyncs: getUserSyncs(syncEndPoint, cookieName, storage) }; From c174c9edc0db43e90bdf788b0a2b2800b554d99a Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 1 Aug 2024 15:18:46 +0530 Subject: [PATCH 05/12] import bidUtils.js in IdxBidadapter to reduce the code duplicataion --- .../creative-renderer-display/renderer.js | 2 +- .../creative-renderer-native/renderer.js | 2 +- libraries/precisoUtils/precisoUtils.js | 149 ----------------- modules/idxBidAdapter.js | 28 +--- modules/precisoBidAdapter.js | 2 +- .../precisoUtils/precisoUtils_spec.js | 155 ------------------ test/spec/modules/precisoBidAdapter_spec.js | 1 + 7 files changed, 6 insertions(+), 333 deletions(-) delete mode 100644 libraries/precisoUtils/precisoUtils.js delete mode 100644 test/spec/libraries/precisoUtils/precisoUtils_spec.js diff --git a/libraries/creative-renderer-display/renderer.js b/libraries/creative-renderer-display/renderer.js index 72f3658fe79..146afab46ae 100644 --- a/libraries/creative-renderer-display/renderer.js +++ b/libraries/creative-renderer-display/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "!function(){\"use strict\";window.render=function({ad:d,adUrl:i,width:n,height:e},{mkFrame:o},r){if(!d&&!i)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const t=r.document,s={width:n,height:e};i&&!d?s.src=i:s.srcdoc=d,t.body.appendChild(o(t,s))}}}();" \ No newline at end of file +export const RENDERER = "(()=>{\"use strict\";window.render=function({ad:d,adUrl:e,width:i,height:r},{mkFrame:n},o){if(!d&&!e)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const s=o.document,t={width:i,height:r};e&&!d?t.src=e:t.srcdoc=d,s.body.appendChild(n(s,t))}}})();" \ No newline at end of file diff --git a/libraries/creative-renderer-native/renderer.js b/libraries/creative-renderer-native/renderer.js index 57d86fc8ce3..d7d85cdd7ba 100644 --- a/libraries/creative-renderer-native/renderer.js +++ b/libraries/creative-renderer-native/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "!function(){\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}}();" \ No newline at end of file +export const RENDERER = "(()=>{\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}})();" \ No newline at end of file diff --git a/libraries/precisoUtils/precisoUtils.js b/libraries/precisoUtils/precisoUtils.js deleted file mode 100644 index 171d0f9fa57..00000000000 --- a/libraries/precisoUtils/precisoUtils.js +++ /dev/null @@ -1,149 +0,0 @@ -import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; -import { replaceAuctionPrice } from '../../src/utils.js'; -import { ajax } from '../../src/ajax.js'; - -export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests = [], bidderRequest) => { - // convert Native ORTB definition to old-style prebid native definition - validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); - var city = Intl.DateTimeFormat().resolvedOptions().timeZone; - let req = { - // bidRequest: bidderRequest, - id: validBidRequests[0].auctionId, - cur: validBidRequests[0].params.currency || ['USD'], - imp: validBidRequests.map(req => { - const { bidId, sizes } = req - const impValue = { - id: bidId, - bidfloor: req.params.bidFloor, - bidfloorcur: req.params.currency - } - if (req.mediaTypes.banner) { - impValue.banner = { - format: (req.mediaTypes.banner.sizes || sizes).map(size => { - return { w: size[0], h: size[1] } - }), - - } - } - return impValue - }), - user: { - id: validBidRequests[0].userId.pubcid || '', - buyeruid: readFromAllStorages(buyerKey, storage2), - geo: { - country: validBidRequests[0].params.region || city, - }, - - }, - device: validBidRequests[0].ortb2.device, - site: validBidRequests[0].ortb2.site, - source: validBidRequests[0].ortb2.source, - bcat: validBidRequests[0].ortb2.bcat || validBidRequests[0].params.bcat, - badv: validBidRequests[0].ortb2.badv || validBidRequests[0].params.badv, - wlang: validBidRequests[0].ortb2.wlang || validBidRequests[0].params.wlang, - }; - if (req.device && req.device != 'undefined') { - req.device.geo = { - country: req.user.geo.country - }; - }; - req.site.publisher = { - publisherId: validBidRequests[0].params.publisherId - }; - - // req.language.indexOf('-') != -1 && (req.language = req.language.split('-')[0]) - if (bidderRequest) { - if (bidderRequest.uspConsent) { - req.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - req.gdpr = bidderRequest.gdprConsent - } - if (bidderRequest.gppConsent) { - req.gpp = bidderRequest.gppConsent; - } - } - - return { - method: 'POST', - url: endpoint, - data: req, - - }; -} - -export function interpretResponse(serverResponse) { - const bidsValue = [] - const bidResponse = serverResponse.body - bidResponse.seatbid.forEach(seat => { - seat.bid.forEach(bid => { - bidsValue.push({ - requestId: bid.impid, - cpm: bid.price, - width: bid.w, - height: bid.h, - creativeId: bid.crid, - ad: macroReplace(bid.adm, bid.price), - currency: 'USD', - netRevenue: true, - ttl: 300, - meta: { - advertiserDomains: bid.adomain || '', - }, - }) - }) - }) - return bidsValue -} - -export const getUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { - let userId = 'NA'; - // let userId = readFromAllStorages(strId, storage); - let syncs = []; - let syncUrl = `${syncEndpoint}id=${userId}` - - if (gdprConsent) { - syncUrl = syncUrl + `&gdpr=${Number(gdprConsent.gdprApplies && 1)}&gdpr_consent=${encodeURIComponent(gdprConsent.consentString || '')}`; - } else { - syncUrl = syncUrl + `&gdpr=0&gdpr_consent=` - } - if (uspConsent) { - syncUrl = syncUrl + `&us_privacy=${uspConsent}` - } else { - syncUrl = syncUrl + `&us_privacy=` - } - - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: syncUrl + `&t=4` - }); - } else { - syncs.push({ - type: 'image', - url: syncUrl + `&t=2` - }); - } - - return syncs -} - -export function onBidWon(bid) { - if (bid.nurl) { - const resolvedNurl = replaceAuctionPrice(bid.nurl, bid.price); - ajax(resolvedNurl); - } -} - -/* replacing auction_price macro from adm */ -function macroReplace(adm, cpm) { - let replacedadm = replaceAuctionPrice(adm, cpm); - return replacedadm; -} - -export function readFromAllStorages(name, storage) { - const fromCookie = storage.getCookie(name); - const fromLocalStorage = storage.getDataFromLocalStorage(name); - - return fromCookie || fromLocalStorage || 'NA'; -} diff --git a/modules/idxBidAdapter.js b/modules/idxBidAdapter.js index 48739275788..61e9280ff8d 100644 --- a/modules/idxBidAdapter.js +++ b/modules/idxBidAdapter.js @@ -1,6 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js' import { BANNER } from '../src/mediaTypes.js' import { isArray, isNumber } from '../src/utils.js' +import { interpretResponse } from '../libraries/bidUtils/bidUtils.js'; const BIDDER_CODE = 'idx' const ENDPOINT_URL = 'https://dev-event.dxmdp.com/rest/api/v1/bid' @@ -49,32 +50,7 @@ export const spec = { } } }, - interpretResponse: function (serverResponse) { - const response = serverResponse.body - - const bids = [] - - response.seatbid.forEach(seat => { - seat.bid.forEach(bid => { - bids.push({ - requestId: bid.impid, - cpm: bid.price, - width: bid.w, - height: bid.h, - creativeId: bid.crid, - ad: bid.adm, - currency: 'USD', - netRevenue: true, - ttl: 300, - meta: { - advertiserDomains: bid.adomain || [], - }, - }) - }) - }) - - return bids - }, + interpretResponse, } registerBidder(spec) diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index 2a833142500..7ac0e991816 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -3,7 +3,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { MODULE_TYPE_UID } from '../src/activities/modules.js'; -import { getUserSyncs, buildRequests, interpretResponse, onBidWon, readFromAllStorages } from '../libraries/precisoUtils/precisoUtils.js'; +import { getUserSyncs, buildRequests, interpretResponse, onBidWon, readFromAllStorages } from '../libraries/bidUtils/bidUtils.js'; const BIDDER__CODE = 'preciso'; const strId = '_sharedid'; diff --git a/test/spec/libraries/precisoUtils/precisoUtils_spec.js b/test/spec/libraries/precisoUtils/precisoUtils_spec.js deleted file mode 100644 index 3c4493a3033..00000000000 --- a/test/spec/libraries/precisoUtils/precisoUtils_spec.js +++ /dev/null @@ -1,155 +0,0 @@ - -import { expect } from 'chai'; -import { buildRequests, interpretResponse, getUserSyncs } from '../../../../libraries/precisoUtils/precisoUtils.js'; -import { getStorageManager } from '../../../../src/storageManager.js'; -import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; - -const DEFAULT_PRICE = 1 -const DEFAULT_CURRENCY = 'USD' -const DEFAULT_BANNER_WIDTH = 300 -const DEFAULT_BANNER_HEIGHT = 250 -const BIDDER_CODE = 'bidder'; -const TESTDOMAIN = 'test.org' -const cookieName = 'test'; - -const bidEndPoint = `https://${TESTDOMAIN}/bid_request/openrtb`; -const syncEndPoint = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?`; -const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE }); - -describe('bidderOperations', function () { - let bid = { - bidId: '23fhj33i987f', - bidder: BIDDER_CODE, - mediaTypes: { - banner: { - sizes: [[DEFAULT_BANNER_WIDTH, DEFAULT_BANNER_HEIGHT]] - } - }, - params: { - host: 'prebid', - sourceid: '0', - publisherId: '0', - mediaType: 'banner', - region: 'IND' - - }, - userId: { - pubcid: '12355454test' - - }, - user: { - geo: { - region: 'IND', - } - }, - ortb2: { - device: { - w: 1920, - h: 166, - dnt: 0, - }, - site: { - domain: 'localHost' - }, - source: { - tid: 'eaff09b-a1ab-4ec6-a81e-c5a75bc1dde3' - } - - } - - }; - - const spec = { - // isBidRequestValid: isBidRequestValid(), - buildRequests: buildRequests(bidEndPoint, storage, cookieName), - interpretResponse, - getUserSyncs: getUserSyncs(syncEndPoint, cookieName, storage) - }; - - describe('buildRequests', function () { - let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', function () { - expect(serverRequest).to.exist; - expect(serverRequest.method).to.exist; - expect(serverRequest.url).to.exist; - expect(serverRequest.data).to.exist; - }); - it('Returns POST method', function () { - expect(serverRequest.method).to.equal('POST'); - }); - it('Returns valid URL', function () { - expect(serverRequest.url).to.equal(`https://${TESTDOMAIN}/bid_request/openrtb`); - }); - it('Returns valid data if array of bids is valid', function () { - let data = serverRequest.data; - expect(data).to.be.an('object'); - expect(data.device).to.be.a('object'); - expect(data.user).to.be.a('object'); - expect(data.source).to.be.a('object'); - expect(data.site).to.be.a('object'); - }); - it('Returns data.device is undefined if no valid device object is passed', function () { - delete bid.ortb2.device; - serverRequest = spec.buildRequests([bid]); - let data = serverRequest.data; - expect(data.device).to.be.undefined; - }); - }); - - describe('interpretResponse', function () { - it('should get correct bid response', function () { - let response = { - bidderRequestId: 'f6adb85f-4e19-45a0-b41e-2a5b9a48f23a', - seatbid: [ - { - bid: [ - { - id: '123', - impid: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', - price: DEFAULT_PRICE, - adm: 'hi', - cid: 'test_cid', - crid: 'test_banner_crid', - w: DEFAULT_BANNER_WIDTH, - h: DEFAULT_BANNER_HEIGHT, - adomain: [], - } - ], - seat: BIDDER_CODE - } - ], - } - let expectedResponse = [ - { - requestId: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', - cpm: DEFAULT_PRICE, - width: DEFAULT_BANNER_WIDTH, - height: DEFAULT_BANNER_HEIGHT, - creativeId: 'test_banner_crid', - ad: 'hi', - currency: DEFAULT_CURRENCY, - netRevenue: true, - ttl: 300, - meta: { advertiserDomains: [] }, - } - ] - let result = spec.interpretResponse({ body: response }) - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])) - }) - }); - describe('getUserSyncs', function () { - const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4`; - const syncOptions = { - iframeEnabled: true - }; - let userSync = spec.getUserSyncs(syncOptions); - it('Returns valid URL and type', function () { - expect(userSync).to.be.an('array').with.lengthOf(1); - expect(userSync[0].type).to.exist; - expect(userSync[0].url).to.exist; - expect(userSync).to.deep.equal([ - { type: 'iframe', url: syncUrl } - ]); - }); - }); -}); diff --git a/test/spec/modules/precisoBidAdapter_spec.js b/test/spec/modules/precisoBidAdapter_spec.js index 4ac1c479bb9..e1173fe7db3 100644 --- a/test/spec/modules/precisoBidAdapter_spec.js +++ b/test/spec/modules/precisoBidAdapter_spec.js @@ -13,6 +13,7 @@ describe('PrecisoAdapter', function () { precisoBid: true, bidId: '23fhj33i987f', bidder: 'preciso', + buyerUid: 'testuid', mediaTypes: { banner: { sizes: [[DEFAULT_BANNER_WIDTH, DEFAULT_BANNER_HEIGHT]] From 65af09ed0c15703683d3c0ee683f5c14e3885406 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 1 Aug 2024 15:19:17 +0530 Subject: [PATCH 06/12] import bidUtils.js in IdxBidadapter to reduce the code duplicataion --- libraries/bidUtils/bidUtils.js | 149 +++++++++++++++++ test/spec/libraries/bidUtils/bidUtils_spec.js | 156 ++++++++++++++++++ 2 files changed, 305 insertions(+) create mode 100644 libraries/bidUtils/bidUtils.js create mode 100644 test/spec/libraries/bidUtils/bidUtils_spec.js diff --git a/libraries/bidUtils/bidUtils.js b/libraries/bidUtils/bidUtils.js new file mode 100644 index 00000000000..cacaded7aae --- /dev/null +++ b/libraries/bidUtils/bidUtils.js @@ -0,0 +1,149 @@ +import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; +import { replaceAuctionPrice } from '../../src/utils.js'; +import { ajax } from '../../src/ajax.js'; + +export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests = [], bidderRequest) => { + // convert Native ORTB definition to old-style prebid native definition + validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); + var city = Intl.DateTimeFormat().resolvedOptions().timeZone; + let req = { + // bidRequest: bidderRequest, + id: validBidRequests[0].auctionId, + cur: validBidRequests[0].params.currency || ['USD'], + imp: validBidRequests.map(req => { + const { bidId, sizes } = req + const impValue = { + id: bidId, + bidfloor: req.params.bidFloor, + bidfloorcur: req.params.currency + } + if (req.mediaTypes.banner) { + impValue.banner = { + format: (req.mediaTypes.banner.sizes || sizes).map(size => { + return { w: size[0], h: size[1] } + }), + + } + } + return impValue + }), + user: { + id: validBidRequests[0].userId.pubcid || '', + buyeruid: validBidRequests[0].buyerUid || readFromAllStorages(buyerKey, storage2), + geo: { + country: validBidRequests[0].params.region || city, + }, + + }, + device: validBidRequests[0].ortb2.device, + site: validBidRequests[0].ortb2.site, + source: validBidRequests[0].ortb2.source, + bcat: validBidRequests[0].ortb2.bcat || validBidRequests[0].params.bcat, + badv: validBidRequests[0].ortb2.badv || validBidRequests[0].params.badv, + wlang: validBidRequests[0].ortb2.wlang || validBidRequests[0].params.wlang, + }; + if (req.device && req.device != 'undefined') { + req.device.geo = { + country: req.user.geo.country + }; + }; + req.site.publisher = { + publisherId: validBidRequests[0].params.publisherId + }; + + // req.language.indexOf('-') != -1 && (req.language = req.language.split('-')[0]) + if (bidderRequest) { + if (bidderRequest.uspConsent) { + req.ccpa = bidderRequest.uspConsent; + } + if (bidderRequest.gdprConsent) { + req.gdpr = bidderRequest.gdprConsent + } + if (bidderRequest.gppConsent) { + req.gpp = bidderRequest.gppConsent; + } + } + + return { + method: 'POST', + url: endpoint, + data: req, + + }; +} + +export function interpretResponse(serverResponse) { + const bidsValue = [] + const bidResponse = serverResponse.body + bidResponse.seatbid.forEach(seat => { + seat.bid.forEach(bid => { + bidsValue.push({ + requestId: bid.impid, + cpm: bid.price, + width: bid.w, + height: bid.h, + creativeId: bid.crid, + ad: macroReplace(bid.adm, bid.price), + currency: 'USD', + netRevenue: true, + ttl: 300, + meta: { + advertiserDomains: bid.adomain || '', + }, + }) + }) + }) + return bidsValue +} + +export const getUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { + let userId = 'NA'; + // let userId = readFromAllStorages(strId, storage); + let syncs = []; + let syncUrl = `${syncEndpoint}id=${userId}` + + if (gdprConsent) { + syncUrl = syncUrl + `&gdpr=${Number(gdprConsent.gdprApplies && 1)}&gdpr_consent=${encodeURIComponent(gdprConsent.consentString || '')}`; + } else { + syncUrl = syncUrl + `&gdpr=0&gdpr_consent=` + } + if (uspConsent) { + syncUrl = syncUrl + `&us_privacy=${uspConsent}` + } else { + syncUrl = syncUrl + `&us_privacy=` + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: syncUrl + `&t=4` + }); + } else { + syncs.push({ + type: 'image', + url: syncUrl + `&t=2` + }); + } + + return syncs +} + +export function onBidWon(bid) { + if (bid.nurl) { + const resolvedNurl = replaceAuctionPrice(bid.nurl, bid.price); + ajax(resolvedNurl); + } +} + +/* replacing auction_price macro from adm */ +function macroReplace(adm, cpm) { + let replacedadm = replaceAuctionPrice(adm, cpm); + return replacedadm; +} + +export function readFromAllStorages(name, storage) { + const fromCookie = storage.getCookie(name); + const fromLocalStorage = storage.getDataFromLocalStorage(name); + + return fromCookie || fromLocalStorage || 'NA'; +} diff --git a/test/spec/libraries/bidUtils/bidUtils_spec.js b/test/spec/libraries/bidUtils/bidUtils_spec.js new file mode 100644 index 00000000000..b4b0d2eb889 --- /dev/null +++ b/test/spec/libraries/bidUtils/bidUtils_spec.js @@ -0,0 +1,156 @@ + +import { expect } from 'chai'; +import { buildRequests, interpretResponse, getUserSyncs } from '../../../../libraries/bidUtils/bidUtils.js'; +import { getStorageManager } from '../../../../src/storageManager.js'; +import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; + +const DEFAULT_PRICE = 1 +const DEFAULT_CURRENCY = 'USD' +const DEFAULT_BANNER_WIDTH = 300 +const DEFAULT_BANNER_HEIGHT = 250 +const BIDDER_CODE = 'preciso'; +const TESTDOMAIN = 'test.org' +const cookieName = '_pre|id'; + +const bidEndPoint = `https://${TESTDOMAIN}/bid_request/openrtb`; +const syncEndPoint = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?`; +const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE }); + +describe('bidderOperations', function () { + let bid = { + bidId: '23fhj33i987f', + bidder: BIDDER_CODE, + buyerUid: 'testuid', + mediaTypes: { + banner: { + sizes: [[DEFAULT_BANNER_WIDTH, DEFAULT_BANNER_HEIGHT]] + } + }, + params: { + host: 'prebid', + sourceid: '0', + publisherId: '0', + mediaType: 'banner', + region: 'IND' + + }, + userId: { + pubcid: '12355454test' + + }, + user: { + geo: { + region: 'IND', + } + }, + ortb2: { + device: { + w: 1920, + h: 166, + dnt: 0, + }, + site: { + domain: 'localHost' + }, + source: { + tid: 'eaff09b-a1ab-4ec6-a81e-c5a75bc1dde3' + } + + } + + }; + + const spec = { + // isBidRequestValid: isBidRequestValid(), + buildRequests: buildRequests(bidEndPoint, storage, cookieName), + interpretResponse, + getUserSyncs: getUserSyncs(syncEndPoint, cookieName, storage) + }; + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', function () { + expect(serverRequest.url).to.equal(`https://${TESTDOMAIN}/bid_request/openrtb`); + }); + it('Returns valid data if array of bids is valid', function () { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data.device).to.be.a('object'); + expect(data.user).to.be.a('object'); + expect(data.source).to.be.a('object'); + expect(data.site).to.be.a('object'); + }); + it('Returns data.device is undefined if no valid device object is passed', function () { + delete bid.ortb2.device; + serverRequest = spec.buildRequests([bid]); + let data = serverRequest.data; + expect(data.device).to.be.undefined; + }); + }); + + describe('interpretResponse', function () { + it('should get correct bid response', function () { + let response = { + bidderRequestId: 'f6adb85f-4e19-45a0-b41e-2a5b9a48f23a', + seatbid: [ + { + bid: [ + { + id: '123', + impid: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', + price: DEFAULT_PRICE, + adm: 'hi', + cid: 'test_cid', + crid: 'test_banner_crid', + w: DEFAULT_BANNER_WIDTH, + h: DEFAULT_BANNER_HEIGHT, + adomain: [], + } + ], + seat: BIDDER_CODE + } + ], + } + let expectedResponse = [ + { + requestId: 'b4f290d7-d4ab-4778-ab94-2baf06420b22', + cpm: DEFAULT_PRICE, + width: DEFAULT_BANNER_WIDTH, + height: DEFAULT_BANNER_HEIGHT, + creativeId: 'test_banner_crid', + ad: 'hi', + currency: DEFAULT_CURRENCY, + netRevenue: true, + ttl: 300, + meta: { advertiserDomains: [] }, + } + ] + let result = spec.interpretResponse({ body: response }) + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])) + }) + }); + describe('getUserSyncs', function () { + const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4`; + const syncOptions = { + iframeEnabled: true + }; + let userSync = spec.getUserSyncs(syncOptions); + it('Returns valid URL and type', function () { + expect(userSync).to.be.an('array').with.lengthOf(1); + expect(userSync[0].type).to.exist; + expect(userSync[0].url).to.exist; + expect(userSync).to.deep.equal([ + { type: 'iframe', url: syncUrl } + ]); + }); + }); +}); From d4c4bd767a9184ab54b6536c0a1b5dfd63cfa4b1 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 1 Aug 2024 15:35:42 +0530 Subject: [PATCH 07/12] Error fix --- libraries/creative-renderer-display/renderer.js | 2 +- libraries/creative-renderer-native/renderer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/creative-renderer-display/renderer.js b/libraries/creative-renderer-display/renderer.js index 146afab46ae..72f3658fe79 100644 --- a/libraries/creative-renderer-display/renderer.js +++ b/libraries/creative-renderer-display/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "(()=>{\"use strict\";window.render=function({ad:d,adUrl:e,width:i,height:r},{mkFrame:n},o){if(!d&&!e)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const s=o.document,t={width:i,height:r};e&&!d?t.src=e:t.srcdoc=d,s.body.appendChild(n(s,t))}}})();" \ No newline at end of file +export const RENDERER = "!function(){\"use strict\";window.render=function({ad:d,adUrl:i,width:n,height:e},{mkFrame:o},r){if(!d&&!i)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const t=r.document,s={width:n,height:e};i&&!d?s.src=i:s.srcdoc=d,t.body.appendChild(o(t,s))}}}();" \ No newline at end of file diff --git a/libraries/creative-renderer-native/renderer.js b/libraries/creative-renderer-native/renderer.js index d7d85cdd7ba..57d86fc8ce3 100644 --- a/libraries/creative-renderer-native/renderer.js +++ b/libraries/creative-renderer-native/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "(()=>{\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}})();" \ No newline at end of file +export const RENDERER = "!function(){\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}}();" \ No newline at end of file From c291e6d496ede7778b26784e152e775a71e1ed79 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Tue, 6 Aug 2024 13:04:35 +0530 Subject: [PATCH 08/12] Imported bidUtils library into redtram bid adapter --- libraries/bidUtils/bidUtils.js | 95 +++++++++++-------- modules/precisoBidAdapter.js | 25 ++--- modules/redtramBidAdapter.js | 66 ++++++------- test/spec/libraries/bidUtils/bidUtils_spec.js | 8 +- test/spec/modules/precisoBidAdapter_spec.js | 3 +- 5 files changed, 102 insertions(+), 95 deletions(-) diff --git a/libraries/bidUtils/bidUtils.js b/libraries/bidUtils/bidUtils.js index cacaded7aae..cb0ff9fda5e 100644 --- a/libraries/bidUtils/bidUtils.js +++ b/libraries/bidUtils/bidUtils.js @@ -1,8 +1,13 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; import { replaceAuctionPrice } from '../../src/utils.js'; +import { getStorageManager } from '../../src/storageManager.js'; import { ajax } from '../../src/ajax.js'; +import { config } from '../../src/config.js'; +import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; -export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests = [], bidderRequest) => { +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); + +export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest) => { // convert Native ORTB definition to old-style prebid native definition validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); var city = Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -29,7 +34,7 @@ export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests }), user: { id: validBidRequests[0].userId.pubcid || '', - buyeruid: validBidRequests[0].buyerUid || readFromAllStorages(buyerKey, storage2), + buyeruid: validBidRequests[0].buyerUid || '', geo: { country: validBidRequests[0].params.region || city, }, @@ -52,18 +57,7 @@ export const buildRequests = (endpoint, storage2, buyerKey) => (validBidRequests }; // req.language.indexOf('-') != -1 && (req.language = req.language.split('-')[0]) - if (bidderRequest) { - if (bidderRequest.uspConsent) { - req.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - req.gdpr = bidderRequest.gdprConsent - } - if (bidderRequest.gppConsent) { - req.gpp = bidderRequest.gppConsent; - } - } - + consentCheck(bidderRequest, req); return { method: 'POST', url: endpoint, @@ -96,36 +90,46 @@ export function interpretResponse(serverResponse) { return bidsValue } -export const getUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { - let userId = 'NA'; - // let userId = readFromAllStorages(strId, storage); - let syncs = []; - let syncUrl = `${syncEndpoint}id=${userId}` - - if (gdprConsent) { - syncUrl = syncUrl + `&gdpr=${Number(gdprConsent.gdprApplies && 1)}&gdpr_consent=${encodeURIComponent(gdprConsent.consentString || '')}`; - } else { - syncUrl = syncUrl + `&gdpr=0&gdpr_consent=` +export const buildUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent) => { + let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; + const isCk2trk = syncEndpoint.includes('ck.2trk.info'); + const isSpec = syncOptions.spec; + if (isCk2trk) { + if (!Object.is(isSpec, true)) { + let syncId = storage.getCookie('_sharedid'); + syncEndpoint = syncEndpoint + 'id=' + syncId; + } else { + syncEndpoint = syncEndpoint + 'id=NA'; + } } - if (uspConsent) { - syncUrl = syncUrl + `&us_privacy=${uspConsent}` + // Base sync URL + let syncUrl = isCk2trk ? syncEndpoint : `${syncEndpoint}/${syncType}?pbjs=1`; + + if (gdprConsent && gdprConsent.consentString) { + if (typeof gdprConsent.gdprApplies === 'boolean') { + syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; + } } else { - syncUrl = syncUrl + `&us_privacy=` + syncUrl += isCk2trk ? `&gdpr=0&gdpr_consent=` : ''; } - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: syncUrl + `&t=4` - }); + if (isCk2trk) { + syncUrl += uspConsent ? `&us_privacy=${uspConsent}` : `&us_privacy=`; + syncUrl += (syncOptions.iframeEnabled) ? `&t=4` : `&t=2` } else { - syncs.push({ - type: 'image', - url: syncUrl + `&t=2` - }); + if (uspConsent && uspConsent.consentString) { + syncUrl += `&ccpa_consent=${uspConsent.consentString}`; + } + const coppa = config.getConfig('coppa') ? 1 : 0; + syncUrl += `&coppa=${coppa}`; } - return syncs + return [{ + type: syncType, + url: syncUrl + }]; } export function onBidWon(bid) { @@ -141,9 +145,16 @@ function macroReplace(adm, cpm) { return replacedadm; } -export function readFromAllStorages(name, storage) { - const fromCookie = storage.getCookie(name); - const fromLocalStorage = storage.getDataFromLocalStorage(name); - - return fromCookie || fromLocalStorage || 'NA'; +export function consentCheck(bidderRequest, req) { + if (bidderRequest) { + if (bidderRequest.uspConsent) { + req.ccpa = bidderRequest.uspConsent; + } + if (bidderRequest.gdprConsent) { + req.gdpr = bidderRequest.gdprConsent + } + if (bidderRequest.gppConsent) { + req.gpp = bidderRequest.gppConsent; + } + } } diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index 7ac0e991816..d019f509532 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -3,22 +3,18 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { MODULE_TYPE_UID } from '../src/activities/modules.js'; -import { getUserSyncs, buildRequests, interpretResponse, onBidWon, readFromAllStorages } from '../libraries/bidUtils/bidUtils.js'; +import { buildUserSyncs, buildRequests, interpretResponse, onBidWon } from '../libraries/bidUtils/bidUtils.js'; const BIDDER__CODE = 'preciso'; -const strId = '_sharedid'; -const buyerKey = '_pre|id'; +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); +export const storage2 = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); const SUPPORTED_MEDIA_TYPES = [BANNER]; const GVLID = 874; let precisoId = 'NA'; -let sharedId = 'NA' +let sharedId = 'NA'; const endpoint = 'https://ssp-bidder.mndtrk.com/bid_request/openrtb'; -const syncEndpoint = 'https://ck.2trk.info/rtb/user/usersync.aspx?'; -// const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId='; - -export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); -export const storage2 = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); +let syncEndpoint = 'https://ck.2trk.info/rtb/user/usersync.aspx?'; export const spec = { code: BIDDER__CODE, @@ -26,11 +22,10 @@ export const spec = { gvlid: GVLID, isBidRequestValid: (bid) => { - sharedId = readFromAllStorages(strId, storage); + sharedId = storage.getDataFromLocalStorage('_sharedid') || storage.getCookie('_sharedid'); let precisoBid = true; const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId=' + sharedId; - precisoId = readFromAllStorages(buyerKey, storage); - + precisoId = storage2.getDataFromLocalStorage('_pre|id'); if (Object.is(precisoId, 'NA') || Object.is(precisoId, null) || Object.is(precisoId, undefined)) { if (!bid.precisoBid) { precisoBid = false; @@ -40,10 +35,10 @@ export const spec = { return Boolean(bid.bidId && bid.params && bid.params.publisherId && precisoBid); }, - buildRequests: buildRequests(endpoint, storage2, buyerKey), + buildRequests: buildRequests(endpoint), interpretResponse, onBidWon, - getUserSyncs: getUserSyncs(syncEndpoint) + getUserSyncs: buildUserSyncs(syncEndpoint), }; registerBidder(spec); @@ -57,12 +52,10 @@ async function getapi(url) { var data = await response.json(); const dataMap = new Map(Object.entries(data)); - const uuidValue = dataMap.get('UUID'); if (!Object.is(uuidValue, null) && !Object.is(uuidValue, undefined)) { storage2.setDataInLocalStorage('_pre|id', uuidValue); - logInfo('DEBUG nonNull uuidValue:' + uuidValue); } return data; } catch (error) { diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index e1dc0e2a148..fc81b3d6aa5 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -7,7 +7,7 @@ import { } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; +import { consentCheck, buildUserSyncs } from '../libraries/bidUtils/bidUtils.js'; const BIDDER_CODE = 'redtram'; const AD_URL = 'https://prebid.redtram.com/pbjs'; @@ -65,15 +65,16 @@ export const spec = { page: location.pathname, placements: placements }; + consentCheck(bidderRequest, request); - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent; - } - } + // if (bidderRequest) { + // if (bidderRequest.uspConsent) { + // request.ccpa = bidderRequest.uspConsent; + // } + // if (bidderRequest.gdprConsent) { + // request.gdpr = bidderRequest.gdprConsent; + // } + // } const len = validBidRequests.length; for (let i = 0; i < len; i++) { @@ -119,29 +120,30 @@ export const spec = { } return response; }, - - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - - return [{ - type: syncType, - url: syncUrl - }]; - }, + getUserSyncs: buildUserSyncs(SYNC_URL), + + // getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { + // let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; + // let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; + // if (gdprConsent && gdprConsent.consentString) { + // if (typeof gdprConsent.gdprApplies === 'boolean') { + // syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + // } else { + // syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; + // } + // } + // if (uspConsent && uspConsent.consentString) { + // syncUrl += `&ccpa_consent=${uspConsent.consentString}`; + // } + + // const coppa = config.getConfig('coppa') ? 1 : 0; + // syncUrl += `&coppa=${coppa}`; + + // return [{ + // type: syncType, + // url: syncUrl + // }]; + // }, onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; diff --git a/test/spec/libraries/bidUtils/bidUtils_spec.js b/test/spec/libraries/bidUtils/bidUtils_spec.js index b4b0d2eb889..c448e1dac25 100644 --- a/test/spec/libraries/bidUtils/bidUtils_spec.js +++ b/test/spec/libraries/bidUtils/bidUtils_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { buildRequests, interpretResponse, getUserSyncs } from '../../../../libraries/bidUtils/bidUtils.js'; +import { buildRequests, interpretResponse, buildUserSyncs } from '../../../../libraries/bidUtils/bidUtils.js'; import { getStorageManager } from '../../../../src/storageManager.js'; import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; @@ -64,7 +64,7 @@ describe('bidderOperations', function () { // isBidRequestValid: isBidRequestValid(), buildRequests: buildRequests(bidEndPoint, storage, cookieName), interpretResponse, - getUserSyncs: getUserSyncs(syncEndPoint, cookieName, storage) + buildUserSyncs: buildUserSyncs(syncEndPoint) }; describe('buildRequests', function () { @@ -139,11 +139,11 @@ describe('bidderOperations', function () { }) }); describe('getUserSyncs', function () { - const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4`; + const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?/iframe?pbjs=1&coppa=0`; const syncOptions = { iframeEnabled: true }; - let userSync = spec.getUserSyncs(syncOptions); + let userSync = spec.buildUserSyncs(syncOptions); it('Returns valid URL and type', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; diff --git a/test/spec/modules/precisoBidAdapter_spec.js b/test/spec/modules/precisoBidAdapter_spec.js index e1173fe7db3..60cdd43504a 100644 --- a/test/spec/modules/precisoBidAdapter_spec.js +++ b/test/spec/modules/precisoBidAdapter_spec.js @@ -141,7 +141,8 @@ describe('PrecisoAdapter', function () { describe('getUserSyncs', function () { const syncUrl = 'https://ck.2trk.info/rtb/user/usersync.aspx?id=NA&gdpr=0&gdpr_consent=&us_privacy=&t=4'; const syncOptions = { - iframeEnabled: true + iframeEnabled: true, + spec: true }; let userSync = spec.getUserSyncs(syncOptions); it('Returns valid URL and type', function () { From 510053a00dfcf4740c12dc75b2718993629483d9 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 8 Aug 2024 13:36:36 +0530 Subject: [PATCH 09/12] import common library in mediabramaBidAdapter --- libraries/bidUtils/bidUtils.js | 58 +--- libraries/bidUtils/bidUtilsCommon.js | 185 ++++++++++++ modules/mediabramaBidAdapter.js | 149 +--------- modules/precisoBidAdapter.js | 3 +- modules/redtramBidAdapter.js | 149 +--------- .../libraries/bidUtils/bidUtilsCommon_spec.js | 267 ++++++++++++++++++ test/spec/libraries/bidUtils/bidUtils_spec.js | 34 +-- 7 files changed, 485 insertions(+), 360 deletions(-) create mode 100644 libraries/bidUtils/bidUtilsCommon.js create mode 100644 test/spec/libraries/bidUtils/bidUtilsCommon_spec.js diff --git a/libraries/bidUtils/bidUtils.js b/libraries/bidUtils/bidUtils.js index cb0ff9fda5e..fb1fac0771a 100644 --- a/libraries/bidUtils/bidUtils.js +++ b/libraries/bidUtils/bidUtils.js @@ -2,8 +2,8 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; import { replaceAuctionPrice } from '../../src/utils.js'; import { getStorageManager } from '../../src/storageManager.js'; import { ajax } from '../../src/ajax.js'; -import { config } from '../../src/config.js'; import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; +import { consentCheck } from './bidUtilsCommon.js'; export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); @@ -90,48 +90,6 @@ export function interpretResponse(serverResponse) { return bidsValue } -export const buildUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - const isCk2trk = syncEndpoint.includes('ck.2trk.info'); - const isSpec = syncOptions.spec; - if (isCk2trk) { - if (!Object.is(isSpec, true)) { - let syncId = storage.getCookie('_sharedid'); - syncEndpoint = syncEndpoint + 'id=' + syncId; - } else { - syncEndpoint = syncEndpoint + 'id=NA'; - } - } - // Base sync URL - let syncUrl = isCk2trk ? syncEndpoint : `${syncEndpoint}/${syncType}?pbjs=1`; - - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } else { - syncUrl += isCk2trk ? `&gdpr=0&gdpr_consent=` : ''; - } - - if (isCk2trk) { - syncUrl += uspConsent ? `&us_privacy=${uspConsent}` : `&us_privacy=`; - syncUrl += (syncOptions.iframeEnabled) ? `&t=4` : `&t=2` - } else { - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - } - - return [{ - type: syncType, - url: syncUrl - }]; -} - export function onBidWon(bid) { if (bid.nurl) { const resolvedNurl = replaceAuctionPrice(bid.nurl, bid.price); @@ -144,17 +102,3 @@ function macroReplace(adm, cpm) { let replacedadm = replaceAuctionPrice(adm, cpm); return replacedadm; } - -export function consentCheck(bidderRequest, req) { - if (bidderRequest) { - if (bidderRequest.uspConsent) { - req.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - req.gdpr = bidderRequest.gdprConsent - } - if (bidderRequest.gppConsent) { - req.gpp = bidderRequest.gppConsent; - } - } -} diff --git a/libraries/bidUtils/bidUtilsCommon.js b/libraries/bidUtils/bidUtilsCommon.js new file mode 100644 index 00000000000..e662148414c --- /dev/null +++ b/libraries/bidUtils/bidUtilsCommon.js @@ -0,0 +1,185 @@ +import { config } from '../../src/config.js'; +import { + isFn, + isStr, + deepAccess, + getWindowTop, + triggerPixel +} from '../../src/utils.js'; +import { BANNER, VIDEO, NATIVE } from '../../src/mediaTypes.js'; +import { getStorageManager } from '../../src/storageManager.js'; +import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; + +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); + +function isBidResponseValid(bid) { + if (!bid.requestId || !bid.cpm || !bid.creativeId || + !bid.ttl || !bid.currency || !bid.meta) { + return false; + } + + switch (bid.mediaType) { + case BANNER: + return Boolean(bid.width && bid.height && bid.ad); + case VIDEO: + return Boolean(bid.vastXml || bid.vastUrl); + case NATIVE: + return Boolean(bid.native && bid.native.impressionTrackers); + default: + return false; + } +} + +export function getBidFloor(bid) { + if (!isFn(bid.getFloor)) { + return deepAccess(bid, 'params.bidFloor', 0); + } + + try { + const bidFloor = bid.getFloor({ + currency: 'USD', + mediaType: '*', + size: '*', + }); + return bidFloor.floor; + } catch (_) { + return 0 + } +} + +export function isBidRequestValid(bid) { + return Boolean(bid.bidId && bid.params && bid.params.placementId); +} + +export const buildBidRequests = (adurl) => (validBidRequests = [], bidderRequest) => { + const winTop = getWindowTop(); + const location = winTop.location; + const placements = []; + + const request = { + deviceWidth: winTop.screen.width, + deviceHeight: winTop.screen.height, + language: (navigator && navigator.language) ? navigator.language.split('-')[0] : '', + host: location.host, + page: location.pathname, + placements: placements + }; + consentCheck(bidderRequest, request); + + // if (bidderRequest) { + // if (bidderRequest.uspConsent) { + // request.ccpa = bidderRequest.uspConsent; + // } + // if (bidderRequest.gdprConsent) { + // request.gdpr = bidderRequest.gdprConsent; + // } + // } + + const len = validBidRequests.length; + for (let i = 0; i < len; i++) { + const bid = validBidRequests[i]; + const placement = { + placementId: bid.params.placementId, + bidId: bid.bidId, + schain: bid.schain || {}, + bidfloor: getBidFloor(bid) + }; + + if (typeof bid.userId !== 'undefined') { + placement.userId = bid.userId; + } + + const mediaType = bid.mediaTypes; + + if (mediaType && mediaType[BANNER] && mediaType[BANNER].sizes) { + placement.sizes = mediaType[BANNER].sizes; + placement.adFormat = BANNER; + } + + placements.push(placement); + } + + return { + method: 'POST', + url: adurl, + data: request + }; +} + +export function interpretResponse(serverResponse) { + let response = []; + for (let i = 0; i < serverResponse.body.length; i++) { + let resItem = serverResponse.body[i]; + if (isBidResponseValid(resItem)) { + const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; + resItem.meta = { ...resItem.meta, advertiserDomains }; + + response.push(resItem); + } + } + return response; +} + +export function consentCheck(bidderRequest, req) { + if (bidderRequest) { + if (bidderRequest.uspConsent) { + req.ccpa = bidderRequest.uspConsent; + } + if (bidderRequest.gdprConsent) { + req.gdpr = bidderRequest.gdprConsent + } + if (bidderRequest.gppConsent) { + req.gpp = bidderRequest.gppConsent; + } + } +} + +export const buildUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent) => { + let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; + const isCk2trk = syncEndpoint.includes('ck.2trk.info'); + const isSpec = syncOptions.spec; + if (isCk2trk) { + if (!Object.is(isSpec, true)) { + let syncId = storage.getCookie('_sharedid'); + syncEndpoint = syncEndpoint + 'id=' + syncId; + } else { + syncEndpoint = syncEndpoint + 'id=NA'; + } + } + // Base sync URL + let syncUrl = isCk2trk ? syncEndpoint : `${syncEndpoint}/${syncType}?pbjs=1`; + + if (gdprConsent && gdprConsent.consentString) { + if (typeof gdprConsent.gdprApplies === 'boolean') { + syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; + } + } else { + syncUrl += isCk2trk ? `&gdpr=0&gdpr_consent=` : ''; + } + + if (isCk2trk) { + syncUrl += uspConsent ? `&us_privacy=${uspConsent}` : `&us_privacy=`; + syncUrl += (syncOptions.iframeEnabled) ? `&t=4` : `&t=2` + } else { + if (uspConsent && uspConsent.consentString) { + syncUrl += `&ccpa_consent=${uspConsent.consentString}`; + } + const coppa = config.getConfig('coppa') ? 1 : 0; + syncUrl += `&coppa=${coppa}`; + } + + return [{ + type: syncType, + url: syncUrl + }]; +} + +export function bidWinReport (bid) { + const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; + if (isStr(bid.nurl) && bid.nurl !== '') { + bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); + triggerPixel(bid.nurl); + } +} diff --git a/modules/mediabramaBidAdapter.js b/modules/mediabramaBidAdapter.js index caf6854fe03..89469fbb52f 100644 --- a/modules/mediabramaBidAdapter.js +++ b/modules/mediabramaBidAdapter.js @@ -1,155 +1,20 @@ -import { - isFn, - isStr, - deepAccess, - getWindowTop, - triggerPixel -} from '../src/utils.js'; + import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; +import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/bidUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'mediabrama'; const AD_URL = 'https://prebid.mediabrama.com/pbjs'; const SYNC_URL = 'https://prebid.mediabrama.com/sync'; -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || - !bid.ttl || !bid.currency || !bid.meta) { - return false; - } - - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - default: - return false; - } -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidFloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], - - isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && bid.params.placementId); - }, - - buildRequests: (validBidRequests = [], bidderRequest) => { - const winTop = getWindowTop(); - const location = winTop.location; - const placements = []; - - const request = { - deviceWidth: winTop.screen.width, - deviceHeight: winTop.screen.height, - language: (navigator && navigator.language) ? navigator.language.split('-')[0] : '', - host: location.host, - page: location.pathname, - placements: placements - }; - - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent; - } - } - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - const placement = { - placementId: bid.params.placementId, - bidId: bid.bidId, - schain: bid.schain || {}, - bidfloor: getBidFloor(bid) - }; - - if (typeof bid.userId !== 'undefined') { - placement.userId = bid.userId; - } - - const mediaType = bid.mediaTypes; - - if (mediaType && mediaType[BANNER] && mediaType[BANNER].sizes) { - placement.sizes = mediaType[BANNER].sizes; - placement.adFormat = BANNER; - } - - placements.push(placement); - } - - return { - method: 'POST', - url: AD_URL, - data: request - }; - }, - - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - }, - - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - - return [{ - type: syncType, - url: syncUrl - }]; - }, - - onBidWon: (bid) => { - const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); - triggerPixel(bid.nurl); - } - } + isBidRequestValid: isBidRequestValid, + buildRequests: buildBidRequests(AD_URL), + interpretResponse: interpretResponse, + getUserSyncs: buildUserSyncs(SYNC_URL), + onBidWon: bidWinReport }; registerBidder(spec); diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index d019f509532..08b7a4a532e 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -3,7 +3,8 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { MODULE_TYPE_UID } from '../src/activities/modules.js'; -import { buildUserSyncs, buildRequests, interpretResponse, onBidWon } from '../libraries/bidUtils/bidUtils.js'; +import { buildRequests, interpretResponse, onBidWon } from '../libraries/bidUtils/bidUtils.js'; +import { buildUserSyncs } from '../libraries/bidUtils/bidUtilsCommon.js'; const BIDDER__CODE = 'preciso'; export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index fc81b3d6aa5..c619a261950 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -1,157 +1,20 @@ -import { - isFn, - isStr, - deepAccess, - getWindowTop, - triggerPixel -} from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { consentCheck, buildUserSyncs } from '../libraries/bidUtils/bidUtils.js'; + +import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/bidUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'redtram'; const AD_URL = 'https://prebid.redtram.com/pbjs'; const SYNC_URL = 'https://prebid.redtram.com/sync'; -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || - !bid.ttl || !bid.currency || !bid.meta) { - return false; - } - - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - default: - return false; - } -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidFloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], - - isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && bid.params.placementId); - }, - - buildRequests: (validBidRequests = [], bidderRequest) => { - const winTop = getWindowTop(); - const location = winTop.location; - const placements = []; - - const request = { - deviceWidth: winTop.screen.width, - deviceHeight: winTop.screen.height, - language: (navigator && navigator.language) ? navigator.language.split('-')[0] : '', - host: location.host, - page: location.pathname, - placements: placements - }; - consentCheck(bidderRequest, request); - - // if (bidderRequest) { - // if (bidderRequest.uspConsent) { - // request.ccpa = bidderRequest.uspConsent; - // } - // if (bidderRequest.gdprConsent) { - // request.gdpr = bidderRequest.gdprConsent; - // } - // } - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - const placement = { - placementId: bid.params.placementId, - bidId: bid.bidId, - schain: bid.schain || {}, - bidfloor: getBidFloor(bid) - }; - - if (typeof bid.userId !== 'undefined') { - placement.userId = bid.userId; - } - - const mediaType = bid.mediaTypes; - - if (mediaType && mediaType[BANNER] && mediaType[BANNER].sizes) { - placement.sizes = mediaType[BANNER].sizes; - placement.adFormat = BANNER; - } - - placements.push(placement); - } - - return { - method: 'POST', - url: AD_URL, - data: request - }; - }, - - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - }, + isBidRequestValid: isBidRequestValid, + buildRequests: buildBidRequests(AD_URL), + interpretResponse: interpretResponse, getUserSyncs: buildUserSyncs(SYNC_URL), - - // getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - // let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - // let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; - // if (gdprConsent && gdprConsent.consentString) { - // if (typeof gdprConsent.gdprApplies === 'boolean') { - // syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - // } else { - // syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - // } - // } - // if (uspConsent && uspConsent.consentString) { - // syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - // } - - // const coppa = config.getConfig('coppa') ? 1 : 0; - // syncUrl += `&coppa=${coppa}`; - - // return [{ - // type: syncType, - // url: syncUrl - // }]; - // }, - - onBidWon: (bid) => { - const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); - triggerPixel(bid.nurl); - } - } + onBidWon: bidWinReport }; registerBidder(spec); diff --git a/test/spec/libraries/bidUtils/bidUtilsCommon_spec.js b/test/spec/libraries/bidUtils/bidUtilsCommon_spec.js new file mode 100644 index 00000000000..78c48f3a9b1 --- /dev/null +++ b/test/spec/libraries/bidUtils/bidUtilsCommon_spec.js @@ -0,0 +1,267 @@ +import {expect} from 'chai'; + +import { BANNER } from '../../../../src/mediaTypes.js'; +import * as utils from '../../../../src/utils.js'; +import { interpretResponse, isBidRequestValid, buildUserSyncs, buildBidRequests, bidWinReport } from '../../../../libraries/bidUtils/bidUtilsCommon.js'; + +const BIDDER_CODE = 'bidder'; +const TESTDOMAIN = 'test.org' +const AD_URL = `https://${TESTDOMAIN}/pbjs`; +const SYNC_URL = `https://${TESTDOMAIN}/sync`; + +describe('bidUtilsCommon', function () { + const bid = { + bidId: '23dc19818e5293', + bidder: BIDDER_CODE, + mediaTypes: { + [BANNER]: { + sizes: [[300, 250]] + } + }, + params: { + placementId: 23611, + } + }; + + const bidderRequest = { + refererInfo: { + referer: 'test.com' + } + }; + + const spec = { + isBidRequestValid: isBidRequestValid, + buildRequests: buildBidRequests(AD_URL), + interpretResponse, + getUserSyncs: buildUserSyncs(SYNC_URL), + onBidWon: bidWinReport + }; + + describe('isBidRequestValid', function () { + it('Should return true if there are bidId, params and key parameters present', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false if at least one of parameters is not present', function () { + delete bid.params.placementId; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid], bidderRequest); + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid data if array of bids is valid', function () { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + expect(data.language).to.be.a('string'); + expect(data.host).to.be.a('string'); + expect(data.page).to.be.a('string'); + expect(data.gdpr).to.not.exist; + expect(data.ccpa).to.not.exist; + let placement = data['placements'][0]; + expect(placement).to.have.keys('placementId', 'bidId', 'adFormat', 'sizes', 'schain', 'bidfloor'); + expect(placement.placementId).to.equal(23611); + expect(placement.bidId).to.equal('23dc19818e5293'); + expect(placement.adFormat).to.equal(BANNER); + expect(placement.schain).to.be.an('object'); + expect(placement.sizes).to.be.an('array'); + expect(placement.bidfloor).to.exist.and.to.equal(0); + }); + + it('Returns data with gdprConsent and without uspConsent', function () { + bidderRequest.gdprConsent = 'test'; + serverRequest = spec.buildRequests([bid], bidderRequest); + let data = serverRequest.data; + expect(data.gdpr).to.exist; + expect(data.gdpr).to.be.a('string'); + expect(data.gdpr).to.equal(bidderRequest.gdprConsent); + expect(data.ccpa).to.not.exist; + delete bidderRequest.gdprConsent; + }); + + it('Returns data with uspConsent and without gdprConsent', function () { + bidderRequest.uspConsent = 'test'; + serverRequest = spec.buildRequests([bid], bidderRequest); + let data = serverRequest.data; + expect(data.ccpa).to.exist; + expect(data.ccpa).to.be.a('string'); + expect(data.ccpa).to.equal(bidderRequest.uspConsent); + expect(data.gdpr).to.not.exist; + }); + + it('Returns empty data if no valid requests are passed', function () { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', function () { + it('Should interpret banner response', function () { + const banner = { + body: [{ + mediaType: 'banner', + width: 300, + height: 250, + cpm: 0.4, + ad: 'Test', + requestId: '23dc19818e5293', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1', + meta: {} + }] + }; + let bannerResponses = spec.interpretResponse(banner); + expect(bannerResponses).to.be.an('array').that.is.not.empty; + let dataItem = bannerResponses[0]; + expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', + 'netRevenue', 'currency', 'dealId', 'mediaType', 'meta'); + expect(dataItem.requestId).to.equal('23dc19818e5293'); + expect(dataItem.cpm).to.equal(0.4); + expect(dataItem.width).to.equal(300); + expect(dataItem.height).to.equal(250); + expect(dataItem.ad).to.equal('Test'); + expect(dataItem.ttl).to.equal(120); + expect(dataItem.creativeId).to.equal('2'); + expect(dataItem.netRevenue).to.be.true; + expect(dataItem.currency).to.equal('USD'); + expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains'); + }); + it('Should return an empty array if invalid banner response is passed', function () { + const invBanner = { + body: [{ + width: 300, + cpm: 0.4, + ad: 'Test', + requestId: '23dc19818e5293', + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }; + + let serverResponses = spec.interpretResponse(invBanner); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + it('Should return an empty array if invalid response is passed', function () { + const invalid = { + body: [{ + ttl: 120, + creativeId: '2', + netRevenue: true, + currency: 'USD', + dealId: '1' + }] + }; + let serverResponses = spec.interpretResponse(invalid); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + + describe('getUserSyncs', function () { + it('should do nothing on getUserSyncs', function () { + const syncData = spec.getUserSyncs({}, {}, { + consentString: 'ALL', + gdprApplies: true + }, {}); + expect(syncData).to.be.an('array').which.is.not.empty; + expect(syncData[0]).to.be.an('object') + expect(syncData[0].type).to.be.a('string') + expect(syncData[0].type).to.equal('image') + expect(syncData[0].url).to.be.a('string') + expect(syncData[0].url).to.equal(`https://${TESTDOMAIN}/sync/image?pbjs=1&gdpr=1&gdpr_consent=ALL&coppa=0`) + }); + }); + + describe('on bidWon', function () { + beforeEach(function() { + sinon.stub(utils, 'triggerPixel'); + }); + afterEach(function() { + utils.triggerPixel.restore(); + }); + it('should replace nurl for banner', function () { + const nurl = 'nurl/?ap=${' + 'AUCTION_PRICE}'; + const bid = { + 'bidderCode': 'redtram', + 'width': 300, + 'height': 250, + 'statusMessage': 'Bid available', + 'adId': '5691dd18ba6ab6', + 'requestId': '23dc19818e5293', + 'transactionId': '948c716b-bf64-4303-bcf4-395c2f6a9770', + 'auctionId': 'a6b7c61f-15a9-481b-8f64-e859787e9c07', + 'mediaType': 'banner', + 'source': 'client', + 'ad': "
\n", + 'cpm': 0.68, + 'nurl': nurl, + 'creativeId': 'test', + 'currency': 'USD', + 'dealId': '', + 'meta': { + 'advertiserDomains': [], + 'dchain': { + 'ver': '1.0', + 'complete': 0, + 'nodes': [ + { + 'name': 'redtram' + } + ] + } + }, + 'netRevenue': true, + 'ttl': 120, + 'metrics': {}, + 'adapterCode': 'redtram', + 'originalCpm': 0.68, + 'originalCurrency': 'USD', + 'responseTimestamp': 1668162732297, + 'requestTimestamp': 1668162732292, + 'bidder': 'redtram', + 'adUnitCode': 'div-prebid', + 'timeToRespond': 5, + 'pbLg': '0.50', + 'pbMg': '0.60', + 'pbHg': '0.68', + 'pbAg': '0.65', + 'pbDg': '0.68', + 'pbCg': '', + 'size': '300x250', + 'adserverTargeting': { + 'hb_bidder': 'redtram', + 'hb_adid': '5691dd18ba6ab6', + 'hb_pb': '0.68', + 'hb_size': '300x250', + 'hb_source': 'client', + 'hb_format': 'banner', + 'hb_adomain': '' + }, + 'status': 'rendered', + 'params': [ + { + 'placementId': 23611 + } + ] + }; + spec.onBidWon(bid); + expect(bid.nurl).to.deep.equal('nurl/?ap=0.68'); + }); + }); +}); diff --git a/test/spec/libraries/bidUtils/bidUtils_spec.js b/test/spec/libraries/bidUtils/bidUtils_spec.js index c448e1dac25..a7792b3fb16 100644 --- a/test/spec/libraries/bidUtils/bidUtils_spec.js +++ b/test/spec/libraries/bidUtils/bidUtils_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { buildRequests, interpretResponse, buildUserSyncs } from '../../../../libraries/bidUtils/bidUtils.js'; +import { buildRequests, interpretResponse } from '../../../../libraries/bidUtils/bidUtils.js'; import { getStorageManager } from '../../../../src/storageManager.js'; import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; @@ -64,7 +64,7 @@ describe('bidderOperations', function () { // isBidRequestValid: isBidRequestValid(), buildRequests: buildRequests(bidEndPoint, storage, cookieName), interpretResponse, - buildUserSyncs: buildUserSyncs(syncEndPoint) + // buildUserSyncs: buildUserSyncs(syncEndPoint) }; describe('buildRequests', function () { @@ -138,19 +138,19 @@ describe('bidderOperations', function () { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])) }) }); - describe('getUserSyncs', function () { - const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?/iframe?pbjs=1&coppa=0`; - const syncOptions = { - iframeEnabled: true - }; - let userSync = spec.buildUserSyncs(syncOptions); - it('Returns valid URL and type', function () { - expect(userSync).to.be.an('array').with.lengthOf(1); - expect(userSync[0].type).to.exist; - expect(userSync[0].url).to.exist; - expect(userSync).to.deep.equal([ - { type: 'iframe', url: syncUrl } - ]); - }); - }); + // describe('getUserSyncs', function () { + // const syncUrl = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?/iframe?pbjs=1&coppa=0`; + // const syncOptions = { + // iframeEnabled: true + // }; + // let userSync = spec.buildUserSyncs(syncOptions); + // it('Returns valid URL and type', function () { + // expect(userSync).to.be.an('array').with.lengthOf(1); + // expect(userSync[0].type).to.exist; + // expect(userSync[0].url).to.exist; + // expect(userSync).to.deep.equal([ + // { type: 'iframe', url: syncUrl } + // ]); + // }); + // }); }); From e9c773edb452391f90ec09856f90315c85200227 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Thu, 8 Aug 2024 14:15:29 +0530 Subject: [PATCH 10/12] import common library in loganBidAdapter to remove code duplication --- modules/loganBidAdapter.js | 91 +++----------------------------------- 1 file changed, 7 insertions(+), 84 deletions(-) diff --git a/modules/loganBidAdapter.js b/modules/loganBidAdapter.js index bec23cddc2d..9ca0fc28f74 100644 --- a/modules/loganBidAdapter.js +++ b/modules/loganBidAdapter.js @@ -1,54 +1,18 @@ -import { isFn, deepAccess, getWindowTop } from '../src/utils.js'; +import { getWindowTop } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import { buildUserSyncs, interpretResponse, isBidRequestValid, getBidFloor, consentCheck } from '../libraries/bidUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'logan'; const AD_URL = 'https://USeast2.logan.ai/pbjs'; -const SYNC_URL = 'https://ssp-cookie.logan.ai' - -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || - !bid.ttl || !bid.currency || !bid.meta) { - return false; - } - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.vastXml || bid.vastUrl); - case NATIVE: - return Boolean(bid.native && bid.native.impressionTrackers); - default: - return false; - } -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', - }); - return bidFloor.floor; - } catch (_) { - return 0 - } -} +const SYNC_URL = 'https://ssp-cookie.logan.ai'; export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO, NATIVE], - isBidRequestValid: (bid) => { - return Boolean(bid.bidId && bid.params && bid.params.placementId); - }, + isBidRequestValid: isBidRequestValid, buildRequests: (validBidRequests = [], bidderRequest) => { // convert Native ORTB definition to old-style prebid native definition @@ -67,14 +31,7 @@ export const spec = { placements: placements }; - if (bidderRequest) { - if (bidderRequest.uspConsent) { - request.ccpa = bidderRequest.uspConsent; - } - if (bidderRequest.gdprConsent) { - request.gdpr = bidderRequest.gdprConsent; - } - } + consentCheck(bidderRequest, request); const len = validBidRequests.length; for (let i = 0; i < len; i++) { @@ -123,42 +80,8 @@ export const spec = { }; }, - interpretResponse: (serverResponse) => { - let response = []; - for (let i = 0; i < serverResponse.body.length; i++) { - let resItem = serverResponse.body[i]; - if (isBidResponseValid(resItem)) { - const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; - resItem.meta = { ...resItem.meta, advertiserDomains }; - - response.push(resItem); - } - } - return response; - }, - - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { - let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; - let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`; - if (gdprConsent && gdprConsent.consentString) { - if (typeof gdprConsent.gdprApplies === 'boolean') { - syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; - } else { - syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; - } - } - if (uspConsent && uspConsent.consentString) { - syncUrl += `&ccpa_consent=${uspConsent.consentString}`; - } - - const coppa = config.getConfig('coppa') ? 1 : 0; - syncUrl += `&coppa=${coppa}`; - - return [{ - type: syncType, - url: syncUrl - }]; - } + interpretResponse: interpretResponse, + getUserSyncs: buildUserSyncs(SYNC_URL), }; registerBidder(spec); From 8659a3acdcc4b603e5b6091d7b94eff35acd4579 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Mon, 12 Aug 2024 23:14:33 +0530 Subject: [PATCH 11/12] removed storageManaser from library --- .../creative-renderer-display/renderer.js | 2 +- .../creative-renderer-native/renderer.js | 2 +- .../{bidUtils => precisoUtils}/bidUtils.js | 4 ---- .../bidUtilsCommon.js | 16 ++----------- modules/idxBidAdapter.js | 2 +- modules/loganBidAdapter.js | 7 ++++-- modules/mediabramaBidAdapter.js | 6 +++-- modules/precisoBidAdapter.js | 24 +++++++++++++------ modules/redtramBidAdapter.js | 6 +++-- .../bidUtilsCommon_spec.js | 6 ++--- .../bidUtils_spec.js | 10 ++------ 11 files changed, 40 insertions(+), 45 deletions(-) rename libraries/{bidUtils => precisoUtils}/bidUtils.js (92%) rename libraries/{bidUtils => precisoUtils}/bidUtilsCommon.js (88%) rename test/spec/libraries/{bidUtils => precisoUtils}/bidUtilsCommon_spec.js (98%) rename test/spec/libraries/{bidUtils => precisoUtils}/bidUtils_spec.js (90%) diff --git a/libraries/creative-renderer-display/renderer.js b/libraries/creative-renderer-display/renderer.js index 72f3658fe79..146afab46ae 100644 --- a/libraries/creative-renderer-display/renderer.js +++ b/libraries/creative-renderer-display/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "!function(){\"use strict\";window.render=function({ad:d,adUrl:i,width:n,height:e},{mkFrame:o},r){if(!d&&!i)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const t=r.document,s={width:n,height:e};i&&!d?s.src=i:s.srcdoc=d,t.body.appendChild(o(t,s))}}}();" \ No newline at end of file +export const RENDERER = "(()=>{\"use strict\";window.render=function({ad:d,adUrl:e,width:i,height:r},{mkFrame:n},o){if(!d&&!e)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const s=o.document,t={width:i,height:r};e&&!d?t.src=e:t.srcdoc=d,s.body.appendChild(n(s,t))}}})();" \ No newline at end of file diff --git a/libraries/creative-renderer-native/renderer.js b/libraries/creative-renderer-native/renderer.js index 57d86fc8ce3..d7d85cdd7ba 100644 --- a/libraries/creative-renderer-native/renderer.js +++ b/libraries/creative-renderer-native/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "!function(){\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}}();" \ No newline at end of file +export const RENDERER = "(()=>{\"use strict\";const e=\"Prebid Native\",t={title:\"text\",data:\"value\",img:\"url\",video:\"vasttag\"};function n(e,t){return new Promise(((n,r)=>{const i=t.createElement(\"script\");i.onload=n,i.onerror=r,i.src=e,t.body.appendChild(i)}))}function r(e,t,r,i,o=n){const{rendererUrl:s,assets:a,ortb:d,adTemplate:c}=t,l=i.document;return s?o(s,l).then((()=>{if(\"function\"!=typeof i.renderAd)throw new Error(`Renderer from '${s}' does not define renderAd()`);const e=a||[];return e.ortb=d,i.renderAd(e)})):Promise.resolve(r(c??l.body.innerHTML))}window.render=function({adId:n,native:i},{sendMessage:o},s,a=r){const{head:d,body:c}=s.document,l=()=>o(e,{action:\"resizeNativeHeight\",height:c.offsetHeight,width:c.offsetWidth}),u=function(e,{assets:n=[],ortb:r,nativeKeys:i={}}){const o=Object.fromEntries(n.map((({key:e,value:t})=>[e,t])));let s=Object.fromEntries(Object.entries(i).flatMap((([t,n])=>{const r=o.hasOwnProperty(t)?o[t]:void 0;return[[`##${n}##`,r],[`${n}:${e}`,r]]})));return r&&Object.assign(s,{\"##hb_native_linkurl##\":r.link?.url,\"##hb_native_privacy##\":r.privacy},Object.fromEntries((r.assets||[]).flatMap((e=>{const n=Object.keys(t).find((t=>e[t]));return[n&&[`##hb_native_asset_id_${e.id}##`,e[n][t[n]]],e.link?.url&&[`##hb_native_asset_link_id_${e.id}##`,e.link.url]].filter((e=>e))})))),s=Object.entries(s).concat([[/##hb_native_asset_(link_)?id_\\d+##/g]]),function(e){return s.reduce(((e,[t,n])=>e.replaceAll(t,n||\"\")),e)}}(n,i);return d&&(d.innerHTML=u(d.innerHTML)),a(n,i,u,s).then((t=>{c.innerHTML=t,\"function\"==typeof s.postRenderAd&&s.postRenderAd({adId:n,...i}),s.document.querySelectorAll(\".pb-click\").forEach((t=>{const n=t.getAttribute(\"hb_native_asset_id\");t.addEventListener(\"click\",(()=>o(e,{action:\"click\",assetId:n})))})),o(e,{action:\"fireNativeImpressionTrackers\"}),\"complete\"===s.document.readyState?l():s.onload=l}))}})();" \ No newline at end of file diff --git a/libraries/bidUtils/bidUtils.js b/libraries/precisoUtils/bidUtils.js similarity index 92% rename from libraries/bidUtils/bidUtils.js rename to libraries/precisoUtils/bidUtils.js index fb1fac0771a..2193a535bc3 100644 --- a/libraries/bidUtils/bidUtils.js +++ b/libraries/precisoUtils/bidUtils.js @@ -1,12 +1,8 @@ import { convertOrtbRequestToProprietaryNative } from '../../src/native.js'; import { replaceAuctionPrice } from '../../src/utils.js'; -import { getStorageManager } from '../../src/storageManager.js'; import { ajax } from '../../src/ajax.js'; -import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; import { consentCheck } from './bidUtilsCommon.js'; -export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); - export const buildRequests = (endpoint) => (validBidRequests = [], bidderRequest) => { // convert Native ORTB definition to old-style prebid native definition validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); diff --git a/libraries/bidUtils/bidUtilsCommon.js b/libraries/precisoUtils/bidUtilsCommon.js similarity index 88% rename from libraries/bidUtils/bidUtilsCommon.js rename to libraries/precisoUtils/bidUtilsCommon.js index e662148414c..cb9699035fb 100644 --- a/libraries/bidUtils/bidUtilsCommon.js +++ b/libraries/precisoUtils/bidUtilsCommon.js @@ -7,10 +7,6 @@ import { triggerPixel } from '../../src/utils.js'; import { BANNER, VIDEO, NATIVE } from '../../src/mediaTypes.js'; -import { getStorageManager } from '../../src/storageManager.js'; -import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; - -export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); function isBidResponseValid(bid) { if (!bid.requestId || !bid.cpm || !bid.creativeId || @@ -134,18 +130,10 @@ export function consentCheck(bidderRequest, req) { } } -export const buildUserSyncs = (syncEndpoint) => (syncOptions, serverResponses, gdprConsent, uspConsent) => { +export const buildUserSyncs = (syncOptions, serverResponses, gdprConsent, uspConsent, syncEndpoint) => { let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image'; const isCk2trk = syncEndpoint.includes('ck.2trk.info'); - const isSpec = syncOptions.spec; - if (isCk2trk) { - if (!Object.is(isSpec, true)) { - let syncId = storage.getCookie('_sharedid'); - syncEndpoint = syncEndpoint + 'id=' + syncId; - } else { - syncEndpoint = syncEndpoint + 'id=NA'; - } - } + // Base sync URL let syncUrl = isCk2trk ? syncEndpoint : `${syncEndpoint}/${syncType}?pbjs=1`; diff --git a/modules/idxBidAdapter.js b/modules/idxBidAdapter.js index 61e9280ff8d..12adb4058ae 100644 --- a/modules/idxBidAdapter.js +++ b/modules/idxBidAdapter.js @@ -1,7 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js' import { BANNER } from '../src/mediaTypes.js' import { isArray, isNumber } from '../src/utils.js' -import { interpretResponse } from '../libraries/bidUtils/bidUtils.js'; +import { interpretResponse } from '../libraries/precisoUtils/bidUtils.js'; const BIDDER_CODE = 'idx' const ENDPOINT_URL = 'https://dev-event.dxmdp.com/rest/api/v1/bid' diff --git a/modules/loganBidAdapter.js b/modules/loganBidAdapter.js index 9ca0fc28f74..4e2652e452f 100644 --- a/modules/loganBidAdapter.js +++ b/modules/loganBidAdapter.js @@ -2,7 +2,7 @@ import { getWindowTop } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import { buildUserSyncs, interpretResponse, isBidRequestValid, getBidFloor, consentCheck } from '../libraries/bidUtils/bidUtilsCommon.js'; +import { buildUserSyncs, interpretResponse, isBidRequestValid, getBidFloor, consentCheck } from '../libraries/precisoUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'logan'; const AD_URL = 'https://USeast2.logan.ai/pbjs'; @@ -81,7 +81,10 @@ export const spec = { }, interpretResponse: interpretResponse, - getUserSyncs: buildUserSyncs(SYNC_URL), + getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { + return buildUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_URL); + } + }; registerBidder(spec); diff --git a/modules/mediabramaBidAdapter.js b/modules/mediabramaBidAdapter.js index 89469fbb52f..9722f1672ba 100644 --- a/modules/mediabramaBidAdapter.js +++ b/modules/mediabramaBidAdapter.js @@ -1,7 +1,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/bidUtils/bidUtilsCommon.js'; +import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/precisoUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'mediabrama'; const AD_URL = 'https://prebid.mediabrama.com/pbjs'; @@ -13,7 +13,9 @@ export const spec = { isBidRequestValid: isBidRequestValid, buildRequests: buildBidRequests(AD_URL), interpretResponse: interpretResponse, - getUserSyncs: buildUserSyncs(SYNC_URL), + getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { + return buildUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_URL); + }, onBidWon: bidWinReport }; diff --git a/modules/precisoBidAdapter.js b/modules/precisoBidAdapter.js index 08b7a4a532e..6f6ab82eca2 100644 --- a/modules/precisoBidAdapter.js +++ b/modules/precisoBidAdapter.js @@ -3,12 +3,12 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { MODULE_TYPE_UID } from '../src/activities/modules.js'; -import { buildRequests, interpretResponse, onBidWon } from '../libraries/bidUtils/bidUtils.js'; -import { buildUserSyncs } from '../libraries/bidUtils/bidUtilsCommon.js'; +import { buildRequests, interpretResponse, onBidWon } from '../libraries/precisoUtils/bidUtils.js'; +import { buildUserSyncs } from '../libraries/precisoUtils/bidUtilsCommon.js'; const BIDDER__CODE = 'preciso'; -export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: 'sharedId' }); -export const storage2 = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); +// export const storage2 = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER__CODE }); const SUPPORTED_MEDIA_TYPES = [BANNER]; const GVLID = 874; let precisoId = 'NA'; @@ -26,7 +26,7 @@ export const spec = { sharedId = storage.getDataFromLocalStorage('_sharedid') || storage.getCookie('_sharedid'); let precisoBid = true; const preCall = 'https://ssp-usersync.mndtrk.com/getUUID?sharedId=' + sharedId; - precisoId = storage2.getDataFromLocalStorage('_pre|id'); + precisoId = storage.getDataFromLocalStorage('_pre|id'); if (Object.is(precisoId, 'NA') || Object.is(precisoId, null) || Object.is(precisoId, undefined)) { if (!bid.precisoBid) { precisoBid = false; @@ -39,7 +39,17 @@ export const spec = { buildRequests: buildRequests(endpoint), interpretResponse, onBidWon, - getUserSyncs: buildUserSyncs(syncEndpoint), + getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { + const isSpec = syncOptions.spec; + if (!Object.is(isSpec, true)) { + let syncId = storage.getCookie('_sharedid'); + syncEndpoint = syncEndpoint + 'id=' + syncId; + } else { + syncEndpoint = syncEndpoint + 'id=NA'; + } + + return buildUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, syncEndpoint); + } }; registerBidder(spec); @@ -56,7 +66,7 @@ async function getapi(url) { const uuidValue = dataMap.get('UUID'); if (!Object.is(uuidValue, null) && !Object.is(uuidValue, undefined)) { - storage2.setDataInLocalStorage('_pre|id', uuidValue); + storage.setDataInLocalStorage('_pre|id', uuidValue); } return data; } catch (error) { diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index 36f436b8ce7..bacc209f991 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -1,6 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; -import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/bidUtils/bidUtilsCommon.js'; +import { bidWinReport, buildBidRequests, buildUserSyncs, interpretResponse, isBidRequestValid } from '../libraries/precisoUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'redtram'; const AD_URL = 'https://prebid.redtram.com/pbjs'; @@ -12,7 +12,9 @@ export const spec = { isBidRequestValid: isBidRequestValid, buildRequests: buildBidRequests(AD_URL), interpretResponse: interpretResponse, - getUserSyncs: buildUserSyncs(SYNC_URL), + getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => { + return buildUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_URL); + }, onBidWon: bidWinReport }; diff --git a/test/spec/libraries/bidUtils/bidUtilsCommon_spec.js b/test/spec/libraries/precisoUtils/bidUtilsCommon_spec.js similarity index 98% rename from test/spec/libraries/bidUtils/bidUtilsCommon_spec.js rename to test/spec/libraries/precisoUtils/bidUtilsCommon_spec.js index 78c48f3a9b1..754b104d96d 100644 --- a/test/spec/libraries/bidUtils/bidUtilsCommon_spec.js +++ b/test/spec/libraries/precisoUtils/bidUtilsCommon_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import { BANNER } from '../../../../src/mediaTypes.js'; import * as utils from '../../../../src/utils.js'; -import { interpretResponse, isBidRequestValid, buildUserSyncs, buildBidRequests, bidWinReport } from '../../../../libraries/bidUtils/bidUtilsCommon.js'; +import { interpretResponse, isBidRequestValid, buildUserSyncs, buildBidRequests, bidWinReport } from '../../../../libraries/precisoUtils/bidUtilsCommon.js'; const BIDDER_CODE = 'bidder'; const TESTDOMAIN = 'test.org' @@ -33,7 +33,7 @@ describe('bidUtilsCommon', function () { isBidRequestValid: isBidRequestValid, buildRequests: buildBidRequests(AD_URL), interpretResponse, - getUserSyncs: buildUserSyncs(SYNC_URL), + getUserSyncs: buildUserSyncs, onBidWon: bidWinReport }; @@ -178,7 +178,7 @@ describe('bidUtilsCommon', function () { const syncData = spec.getUserSyncs({}, {}, { consentString: 'ALL', gdprApplies: true - }, {}); + }, {}, SYNC_URL); expect(syncData).to.be.an('array').which.is.not.empty; expect(syncData[0]).to.be.an('object') expect(syncData[0].type).to.be.a('string') diff --git a/test/spec/libraries/bidUtils/bidUtils_spec.js b/test/spec/libraries/precisoUtils/bidUtils_spec.js similarity index 90% rename from test/spec/libraries/bidUtils/bidUtils_spec.js rename to test/spec/libraries/precisoUtils/bidUtils_spec.js index a7792b3fb16..eecfea4b70e 100644 --- a/test/spec/libraries/bidUtils/bidUtils_spec.js +++ b/test/spec/libraries/precisoUtils/bidUtils_spec.js @@ -1,8 +1,6 @@ import { expect } from 'chai'; -import { buildRequests, interpretResponse } from '../../../../libraries/bidUtils/bidUtils.js'; -import { getStorageManager } from '../../../../src/storageManager.js'; -import { MODULE_TYPE_UID } from '../../../../src/activities/modules.js'; +import { buildRequests, interpretResponse } from '../../../../libraries/precisoUtils/bidUtils.js'; const DEFAULT_PRICE = 1 const DEFAULT_CURRENCY = 'USD' @@ -10,11 +8,7 @@ const DEFAULT_BANNER_WIDTH = 300 const DEFAULT_BANNER_HEIGHT = 250 const BIDDER_CODE = 'preciso'; const TESTDOMAIN = 'test.org' -const cookieName = '_pre|id'; - const bidEndPoint = `https://${TESTDOMAIN}/bid_request/openrtb`; -const syncEndPoint = `https://${TESTDOMAIN}/rtb/user/usersync.aspx?`; -const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE }); describe('bidderOperations', function () { let bid = { @@ -62,7 +56,7 @@ describe('bidderOperations', function () { const spec = { // isBidRequestValid: isBidRequestValid(), - buildRequests: buildRequests(bidEndPoint, storage, cookieName), + buildRequests: buildRequests(bidEndPoint), interpretResponse, // buildUserSyncs: buildUserSyncs(syncEndPoint) }; From c2b8c276e8b221db61ba318b6e86111216501479 Mon Sep 17 00:00:00 2001 From: Nikhil Gopal chennissery Date: Fri, 16 Aug 2024 10:00:42 +0530 Subject: [PATCH 12/12] renderer.js changes reverted --- integrationExamples/gpt/precisoExample.html | 8 +++++--- libraries/creative-renderer-display/renderer.js | 2 +- libraries/creative-renderer-native/renderer.js | 2 +- libraries/precisoUtils/bidUtils.js | 5 ++++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/integrationExamples/gpt/precisoExample.html b/integrationExamples/gpt/precisoExample.html index f354f0eaf5c..04f44b28345 100644 --- a/integrationExamples/gpt/precisoExample.html +++ b/integrationExamples/gpt/precisoExample.html @@ -8,7 +8,7 @@