From 1d3c3bafe520b8754fa911b9501f881bcc0147f1 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Mon, 27 Oct 2025 11:08:01 +0100 Subject: [PATCH 1/2] Bid response filter: extending with mediaTypes --- libraries/ortbConverter/processors/default.js | 9 +++ modules/bidResponseFilter/index.js | 15 +++- test/spec/modules/bidResponseFilter_spec.js | 79 ++++++++++++++++--- 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index b1fb5be77a5..e4fb5164900 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -111,6 +111,15 @@ export const DEFAULT_PROCESSORS = { if (bid.ext?.eventtrackers) { bidResponse.eventtrackers = (bidResponse.eventtrackers ?? []).concat(bid.ext.eventtrackers); } + if (bid.mtype) { + const bidMediaTypeMap = { + 1: 'banner', + 2: 'video', + 3: 'audio', + 4: 'native' + }; + bidResponse.meta.mediaType = bidMediaTypeMap[bid.mtype]; + } } } } diff --git a/modules/bidResponseFilter/index.js b/modules/bidResponseFilter/index.js index 5b138965983..309a4826512 100644 --- a/modules/bidResponseFilter/index.js +++ b/modules/bidResponseFilter/index.js @@ -6,6 +6,7 @@ export const MODULE_NAME = 'bidResponseFilter'; export const BID_CATEGORY_REJECTION_REASON = 'Category is not allowed'; export const BID_ADV_DOMAINS_REJECTION_REASON = 'Adv domain is not allowed'; export const BID_ATTR_REJECTION_REASON = 'Attr is not allowed'; +export const BID_MEDIA_TYPE_REJECTION_REASON = `Media type is not allowed`; let moduleConfig; let enabled = false; @@ -29,13 +30,20 @@ export function reset() { export function addBidResponseHook(next, adUnitCode, bid, reject, index = auctionManager.index) { const {bcat = [], badv = []} = index.getOrtb2(bid) || {}; - const battr = index.getBidRequest(bid)?.ortb2Imp[bid.mediaType]?.battr || index.getAdUnit(bid)?.ortb2Imp[bid.mediaType]?.battr || []; + const adUnit = index.getAdUnit(bid); + const battr = index.getBidRequest(bid)?.ortb2Imp[bid.mediaType]?.battr || adUnit?.ortb2Imp[bid.mediaType]?.battr || []; const catConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.cat || {})}; const advConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.adv || {})}; const attrConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.attr || {})}; + const mediaTypesConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.mediaTypes || {})}; - const { primaryCatId, secondaryCatIds = [], advertiserDomains = [], attr: metaAttr } = bid.meta || {}; + const { + primaryCatId, secondaryCatIds = [], + advertiserDomains = [], + attr: metaAttr, + mediaType: metaMediaType, + } = bid.meta || {}; // checking if bid fulfills ortb2 fields rules if ((catConfig.enforce && bcat.some(category => [primaryCatId, ...secondaryCatIds].includes(category))) || @@ -47,6 +55,9 @@ export function addBidResponseHook(next, adUnitCode, bid, reject, index = auctio } else if ((attrConfig.enforce && battr.includes(metaAttr)) || (attrConfig.blockUnknown && !metaAttr)) { reject(BID_ATTR_REJECTION_REASON); + } else if ((mediaTypesConfig.enforce && !Object.keys(adUnit?.mediaTypes || {}).includes(metaMediaType)) || + (mediaTypesConfig.blockUnknown && !metaMediaType)) { + reject(BID_MEDIA_TYPE_REJECTION_REASON); } else { return next(adUnitCode, bid, reject); } diff --git a/test/spec/modules/bidResponseFilter_spec.js b/test/spec/modules/bidResponseFilter_spec.js index 6251fe35250..1480cc8f96f 100644 --- a/test/spec/modules/bidResponseFilter_spec.js +++ b/test/spec/modules/bidResponseFilter_spec.js @@ -3,11 +3,12 @@ import { BID_ADV_DOMAINS_REJECTION_REASON, BID_ATTR_REJECTION_REASON, BID_CATEGORY_REJECTION_REASON, - init, - MODULE_NAME - , reset} from '../../../modules/bidResponseFilter/index.js'; -import {config} from '../../../src/config.js'; -import {addBidResponse} from '../../../src/auction.js'; + BID_MEDIA_TYPE_REJECTION_REASON, + MODULE_NAME, + reset +} from '../../../modules/bidResponseFilter/index.js'; +import { addBidResponse } from '../../../src/auction.js'; +import { config } from '../../../src/config.js'; describe('bidResponseFilter', () => { let mockAuctionIndex @@ -56,11 +57,19 @@ describe('bidResponseFilter', () => { badv: [], bcat: ['BANNED_CAT1', 'BANNED_CAT2'] }); + mockAuctionIndex.getAdUnit = () => ({ + mediaTypes: { + banner: {} + }, + ortb2Imp: {} + }) + const bid = { meta: { advertiserDomains: ['domain1.com', 'domain2.com'], primaryCatId: 'EXAMPLE-CAT-ID', - attr: 'attr' + attr: 'attr', + mediaType: 'banner' } }; @@ -138,10 +147,18 @@ describe('bidResponseFilter', () => { meta: { advertiserDomains: ['validdomain1.com', 'validdomain2.com'], primaryCatId: 'BANNED_CAT1', - attr: 'valid_attr' + attr: 'valid_attr', + mediaType: 'banner', } }; + mockAuctionIndex.getAdUnit = () => ({ + mediaTypes: { + banner: {} + }, + ortb2Imp: {} + }) + mockAuctionIndex.getOrtb2 = () => ({ badv: ['domain2.com'], bcat: ['BANNED_CAT1', 'BANNED_CAT2'] }); @@ -159,7 +176,8 @@ describe('bidResponseFilter', () => { meta: { advertiserDomains: ['validdomain1.com', 'validdomain2.com'], primaryCatId: undefined, - attr: 'valid_attr' + attr: 'valid_attr', + mediaType: 'banner' } }; @@ -167,10 +185,53 @@ describe('bidResponseFilter', () => { badv: ['domain2.com'], bcat: ['BANNED_CAT1', 'BANNED_CAT2'] }); + mockAuctionIndex.getAdUnit = () => ({ + mediaTypes: { + banner: {} + }, + ortb2Imp: {} + }) + config.setConfig({[MODULE_NAME]: {cat: {blockUnknown: false}}}); addBidResponseHook(call, 'adcode', bid, () => { - }); + }, mockAuctionIndex); sinon.assert.calledOnce(call); }); + + it('should reject bid for meta.mediaType not present on adunit', () => { + const reject = sinon.stub(); + const call = sinon.stub(); + const bid = { + meta: { + advertiserDomains: ['validdomain1.com', 'validdomain2.com'], + primaryCatId: 'VALID_CAT', + attr: 6, + mediaType: 'audio' + }, + }; + + mockAuctionIndex.getOrtb2 = () => ({ + badv: [], bcat: [] + }); + + mockAuctionIndex.getBidRequest = () => ({ + ortb2Imp: { + banner: { + }, + video: { + }, + } + }) + + mockAuctionIndex.getAdUnit = () => ({ + mediaTypes: { + banner: {}, + }, + ortb2Imp: {} + }) + + addBidResponseHook(call, 'adcode', bid, reject, mockAuctionIndex); + sinon.assert.calledWith(reject, BID_MEDIA_TYPE_REJECTION_REASON); + }); }) From 5a53a3f73468d3875785701c915a19c001eea700 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Thu, 30 Oct 2025 13:31:29 +0100 Subject: [PATCH 2/2] removing mtype handling --- libraries/ortbConverter/processors/default.js | 9 --------- modules/bidResponseFilter/index.js | 6 +++--- test/spec/modules/bidResponseFilter_spec.js | 8 ++++---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index e4fb5164900..b1fb5be77a5 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -111,15 +111,6 @@ export const DEFAULT_PROCESSORS = { if (bid.ext?.eventtrackers) { bidResponse.eventtrackers = (bidResponse.eventtrackers ?? []).concat(bid.ext.eventtrackers); } - if (bid.mtype) { - const bidMediaTypeMap = { - 1: 'banner', - 2: 'video', - 3: 'audio', - 4: 'native' - }; - bidResponse.meta.mediaType = bidMediaTypeMap[bid.mtype]; - } } } } diff --git a/modules/bidResponseFilter/index.js b/modules/bidResponseFilter/index.js index 309a4826512..64026958bc6 100644 --- a/modules/bidResponseFilter/index.js +++ b/modules/bidResponseFilter/index.js @@ -30,8 +30,8 @@ export function reset() { export function addBidResponseHook(next, adUnitCode, bid, reject, index = auctionManager.index) { const {bcat = [], badv = []} = index.getOrtb2(bid) || {}; - const adUnit = index.getAdUnit(bid); - const battr = index.getBidRequest(bid)?.ortb2Imp[bid.mediaType]?.battr || adUnit?.ortb2Imp[bid.mediaType]?.battr || []; + const bidRequest = index.getBidRequest(bid); + const battr = bidRequest?.ortb2Imp[bid.mediaType]?.battr || index.getAdUnit(bid)?.ortb2Imp[bid.mediaType]?.battr || []; const catConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.cat || {})}; const advConfig = {enforce: true, blockUnknown: true, ...(moduleConfig?.adv || {})}; @@ -55,7 +55,7 @@ export function addBidResponseHook(next, adUnitCode, bid, reject, index = auctio } else if ((attrConfig.enforce && battr.includes(metaAttr)) || (attrConfig.blockUnknown && !metaAttr)) { reject(BID_ATTR_REJECTION_REASON); - } else if ((mediaTypesConfig.enforce && !Object.keys(adUnit?.mediaTypes || {}).includes(metaMediaType)) || + } else if ((mediaTypesConfig.enforce && !Object.keys(bidRequest?.mediaTypes || {}).includes(metaMediaType)) || (mediaTypesConfig.blockUnknown && !metaMediaType)) { reject(BID_MEDIA_TYPE_REJECTION_REASON); } else { diff --git a/test/spec/modules/bidResponseFilter_spec.js b/test/spec/modules/bidResponseFilter_spec.js index 1480cc8f96f..c37003bde50 100644 --- a/test/spec/modules/bidResponseFilter_spec.js +++ b/test/spec/modules/bidResponseFilter_spec.js @@ -57,7 +57,7 @@ describe('bidResponseFilter', () => { badv: [], bcat: ['BANNED_CAT1', 'BANNED_CAT2'] }); - mockAuctionIndex.getAdUnit = () => ({ + mockAuctionIndex.getBidRequest = () => ({ mediaTypes: { banner: {} }, @@ -152,7 +152,7 @@ describe('bidResponseFilter', () => { } }; - mockAuctionIndex.getAdUnit = () => ({ + mockAuctionIndex.getBidRequest = () => ({ mediaTypes: { banner: {} }, @@ -185,7 +185,7 @@ describe('bidResponseFilter', () => { badv: ['domain2.com'], bcat: ['BANNED_CAT1', 'BANNED_CAT2'] }); - mockAuctionIndex.getAdUnit = () => ({ + mockAuctionIndex.getBidRequest = () => ({ mediaTypes: { banner: {} }, @@ -224,7 +224,7 @@ describe('bidResponseFilter', () => { } }) - mockAuctionIndex.getAdUnit = () => ({ + mockAuctionIndex.getBidRequest = () => ({ mediaTypes: { banner: {}, },