From 2f8a35c9371bebab85c6b7a0837f9c33536b28fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C5=BCbieta=20SZPONDER?= Date: Mon, 19 Aug 2024 14:00:29 +0200 Subject: [PATCH 01/25] add support of dsa --- modules/smartadserverBidAdapter.js | 27 ++++++-- .../modules/smartadserverBidAdapter_spec.js | 61 +++++++++++++++++-- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index a90f99da2f7..10a31cb8903 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -1,4 +1,14 @@ -import { deepAccess, deepClone, isArrayOfNums, isFn, isInteger, isPlainObject, logError } from '../src/utils.js'; +import { + deepAccess, + deepClone, + isArray, + isArrayOfNums, + isEmpty, + isFn, + isInteger, + isPlainObject, + logError +} from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -156,9 +166,6 @@ export const spec = { method: 'POST', url: (domain !== undefined ? domain : 'https://prg.smartadserver.com') + '/prebid/v1', data: JSON.stringify(payload), - options: { - browsingTopics: false - } }; }, @@ -199,11 +206,16 @@ export const spec = { sdc: sellerDefinedContext }; - const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid') || deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); + const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid', deepAccess(bid, 'ortb2Imp.ext.data.pbadslot', '')); if (gpid) { payload.gpid = gpid; } + const dsa = deepAccess(bid, 'ortb2.regs.ext.dsa'); + if (dsa) { + payload.dsa = dsa; + } + if (bidderRequest) { if (bidderRequest.gdprConsent) { payload.addtl_consent = bidderRequest.gdprConsent.addtlConsent; @@ -285,7 +297,10 @@ export const spec = { netRevenue: response.isNetCpm, ttl: response.ttl, dspPixels: response.dspPixels, - meta: { advertiserDomains: response.adomain ? response.adomain : [] } + meta: { + ...isArray(response.adomain) && !isEmpty(response.adomain) ? { advertiserDomains: response.adomain } : {}, + ...!isEmpty(response.dsa) ? { dsa: response.dsa } : {} + } }; if (bidRequest.mediaType === VIDEO) { diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 2f06331f616..f5f9751dba8 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -458,11 +458,30 @@ describe('Smart bid adapter tests', function () { expect(syncs).to.have.lengthOf(0); }); - it('should set browsingTopics=false in request.options', () => { - const requests = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL); - expect(requests[0]).to.have.property('options').and.to.deep.equal({ - browsingTopics: false - }); + it('Verify metadata', function () { + const adomain = ['advertiser-domain.com']; + const dsa = { + dsarequired: 1, + pubrender: 0, + datatopub: 1, + transparency: [{ + domain: 'smartadserver.com', + dsaparams: [1, 2] + }] + }; + const request = spec.buildRequests(DEFAULT_PARAMS); + const bids = spec.interpretResponse({ + body: { + ...BID_RESPONSE.body, + adomain, + dsa, + } + }, request[0]); + + expect(bids[0].cpm).to.equal(12); + expect(bids[0]).to.have.property('meta'); + expect(bids[0].meta).to.have.property('advertiserDomains').and.to.deep.equal(adomain); + expect(bids[0].meta).to.have.property('dsa').and.to.deep.equal(dsa); }); describe('gdpr tests', function () { @@ -1512,6 +1531,38 @@ describe('Smart bid adapter tests', function () { }); }); + describe('Digital Services Act (DSA)', function () { + it('should include dsa if ortb2.regs.ext.dsa available', function () { + const dsa = { + dsarequired: 1, + pubrender: 0, + datatopub: 1, + transparency: [ + { + domain: 'ok.domain.com', + dsaparams: [1, 2] + }, + { + domain: 'ko.domain.com', + dsaparams: [1, '3'] + } + ] + }; + + const bidRequests = deepClone(DEFAULT_PARAMS_WO_OPTIONAL); + bidRequests[0].ortb2 = { + regs: { + ext: { dsa } + } + }; + + const request = spec.buildRequests(bidRequests); + const requestContent = JSON.parse(request[0].data); + + expect(requestContent).to.have.property('dsa').and.to.deep.equal(dsa); + }); + }); + describe('#getValuableProperty method', function () { it('should return an object when calling with a number value', () => { const obj = spec.getValuableProperty('prop', 3); From 9483a8123371222193ca414ed3021f7cb7b33468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C5=BCbieta=20SZPONDER?= Date: Mon, 19 Aug 2024 14:19:03 +0200 Subject: [PATCH 02/25] restore topics --- modules/smartadserverBidAdapter.js | 5 ++++- test/spec/modules/smartadserverBidAdapter_spec.js | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 10a31cb8903..840ba8a82aa 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -166,6 +166,9 @@ export const spec = { method: 'POST', url: (domain !== undefined ? domain : 'https://prg.smartadserver.com') + '/prebid/v1', data: JSON.stringify(payload), + options: { + browsingTopics: false + } }; }, @@ -206,7 +209,7 @@ export const spec = { sdc: sellerDefinedContext }; - const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid', deepAccess(bid, 'ortb2Imp.ext.data.pbadslot', '')); + const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid') || deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); if (gpid) { payload.gpid = gpid; } diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index f5f9751dba8..fa7993f768b 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -458,6 +458,12 @@ describe('Smart bid adapter tests', function () { expect(syncs).to.have.lengthOf(0); }); + it('should set browsingTopics=false in request.options', () => { + const requests = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL); + expect(requests[0]).to.have.property('options').and.to.deep.equal({ + browsingTopics: false + }); + it('Verify metadata', function () { const adomain = ['advertiser-domain.com']; const dsa = { From 6acff45ab7732c493ef9a97985e16287da46ca8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C5=BCbieta=20SZPONDER?= Date: Tue, 20 Aug 2024 10:13:57 +0200 Subject: [PATCH 03/25] DSA fix for UT --- test/spec/modules/smartadserverBidAdapter_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index fa7993f768b..08b9f616551 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -462,6 +462,7 @@ describe('Smart bid adapter tests', function () { const requests = spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL); expect(requests[0]).to.have.property('options').and.to.deep.equal({ browsingTopics: false + }); }); it('Verify metadata', function () { From d5a31781032e3d4face9598f3464f8323f290569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 11 Sep 2024 12:00:25 +0200 Subject: [PATCH 04/25] drafy of adapter --- modules/equativBidAdapter.js | 113 +++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 modules/equativBidAdapter.js diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js new file mode 100644 index 00000000000..3330b78d62f --- /dev/null +++ b/modules/equativBidAdapter.js @@ -0,0 +1,113 @@ +import {BANNER} from '../src/mediaTypes.js'; +import {ortbConverter} from '../libraries/ortbConverter/converter.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {deepAccess, deepSetValue, mergeDeep} from '../src/utils.js'; + +/** + * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid + * @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest + */ + +registerBidder({ + code: 'equativ', + gvlid: 45, + supportedMediaTypes: [BANNER], + + /** + * @param bidRequests + * @param bidderRequest + * @returns {ServerRequest[]} + */ + buildRequests: (bidRequests, bidderRequest) => { + return { + data: converter.toORTB({bidderRequest, bidRequests}), + method: 'POST', + // url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169' + url: 'https://feature-ssb-engine-pips-2655-testenv.internal.smartadserver.com/api/bid?callerId=169' + }; + }, + + /** + * @param serverResponse + * @param bidRequest + * @return {Bid[]} + */ + interpretResponse: (serverResponse, bidRequest) => converter.fromORTB({request: bidRequest.data, response: serverResponse.body}), + + /** + * @param bidRequest + * @return {boolean} + */ + isBidRequestValid: (bidRequest) => { + return !(!bidRequest.params.networkId && + !deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') && + !deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') && + !deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id')); + }, + + /** + * @param syncOptions + * @param serverResponses + * @return {{type: (string), url: (*|string)}[]} + */ + getUserSyncs: (syncOptions, serverResponses) => { + if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { + return { + type: 'iframe', + url: serverResponses[0].body.cSyncUrl + }; + } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { + serverResponses[0].body.dspPixels.forEach((pixel) => { + return { + type: 'image', + url: pixel + }; + }); + } + } +}); + +const converter = ortbConverter({ + context: { + netRevenue: true, + ttl: 300 + }, + + imp(buildImp, bidRequest, context) { + const imp = buildImp(bidRequest, context); + const { siteId, pageId, formatId } = bidRequest.params; + + if (siteId || pageId || formatId) { + const bidder = {}; + + if (siteId) { + bidder.siteId = siteId; + } + + if (pageId) { + bidder.pageId = pageId; + } + + if (formatId) { + bidder.formatId = formatId; + } + + mergeDeep(imp, { + ext: { bidder } + }); + } + + return imp; + }, + + request(buildRequest, imps, bidderRequest, context) { + const bid = context.bidRequests[0]; + const req = buildRequest(imps, bidderRequest, context); + + if (bid.params.networkId) { + deepSetValue(req, 'site.publisher.id', bid.params.networkId); + } + + return req; + } +}); From 92091d401f1ce0ab4f134707fbcc4989f7cdfb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Thu, 12 Sep 2024 13:33:20 +0200 Subject: [PATCH 05/25] fixes after dev test --- modules/equativBidAdapter.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 3330b78d62f..f0f48b7eb1c 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -39,10 +39,10 @@ registerBidder({ * @return {boolean} */ isBidRequestValid: (bidRequest) => { - return !(!bidRequest.params.networkId && - !deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') && - !deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') && - !deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id')); + return bidRequest.params.networkId || + deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') || + deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') || + deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id'); }, /** @@ -52,17 +52,19 @@ registerBidder({ */ getUserSyncs: (syncOptions, serverResponses) => { if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - return { + return [{ type: 'iframe', url: serverResponses[0].body.cSyncUrl - }; + }]; } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { + const syncs = []; serverResponses[0].body.dspPixels.forEach((pixel) => { - return { + syncs.push({ type: 'image', url: pixel - }; + }); }); + return syncs; } } }); From 23eac335ff99da9a8f8ce2463a6cd4be569e9474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Thu, 12 Sep 2024 14:39:47 +0200 Subject: [PATCH 06/25] make world simpler --- modules/equativBidAdapter.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index f0f48b7eb1c..55e13fb9862 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -57,14 +57,10 @@ registerBidder({ url: serverResponses[0].body.cSyncUrl }]; } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { - const syncs = []; - serverResponses[0].body.dspPixels.forEach((pixel) => { - syncs.push({ - type: 'image', - url: pixel - }); - }); - return syncs; + return serverResponses[0].body.dspPixels.forEach((pixel) => ({ + type: 'image', + url: pixel + })); } } }); From 3a5eda0a5127e46f159d55efff599146a659162a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Thu, 12 Sep 2024 14:45:20 +0200 Subject: [PATCH 07/25] fix prev commit --- modules/equativBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 55e13fb9862..a19f026786a 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -57,7 +57,7 @@ registerBidder({ url: serverResponses[0].body.cSyncUrl }]; } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { - return serverResponses[0].body.dspPixels.forEach((pixel) => ({ + return serverResponses[0].body.dspPixels.map((pixel) => ({ type: 'image', url: pixel })); From 86a7845161c4d1544ff4a2fa6ce6dae25d9b6497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Thu, 12 Sep 2024 14:56:06 +0200 Subject: [PATCH 08/25] return empty userSyncs array by default --- modules/equativBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index a19f026786a..6261b8fe416 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -62,6 +62,7 @@ registerBidder({ url: pixel })); } + return []; } }); From 52752e7772e5c530c74681e338c05667014c56ba Mon Sep 17 00:00:00 2001 From: janzych-smart Date: Mon, 16 Sep 2024 13:44:52 +0200 Subject: [PATCH 09/25] adjustments --- modules/equativBidAdapter.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 6261b8fe416..5b012f60678 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -8,7 +8,7 @@ import {deepAccess, deepSetValue, mergeDeep} from '../src/utils.js'; * @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest */ -registerBidder({ +export const spec = { code: 'equativ', gvlid: 45, supportedMediaTypes: [BANNER], @@ -39,10 +39,10 @@ registerBidder({ * @return {boolean} */ isBidRequestValid: (bidRequest) => { - return bidRequest.params.networkId || + return !!(deepAccess(bidRequest, 'params.networkId') || deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') || deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') || - deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id'); + deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id')); }, /** @@ -64,9 +64,9 @@ registerBidder({ } return []; } -}); +}; -const converter = ortbConverter({ +export const converter = ortbConverter({ context: { netRevenue: true, ttl: 300 @@ -110,3 +110,5 @@ const converter = ortbConverter({ return req; } }); + +registerBidder(spec); From b75a5c2a6b45b8c8ff00835e10fcc97f02ee1c8b Mon Sep 17 00:00:00 2001 From: janzych-smart Date: Mon, 16 Sep 2024 13:45:29 +0200 Subject: [PATCH 10/25] apply prettier --- modules/equativBidAdapter.js | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 5b012f60678..7230214cdf4 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -1,7 +1,7 @@ -import {BANNER} from '../src/mediaTypes.js'; -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {deepAccess, deepSetValue, mergeDeep} from '../src/utils.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -20,10 +20,10 @@ export const spec = { */ buildRequests: (bidRequests, bidderRequest) => { return { - data: converter.toORTB({bidderRequest, bidRequests}), + data: converter.toORTB({ bidderRequest, bidRequests }), method: 'POST', // url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169' - url: 'https://feature-ssb-engine-pips-2655-testenv.internal.smartadserver.com/api/bid?callerId=169' + url: 'https://feature-ssb-engine-pips-2655-testenv.internal.smartadserver.com/api/bid?callerId=169', }; }, @@ -32,17 +32,23 @@ export const spec = { * @param bidRequest * @return {Bid[]} */ - interpretResponse: (serverResponse, bidRequest) => converter.fromORTB({request: bidRequest.data, response: serverResponse.body}), + interpretResponse: (serverResponse, bidRequest) => + converter.fromORTB({ + request: bidRequest.data, + response: serverResponse.body, + }), /** * @param bidRequest * @return {boolean} */ isBidRequestValid: (bidRequest) => { - return !!(deepAccess(bidRequest, 'params.networkId') || + return !!( + deepAccess(bidRequest, 'params.networkId') || deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') || deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') || - deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id')); + deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id') + ); }, /** @@ -52,24 +58,26 @@ export const spec = { */ getUserSyncs: (syncOptions, serverResponses) => { if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - return [{ - type: 'iframe', - url: serverResponses[0].body.cSyncUrl - }]; + return [ + { + type: 'iframe', + url: serverResponses[0].body.cSyncUrl, + }, + ]; } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { return serverResponses[0].body.dspPixels.map((pixel) => ({ type: 'image', - url: pixel + url: pixel, })); } return []; - } + }, }; export const converter = ortbConverter({ context: { netRevenue: true, - ttl: 300 + ttl: 300, }, imp(buildImp, bidRequest, context) { @@ -92,7 +100,7 @@ export const converter = ortbConverter({ } mergeDeep(imp, { - ext: { bidder } + ext: { bidder }, }); } @@ -108,7 +116,7 @@ export const converter = ortbConverter({ } return req; - } + }, }); registerBidder(spec); From 9ec6fe4d1480178c0304e9431e8989849b898015 Mon Sep 17 00:00:00 2001 From: janzych-smart Date: Tue, 17 Sep 2024 15:45:14 +0200 Subject: [PATCH 11/25] unit tests for Equativ adapter --- modules/equativBidAdapter.js | 32 ++-- test/spec/modules/equativBidAdapter_spec.js | 202 ++++++++++++++++++++ 2 files changed, 218 insertions(+), 16 deletions(-) create mode 100644 test/spec/modules/equativBidAdapter_spec.js diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 7230214cdf4..600bf498580 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -56,22 +56,22 @@ export const spec = { * @param serverResponses * @return {{type: (string), url: (*|string)}[]} */ - getUserSyncs: (syncOptions, serverResponses) => { - if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - return [ - { - type: 'iframe', - url: serverResponses[0].body.cSyncUrl, - }, - ]; - } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { - return serverResponses[0].body.dspPixels.map((pixel) => ({ - type: 'image', - url: pixel, - })); - } - return []; - }, + // getUserSyncs: (syncOptions, serverResponses) => { + // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { + // return [ + // { + // type: 'iframe', + // url: serverResponses[0].body.cSyncUrl, + // }, + // ]; + // } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { + // return serverResponses[0].body.dspPixels.map((pixel) => ({ + // type: 'image', + // url: pixel, + // })); + // } + // return []; + // }, }; export const converter = ortbConverter({ diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js new file mode 100644 index 00000000000..5e4416bcb7e --- /dev/null +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -0,0 +1,202 @@ +import { spec, converter } from 'modules/equativBidAdapter.js'; + +describe('Equativ bid adapter tests', function () { + const DEFAULT_BID_REQUESTS = [ + { + adUnitCode: 'eqtv_42', + bidId: 'abcd1234', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 200], + ], + }, + }, + bidder: 'equativ', + params: { + siteId: '1234', + pageId: '5678', + formatId: '90', + networkId: 111, + }, + requestId: 'efgh5678', + ortb2Imp: { + ext: { + tid: 'zsfgzzg', + }, + }, + }, + ]; + + const DEFAULT_BIDDER_REQUEST = { + bidderCode: 'equativ', + bids: DEFAULT_BID_REQUESTS, + }; + + const SAMPLE_RESPONSE = { + body: { + id: '12h712u7-k22g-8124-ab7a-h268s22dy271', + seatbid: [ + { + bid: [ + { + id: '1bh7jku7-ko2g-8654-ab72-h268shvwy271', + impid: 'r12gwgf231', + price: 0.6565, + adm: '

AD

', + adomain: ['abc.com'], + cid: '1242512', + crid: '535231', + w: 300, + h: 600, + mtype: 1, + cat: ['IAB19', 'IAB19-1'], + cattax: 1, + }, + ], + seat: '4212', + }, + ], + cur: 'USD', + statuscode: 0, + }, + }; + + describe('buildRequests', () => { + it('should build correct request using ORTB converter', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + const dataFromConverter = converter.toORTB({ + bidderRequest: DEFAULT_BIDDER_REQUEST, + bidRequests: DEFAULT_BID_REQUESTS, + }); + expect(request).to.deep.equal({ + data: { ...dataFromConverter, id: request.data.id }, + method: 'POST', + url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169', + }); + }); + + it('should add ext.bidder to imp object when siteId is defined', () => { + const bidRequests = [ + { ...DEFAULT_BID_REQUESTS[0], params: { siteId: 123 } }, + ]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0].ext.bidder).to.deep.equal({ + siteId: 123, + }); + }); + + it('should add ext.bidder to imp object when pageId is defined', () => { + const bidRequests = [ + { ...DEFAULT_BID_REQUESTS[0], params: { pageId: 123 } }, + ]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0].ext.bidder).to.deep.equal({ + pageId: 123, + }); + }); + + it('should add ext.bidder to imp object when formatId is defined', () => { + const bidRequests = [ + { ...DEFAULT_BID_REQUESTS[0], params: { formatId: 123 } }, + ]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0].ext.bidder).to.deep.equal({ + formatId: 123, + }); + }); + + it('should not add ext.bidder to imp object when siteId, pageId, formatId are not defined', () => { + const bidRequests = [{ ...DEFAULT_BID_REQUESTS[0], params: {} }]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0].ext.bidder).to.be.undefined; + }); + + it('should add site.publisher.id param', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + expect(request.data.site.publisher.id).to.equal(111); + }); + }); + + describe('interpretResponse', () => { + it('should return data returned by ORTB converter', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + const bids = spec.interpretResponse(SAMPLE_RESPONSE, request); + expect(bids).to.deep.equal( + converter.fromORTB({ + request: request.data, + response: SAMPLE_RESPONSE.body, + }) + ); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true if params.networkId is set', () => { + const bidRequest = { + params: { + networkId: 123, + }, + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return true if ortb2Imp.site.publisher.id is set', () => { + const bidRequest = { + ortb2Imp: { + site: { + publisher: { + id: 123, + }, + }, + }, + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return true if ortb2Imp.app.publisher.id is set', () => { + const bidRequest = { + ortb2Imp: { + app: { + publisher: { + id: 123, + }, + }, + }, + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return true if ortb2Imp.dooh.publisher.id is set', () => { + const bidRequest = { + ortb2Imp: { + dooh: { + publisher: { + id: 123, + }, + }, + }, + }; + expect(spec.isBidRequestValid(bidRequest)).to.equal(true); + }); + + it('should return false if networkId is not set', () => { + const bidRequest = {}; + expect(spec.isBidRequestValid(bidRequest)).to.equal(false); + }); + }); +}); From 259cba2db674bae271eed22ea9f1de69bf50fefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Fri, 20 Sep 2024 11:53:21 +0200 Subject: [PATCH 12/25] add dsp user sync --- modules/equativBidAdapter.js | 38 ++++++++++----------- test/spec/modules/equativBidAdapter_spec.js | 37 ++++++++++++++++++-- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 600bf498580..828ca74eea2 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -22,8 +22,7 @@ export const spec = { return { data: converter.toORTB({ bidderRequest, bidRequests }), method: 'POST', - // url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169' - url: 'https://feature-ssb-engine-pips-2655-testenv.internal.smartadserver.com/api/bid?callerId=169', + url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169', }; }, @@ -53,25 +52,24 @@ export const spec = { /** * @param syncOptions - * @param serverResponses - * @return {{type: (string), url: (*|string)}[]} + * @param serverResponse + * @return {{type: string, url: string}[]} */ - // getUserSyncs: (syncOptions, serverResponses) => { - // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - // return [ - // { - // type: 'iframe', - // url: serverResponses[0].body.cSyncUrl, - // }, - // ]; - // } else if (syncOptions.pixelEnabled && serverResponses[0]?.body.dspPixels) { - // return serverResponses[0].body.dspPixels.map((pixel) => ({ - // type: 'image', - // url: pixel, - // })); - // } - // return []; - // }, + getUserSyncs: (syncOptions, serverResponse) => { + // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { + // return [ + // { + // type: 'iframe', + // url: serverResponses[0].body.cSyncUrl, + // }, + // ]; + // } + return (syncOptions.pixelEnabled && serverResponse.body.dspPixels) + ? serverResponse.body.dspPixels.map((pixel) => ({ + type: 'image', + url: pixel, + })) : []; + }, }; export const converter = ortbConverter({ diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index 5e4416bcb7e..e92fd1666fa 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -15,9 +15,6 @@ describe('Equativ bid adapter tests', function () { }, bidder: 'equativ', params: { - siteId: '1234', - pageId: '5678', - formatId: '90', networkId: 111, }, requestId: 'efgh5678', @@ -63,6 +60,13 @@ describe('Equativ bid adapter tests', function () { }, }; + const RESPONSE_WITH_DSP_PIXELS = { + ...SAMPLE_RESPONSE, + body: { + dspPixels: ['1st-pixel', '2nd-pixel', '3rd-pixel'] + } + }; + describe('buildRequests', () => { it('should build correct request using ORTB converter', () => { const request = spec.buildRequests( @@ -129,6 +133,33 @@ describe('Equativ bid adapter tests', function () { }); }); + describe('getUserSyncs', () => { + it('should return empty array if no pixel sync not enabled', function () { + const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); + expect(syncs).to.deep.equal([]); + }); + + it('should return empty array if no pixels available', function () { + const syncs = spec.getUserSyncs( + { pixelEnabled: true }, + SAMPLE_RESPONSE + ); + expect(syncs).to.deep.equal([]); + }); + + it('should register dsp pixels', function () { + const syncs = spec.getUserSyncs( + { pixelEnabled: true }, + RESPONSE_WITH_DSP_PIXELS + ); + expect(syncs).to.have.lengthOf(3); + expect(syncs[1]).to.deep.equal({ + type: 'image', + url: '2nd-pixel', + }); + }); + }); + describe('interpretResponse', () => { it('should return data returned by ORTB converter', () => { const request = spec.buildRequests( From 9a92f9d243159d1e3cf971cc6c56a98b8fd653fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Fri, 20 Sep 2024 11:53:30 +0200 Subject: [PATCH 13/25] add readme --- modules/equativBidAdapter.md | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 modules/equativBidAdapter.md diff --git a/modules/equativBidAdapter.md b/modules/equativBidAdapter.md new file mode 100644 index 00000000000..7d1210b9a5d --- /dev/null +++ b/modules/equativBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +``` +Module Name: Equativ Bidder Adapter (beta) +Module Type: Bidder Adapter +Maintainer: support@equativ.com +``` + +# Description + +Connect to Equativ for bids. + +The Equativ adapter requires setup and approval from the Equativ team. Please reach out to your technical account manager for more information. + +# Test Parameters + +## Web or In-app +```javascript +var adUnits = [ + { + code: '/589236/banner_1', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: 'equativ', + params: { + networkId: 10, // mandatory if no ortb2Imp.(site or app).publisher.id defined + siteId: 20743, // optional + pageId: 89653, // optional + formatId: 291, // optional + } + } + ] + } +]; +``` \ No newline at end of file From 811932cbbe8b869192295e3d4655b63ea2a45f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Fri, 20 Sep 2024 13:59:29 +0200 Subject: [PATCH 14/25] body can be undef --- modules/equativBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 828ca74eea2..f4ddba0d840 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -64,7 +64,7 @@ export const spec = { // }, // ]; // } - return (syncOptions.pixelEnabled && serverResponse.body.dspPixels) + return (syncOptions.pixelEnabled && serverResponse.body?.dspPixels) ? serverResponse.body.dspPixels.map((pixel) => ({ type: 'image', url: pixel, From ae67b8ae7911427fbf99a580dd419d886bae9f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 25 Sep 2024 14:44:43 +0200 Subject: [PATCH 15/25] support additional br params --- modules/equativBidAdapter.js | 6 +++- test/spec/modules/equativBidAdapter_spec.js | 32 ++++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index f4ddba0d840..6b3b5cf2da3 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -22,7 +22,7 @@ export const spec = { return { data: converter.toORTB({ bidderRequest, bidRequests }), method: 'POST', - url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169', + url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169' }; }, @@ -82,6 +82,10 @@ export const converter = ortbConverter({ const imp = buildImp(bidRequest, context); const { siteId, pageId, formatId } = bidRequest.params; + imp.bidfloor = imp.bidfloor || 0.0; + imp.secure = Number(window.location.protocol === 'https:'); + imp.tagid = bidRequest.adUnitCode; + if (siteId || pageId || formatId) { const bidder = {}; diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index e92fd1666fa..bd6f2410f44 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -1,6 +1,6 @@ import { spec, converter } from 'modules/equativBidAdapter.js'; -describe('Equativ bid adapter tests', function () { +describe('Equativ bid adapter tests', () => { const DEFAULT_BID_REQUESTS = [ { adUnitCode: 'eqtv_42', @@ -131,15 +131,39 @@ describe('Equativ bid adapter tests', function () { ); expect(request.data.site.publisher.id).to.equal(111); }); + + it('should send default floor of 0.0', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + expect(request.data.imp[0]).to.have.property('bidfloor').that.eq(0.0); + }); + + it('should send secure connection', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + expect(request.data.imp[0]).to.have.property('secure').that.within(0, 1); + }); + + it('should have tagid', () => { + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + expect(request.data.imp[0]).to.have.property('tagid').that.eq(DEFAULT_BID_REQUESTS[0].adUnitCode); + }); }); describe('getUserSyncs', () => { - it('should return empty array if no pixel sync not enabled', function () { + it('should return empty array if no pixel sync not enabled', () => { const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); expect(syncs).to.deep.equal([]); }); - it('should return empty array if no pixels available', function () { + it('should return empty array if no pixels available', () => { const syncs = spec.getUserSyncs( { pixelEnabled: true }, SAMPLE_RESPONSE @@ -147,7 +171,7 @@ describe('Equativ bid adapter tests', function () { expect(syncs).to.deep.equal([]); }); - it('should register dsp pixels', function () { + it('should register dsp pixels', () => { const syncs = spec.getUserSyncs( { pixelEnabled: true }, RESPONSE_WITH_DSP_PIXELS From bc4e78a3cce7775d25208fef2c6dabd7a41dd454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Fri, 27 Sep 2024 08:27:59 +0200 Subject: [PATCH 16/25] remove user sync --- modules/equativBidAdapter.js | 30 ++++++------- test/spec/modules/equativBidAdapter_spec.js | 48 ++++++++++----------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 6b3b5cf2da3..d89a6a9f461 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -55,21 +55,21 @@ export const spec = { * @param serverResponse * @return {{type: string, url: string}[]} */ - getUserSyncs: (syncOptions, serverResponse) => { - // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - // return [ - // { - // type: 'iframe', - // url: serverResponses[0].body.cSyncUrl, - // }, - // ]; - // } - return (syncOptions.pixelEnabled && serverResponse.body?.dspPixels) - ? serverResponse.body.dspPixels.map((pixel) => ({ - type: 'image', - url: pixel, - })) : []; - }, + // getUserSyncs: (syncOptions, serverResponse) => { + // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { + // return [ + // { + // type: 'iframe', + // url: serverResponses[0].body.cSyncUrl, + // }, + // ]; + // } + // return (syncOptions.pixelEnabled && serverResponse.body?.dspPixels) + // ? serverResponse.body.dspPixels.map((pixel) => ({ + // type: 'image', + // url: pixel, + // })) : []; + // }, }; export const converter = ortbConverter({ diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index bd6f2410f44..80a31adb9b9 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -157,32 +157,32 @@ describe('Equativ bid adapter tests', () => { }); }); - describe('getUserSyncs', () => { - it('should return empty array if no pixel sync not enabled', () => { - const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); - expect(syncs).to.deep.equal([]); - }); + // describe('getUserSyncs', () => { + // it('should return empty array if no pixel sync not enabled', () => { + // const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); + // expect(syncs).to.deep.equal([]); + // }); - it('should return empty array if no pixels available', () => { - const syncs = spec.getUserSyncs( - { pixelEnabled: true }, - SAMPLE_RESPONSE - ); - expect(syncs).to.deep.equal([]); - }); + // it('should return empty array if no pixels available', () => { + // const syncs = spec.getUserSyncs( + // { pixelEnabled: true }, + // SAMPLE_RESPONSE + // ); + // expect(syncs).to.deep.equal([]); + // }); - it('should register dsp pixels', () => { - const syncs = spec.getUserSyncs( - { pixelEnabled: true }, - RESPONSE_WITH_DSP_PIXELS - ); - expect(syncs).to.have.lengthOf(3); - expect(syncs[1]).to.deep.equal({ - type: 'image', - url: '2nd-pixel', - }); - }); - }); + // it('should register dsp pixels', () => { + // const syncs = spec.getUserSyncs( + // { pixelEnabled: true }, + // RESPONSE_WITH_DSP_PIXELS + // ); + // expect(syncs).to.have.lengthOf(3); + // expect(syncs[1]).to.deep.equal({ + // type: 'image', + // url: '2nd-pixel', + // }); + // }); + // }); describe('interpretResponse', () => { it('should return data returned by ORTB converter', () => { From 3148ed83e475dde83ecf875eb317a21cced9162e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Tue, 8 Oct 2024 10:38:25 +0200 Subject: [PATCH 17/25] do not send dt param --- modules/equativBidAdapter.js | 2 ++ test/spec/modules/equativBidAdapter_spec.js | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index d89a6a9f461..80b34f86243 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -82,6 +82,8 @@ export const converter = ortbConverter({ const imp = buildImp(bidRequest, context); const { siteId, pageId, formatId } = bidRequest.params; + delete imp.dt; + imp.bidfloor = imp.bidfloor || 0.0; imp.secure = Number(window.location.protocol === 'https:'); imp.tagid = bidRequest.adUnitCode; diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index 80a31adb9b9..ae89cf8d61d 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -60,12 +60,12 @@ describe('Equativ bid adapter tests', () => { }, }; - const RESPONSE_WITH_DSP_PIXELS = { - ...SAMPLE_RESPONSE, - body: { - dspPixels: ['1st-pixel', '2nd-pixel', '3rd-pixel'] - } - }; + // const RESPONSE_WITH_DSP_PIXELS = { + // ...SAMPLE_RESPONSE, + // body: { + // dspPixels: ['1st-pixel', '2nd-pixel', '3rd-pixel'] + // } + // }; describe('buildRequests', () => { it('should build correct request using ORTB converter', () => { @@ -155,6 +155,15 @@ describe('Equativ bid adapter tests', () => { ); expect(request.data.imp[0]).to.have.property('tagid').that.eq(DEFAULT_BID_REQUESTS[0].adUnitCode); }); + + it('should remove dt', () => { + const bidRequests = [ + { ...DEFAULT_BID_REQUESTS[0], ortb2Imp: { dt: 1728377558235 } } + ]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0]).to.not.have.property('dt'); + }); }); // describe('getUserSyncs', () => { From f08f05d91cf7f16382894b97e66e299de99b985d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 9 Oct 2024 08:30:48 +0200 Subject: [PATCH 18/25] handle floors and network id --- modules/equativBidAdapter.js | 45 ++++-- modules/equativBidAdapter.md | 2 +- test/spec/modules/equativBidAdapter_spec.js | 165 +++++++++++++++++++- 3 files changed, 195 insertions(+), 17 deletions(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 80b34f86243..9b63904abf4 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -1,7 +1,7 @@ import { BANNER } from '../src/mediaTypes.js'; import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; +import { deepAccess, deepSetValue, isFn, mergeDeep } from '../src/utils.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -26,10 +26,31 @@ export const spec = { }; }, + /** + * @param bidRequest + * @returns {number} + */ + getMinFloor: (bidRequest) => { + const floors = []; + + if (isFn(bidRequest.getFloor)) { + deepAccess(bidRequest, 'mediaTypes.banner.sizes').forEach(size => { + const floor = bidRequest.getFloor({ size }).floor; + if (!isNaN(floor)) { + floors.push(floor); + } else { + floors.push(0.0); + } + }); + } + + return floors.length ? Math.min(...floors) : 0.0; + }, + /** * @param serverResponse * @param bidRequest - * @return {Bid[]} + * @returns {Bid[]} */ interpretResponse: (serverResponse, bidRequest) => converter.fromORTB({ @@ -39,21 +60,21 @@ export const spec = { /** * @param bidRequest - * @return {boolean} + * @returns {boolean} */ isBidRequestValid: (bidRequest) => { return !!( deepAccess(bidRequest, 'params.networkId') || - deepAccess(bidRequest, 'ortb2Imp.site.publisher.id') || - deepAccess(bidRequest, 'ortb2Imp.app.publisher.id') || - deepAccess(bidRequest, 'ortb2Imp.dooh.publisher.id') + deepAccess(bidRequest, 'ortb2.site.publisher.id') || + deepAccess(bidRequest, 'ortb2.app.publisher.id') || + deepAccess(bidRequest, 'ortb2.dooh.publisher.id') ); }, /** * @param syncOptions * @param serverResponse - * @return {{type: string, url: string}[]} + * @returns {{type: string, url: string}[]} */ // getUserSyncs: (syncOptions, serverResponse) => { // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { @@ -84,7 +105,7 @@ export const converter = ortbConverter({ delete imp.dt; - imp.bidfloor = imp.bidfloor || 0.0; + imp.bidfloor = imp.bidfloor || spec.getMinFloor(bidRequest); imp.secure = Number(window.location.protocol === 'https:'); imp.tagid = bidRequest.adUnitCode; @@ -115,7 +136,13 @@ export const converter = ortbConverter({ const bid = context.bidRequests[0]; const req = buildRequest(imps, bidderRequest, context); - if (bid.params.networkId) { + if (deepAccess(bid, 'ortb2.site.publisher')) { + deepSetValue(req, 'site.publisher.id', bid.ortb2.site.publisher.id || bid.params.networkId); + } else if (deepAccess(bid, 'ortb2.app.publisher')) { + deepSetValue(req, 'app.publisher.id', bid.ortb2.app.publisher.id || bid.params.networkId); + } else if (deepAccess(bid, 'ortb2.dooh.publisher')) { + deepSetValue(req, 'dooh.publisher.id', bid.ortb2.dooh.publisher.id || bid.params.networkId); + } else { deepSetValue(req, 'site.publisher.id', bid.params.networkId); } diff --git a/modules/equativBidAdapter.md b/modules/equativBidAdapter.md index 7d1210b9a5d..ceee6d19bdc 100644 --- a/modules/equativBidAdapter.md +++ b/modules/equativBidAdapter.md @@ -28,7 +28,7 @@ var adUnits = [ { bidder: 'equativ', params: { - networkId: 10, // mandatory if no ortb2Imp.(site or app).publisher.id defined + networkId: 13, // mandatory if no ortb2.(site or app).publisher.id set siteId: 20743, // optional pageId: 89653, // optional formatId: 291, // optional diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index ae89cf8d61d..0310b102145 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -9,7 +9,7 @@ describe('Equativ bid adapter tests', () => { banner: { sizes: [ [300, 250], - [300, 200], + [300, 600], ], }, }, @@ -132,6 +132,99 @@ describe('Equativ bid adapter tests', () => { expect(request.data.site.publisher.id).to.equal(111); }); + it('should pass ortb2.site.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + site: { + publisher: { + id: 98, + } + } + } + }]; + delete bidRequests[0].params; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.site.publisher.id).to.equal(98); + }); + + it('should pass networkId as site.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + site: { + publisher: {} + } + } + }]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.site.publisher.id).to.equal(111); + }); + + it('should pass ortb2.app.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + app: { + publisher: { + id: 27, + } + } + } + }]; + delete bidRequests[0].params; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.app.publisher.id).to.equal(27); + }); + + it('should pass networkId as app.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + app: { + publisher: {} + } + } + }]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.app.publisher.id).to.equal(111); + }); + + it('should pass ortb2.dooh.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + dooh: { + publisher: { + id: 35, + } + } + } + }]; + delete bidRequests[0].params; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.dooh.publisher.id).to.equal(35); + }); + + it('should pass networkId as dooh.publisher.id', () => { + const bidRequests = [{ + ...DEFAULT_BID_REQUESTS[0], + ortb2: { + dooh: { + publisher: {} + } + } + }]; + const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.data.dooh.publisher.id).to.equal(111); + }); + it('should send default floor of 0.0', () => { const request = spec.buildRequests( DEFAULT_BID_REQUESTS, @@ -166,6 +259,64 @@ describe('Equativ bid adapter tests', () => { }); }); + describe('getMinFloor', () => { + it('should return floor of 0.0 if floor module not available', () => { + const bid = { + ...DEFAULT_BID_REQUESTS[0], + getFloor: false, + }; + expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + }); + + it('should return proper min floor', () => { + const bid = { + ...DEFAULT_BID_REQUESTS[0], + getFloor: data => { + if (data.size[0] === 300 && data.size[1] === 250) { + return { floor: 1.13 }; + } else if (data.size[0] === 300 && data.size[1] === 600) { + return { floor: 1.39 }; + } else { + return { floor: 0.52 }; + } + } + }; + expect(spec.getMinFloor(bid)).to.deep.eq(1.13); + }); + + it('should return global media type floor if no rule for size', () => { + const bid = { + ...DEFAULT_BID_REQUESTS[0], + getFloor: data => { + if (data.size[0] === 728 && data.size[1] === 90) { + return { floor: 1.13 }; + } else if (data.size[0] === 300 && data.size[1] === 600) { + return { floor: 1.36 }; + } else { + return { floor: 0.34 }; + } + } + }; + expect(spec.getMinFloor(bid)).to.deep.eq(0.34); + }); + + it('should return floor of 0 if no rule for size', () => { + const bid = { + ...DEFAULT_BID_REQUESTS[0], + getFloor: data => { + if (data.size[0] === 728 && data.size[1] === 90) { + return { floor: 1.13 }; + } else if (data.size[0] === 300 && data.size[1] === 600) { + return { floor: 1.36 }; + } else { + return {}; + } + } + }; + expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + }); + }); + // describe('getUserSyncs', () => { // it('should return empty array if no pixel sync not enabled', () => { // const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); @@ -219,9 +370,9 @@ describe('Equativ bid adapter tests', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true if ortb2Imp.site.publisher.id is set', () => { + it('should return true if ortb2.site.publisher.id is set', () => { const bidRequest = { - ortb2Imp: { + ortb2: { site: { publisher: { id: 123, @@ -232,9 +383,9 @@ describe('Equativ bid adapter tests', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true if ortb2Imp.app.publisher.id is set', () => { + it('should return true if ortb2.app.publisher.id is set', () => { const bidRequest = { - ortb2Imp: { + ortb2: { app: { publisher: { id: 123, @@ -245,9 +396,9 @@ describe('Equativ bid adapter tests', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true if ortb2Imp.dooh.publisher.id is set', () => { + it('should return true if ortb2.dooh.publisher.id is set', () => { const bidRequest = { - ortb2Imp: { + ortb2: { dooh: { publisher: { id: 123, From 3fac9a9998b6bb09a328d6d4576823e5d54a0ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Thu, 10 Oct 2024 12:10:21 +0200 Subject: [PATCH 19/25] handle empty media types --- modules/equativBidAdapter.js | 2 +- test/spec/modules/equativBidAdapter_spec.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 9b63904abf4..c5c96039f67 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -34,7 +34,7 @@ export const spec = { const floors = []; if (isFn(bidRequest.getFloor)) { - deepAccess(bidRequest, 'mediaTypes.banner.sizes').forEach(size => { + (deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []).forEach(size => { const floor = bidRequest.getFloor({ size }).floor; if (!isNaN(floor)) { floors.push(floor); diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index 0310b102145..c2465176ac1 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -268,6 +268,14 @@ describe('Equativ bid adapter tests', () => { expect(spec.getMinFloor(bid)).to.deep.eq(0.0); }); + it('should return floor of 0.0 if mediaTypes not defined', () => { + const bid = { + getFloor: () => ({}) + }; + expect(bid.mediaTypes).to.be.undefined; + expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + }); + it('should return proper min floor', () => { const bid = { ...DEFAULT_BID_REQUESTS[0], From e65525d565c6e7706f283161a33ffcf7ee194b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Tue, 15 Oct 2024 16:21:11 +0200 Subject: [PATCH 20/25] get min floor --- modules/smartadserverBidAdapter.js | 27 +++--- .../modules/smartadserverBidAdapter_spec.js | 92 ++++++++++++++++--- 2 files changed, 96 insertions(+), 23 deletions(-) diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 840ba8a82aa..53b13ecf944 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -6,7 +6,6 @@ import { isEmpty, isFn, isInteger, - isPlainObject, logError } from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; @@ -176,7 +175,7 @@ export const spec = { * Makes server requests from the list of BidRequests. * * @param {BidRequest[]} validBidRequests an array of bids - * @param {BidderRequest} bidderRequest bidder request object + * @param {BidRequest} bidderRequest bidder request object * @return {ServerRequest[]} Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { @@ -332,18 +331,22 @@ export const spec = { * @param {string} mediaType Bid media type * @return {number} Floor price */ - getBidFloor: function (bid, currency, mediaType) { - if (!isFn(bid.getFloor)) { - return DEFAULT_FLOOR; + getBidFloor: (bid, currency, mediaType) => { + const floors = []; + + if (isFn(bid.getFloor)) { + (deepAccess(bid, `mediaTypes.${mediaType}.${mediaType === BANNER ? 'sizes' : 'playerSize'}`) || []).forEach(size => { + const floor = bid.getFloor({ + currency: currency || 'USD', + mediaType, + size + }).floor; + + floors.push(!isNaN(floor) ? floor : DEFAULT_FLOOR); + }); } - const floor = bid.getFloor({ - currency: currency || 'USD', - mediaType, - size: '*' - }); - - return isPlainObject(floor) && !isNaN(floor.floor) ? floor.floor : DEFAULT_FLOOR; + return floors.length ? Math.min(...floors) : DEFAULT_FLOOR; }, /** diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 08b9f616551..cbc680fd313 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -1311,17 +1311,6 @@ describe('Smart bid adapter tests', function () { expect(bidRequest.bidfloor).to.deep.equal(DEFAULT_PARAMS[0].params.bidfloor); }); - it('should return floor from module', function() { - const moduleFloor = 1.5; - const bidRequest = JSON.parse((spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL))[0].data); - bidRequest.getFloor = function () { - return { floor: moduleFloor }; - }; - - const floor = spec.getBidFloor(bidRequest, 'EUR'); - expect(floor).to.deep.equal(moduleFloor); - }); - it('should return default floor when module not activated', function() { const bidRequest = JSON.parse((spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL))[0].data); @@ -1425,6 +1414,87 @@ describe('Smart bid adapter tests', function () { expect(bannerRequest).to.not.equal(null).and.to.not.be.undefined; expect(bannerRequest).to.have.property('bidfloor').and.to.equal(1.93); }); + + describe('#getBidFloor', () => { + let bid; + beforeEach(() => { + bid = { + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, + getFloor: (data) => { + if (data.mediaType === BANNER) { + if (data.size[0] === 300 && data.size[1] === 250) { + return { floor: 1.2 }; + } else if (data.size[0] === 300 && data.size[1] === 600) { + return { floor: 1.4 }; + } else if (data.size[0] === 30 && data.size[1] === 60) { + return 'string'; + } else { + return { floor: 1.0 }; + } + } else if (data.mediaType === VIDEO) { + if (data.size[0] === 640 && data.size[1] === 480) { + return { floor: 2.3 }; + } else { + return { floor: 2.1 }; + } + } else { + return {}; + } + } + }; + }); + + it('should return lowest floor from specified ones', () => { + expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(1.2); + }); + + it('should return default floor for media type whatever size', () => { + bid.mediaTypes.banner.sizes.push([300, 400]); + expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(1.0); + }); + + it('should return default floor', () => { + expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(0); + }); + + it('should return default floor when currency not passed', () => { + expect(spec.getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); + }); + + it('should return handle not number from floor module', () => { + bid.mediaTypes.banner.sizes.push([30, 60]); + expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(0); + }); + + it('should return proper video floor', () => { + bid.mediaTypes = { + video: { + playerSize: [ + [640, 480] + ] + } + }; + expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(2.3); + }); + + it('should return default video floor', () => { + bid.mediaTypes = { + video: { + playerSize: [ + [640, 490] + ] + } + }; + expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(2.1); + }); + }); }); describe('Verify bid requests with multiple mediaTypes', function () { From 9ce2bc29020b3078c7c25273f8c9b74bcd8c20c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 16 Oct 2024 12:23:13 +0200 Subject: [PATCH 21/25] fix desc for u.t. --- test/spec/modules/smartadserverBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index cbc680fd313..62c1b0de92c 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -1468,7 +1468,7 @@ describe('Smart bid adapter tests', function () { expect(spec.getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); }); - it('should return handle not number from floor module', () => { + it('should handle not number returned by floor module', () => { bid.mediaTypes.banner.sizes.push([30, 60]); expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(0); }); From fb9b8936bce3ff4f1174ddd0508014d619babf28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 16 Oct 2024 12:25:42 +0200 Subject: [PATCH 22/25] better name for u.t. --- test/spec/modules/smartadserverBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 62c1b0de92c..5800a967c8c 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -1468,7 +1468,7 @@ describe('Smart bid adapter tests', function () { expect(spec.getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); }); - it('should handle not number returned by floor module', () => { + it('should return DEFAULT_FLOOR in case of not a number value from floor module', () => { bid.mediaTypes.banner.sizes.push([30, 60]); expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(0); }); From 9f9c13325ce38e51b2495d327bac2d67b474f34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 16 Oct 2024 12:32:10 +0200 Subject: [PATCH 23/25] add u.t. for not supported media type --- test/spec/modules/smartadserverBidAdapter_spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 5800a967c8c..0a62d5207db 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -1494,6 +1494,10 @@ describe('Smart bid adapter tests', function () { }; expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(2.1); }); + + it('should return DEFAULT_FLOOR for not supported media type', () => { + expect(spec.getBidFloor(bid, 'USD', 'test')).to.deep.eq(0); + }); }); }); From 08e3c525e94ad3250a62c2f99001a00338565bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Wed, 16 Oct 2024 12:52:15 +0200 Subject: [PATCH 24/25] improve currency u.t. --- .../modules/smartadserverBidAdapter_spec.js | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 0a62d5207db..3ee00a99bd9 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -1428,49 +1428,53 @@ describe('Smart bid adapter tests', function () { } }, getFloor: (data) => { - if (data.mediaType === BANNER) { - if (data.size[0] === 300 && data.size[1] === 250) { - return { floor: 1.2 }; - } else if (data.size[0] === 300 && data.size[1] === 600) { - return { floor: 1.4 }; - } else if (data.size[0] === 30 && data.size[1] === 60) { - return 'string'; + if (data.currency === 'USD') { + if (data.mediaType === BANNER) { + if (data.size[0] === 300 && data.size[1] === 250) { + return { floor: 1.2 }; + } else if (data.size[0] === 300 && data.size[1] === 600) { + return { floor: 1.4 }; + } else if (data.size[0] === 30 && data.size[1] === 60) { + return 'string'; + } else { + return { floor: 1.0 }; + } + } else if (data.mediaType === VIDEO) { + if (data.size[0] === 640 && data.size[1] === 480) { + return { floor: 2.3 }; + } else { + return { floor: 2.1 }; + } } else { - return { floor: 1.0 }; - } - } else if (data.mediaType === VIDEO) { - if (data.size[0] === 640 && data.size[1] === 480) { - return { floor: 2.3 }; - } else { - return { floor: 2.1 }; + return {}; } } else { - return {}; + return undefined; } } }; }); it('should return lowest floor from specified ones', () => { - expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(1.2); + expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.2); }); it('should return default floor for media type whatever size', () => { bid.mediaTypes.banner.sizes.push([300, 400]); - expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(1.0); + expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.0); }); it('should return default floor', () => { - expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(0); + expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(0); }); - it('should return default floor when currency not passed', () => { + it('should return floor when currency not passed', () => { expect(spec.getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); }); it('should return DEFAULT_FLOOR in case of not a number value from floor module', () => { bid.mediaTypes.banner.sizes.push([30, 60]); - expect(spec.getBidFloor(bid, 'DKK', BANNER)).to.deep.eq(0); + expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(0); }); it('should return proper video floor', () => { @@ -1481,7 +1485,7 @@ describe('Smart bid adapter tests', function () { ] } }; - expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(2.3); + expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.3); }); it('should return default video floor', () => { @@ -1492,7 +1496,7 @@ describe('Smart bid adapter tests', function () { ] } }; - expect(spec.getBidFloor(bid, 'DKK', VIDEO)).to.deep.eq(2.1); + expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.1); }); it('should return DEFAULT_FLOOR for not supported media type', () => { From 0bc782c77da2019ebd8ed21c260e6192223f2136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Sok=C3=B3=C5=82?= Date: Fri, 25 Oct 2024 09:19:40 +0200 Subject: [PATCH 25/25] updates after pr review --- libraries/equativUtils/equativUtils.js | 30 ++++++++++++++++ modules/equativBidAdapter.js | 28 +++------------ modules/smartadserverBidAdapter.js | 36 +++---------------- test/spec/modules/equativBidAdapter_spec.js | 16 +++++---- .../modules/smartadserverBidAdapter_spec.js | 23 ++++++------ 5 files changed, 60 insertions(+), 73 deletions(-) create mode 100644 libraries/equativUtils/equativUtils.js diff --git a/libraries/equativUtils/equativUtils.js b/libraries/equativUtils/equativUtils.js new file mode 100644 index 00000000000..bdcbdad2f33 --- /dev/null +++ b/libraries/equativUtils/equativUtils.js @@ -0,0 +1,30 @@ +import { VIDEO } from '../../src/mediaTypes.js'; +import { deepAccess, isFn } from '../../src/utils.js'; + +const DEFAULT_FLOOR = 0.0; + +/** + * Get floors from Prebid Price Floors module + * + * @param {object} bid Bid request object + * @param {string} currency Ad server currency + * @param {string} mediaType Bid media type + * @return {number} Floor price + */ +export function getBidFloor (bid, currency, mediaType) { + const floors = []; + + if (isFn(bid.getFloor)) { + (deepAccess(bid, `mediaTypes.${mediaType}.${mediaType === VIDEO ? 'playerSize' : 'sizes'}`) || []).forEach(size => { + const floor = bid.getFloor({ + currency: currency || 'USD', + mediaType, + size + }).floor; + + floors.push(!isNaN(floor) ? floor : DEFAULT_FLOOR); + }); + } + + return floors.length ? Math.min(...floors) : DEFAULT_FLOOR; +} diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index c5c96039f67..2c071fe832a 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -1,7 +1,8 @@ import { BANNER } from '../src/mediaTypes.js'; +import { getBidFloor } from '../libraries/equativUtils/equativUtils.js' import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { deepAccess, deepSetValue, isFn, mergeDeep } from '../src/utils.js'; +import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -26,27 +27,6 @@ export const spec = { }; }, - /** - * @param bidRequest - * @returns {number} - */ - getMinFloor: (bidRequest) => { - const floors = []; - - if (isFn(bidRequest.getFloor)) { - (deepAccess(bidRequest, 'mediaTypes.banner.sizes') || []).forEach(size => { - const floor = bidRequest.getFloor({ size }).floor; - if (!isNaN(floor)) { - floors.push(floor); - } else { - floors.push(0.0); - } - }); - } - - return floors.length ? Math.min(...floors) : 0.0; - }, - /** * @param serverResponse * @param bidRequest @@ -105,8 +85,8 @@ export const converter = ortbConverter({ delete imp.dt; - imp.bidfloor = imp.bidfloor || spec.getMinFloor(bidRequest); - imp.secure = Number(window.location.protocol === 'https:'); + imp.bidfloor = imp.bidfloor || getBidFloor(bidRequest); + imp.secure = 1; imp.tagid = bidRequest.adUnitCode; if (siteId || pageId || formatId) { diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 53b13ecf944..e0ddf0a66e6 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -4,23 +4,23 @@ import { isArray, isArrayOfNums, isEmpty, - isFn, isInteger, logError } from '../src/utils.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; +import { getBidFloor } from '../libraries/equativUtils/equativUtils.js' import { registerBidder } from '../src/adapters/bidderFactory.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid * @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest + * @typedef {import('../src/adapters/bidderFactory.js').UserSync} UserSync */ const BIDDER_CODE = 'smartadserver'; const GVL_ID = 45; -const DEFAULT_FLOOR = 0.0; export const spec = { code: BIDDER_CODE, @@ -256,7 +256,7 @@ export const spec = { if (isSupportedVideoContext) { let videoPayload = deepClone(payload); spec.fillPayloadForVideoBidRequest(videoPayload, videoMediaType, bid.params.video); - videoPayload.bidfloor = bid.params.bidfloor || spec.getBidFloor(bid, adServerCurrency, VIDEO); + videoPayload.bidfloor = bid.params.bidfloor || getBidFloor(bid, adServerCurrency, VIDEO); bidRequests.push(spec.createServerRequest(videoPayload, bid.params.domain)); } } else { @@ -264,7 +264,7 @@ export const spec = { spec.fillPayloadForVideoBidRequest(payload, videoMediaType, bid.params.video); } - payload.bidfloor = bid.params.bidfloor || spec.getBidFloor(bid, adServerCurrency, type); + payload.bidfloor = bid.params.bidfloor || getBidFloor(bid, adServerCurrency, type); bidRequests.push(spec.createServerRequest(payload, bid.params.domain)); } else { bidRequests.push({}); @@ -323,38 +323,12 @@ export const spec = { return bidResponses; }, - /** - * Get floors from Prebid Price Floors module - * - * @param {object} bid Bid request object - * @param {string} currency Ad server currency - * @param {string} mediaType Bid media type - * @return {number} Floor price - */ - getBidFloor: (bid, currency, mediaType) => { - const floors = []; - - if (isFn(bid.getFloor)) { - (deepAccess(bid, `mediaTypes.${mediaType}.${mediaType === BANNER ? 'sizes' : 'playerSize'}`) || []).forEach(size => { - const floor = bid.getFloor({ - currency: currency || 'USD', - mediaType, - size - }).floor; - - floors.push(!isNaN(floor) ? floor : DEFAULT_FLOOR); - }); - } - - return floors.length ? Math.min(...floors) : DEFAULT_FLOOR; - }, - /** * User syncs. * * @param {*} syncOptions Publisher prebid configuration. * @param {*} serverResponses A successful response from the server. - * @return {syncs[]} An array of syncs that should be executed. + * @return {UserSync[]} An array of syncs that should be executed. */ getUserSyncs: function (syncOptions, serverResponses) { const syncs = []; diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index c2465176ac1..b3009e38710 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -1,3 +1,5 @@ +import { BANNER } from 'src/mediaTypes.js'; +import { getBidFloor } from 'libraries/equativUtils/equativUtils.js' import { spec, converter } from 'modules/equativBidAdapter.js'; describe('Equativ bid adapter tests', () => { @@ -238,7 +240,7 @@ describe('Equativ bid adapter tests', () => { DEFAULT_BID_REQUESTS, DEFAULT_BIDDER_REQUEST ); - expect(request.data.imp[0]).to.have.property('secure').that.within(0, 1); + expect(request.data.imp[0]).to.have.property('secure').that.eq(1); }); it('should have tagid', () => { @@ -259,13 +261,13 @@ describe('Equativ bid adapter tests', () => { }); }); - describe('getMinFloor', () => { + describe('getBidFloor', () => { it('should return floor of 0.0 if floor module not available', () => { const bid = { ...DEFAULT_BID_REQUESTS[0], getFloor: false, }; - expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + expect(getBidFloor(bid)).to.deep.eq(0.0); }); it('should return floor of 0.0 if mediaTypes not defined', () => { @@ -273,7 +275,7 @@ describe('Equativ bid adapter tests', () => { getFloor: () => ({}) }; expect(bid.mediaTypes).to.be.undefined; - expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + expect(getBidFloor(bid)).to.deep.eq(0.0); }); it('should return proper min floor', () => { @@ -289,7 +291,7 @@ describe('Equativ bid adapter tests', () => { } } }; - expect(spec.getMinFloor(bid)).to.deep.eq(1.13); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.13); }); it('should return global media type floor if no rule for size', () => { @@ -305,7 +307,7 @@ describe('Equativ bid adapter tests', () => { } } }; - expect(spec.getMinFloor(bid)).to.deep.eq(0.34); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(0.34); }); it('should return floor of 0 if no rule for size', () => { @@ -321,7 +323,7 @@ describe('Equativ bid adapter tests', () => { } } }; - expect(spec.getMinFloor(bid)).to.deep.eq(0.0); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(0.0); }); }); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 3ee00a99bd9..0935b6c8404 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import { BANNER, VIDEO } from 'src/mediaTypes.js'; import { config } from 'src/config.js'; import { deepClone } from 'src/utils.js'; +import { getBidFloor } from 'libraries/equativUtils/equativUtils.js' import { spec } from 'modules/smartadserverBidAdapter.js'; // Default params with optional ones @@ -1314,7 +1315,7 @@ describe('Smart bid adapter tests', function () { it('should return default floor when module not activated', function() { const bidRequest = JSON.parse((spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL))[0].data); - const floor = spec.getBidFloor(bidRequest, 'EUR'); + const floor = getBidFloor(bidRequest, 'EUR'); expect(floor).to.deep.equal(0); }); @@ -1324,14 +1325,14 @@ describe('Smart bid adapter tests', function () { return { floor: 'one' }; }; - const floor = spec.getBidFloor(bidRequest, 'EUR'); + const floor = getBidFloor(bidRequest, 'EUR'); expect(floor).to.deep.equal(0.0); }); it('should return default floor when currency unknown', function() { const bidRequest = JSON.parse((spec.buildRequests(DEFAULT_PARAMS_WO_OPTIONAL))[0].data); - const floor = spec.getBidFloor(bidRequest, null); + const floor = getBidFloor(bidRequest, null); expect(floor).to.deep.equal(0); }); @@ -1456,25 +1457,25 @@ describe('Smart bid adapter tests', function () { }); it('should return lowest floor from specified ones', () => { - expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.2); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.2); }); it('should return default floor for media type whatever size', () => { bid.mediaTypes.banner.sizes.push([300, 400]); - expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.0); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(1.0); }); it('should return default floor', () => { - expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(0); + expect(getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(0); }); it('should return floor when currency not passed', () => { - expect(spec.getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); + expect(getBidFloor(bid, undefined, BANNER)).to.deep.eq(1.2); }); it('should return DEFAULT_FLOOR in case of not a number value from floor module', () => { bid.mediaTypes.banner.sizes.push([30, 60]); - expect(spec.getBidFloor(bid, 'USD', BANNER)).to.deep.eq(0); + expect(getBidFloor(bid, 'USD', BANNER)).to.deep.eq(0); }); it('should return proper video floor', () => { @@ -1485,7 +1486,7 @@ describe('Smart bid adapter tests', function () { ] } }; - expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.3); + expect(getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.3); }); it('should return default video floor', () => { @@ -1496,11 +1497,11 @@ describe('Smart bid adapter tests', function () { ] } }; - expect(spec.getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.1); + expect(getBidFloor(bid, 'USD', VIDEO)).to.deep.eq(2.1); }); it('should return DEFAULT_FLOOR for not supported media type', () => { - expect(spec.getBidFloor(bid, 'USD', 'test')).to.deep.eq(0); + expect(getBidFloor(bid, 'USD', 'test')).to.deep.eq(0); }); }); });