diff --git a/libraries/mediaImpactUtils/index.js b/libraries/mediaImpactUtils/index.js new file mode 100644 index 00000000000..a56761d8ed4 --- /dev/null +++ b/libraries/mediaImpactUtils/index.js @@ -0,0 +1,61 @@ +import { buildUrl } from '../../src/utils.js'; +import { ajax } from '../../src/ajax.js'; + +/** + * Builds the bid requests and beacon parameters. + * @param {Array} validBidRequests - The array of valid bid requests. + * @param {string} referer - The referer URL. + * @returns {Object} - An object containing bidRequests and beaconParams. + */ +export function buildBidRequestsAndParams(validBidRequests, referer) { + const bidRequests = []; + const beaconParams = { tag: [], partner: [], sizes: [], referer: encodeURIComponent(referer) }; + + validBidRequests.forEach(function (validBidRequest) { + const sizes = validBidRequest.params.sizes || validBidRequest.sizes; + + const bidRequestObject = { + adUnitCode: validBidRequest.adUnitCode, + sizes: sizes, + bidId: validBidRequest.bidId, + referer: referer, + }; + + if (parseInt(validBidRequest.params.unitId)) { + bidRequestObject.unitId = parseInt(validBidRequest.params.unitId); + beaconParams.tag.push(validBidRequest.params.unitId); + } + + if (parseInt(validBidRequest.params.partnerId)) { + bidRequestObject.unitId = 0; + bidRequestObject.partnerId = parseInt(validBidRequest.params.partnerId); + beaconParams.partner.push(validBidRequest.params.partnerId); + } + + bidRequests.push(bidRequestObject); + beaconParams.sizes.push(joinSizesToString(sizes)); + }); + + // Finalize beaconParams + if (beaconParams.partner.length > 0) { + beaconParams.partner = beaconParams.partner.join(','); + } else { + delete beaconParams.partner; + } + beaconParams.tag = beaconParams.tag.join(','); + beaconParams.sizes = beaconParams.sizes.join(','); + + return { bidRequests, beaconParams }; +} + +export function joinSizesToString(sizes) { + return sizes.map(size => size.join('x')).join('|'); +} + +export function postRequest(endpoint, data) { + ajax(endpoint, null, data, { method: 'POST' }); +} + +export function buildEndpointUrl(protocol, hostname, pathname, searchParams) { + return buildUrl({ protocol, hostname, pathname, search: searchParams }); +} diff --git a/modules/adpartnerBidAdapter.js b/modules/adpartnerBidAdapter.js index 471a0bba64a..504809afa87 100644 --- a/modules/adpartnerBidAdapter.js +++ b/modules/adpartnerBidAdapter.js @@ -1,6 +1,5 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { buildUrl } from '../src/utils.js' -import {ajax} from '../src/ajax.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { buildBidRequestsAndParams, postRequest, buildEndpointUrl } from '../libraries/mediaImpactUtils/index.js'; const BIDDER_CODE = 'adpartner'; export const ENDPOINT_PROTOCOL = 'https'; @@ -15,74 +14,25 @@ export const spec = { }, buildRequests: function (validBidRequests, bidderRequest) { - // TODO does it make sense to fall back to window.location.href? const referer = bidderRequest?.refererInfo?.page || window.location.href; - let bidRequests = []; - let beaconParams = { - tag: [], - partner: [], - sizes: [], - referer: '' - }; - - validBidRequests.forEach(function(validBidRequest) { - let bidRequestObject = { - adUnitCode: validBidRequest.adUnitCode, - sizes: validBidRequest.sizes, - bidId: validBidRequest.bidId, - referer: referer - }; - - if (parseInt(validBidRequest.params.unitId)) { - bidRequestObject.unitId = parseInt(validBidRequest.params.unitId); - beaconParams.tag.push(validBidRequest.params.unitId); - } - - if (parseInt(validBidRequest.params.partnerId)) { - bidRequestObject.unitId = 0; - bidRequestObject.partnerId = parseInt(validBidRequest.params.partnerId); - beaconParams.partner.push(validBidRequest.params.partnerId); - } - - bidRequests.push(bidRequestObject); + // Use the common function to build bidRequests and beaconParams + const { bidRequests, beaconParams } = buildBidRequestsAndParams(validBidRequests, referer); - beaconParams.sizes.push(spec.joinSizesToString(validBidRequest.sizes)); - beaconParams.referer = encodeURIComponent(referer); - }); - - if (beaconParams.partner.length > 0) { - beaconParams.partner = beaconParams.partner.join(','); - } else { - delete beaconParams.partner; - } - - beaconParams.tag = beaconParams.tag.join(','); - beaconParams.sizes = beaconParams.sizes.join(','); - - let adPartnerRequestUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: ENDPOINT_PATH, - search: beaconParams - }); + const adPartnerRequestUrl = buildEndpointUrl( + ENDPOINT_PROTOCOL, + ENDPOINT_DOMAIN, + ENDPOINT_PATH, + beaconParams + ); return { method: 'POST', url: adPartnerRequestUrl, - data: JSON.stringify(bidRequests) + data: JSON.stringify(bidRequests), }; }, - joinSizesToString: function(sizes) { - let res = []; - sizes.forEach(function(size) { - res.push(size.join('x')); - }); - - return res.join('|'); - }, - interpretResponse: function (serverResponse, bidRequest) { const validBids = JSON.parse(bidRequest.data); @@ -91,15 +41,12 @@ export const spec = { } return validBids - .map(bid => ({ - bid: bid, - ad: serverResponse.body[bid.adUnitCode] - })) + .map(bid => ({ bid: bid, ad: serverResponse.body[bid.adUnitCode] })) .filter(item => item.ad) .map(item => spec.adResponse(item.bid, item.ad)); }, - adResponse: function(bid, ad) { + adResponse: function (bid, ad) { const bidObject = { requestId: bid.bidId, ad: ad.ad, @@ -110,38 +57,30 @@ export const spec = { creativeId: ad.creativeId, netRevenue: ad.netRevenue, currency: ad.currency, - winNotification: ad.winNotification - } - - bidObject.meta = {}; - if (ad.adomain && ad.adomain.length > 0) { - bidObject.meta.advertiserDomains = ad.adomain; - } + winNotification: ad.winNotification, + meta: ad.adomain && ad.adomain.length > 0 ? { advertiserDomains: ad.adomain } : {}, + }; return bidObject; }, - onBidWon: function(data) { - data.winNotification.forEach(function(unitWon) { - let adPartnerBidWonUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: unitWon.path - }); + onBidWon: function (data) { + data.winNotification.forEach(function (unitWon) { + const adPartnerBidWonUrl = buildEndpointUrl( + ENDPOINT_PROTOCOL, + ENDPOINT_DOMAIN, + unitWon.path + ); if (unitWon.method === 'POST') { - spec.postRequest(adPartnerBidWonUrl, JSON.stringify(unitWon.data)); + postRequest(adPartnerBidWonUrl, JSON.stringify(unitWon.data)); } }); return true; }, - postRequest(endpoint, data) { - ajax(endpoint, null, data, {method: 'POST'}); - }, - - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { const syncs = []; if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) { @@ -205,7 +144,6 @@ export const spec = { return syncs; }, - -} +}; registerBidder(spec); diff --git a/modules/mediaimpactBidAdapter.js b/modules/mediaimpactBidAdapter.js index d62cb789ea4..a1f04a44142 100644 --- a/modules/mediaimpactBidAdapter.js +++ b/modules/mediaimpactBidAdapter.js @@ -1,6 +1,5 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import { buildUrl } from '../src/utils.js' -import {ajax} from '../src/ajax.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { buildBidRequestsAndParams, postRequest, buildEndpointUrl } from '../libraries/mediaImpactUtils/index.js'; const BIDDER_CODE = 'mediaimpact'; export const ENDPOINT_PROTOCOL = 'https'; @@ -15,79 +14,25 @@ export const spec = { }, buildRequests: function (validBidRequests, bidderRequest) { - // TODO does it make sense to fall back to window.location.href? const referer = bidderRequest?.refererInfo?.page || window.location.href; - let bidRequests = []; - let beaconParams = { - tag: [], - partner: [], - sizes: [], - referer: '' - }; - - validBidRequests.forEach(function(validBidRequest) { - let sizes = validBidRequest.sizes; - if (typeof validBidRequest.params.sizes !== 'undefined') { - sizes = validBidRequest.params.sizes; - } - - let bidRequestObject = { - adUnitCode: validBidRequest.adUnitCode, - sizes: sizes, - bidId: validBidRequest.bidId, - referer: referer - }; - - if (parseInt(validBidRequest.params.unitId)) { - bidRequestObject.unitId = parseInt(validBidRequest.params.unitId); - beaconParams.tag.push(validBidRequest.params.unitId); - } - - if (parseInt(validBidRequest.params.partnerId)) { - bidRequestObject.unitId = 0; - bidRequestObject.partnerId = parseInt(validBidRequest.params.partnerId); - beaconParams.partner.push(validBidRequest.params.partnerId); - } - - bidRequests.push(bidRequestObject); - - beaconParams.sizes.push(spec.joinSizesToString(sizes)); - beaconParams.referer = encodeURIComponent(referer); - }); - - if (beaconParams.partner.length > 0) { - beaconParams.partner = beaconParams.partner.join(','); - } else { - delete beaconParams.partner; - } + // Use the common function to build bidRequests and beaconParams + const { bidRequests, beaconParams } = buildBidRequestsAndParams(validBidRequests, referer); - beaconParams.tag = beaconParams.tag.join(','); - beaconParams.sizes = beaconParams.sizes.join(','); - - let adRequestUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: ENDPOINT_PATH, - search: beaconParams - }); + const adRequestUrl = buildEndpointUrl( + ENDPOINT_PROTOCOL, + ENDPOINT_DOMAIN, + ENDPOINT_PATH, + beaconParams + ); return { method: 'POST', url: adRequestUrl, - data: JSON.stringify(bidRequests) + data: JSON.stringify(bidRequests), }; }, - joinSizesToString: function(sizes) { - let res = []; - sizes.forEach(function(size) { - res.push(size.join('x')); - }); - - return res.join('|'); - }, - interpretResponse: function (serverResponse, bidRequest) { const validBids = JSON.parse(bidRequest.data); @@ -96,16 +41,13 @@ export const spec = { } return validBids - .map(bid => ({ - bid: bid, - ad: serverResponse.body[bid.adUnitCode] - })) + .map(bid => ({ bid: bid, ad: serverResponse.body[bid.adUnitCode] })) .filter(item => item.ad) .map(item => spec.adResponse(item.bid, item.ad)); }, - adResponse: function(bid, ad) { - const bidObject = { + adResponse: function (bid, ad) { + return { requestId: bid.bidId, ad: ad.ad, cpm: ad.cpm, @@ -116,36 +58,26 @@ export const spec = { netRevenue: ad.netRevenue, currency: ad.currency, winNotification: ad.winNotification, - meta: {} + meta: ad.meta || {}, }; - - if (ad.meta) { - bidObject.meta = ad.meta; - } - - return bidObject; }, - onBidWon: function(data) { - data.winNotification.forEach(function(unitWon) { - let adBidWonUrl = buildUrl({ - protocol: ENDPOINT_PROTOCOL, - hostname: ENDPOINT_DOMAIN, - pathname: unitWon.path - }); + onBidWon: function (data) { + data.winNotification.forEach(function (unitWon) { + const adBidWonUrl = buildEndpointUrl( + ENDPOINT_PROTOCOL, + ENDPOINT_DOMAIN, + unitWon.path + ); if (unitWon.method === 'POST') { - spec.postRequest(adBidWonUrl, JSON.stringify(unitWon.data)); + postRequest(adBidWonUrl, JSON.stringify(unitWon.data)); } }); return true; }, - postRequest(endpoint, data) { - ajax(endpoint, null, data, {method: 'POST'}); - }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { const syncs = []; @@ -210,7 +142,6 @@ export const spec = { return syncs; }, - -} +}; registerBidder(spec); diff --git a/test/spec/modules/adpartnerBidAdapter_spec.js b/test/spec/modules/adpartnerBidAdapter_spec.js index d9f9b0d0074..597974acce8 100644 --- a/test/spec/modules/adpartnerBidAdapter_spec.js +++ b/test/spec/modules/adpartnerBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec, ENDPOINT_PROTOCOL, ENDPOINT_DOMAIN, ENDPOINT_PATH} from 'modules/adpartnerBidAdapter.js'; import {newBidder} from 'src/adapters/bidderFactory.js'; +import * as miUtils from 'libraries/mediaImpactUtils/index.js'; const BIDDER_CODE = 'adpartner'; @@ -117,7 +118,7 @@ describe('AdpartnerAdapter', function () { describe('joinSizesToString', function () { it('success convert sizes list to string', function () { - const sizesStr = spec.joinSizesToString([[300, 250], [300, 600]]); + const sizesStr = miUtils.joinSizesToString([[300, 250], [300, 600]]); expect(sizesStr).to.equal('300x250|300x600'); }); }); @@ -238,7 +239,7 @@ describe('AdpartnerAdapter', function () { let ajaxStub; beforeEach(() => { - ajaxStub = sinon.stub(spec, 'postRequest') + ajaxStub = sinon.stub(miUtils, 'postRequest') }) afterEach(() => { diff --git a/test/spec/modules/mediaimpactBidAdapter_spec.js b/test/spec/modules/mediaimpactBidAdapter_spec.js index 806f0adeabe..5bf088c0334 100644 --- a/test/spec/modules/mediaimpactBidAdapter_spec.js +++ b/test/spec/modules/mediaimpactBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec, ENDPOINT_PROTOCOL, ENDPOINT_DOMAIN, ENDPOINT_PATH} from 'modules/mediaimpactBidAdapter.js'; import {newBidder} from 'src/adapters/bidderFactory.js'; +import * as miUtils from 'libraries/mediaImpactUtils/index.js'; const BIDDER_CODE = 'mediaimpact'; @@ -117,7 +118,7 @@ describe('MediaimpactAdapter', function () { describe('joinSizesToString', function () { it('success convert sizes list to string', function () { - const sizesStr = spec.joinSizesToString([[300, 250], [300, 600]]); + const sizesStr = miUtils.joinSizesToString([[300, 250], [300, 600]]); expect(sizesStr).to.equal('300x250|300x600'); }); }); @@ -238,7 +239,7 @@ describe('MediaimpactAdapter', function () { let ajaxStub; beforeEach(() => { - ajaxStub = sinon.stub(spec, 'postRequest') + ajaxStub = sinon.stub(miUtils, 'postRequest') }) afterEach(() => {