diff --git a/libraries/teqblazeUtils/bidderUtils.js b/libraries/teqblazeUtils/bidderUtils.js index 42db3194308..ce061ac7f3c 100644 --- a/libraries/teqblazeUtils/bidderUtils.js +++ b/libraries/teqblazeUtils/bidderUtils.js @@ -188,20 +188,24 @@ export const buildRequests = (adUrl) => (validBidRequests = [], bidderRequest = return buildRequestsBase({ adUrl, validBidRequests, bidderRequest, placementProcessingFunction }); }; -export const 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); +export function interpretResponseBuilder({addtlBidValidation = (bid) => true} = {}) { + return function (serverResponse) { + let response = []; + for (let i = 0; i < serverResponse.body.length; i++) { + let resItem = serverResponse.body[i]; + if (isBidResponseValid(resItem) && addtlBidValidation(resItem)) { + const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : []; + resItem.meta = { ...resItem.meta, advertiserDomains }; + + response.push(resItem); + } } + + return response; } +} - return response; -}; +export const interpretResponse = interpretResponseBuilder(); export const getUserSyncs = (syncUrl) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { const type = syncOptions.iframeEnabled ? 'iframe' : 'image'; diff --git a/modules/smarthubBidAdapter.js b/modules/smarthubBidAdapter.js index b5970fbb9ee..baf4c358736 100644 --- a/modules/smarthubBidAdapter.js +++ b/modules/smarthubBidAdapter.js @@ -1,23 +1,28 @@ -import {deepAccess, isFn, logError, logMessage} 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 { + buildPlacementProcessingFunction, + buildRequestsBase, + interpretResponseBuilder, + isBidRequestValid +} from '../libraries/teqblazeUtils/bidderUtils.js'; const BIDDER_CODE = 'smarthub'; const ALIASES = [ {code: 'markapp', skipPbsAliasing: true}, {code: 'jdpmedia', skipPbsAliasing: true}, {code: 'tredio', skipPbsAliasing: true}, + {code: 'vimayx', skipPbsAliasing: true}, ]; const BASE_URLS = { smarthub: 'https://prebid.smart-hub.io/pbjs', markapp: 'https://markapp-prebid.smart-hub.io/pbjs', jdpmedia: 'https://jdpmedia-prebid.smart-hub.io/pbjs', - tredio: 'https://tredio-prebid.smart-hub.io/pbjs' + tredio: 'https://tredio-prebid.smart-hub.io/pbjs', + vimayx: 'https://vimayx-prebid.smart-hub.io/pbjs', }; -function getUrl(partnerName) { +const _getUrl = (partnerName) => { const aliases = ALIASES.map(el => el.code); if (aliases.includes(partnerName)) { return BASE_URLS[partnerName]; @@ -26,187 +31,50 @@ function getUrl(partnerName) { return `${BASE_URLS[BIDDER_CODE]}?partnerName=${partnerName}`; } -function isBidResponseValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency || !bid.hasOwnProperty('netRevenue')) { - return false; - } - switch (bid.mediaType) { - case BANNER: - return Boolean(bid.width && bid.height && bid.ad); - case VIDEO: - return Boolean(bid.width && bid.height && (bid.vastUrl || bid.vastXml)); - case NATIVE: - return Boolean(bid.native && bid.native.impressionTrackers && bid.native.impressionTrackers.length); - default: - return false; - } -} - -function getPlacementReqData(bid) { - const { params, bidId, mediaTypes, bidder } = bid; - const schain = bid.schain || {}; - const { partnerName, seat, token, iabCat, minBidfloor, pos } = params; - const bidfloor = getBidFloor(bid); - - const plcmt = { - partnerName: String(partnerName || bidder).toLowerCase(), - seat, - token, - iabCat, - minBidfloor, - pos, - bidId, - schain, - bidfloor, - }; - - if (mediaTypes && mediaTypes[BANNER]) { - plcmt.adFormat = BANNER; - plcmt.sizes = mediaTypes[BANNER].sizes; - } else if (mediaTypes && mediaTypes[VIDEO]) { - plcmt.adFormat = VIDEO; - plcmt.playerSize = mediaTypes[VIDEO].playerSize; - plcmt.minduration = mediaTypes[VIDEO].minduration; - plcmt.maxduration = mediaTypes[VIDEO].maxduration; - plcmt.mimes = mediaTypes[VIDEO].mimes; - plcmt.protocols = mediaTypes[VIDEO].protocols; - plcmt.startdelay = mediaTypes[VIDEO].startdelay; - plcmt.placement = mediaTypes[VIDEO].plcmt; - plcmt.plcmt = mediaTypes[VIDEO].plcmt; // https://github.com/prebid/Prebid.js/issues/10452 - plcmt.skip = mediaTypes[VIDEO].skip; - plcmt.skipafter = mediaTypes[VIDEO].skipafter; - plcmt.minbitrate = mediaTypes[VIDEO].minbitrate; - plcmt.maxbitrate = mediaTypes[VIDEO].maxbitrate; - plcmt.delivery = mediaTypes[VIDEO].delivery; - plcmt.playbackmethod = mediaTypes[VIDEO].playbackmethod; - plcmt.api = mediaTypes[VIDEO].api; - plcmt.linearity = mediaTypes[VIDEO].linearity; - } else if (mediaTypes && mediaTypes[NATIVE]) { - plcmt.native = mediaTypes[NATIVE]; - plcmt.adFormat = NATIVE; - } - - return plcmt; -} - -function getBidFloor(bid) { - if (!isFn(bid.getFloor)) { - return deepAccess(bid, 'params.bidfloor', 0); - } - - try { - const bidFloor = bid.getFloor({ - currency: 'USD', - mediaType: '*', - size: '*', +const getPartnerName = (bid) => String(bid.params?.partnerName || bid.bidder).toLowerCase(); + +const getPlacementReqData = buildPlacementProcessingFunction({ + addPlacementType() {}, + addCustomFieldsToPlacement(bid, bidderRequest, placement) { + const { seat, token, iabCat, minBidfloor, pos } = bid.params; + Object.assign(placement, { + partnerName: getPartnerName(bid), + seat, + token, + iabCat, + minBidfloor, + pos, }); - return bidFloor.floor; - } catch (e) { - logError(e); - return 0; - } -} - -function buildRequestParams(bidderRequest = {}, placements = []) { - let deviceWidth = 0; - let deviceHeight = 0; - - let winLocation; - try { - const winTop = window.top; - deviceWidth = winTop.screen.width; - deviceHeight = winTop.screen.height; - winLocation = winTop.location; - } catch (e) { - logMessage(e); - winLocation = window.location; - } - - const refferUrl = bidderRequest.refererInfo && bidderRequest.refererInfo.page; - let refferLocation; - try { - refferLocation = refferUrl && new URL(refferUrl); - } catch (e) { - logMessage(e); } - - let location = refferLocation || winLocation; - const language = (navigator && navigator.language) ? navigator.language.split('-')[0] : ''; - const host = location.host; - const page = location.pathname; - const secure = location.protocol === 'https:' ? 1 : 0; - return { - deviceWidth, - deviceHeight, - language, - secure, - host, - page, - placements, - coppa: config.getConfig('coppa') === true ? 1 : 0, - ccpa: bidderRequest.uspConsent || undefined, - gdpr: bidderRequest.gdprConsent || undefined, - tmax: bidderRequest.timeout - }; +}) + +const buildRequests = (validBidRequests = [], bidderRequest = {}) => { + const bidsByPartner = validBidRequests.reduce((bidsByPartner, bid) => { + const partner = getPartnerName(bid); + (bidsByPartner[partner] = bidsByPartner[partner] || []).push(bid); + return bidsByPartner; + }, {}); + return Object.entries(bidsByPartner).map(([partner, validBidRequests]) => { + return buildRequestsBase({ + adUrl: _getUrl(partner), + bidderRequest, + validBidRequests, + placementProcessingFunction: getPlacementReqData + }) + }) } export const spec = { code: BIDDER_CODE, aliases: ALIASES, supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - isBidRequestValid: (bid = {}) => { - const { params, bidId, mediaTypes } = bid; - let valid = Boolean(bidId && params && params.seat && params.token); - - if (mediaTypes && mediaTypes[BANNER]) { - valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes); - } else if (mediaTypes && mediaTypes[VIDEO]) { - valid = valid && Boolean(mediaTypes[VIDEO] && mediaTypes[VIDEO].playerSize); - } else if (mediaTypes && mediaTypes[NATIVE]) { - valid = valid && Boolean(mediaTypes[NATIVE]); - } else { - valid = false; + isBidRequestValid: isBidRequestValid(['seat', 'token'], 'every'), + buildRequests, + interpretResponse: interpretResponseBuilder({ + addtlBidValidation(bid) { + return bid.hasOwnProperty('netRevenue') } - return valid; - }, - - buildRequests: (validBidRequests = [], bidderRequest = {}) => { - // convert Native ORTB definition to old-style prebid native definition - validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); - const tempObj = {}; - - const len = validBidRequests.length; - for (let i = 0; i < len; i++) { - const bid = validBidRequests[i]; - const data = getPlacementReqData(bid); - tempObj[data.partnerName] = tempObj[data.partnerName] || []; - tempObj[data.partnerName].push(data); - } - - return Object.keys(tempObj).map(key => { - const request = buildRequestParams(bidderRequest, tempObj[key]); - return { - method: 'POST', - url: getUrl(key), - 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; - } + }) }; registerBidder(spec); diff --git a/test/spec/modules/smarthubBidAdapter_spec.js b/test/spec/modules/smarthubBidAdapter_spec.js index a5e8787e21a..eb5fe58093d 100644 --- a/test/spec/modules/smarthubBidAdapter_spec.js +++ b/test/spec/modules/smarthubBidAdapter_spec.js @@ -106,7 +106,9 @@ describe('SmartHubBidAdapter', function () { const bidderRequest = { uspConsent: '1---', - gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', + gdprConsent: { + consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw' + }, refererInfo: { page: 'https://test.com' }, @@ -166,7 +168,7 @@ describe('SmartHubBidAdapter', function () { expect(data.host).to.be.a('string'); expect(data.page).to.be.a('string'); expect(data.coppa).to.be.a('number'); - expect(data.gdpr).to.be.a('string'); + expect(data.gdpr.consentString).to.be.a('string'); expect(data.ccpa).to.be.a('string'); expect(data.tmax).to.be.a('number'); expect(data.placements).to.have.lengthOf(3); @@ -212,8 +214,8 @@ describe('SmartHubBidAdapter', function () { serverRequest = spec.buildRequests(bids, bidderRequest); let data = serverRequest[0].data; expect(data.gdpr).to.exist; - expect(data.gdpr).to.be.a('string'); - expect(data.gdpr).to.equal(bidderRequest.gdprConsent); + expect(data.gdpr.consentString).to.be.a('string'); + expect(data.gdpr.consentString).to.equal(bidderRequest.gdprConsent.consentString); expect(data.ccpa).to.not.exist; delete bidderRequest.gdprConsent; });