diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index 7e2a7da3b61..4f8c8c1c550 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -115,10 +115,11 @@ export const spec = { let computedEndpointUrl = ENDPOINT_URL; if (bidderRequest.paapi?.enabled) { - const fledgeConfig = config.getConfig('fledgeConfig') || { + const fromConfig = config.getConfig('paapiConfig') || config.getConfig('fledgeConfig') || { sellerTimeout: 500 }; + const fledgeConfig = { seller: FLEDGE_SELLER_URL, decisionLogicUrl: FLEDGE_DECISION_LOGIC_URL, - sellerTimeout: 500 + ...fromConfig }; mergeDeep(request, { ext: { fledge_config: fledgeConfig } }); computedEndpointUrl = FLEDGE_ENDPOINT_URL; @@ -165,7 +166,6 @@ export const spec = { interpretResponse: function (serverResponse, originalRequest) { let bids; - const fledgeInterestGroupBuyers = config.getConfig('fledgeConfig.interestGroupBuyers') || []; const responseBody = serverResponse.body; let fledgeAuctionConfigs = null; @@ -173,24 +173,35 @@ export const spec = { // we have fledge response // mimic the original response ([{},...]) bids = this.interpretOrtbResponse({ body: responseBody.seatbid[0]?.bid }, originalRequest); - - const seller = responseBody.ext.seller; - const decisionLogicUrl = responseBody.ext.decisionLogicUrl; - const sellerTimeout = 'sellerTimeout' in responseBody.ext ? { sellerTimeout: responseBody.ext.sellerTimeout } : {}; + const paapiAdapterConfig = config.getConfig('paapiConfig') || config.getConfig('fledgeConfig') || {}; + const fledgeInterestGroupBuyers = paapiAdapterConfig.interestGroupBuyers || []; + // values from the response.ext are the most important + const { + decisionLogicUrl = paapiAdapterConfig.decisionLogicUrl || paapiAdapterConfig.decisionLogicURL || + FLEDGE_DECISION_LOGIC_URL, + seller = paapiAdapterConfig.seller || FLEDGE_SELLER_URL, + sellerTimeout = 500 + } = responseBody.ext; + + const fledgeConfig = { + seller, + decisionLogicUrl, + decisionLogicURL: decisionLogicUrl, + sellerTimeout + }; + // fledgeConfig settings are more important; other paapiAdapterConfig settings are facultative + mergeDeep(fledgeConfig, paapiAdapterConfig, fledgeConfig); responseBody.ext.igbid.forEach((igbid) => { - const perBuyerSignals = {}; + const perBuyerSignals = {...fledgeConfig.perBuyerSignals}; // may come from paapiAdapterConfig igbid.igbuyer.forEach(buyerItem => { perBuyerSignals[buyerItem.igdomain] = buyerItem.buyersignal }); fledgeAuctionConfigs = fledgeAuctionConfigs || {}; - fledgeAuctionConfigs[igbid.impid] = mergeDeep( + fledgeAuctionConfigs[igbid.impid] = mergeDeep({}, fledgeConfig, { - seller, - decisionLogicUrl, - interestGroupBuyers: [...fledgeInterestGroupBuyers, ...Object.keys(perBuyerSignals)], + interestGroupBuyers: [...new Set([...fledgeInterestGroupBuyers, ...Object.keys(perBuyerSignals)])], perBuyerSignals, - }, - sellerTimeout + } ); }); } else { diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index cc303dc2f96..f3f9ce8616f 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -460,7 +460,7 @@ describe('RTBHouseAdapter', () => { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; config.setConfig({ fledgeConfig: true }); - const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: {enabled: true} }); + const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: { enabled: true } }); expect(request.url).to.equal('https://prebid-eu.creativecdn.com/bidder/prebidfledge/bids'); expect(request.method).to.equal('POST'); }); @@ -470,7 +470,7 @@ describe('RTBHouseAdapter', () => { delete bidRequest[0].params.test; config.setConfig({ fledgeConfig: false }); - const request = spec.buildRequests(bidRequest, {...bidderRequest, paapi: {enabled: true}}); + const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: {enabled: true} }); const data = JSON.parse(request.data); expect(data.ext).to.exist.and.to.be.a('object'); expect(data.ext.fledge_config).to.exist.and.to.be.a('object'); @@ -480,7 +480,7 @@ describe('RTBHouseAdapter', () => { expect(data.ext.fledge_config.sellerTimeout).to.equal(500); }); - it('sets a fledgeConfig object values when available from config', function () { + it('sets request.ext.fledge_config object values when available from fledgeConfig', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; @@ -490,7 +490,7 @@ describe('RTBHouseAdapter', () => { decisionLogicUrl: 'https://sellers.domain/decision.url' } }); - const request = spec.buildRequests(bidRequest, {...bidderRequest, paapi: {enabled: true}}); + const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: {enabled: true} }); const data = JSON.parse(request.data); expect(data.ext).to.exist.and.to.be.a('object'); expect(data.ext.fledge_config).to.exist.and.to.be.a('object'); @@ -500,6 +500,49 @@ describe('RTBHouseAdapter', () => { expect(data.ext.fledge_config.sellerTimeout).to.not.exist; }); + it('sets request.ext.fledge_config object values when available from paapiConfig', function () { + let bidRequest = Object.assign([], bidRequests); + delete bidRequest[0].params.test; + + config.setConfig({ + paapiConfig: { + seller: 'https://sellers.domain', + decisionLogicUrl: 'https://sellers.domain/decision.url' + } + }); + const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: {enabled: true} }); + const data = JSON.parse(request.data); + expect(data.ext).to.exist.and.to.be.a('object'); + expect(data.ext.fledge_config).to.exist.and.to.be.a('object'); + expect(data.ext.fledge_config).to.contain.keys('seller', 'decisionLogicUrl'); + expect(data.ext.fledge_config.seller).to.equal('https://sellers.domain'); + expect(data.ext.fledge_config.decisionLogicUrl).to.equal('https://sellers.domain/decision.url'); + expect(data.ext.fledge_config.sellerTimeout).to.not.exist; + }); + + it('sets request.ext.fledge_config object values when available from paapiConfig rather than from fledgeConfig if both exist', function () { + let bidRequest = Object.assign([], bidRequests); + delete bidRequest[0].params.test; + + config.setConfig({ + paapiConfig: { + seller: 'https://paapiconfig.sellers.domain', + decisionLogicUrl: 'https://paapiconfig.sellers.domain/decision.url' + }, + fledgeConfig: { + seller: 'https://fledgeconfig.sellers.domain', + decisionLogicUrl: 'https://fledgeconfig.sellers.domain/decision.url' + } + }); + const request = spec.buildRequests(bidRequest, { ...bidderRequest, paapi: {enabled: true} }); + const data = JSON.parse(request.data); + expect(data.ext).to.exist.and.to.be.a('object'); + expect(data.ext.fledge_config).to.exist.and.to.be.a('object'); + expect(data.ext.fledge_config).to.contain.keys('seller', 'decisionLogicUrl'); + expect(data.ext.fledge_config.seller).to.equal('https://paapiconfig.sellers.domain'); + expect(data.ext.fledge_config.decisionLogicUrl).to.equal('https://paapiconfig.sellers.domain/decision.url'); + }); + it('when FLEDGE is disabled, should not send imp.ext.ae', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; @@ -788,6 +831,36 @@ describe('RTBHouseAdapter', () => { }); }); + context('when the response contains FLEDGE auction config and bid request has additional signals in paapiConfig', function () { + let bidderRequest; + config.setConfig({ + paapiConfig: { + interestGroupBuyers: ['https://buyer1.com'], + perBuyerSignals: { + 'https://buyer1.com': { signal: 1 } + }, + customSignal: 1 + } + }); + let response = spec.interpretResponse({body: fledgeResponse}, {bidderRequest}); + + it('should have 2 buyers in interestGroupBuyers', function () { + expect(response.paapi[0].config.interestGroupBuyers.length).to.equal(2); + expect(response.paapi[0].config.interestGroupBuyers).to.have.members(['https://buyer1.com', 'https://buyer-domain.com']); + }); + + it('should have 2 perBuyerSignals with proper values', function () { + expect(response.paapi[0].config.perBuyerSignals).to.contain.keys('https://buyer1.com', 'https://buyer-domain.com'); + expect(response.paapi[0].config.perBuyerSignals['https://buyer1.com']).to.deep.equal({ signal: 1 }); + expect(response.paapi[0].config.perBuyerSignals['https://buyer-domain.com']).to.deep.equal({}); + }); + + it('should contain any custom signal passed via paapiConfig', function () { + expect(response.paapi[0].config).to.contain.keys('customSignal'); + expect(response.paapi[0].config.customSignal).to.equal(1); + }); + }); + context('when the response contains DSA object', function () { it('should get correct bid response', function () { const dsa = {