From 5bef448d0973787ae9ee1ea3e2257229cf1b3300 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Thu, 1 May 2025 14:41:50 +0530 Subject: [PATCH 01/20] Refactor(schain): Move schain to ortb2.source.schain and use FPD validation --- modules/rubiconBidAdapter.js | 4 +- modules/schain.js | 49 +++++---- .../spec/modules/conversantBidAdapter_spec.js | 4 +- test/spec/modules/criteoBidAdapter_spec.js | 2 +- .../modules/improvedigitalBidAdapter_spec.js | 2 +- test/spec/modules/openxBidAdapter_spec.js | 2 +- .../spec/modules/pulsepointBidAdapter_spec.js | 4 +- test/spec/modules/r2b2BidAdapter_spec.js | 11 +- test/spec/modules/rubiconBidAdapter_spec.js | 11 +- test/spec/modules/schain_spec.js | 101 ++++++++++++++---- .../modules/showheroes-bsBidAdapter_spec.js | 6 +- .../spec/modules/stackadaptBidAdapter_spec.js | 4 +- .../modules/trafficgateBidAdapter_spec.js | 2 +- test/spec/ortbConverter/schain_spec.js | 2 +- 14 files changed, 141 insertions(+), 63 deletions(-) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 22f40ca69e6..02f41904099 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -617,8 +617,8 @@ export const spec = { } // if SupplyChain is supplied and contains all required fields - if (bidRequest.schain && hasValidSupplyChainParams(bidRequest.schain)) { - data.rp_schain = spec.serializeSupplyChain(bidRequest.schain); + if (bidRequest.ortb2?.source?.schain && hasValidSupplyChainParams(bidRequest.ortb2.source.schain)) { + data.rp_schain = spec.serializeSupplyChain(bidRequest.ortb2.source.schain); } return data; diff --git a/modules/schain.js b/modules/schain.js index 726679b133f..30a9c1a85a2 100644 --- a/modules/schain.js +++ b/modules/schain.js @@ -1,7 +1,6 @@ import {config} from '../src/config.js'; import adapterManager from '../src/adapterManager.js'; import { - _each, deepAccess, deepClone, deepSetValue, @@ -22,13 +21,8 @@ const shouldBeAString = ' should be a string'; const shouldBeAnInteger = ' should be an Integer'; const shouldBeAnObject = ' should be an object'; const shouldBeAnArray = ' should be an Array'; -const MODE = { - STRICT: 'strict', - RELAXED: 'relaxed', - OFF: 'off' -}; -const MODES = []; // an array of modes -_each(MODE, mode => MODES.push(mode)); +let skipValidation = true; // Default to true (skip validation) + // validate the supply chain object export function isSchainObjectValid(schainObject, returnOnError) { @@ -143,22 +137,24 @@ export function isValidSchainConfig(schainObject) { return true; } -function resolveSchainConfig(schainObject, bidder) { - let mode = MODE.STRICT; +function handleSetConfigFlag(config) { + // Calculate skipValidation from the FPD config + if (config && typeof config === 'object') { + skipValidation = config.skipValidations !== false; + } +} +function resolveSchainConfig(schainObject, bidder) { if (isValidSchainConfig(schainObject)) { - if (isStr(schainObject.validation) && MODES.indexOf(schainObject.validation) != -1) { - mode = schainObject.validation; - } - if (mode === MODE.OFF) { - // no need to validate + if (skipValidation) { + // Skip validation if skipValidations is true (default) return schainObject.config; } else { - // if strict mode and config is invalid, reject config + throw error; otherwise allow config to go through - if (isSchainObjectValid(schainObject.config, !!(mode === MODE.STRICT))) { + // Perform strict validation if skipValidations is false + if (isSchainObjectValid(schainObject.config, true)) { return schainObject.config; } else { - logError(schainErrorPrefix + `due to the 'strict' validation setting, this schain config will not be passed to bidder '${bidder}'. See above error for details.`); + logError(schainErrorPrefix + `due to validation failure, this schain config will not be passed to bidder '${bidder}'. See above error for details.`); } } } @@ -181,7 +177,16 @@ export function makeBidRequestsHook(fn, bidderRequests) { bidderRequest.bids.forEach(bid => { let result = resolveSchainConfig(schainConfig, bidder); if (result) { - bid.schain = deepClone(result); + // Initialize ortb2 object if it doesn't exist + if (!bid.ortb2) { + bid.ortb2 = {}; + } + // Initialize source object if it doesn't exist + if (!bid.ortb2.source) { + bid.ortb2.source = {}; + } + // Set the schain in ortb2.source.schain + bid.ortb2.source.schain = deepClone(result); } }); }); @@ -197,7 +202,8 @@ init() export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) { if (!deepAccess(ortbRequest, 'source.ext.schain')) { - const schain = deepAccess(context, 'bidRequests.0.schain'); + // Look for schain in the new location: ortb2.source.schain + const schain = deepAccess(context, 'bidRequests.0.ortb2.source.schain'); if (schain) { deepSetValue(ortbRequest, 'source.ext.schain', schain); } @@ -205,3 +211,6 @@ export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) { } registerOrtbProcessor({type: REQUEST, name: 'sourceExtSchain', fn: setOrtbSourceExtSchain}); + +// handler to read the skipValidation flag +config.getConfig('firstPartyData', config => handleSetConfigFlag(config.firstPartyData)); diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index e116a99c761..3cfb56d1135 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -453,8 +453,8 @@ describe('Conversant adapter tests', function() { const schain = {complete: 1, ver: '1.0', nodes: [{asi: 'bidderA.com', sid: '00001', hp: 1}]}; const bidsWithSchain = bidRequests.map((bid) => { return Object.assign({ - schain: schain - }, bid); + ortb2: {source: {schain: schain}} + }, bid); }); const request = spec.buildRequests(bidsWithSchain, bidderRequest); const payload = request.data; diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 551db4fc72d..fb8ee1092ba 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1226,7 +1226,7 @@ describe('The Criteo bidding adapter', function () { const bidRequests = [ { bidder: 'criteo', - schain: expectedSchain, + ortb2: {source: {schain: expectedSchain}}, adUnitCode: 'bid-123', mediaTypes: { banner: { diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index adbf30bb5f1..5b9542b62c2 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -553,7 +553,7 @@ describe('Improve Digital Adapter Tests', function () { it('should add schain', function () { const schain = '{"ver":"1.0","complete":1,"nodes":[{"asi":"headerlift.com","sid":"xyz","hp":1}]}'; const bidRequest = Object.assign({}, simpleBidRequest); - bidRequest.schain = schain; + bidRequest.ortb2 = {source: {schain: schain}}; const request = spec.buildRequests([bidRequest], bidderRequestReferrer)[0]; const payload = JSON.parse(request.data); expect(payload.source.ext.schain).to.equal(schain); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 18e26b7612e..ce4562c9bb7 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1106,7 +1106,7 @@ describe('OpenxRtbAdapter', function () { bidId: 'test-bid-id-1', bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1', - schain: schainConfig + ortb2: {source: {schain: schainConfig}} }]; }); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index b6192c1acaf..8f0c272916c 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -136,7 +136,7 @@ describe('PulsePoint Adapter Tests', function () { bidfloor: 1.5, badv: ['cocacola.com', 'lays.com'] }, - schain: { + ortb2: {source: {schain: { 'ver': '1.0', 'complete': 1, 'nodes': [ @@ -149,7 +149,7 @@ describe('PulsePoint Adapter Tests', function () { 'domain': 'publisher.com' } ] - }, + }}} }]; const bidderRequest = { diff --git a/test/spec/modules/r2b2BidAdapter_spec.js b/test/spec/modules/r2b2BidAdapter_spec.js index 63850b78c40..8272297797c 100644 --- a/test/spec/modules/r2b2BidAdapter_spec.js +++ b/test/spec/modules/r2b2BidAdapter_spec.js @@ -91,9 +91,9 @@ describe('R2B2 adapter', function () { } }, site: {}, - device: {} + device: {}, + source: {schain: schain} }, - schain }, { bidder: 'r2b2', params: { @@ -128,9 +128,9 @@ describe('R2B2 adapter', function () { } }, site: {}, - device: {} + device: {}, + source: {schain: schain} }, - schain }]; bidderRequest = { bidderCode: 'r2b2', @@ -150,7 +150,8 @@ describe('R2B2 adapter', function () { } }, site: {}, - device: {} + device: {}, + source: {schain: schain} }, gdprConsent: { consentString: 'consent-string', diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 8b36256f6a6..0ee9d4b8793 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -131,6 +131,9 @@ describe('the rubicon adapter', function () { tid: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', } }, + ortb2: { + source: {} + } } ], start: 1472239426002, @@ -4623,7 +4626,7 @@ describe('the rubicon adapter', function () { beforeEach(() => { bidRequests = getBidderRequest(); schainConfig = getSupplyChainConfig(); - bidRequests.bids[0].schain = schainConfig; + bidRequests.bids[0].ortb2.source.schain = schainConfig; }); it('should properly serialize schain object with correct delimiters', () => { @@ -4642,14 +4645,14 @@ describe('the rubicon adapter', function () { const results = spec.buildRequests(bidRequests.bids, bidRequests); const schain = new URLSearchParams(results[0].data).get('rp_schain').split('!'); const version = schain.shift().split(',')[0]; - expect(version).to.equal(bidRequests.bids[0].schain.ver); + expect(version).to.equal(bidRequests.bids[0].ortb2.source.schain.ver); }); it('should send the correct value for complete in schain', () => { const results = spec.buildRequests(bidRequests.bids, bidRequests); const schain = new URLSearchParams(results[0].data).get('rp_schain').split('!'); const complete = schain.shift().split(',')[1]; - expect(complete).to.equal(String(bidRequests.bids[0].schain.complete)); + expect(complete).to.equal(String(bidRequests.bids[0].ortb2.source.schain.complete)); }); it('should send available params in the right order', () => { @@ -4670,7 +4673,7 @@ describe('the rubicon adapter', function () { it('should copy the schain JSON to to bid.source.ext.schain', () => { const bidderRequest = createVideoBidderRequest(); const schain = getSupplyChainConfig(); - bidderRequest.bids[0].schain = schain; + bidderRequest.bids[0].ortb2.source.schain = schain; const request = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request[0].data.source.ext.schain).to.deep.equal(schain); }); diff --git a/test/spec/modules/schain_spec.js b/test/spec/modules/schain_spec.js index eb8e35749db..ee7712ed9be 100644 --- a/test/spec/modules/schain_spec.js +++ b/test/spec/modules/schain_spec.js @@ -314,7 +314,6 @@ describe('#makeBidRequestsHook', function() { const globalSchainConfig = { 'schain': { - 'validation': 'off', 'config': { 'ver': '1.0', 'complete': 1, @@ -339,7 +338,6 @@ describe('#makeBidRequestsHook', function() { bidders: ['appnexus'], config: { 'schain': { - 'validation': 'strict', 'config': { 'ver': '1.0', 'complete': 1, @@ -366,7 +364,6 @@ describe('#makeBidRequestsHook', function() { bidders: ['appnexus'], config: { 'schain': { - 'validation': 'strict', 'config': { 'ver': '1.0', 'complete': 1, @@ -393,7 +390,6 @@ describe('#makeBidRequestsHook', function() { bidders: ['districtm'], config: { 'schain': { - 'validation': 'relaxed', 'config': { 'ver': '1.0', 'complete': 1, @@ -414,7 +410,6 @@ describe('#makeBidRequestsHook', function() { bidders: ['districtm'], config: { 'schain': { - 'validation': 'relaxed', 'config': { 'ver': 1, 'complete': 1, @@ -452,45 +447,111 @@ describe('#makeBidRequestsHook', function() { }); }); - it('should properly read from bidder schain + global schain configs', function() { + it('should properly read from bidder schain + global schain configs and set in ortb2.source.schain', function() { function testCallback(bidderRequests) { - expect(bidderRequests[0].bids[0].schain).to.exist; - expect(bidderRequests[0].bids[0].schain).to.deep.equal(globalSchainConfig.schain.config); - expect(bidderRequests[1].bids[0].schain).to.exist; - expect(bidderRequests[1].bids[0].schain).to.deep.equal(goodRelaxedBidderConfig.config.schain.config); - expect(bidderRequests[2].bids[0].schain).to.exist; - expect(bidderRequests[2].bids[0].schain).to.deep.equal(goodStrictBidderConfig.config.schain.config); + // Check for rubicon (using global config) + expect(bidderRequests[0].bids[0].ortb2).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); + + // Check for districtm (using goodRelaxedBidderConfig) + expect(bidderRequests[1].bids[0].ortb2).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source.schain).to.deep.equal(goodRelaxedBidderConfig.config.schain.config); + + // Check for appnexus (using goodStrictBidderConfig) + expect(bidderRequests[2].bids[0].ortb2).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source.schain).to.deep.equal(goodStrictBidderConfig.config.schain.config); } const testBidderRequests = deepClone(bidderRequests); config.setBidderConfig(goodStrictBidderConfig); config.setBidderConfig(goodRelaxedBidderConfig); + // Set skipValidations to false to enable strict validation + config.setConfig({ + firstPartyData: { + skipValidations: false + } + }); + makeBidRequestsHook(testCallback, testBidderRequests); }); it('should not share the same schain object between different bid requests', (done) => { config.setBidderConfig(goodStrictBidderConfig); makeBidRequestsHook((requests) => { - requests[0].bids[0].schain.field = 'value'; - expect(requests[1].bids[0].schain.field).to.not.exist; + requests[0].bids[0].ortb2.source.schain.field = 'value'; + expect(requests[1].bids[0].ortb2.source.schain.field).to.not.exist; done(); }, deepClone(bidderRequests)) }); - it('should reject bad strict config but allow a bad relaxed config for bidders trying to override it', function () { + it('should reject bad config when skipValidations is false', function () { function testCallback(bidderRequests) { - expect(bidderRequests[0].bids[0].schain).to.exist; - expect(bidderRequests[0].bids[0].schain).to.deep.equal(globalSchainConfig.schain.config); - expect(bidderRequests[1].bids[0].schain).to.exist; - expect(bidderRequests[1].bids[0].schain).to.deep.equal(badRelaxedBidderConfig.config.schain.config); - expect(bidderRequests[2].bids[0].schain).to.be.undefined; + // Check for rubicon (using global config) + expect(bidderRequests[0].bids[0].ortb2).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); + + // Check for districtm (should not have schain due to validation failure) + expect(bidderRequests[1].bids[0].ortb2).to.not.exist; + + // Check for appnexus (should not have schain due to validation failure) + expect(bidderRequests[2].bids[0].ortb2).to.not.exist; } const testBidderRequests = deepClone(bidderRequests); config.setBidderConfig(badStrictBidderConfig); config.setBidderConfig(badRelaxedBidderConfig); + // Set skipValidations to false to enable strict validation + config.setConfig({ + firstPartyData: { + skipValidations: false + } + }); + + makeBidRequestsHook(testCallback, testBidderRequests); + }); + + it('should accept all configs when skipValidations is true (default)', function () { + function testCallback(bidderRequests) { + // Check for rubicon (using global config) + expect(bidderRequests[0].bids[0].ortb2).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); + + // Check for districtm (should have schain despite validation issues) + expect(bidderRequests[1].bids[0].ortb2).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[1].bids[0].ortb2.source.schain).to.deep.equal(badRelaxedBidderConfig.config.schain.config); + + // Check for appnexus (should have schain despite validation issues) + expect(bidderRequests[2].bids[0].ortb2).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source.schain).to.exist; + expect(bidderRequests[2].bids[0].ortb2.source.schain).to.deep.equal(badStrictBidderConfig.config.schain.config); + } + + const testBidderRequests = deepClone(bidderRequests); + config.setBidderConfig(badStrictBidderConfig); + config.setBidderConfig(badRelaxedBidderConfig); + + // Set skipValidations to true to skip validation (default behavior) + config.setConfig({ + firstPartyData: { + skipValidations: true + } + }); + makeBidRequestsHook(testCallback, testBidderRequests); }); }); diff --git a/test/spec/modules/showheroes-bsBidAdapter_spec.js b/test/spec/modules/showheroes-bsBidAdapter_spec.js index 07211ca37cc..a845bee1320 100644 --- a/test/spec/modules/showheroes-bsBidAdapter_spec.js +++ b/test/spec/modules/showheroes-bsBidAdapter_spec.js @@ -102,7 +102,9 @@ describe('shBidAdapter', () => { ...schain, ...{uspConsent: uspConsent}, }; - bidRequest.schain = schain.schain.config; + bidRequest.ortb2 = { + source: {schain: schain.schain.config} + }; const getFloorResponse = {currency: 'EUR', floor: 3}; bidRequest.getFloor = () => getFloorResponse; const request = spec.buildRequests([bidRequest], await addFPDToBidderRequest(fullRequest)); @@ -110,7 +112,7 @@ describe('shBidAdapter', () => { expect(payload.regs.ext.gdpr).to.eql(Number(gdpr.gdprConsent.gdprApplies)); expect(payload.regs.ext.us_privacy).to.eql(uspConsent); expect(payload.user.ext.consent).to.eql(gdpr.gdprConsent.consentString); - expect(payload.source.ext.schain).to.eql(bidRequest.schain); + expect(payload.source.ext.schain).to.eql(bidRequest.ortb2.source.schain); expect(payload.test).to.eql(0); expect(payload.imp[0].bidfloor).eql(3); expect(payload.imp[0].bidfloorcur).eql('EUR'); diff --git a/test/spec/modules/stackadaptBidAdapter_spec.js b/test/spec/modules/stackadaptBidAdapter_spec.js index ea86adf28ca..43be0a15ee6 100644 --- a/test/spec/modules/stackadaptBidAdapter_spec.js +++ b/test/spec/modules/stackadaptBidAdapter_spec.js @@ -914,7 +914,9 @@ describe('stackadaptBidAdapter', function () { 'ver': '1.0' }; - clonedBidRequests[0].schain = schain; + clonedBidRequests[0].ortb2 = { + source: {schain: schain} + }; clonedBidderRequest.bids = clonedBidRequests; const ortbRequest = spec.buildRequests(clonedBidRequests, clonedBidderRequest).data; diff --git a/test/spec/modules/trafficgateBidAdapter_spec.js b/test/spec/modules/trafficgateBidAdapter_spec.js index fec467309ab..4f5b696eac1 100644 --- a/test/spec/modules/trafficgateBidAdapter_spec.js +++ b/test/spec/modules/trafficgateBidAdapter_spec.js @@ -932,7 +932,7 @@ describe('TrafficgateOpenxRtbAdapter', function () { bidId: 'test-bid-id-1', bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1', - schain: schainConfig + ortb2: {source: {schain: schainConfig}} }]; }); diff --git a/test/spec/ortbConverter/schain_spec.js b/test/spec/ortbConverter/schain_spec.js index 8eeef445948..b297d9182bf 100644 --- a/test/spec/ortbConverter/schain_spec.js +++ b/test/spec/ortbConverter/schain_spec.js @@ -4,7 +4,7 @@ describe('pbjs - ortb source.ext.schain', () => { it('sets schain from request', () => { const req = {}; setOrtbSourceExtSchain(req, {}, { - bidRequests: [{schain: {s: 'chain'}}] + bidRequests: [{ortb2: {source: {schain: {s: 'chain'}}}}] }); expect(req.source.ext.schain).to.eql({s: 'chain'}); }); From da8d60fb27e565ce9dd552fe0e0e7d1277dbc4a7 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Thu, 1 May 2025 15:23:55 +0530 Subject: [PATCH 02/20] Updated the comment --- modules/schain.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/schain.js b/modules/schain.js index 30a9c1a85a2..be66aa8b5c7 100644 --- a/modules/schain.js +++ b/modules/schain.js @@ -21,7 +21,7 @@ const shouldBeAString = ' should be a string'; const shouldBeAnInteger = ' should be an Integer'; const shouldBeAnObject = ' should be an object'; const shouldBeAnArray = ' should be an Array'; -let skipValidation = true; // Default to true (skip validation) +let skipValidation = true; // Default to true (skip validation ) // validate the supply chain object From 3457410a1b14aa4a6617c29c027955ab2bd73cab Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Thu, 1 May 2025 15:47:25 +0530 Subject: [PATCH 03/20] Updated schain consumption in 33across --- modules/33acrossBidAdapter.js | 4 ++-- test/spec/modules/33acrossBidAdapter_spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 9feca97d425..9a0101ea85b 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -316,9 +316,9 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, gppCo } }; - if (firstBidRequest.schain) { + if (firstBidRequest.ortb2?.source?.schain) { ttxRequest.source = setExtensions(ttxRequest.source, { - 'schain': firstBidRequest.schain + 'schain': firstBidRequest.ortb2.source.schain }); } diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index d4ad0184a17..94e83ff4b23 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -1420,7 +1420,7 @@ describe('33acrossBidAdapter:', function () { ]; schainValues.forEach((schain) => { - bidRequests[0].schain = schain; + bidRequests[0].ortb2.source = {schain: schain}; const ttxRequest = new TtxRequestBuilder() .withBanner() From c0f0cc24bb8b08ebbc1b23b6255cccf3e0471081 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Mon, 19 May 2025 10:41:20 +0530 Subject: [PATCH 04/20] removed separate file for schain validation, instead used ortb2 validation --- integrationExamples/schain.html | 212 +++++++++ libraries/ortbConverter/processors/default.js | 5 +- libraries/ortbConverter/processors/schain.js | 32 ++ modules/pubmaticBidAdapter.js | 2 +- modules/schain.js | 444 +++++++++--------- modules/validationFpdModule/config.js | 33 ++ 6 files changed, 510 insertions(+), 218 deletions(-) create mode 100644 integrationExamples/schain.html create mode 100644 libraries/ortbConverter/processors/schain.js diff --git a/integrationExamples/schain.html b/integrationExamples/schain.html new file mode 100644 index 00000000000..b0514114e1f --- /dev/null +++ b/integrationExamples/schain.html @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+
+

Latest News Headlines

+ +
+

Global Tech Summit Announces Breakthrough in AI Development

+

The annual Global Tech Summit concluded yesterday with a major announcement from leading researchers who have developed a new neural network architecture that promises to reduce computational requirements by up to 40% while maintaining accuracy. Industry leaders are already planning implementations that could revolutionize mobile AI applications.

+

"This represents a significant leap forward in making advanced AI accessible on everyday devices," said Dr. Sarah Chen, lead researcher at the Institute for Advanced Computing. "We expect to see this technology in consumer products within the next 18 months."

+

Published: April 15, 2025 | Category: Technology

+
+ +
+

Climate Agreement Reaches Milestone as 150 Nations Commit to New Emissions Targets

+

In a historic development for environmental policy, 150 nations have signed onto the expanded Global Climate Accord, committing to more aggressive emissions reduction targets by 2035. The agreement includes significant financial commitments to support developing nations in their transition to renewable energy sources.

+

Environmental experts have praised the move but caution that implementation will be the true test. "The targets are ambitious and necessary," noted climate scientist Dr. James Rivera. "But the real challenge lies in the policy changes required to meet these goals."

+

Published: April 14, 2025 | Category: Environment

+
+
+ + + + \ No newline at end of file diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index acb76461bfd..245512cd0c8 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -5,6 +5,7 @@ import {setResponseMediaType} from './mediaType.js'; import {fillNativeImp, fillNativeResponse} from './native.js'; import {BID_RESPONSE, IMP, REQUEST} from '../../../src/pbjsORTB.js'; import {clientSectionChecker} from '../../../src/fpd/oneClient.js'; +import {schainProcessor} from './schain.js'; export const DEFAULT_PROCESSORS = { [REQUEST]: { @@ -32,7 +33,9 @@ export const DEFAULT_PROCESSORS = { ortbRequest.tmax = timeout; } } - } + }, + // Add the moveSchainToExt processor to move schain from source.schain to source.ext.schain + moveSchainToExt: schainProcessor[REQUEST].moveSchainToExt }, [IMP]: { fpd: { diff --git a/libraries/ortbConverter/processors/schain.js b/libraries/ortbConverter/processors/schain.js new file mode 100644 index 00000000000..484249bd282 --- /dev/null +++ b/libraries/ortbConverter/processors/schain.js @@ -0,0 +1,32 @@ +/** + * This module handles the relocation of schain object from source.schain to source.ext.schain + */ +import {deepAccess, deepSetValue} from '../../../src/utils.js'; +import {REQUEST} from '../../../src/pbjsORTB.js'; + +/** + * Processor to move schain from source.schain to source.ext.schain + * This ensures that the schain object is validated first and then moved to the ext object + */ +export const schainProcessor = { + [REQUEST]: { + moveSchainToExt: { + // Run this after validation but before the request is sent + priority: -50, + fn(ortbRequest, bidderRequest, context) { + // Check if source.schain exists in the ortbRequest + const schain = deepAccess(ortbRequest, 'source.schain'); + if (schain) { + // Create ext object if it doesn't exist + if (!deepAccess(ortbRequest, 'source.ext')) { + deepSetValue(ortbRequest, 'source.ext', {}); + } + // Move schain to ext.schain + deepSetValue(ortbRequest, 'source.ext.schain', schain); + // Remove original schain + delete ortbRequest.source.schain; + } + } + } + } +}; diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index a3c97682d5b..239bb995ef5 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -15,7 +15,7 @@ import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, PREBID_NATIVE_DATA_KEYS_TO_ORTB const BIDDER_CODE = 'pubmatic'; const LOG_WARN_PREFIX = 'PubMatic: '; -const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=prebid-client'; +const ENDPOINT = 'https://hbopenbid.pubmatic.com:8443/translator?source=prebid-client'; const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/user_sync.html?kdntuid=1&p='; const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p='; const DEFAULT_CURRENCY = 'USD'; diff --git a/modules/schain.js b/modules/schain.js index be66aa8b5c7..13927580b4e 100644 --- a/modules/schain.js +++ b/modules/schain.js @@ -1,216 +1,228 @@ -import {config} from '../src/config.js'; -import adapterManager from '../src/adapterManager.js'; -import { - deepAccess, - deepClone, - deepSetValue, - isArray, - isInteger, - isNumber, - isPlainObject, - isStr, - logError, - logWarn -} from '../src/utils.js'; -import {registerOrtbProcessor, REQUEST} from '../src/pbjsORTB.js'; - -// https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md - -const schainErrorPrefix = 'Invalid schain object found: '; -const shouldBeAString = ' should be a string'; -const shouldBeAnInteger = ' should be an Integer'; -const shouldBeAnObject = ' should be an object'; -const shouldBeAnArray = ' should be an Array'; -let skipValidation = true; // Default to true (skip validation ) - - -// validate the supply chain object -export function isSchainObjectValid(schainObject, returnOnError) { - let failPrefix = 'Detected something wrong within an schain config:'; - let failMsg = ''; - - function appendFailMsg(msg) { - failMsg += '\n' + msg; - } - - function printFailMsg() { - if (returnOnError === true) { - logError(failPrefix, schainObject, failMsg); - } else { - logWarn(failPrefix, schainObject, failMsg); - } - } - - if (!isPlainObject(schainObject)) { - appendFailMsg(`schain.config` + shouldBeAnObject); - printFailMsg(); - if (returnOnError) return false; - } - - // complete: Integer - if (!isNumber(schainObject.complete) || !isInteger(schainObject.complete)) { - appendFailMsg(`schain.config.complete` + shouldBeAnInteger); - } - - // ver: String - if (!isStr(schainObject.ver)) { - appendFailMsg(`schain.config.ver` + shouldBeAString); - } - - // ext: Object [optional] - if (schainObject.hasOwnProperty('ext')) { - if (!isPlainObject(schainObject.ext)) { - appendFailMsg(`schain.config.ext` + shouldBeAnObject); - } - } - - // nodes: Array of objects - if (!isArray(schainObject.nodes)) { - appendFailMsg(`schain.config.nodes` + shouldBeAnArray); - printFailMsg(); - if (returnOnError) return false; - } else { - schainObject.nodes.forEach((node, index) => { - // asi: String - if (!isStr(node.asi)) { - appendFailMsg(`schain.config.nodes[${index}].asi` + shouldBeAString); - } - - // sid: String - if (!isStr(node.sid)) { - appendFailMsg(`schain.config.nodes[${index}].sid` + shouldBeAString); - } - - // hp: Integer - if (!isNumber(node.hp) || !isInteger(node.hp)) { - appendFailMsg(`schain.config.nodes[${index}].hp` + shouldBeAnInteger); - } - - // rid: String [Optional] - if (node.hasOwnProperty('rid')) { - if (!isStr(node.rid)) { - appendFailMsg(`schain.config.nodes[${index}].rid` + shouldBeAString); - } - } - - // name: String [Optional] - if (node.hasOwnProperty('name')) { - if (!isStr(node.name)) { - appendFailMsg(`schain.config.nodes[${index}].name` + shouldBeAString); - } - } - - // domain: String [Optional] - if (node.hasOwnProperty('domain')) { - if (!isStr(node.domain)) { - appendFailMsg(`schain.config.nodes[${index}].domain` + shouldBeAString); - } - } - - // ext: Object [Optional] - if (node.hasOwnProperty('ext')) { - if (!isPlainObject(node.ext)) { - appendFailMsg(`schain.config.nodes[${index}].ext` + shouldBeAnObject); - } - } - }); - } - - if (failMsg.length > 0) { - printFailMsg(); - if (returnOnError) { - return false; - } - } - - return true; -} - -export function isValidSchainConfig(schainObject) { - if (schainObject === undefined) { - return false; - } - if (!isPlainObject(schainObject)) { - logError(schainErrorPrefix + 'the following schain config will not be used as schain is not an object.', schainObject); - return false; - } - return true; -} - -function handleSetConfigFlag(config) { - // Calculate skipValidation from the FPD config - if (config && typeof config === 'object') { - skipValidation = config.skipValidations !== false; - } -} - -function resolveSchainConfig(schainObject, bidder) { - if (isValidSchainConfig(schainObject)) { - if (skipValidation) { - // Skip validation if skipValidations is true (default) - return schainObject.config; - } else { - // Perform strict validation if skipValidations is false - if (isSchainObjectValid(schainObject.config, true)) { - return schainObject.config; - } else { - logError(schainErrorPrefix + `due to validation failure, this schain config will not be passed to bidder '${bidder}'. See above error for details.`); - } - } - } - return null; -} - -export function makeBidRequestsHook(fn, bidderRequests) { - function getSchainForBidder(bidder) { - let bidderSchain = bidderConfigs[bidder] && bidderConfigs[bidder].schain; - return bidderSchain || globalSchainConfig; - } - - const globalSchainConfig = config.getConfig('schain'); - const bidderConfigs = config.getBidderConfig(); - - bidderRequests.forEach(bidderRequest => { - let bidder = bidderRequest.bidderCode; - let schainConfig = getSchainForBidder(bidder); - - bidderRequest.bids.forEach(bid => { - let result = resolveSchainConfig(schainConfig, bidder); - if (result) { - // Initialize ortb2 object if it doesn't exist - if (!bid.ortb2) { - bid.ortb2 = {}; - } - // Initialize source object if it doesn't exist - if (!bid.ortb2.source) { - bid.ortb2.source = {}; - } - // Set the schain in ortb2.source.schain - bid.ortb2.source.schain = deepClone(result); - } - }); - }); - - fn(bidderRequests); -} - -export function init() { - adapterManager.makeBidRequests.after(makeBidRequestsHook); -} - -init() - -export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) { - if (!deepAccess(ortbRequest, 'source.ext.schain')) { - // Look for schain in the new location: ortb2.source.schain - const schain = deepAccess(context, 'bidRequests.0.ortb2.source.schain'); - if (schain) { - deepSetValue(ortbRequest, 'source.ext.schain', schain); - } - } -} - -registerOrtbProcessor({type: REQUEST, name: 'sourceExtSchain', fn: setOrtbSourceExtSchain}); - -// handler to read the skipValidation flag -config.getConfig('firstPartyData', config => handleSetConfigFlag(config.firstPartyData)); +// import { enrichFPD } from "../src/fpd/enrichment"; + +// enrichFPD.before(enrichFPDHook); + +// function enrichFPDHook(next, fpd) { +// console.log("Azzi enrichFpdHook outside >> ",fpd); +// return next(fpd.then(ortb2 => { +// console.log("Azzi enrichFpdHook inside >> ",ortb2); +// return ortb2; +// })) +// } + +// import {config} from '../src/config.js'; +// import adapterManager from '../src/adapterManager.js'; +// import { +// deepAccess, +// deepClone, +// deepSetValue, +// isArray, +// isInteger, +// isNumber, +// isPlainObject, +// isStr, +// logError, +// logWarn +// } from '../src/utils.js'; +// import {registerOrtbProcessor, REQUEST} from '../src/pbjsORTB.js'; + +// // https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md + +// const schainErrorPrefix = 'Invalid schain object found: '; +// const shouldBeAString = ' should be a string'; +// const shouldBeAnInteger = ' should be an Integer'; +// const shouldBeAnObject = ' should be an object'; +// const shouldBeAnArray = ' should be an Array'; +// let skipValidation = true; // Default to true (skip validation ) + + +// // validate the supply chain object +// export function isSchainObjectValid(schainObject, returnOnError) { +// let failPrefix = 'Detected something wrong within an schain config:'; +// let failMsg = ''; + +// function appendFailMsg(msg) { +// failMsg += '\n' + msg; +// } + +// function printFailMsg() { +// if (returnOnError === true) { +// logError(failPrefix, schainObject, failMsg); +// } else { +// logWarn(failPrefix, schainObject, failMsg); +// } +// } + +// if (!isPlainObject(schainObject)) { +// appendFailMsg(`schain.config` + shouldBeAnObject); +// printFailMsg(); +// if (returnOnError) return false; +// } + +// // complete: Integer +// if (!isNumber(schainObject.complete) || !isInteger(schainObject.complete)) { +// appendFailMsg(`schain.config.complete` + shouldBeAnInteger); +// } + +// // ver: String +// if (!isStr(schainObject.ver)) { +// appendFailMsg(`schain.config.ver` + shouldBeAString); +// } + +// // ext: Object [optional] +// if (schainObject.hasOwnProperty('ext')) { +// if (!isPlainObject(schainObject.ext)) { +// appendFailMsg(`schain.config.ext` + shouldBeAnObject); +// } +// } + +// // nodes: Array of objects +// if (!isArray(schainObject.nodes)) { +// appendFailMsg(`schain.config.nodes` + shouldBeAnArray); +// printFailMsg(); +// if (returnOnError) return false; +// } else { +// schainObject.nodes.forEach((node, index) => { +// // asi: String +// if (!isStr(node.asi)) { +// appendFailMsg(`schain.config.nodes[${index}].asi` + shouldBeAString); +// } + +// // sid: String +// if (!isStr(node.sid)) { +// appendFailMsg(`schain.config.nodes[${index}].sid` + shouldBeAString); +// } + +// // hp: Integer +// if (!isNumber(node.hp) || !isInteger(node.hp)) { +// appendFailMsg(`schain.config.nodes[${index}].hp` + shouldBeAnInteger); +// } + +// // rid: String [Optional] +// if (node.hasOwnProperty('rid')) { +// if (!isStr(node.rid)) { +// appendFailMsg(`schain.config.nodes[${index}].rid` + shouldBeAString); +// } +// } + +// // name: String [Optional] +// if (node.hasOwnProperty('name')) { +// if (!isStr(node.name)) { +// appendFailMsg(`schain.config.nodes[${index}].name` + shouldBeAString); +// } +// } + +// // domain: String [Optional] +// if (node.hasOwnProperty('domain')) { +// if (!isStr(node.domain)) { +// appendFailMsg(`schain.config.nodes[${index}].domain` + shouldBeAString); +// } +// } + +// // ext: Object [Optional] +// if (node.hasOwnProperty('ext')) { +// if (!isPlainObject(node.ext)) { +// appendFailMsg(`schain.config.nodes[${index}].ext` + shouldBeAnObject); +// } +// } +// }); +// } + +// if (failMsg.length > 0) { +// printFailMsg(); +// if (returnOnError) { +// return false; +// } +// } + +// return true; +// } + +// export function isValidSchainConfig(schainObject) { +// if (schainObject === undefined) { +// return false; +// } +// if (!isPlainObject(schainObject)) { +// logError(schainErrorPrefix + 'the following schain config will not be used as schain is not an object.', schainObject); +// return false; +// } +// return true; +// } + +// function handleSetConfigFlag(config) { +// // Calculate skipValidation from the FPD config +// if (config && typeof config === 'object') { +// skipValidation = config.skipValidations !== false; +// } +// } + +// function resolveSchainConfig(schainObject, bidder) { +// if (isValidSchainConfig(schainObject)) { +// if (skipValidation) { +// // Skip validation if skipValidations is true (default) +// return schainObject.config; +// } else { +// // Perform strict validation if skipValidations is false +// if (isSchainObjectValid(schainObject.config, true)) { +// return schainObject.config; +// } else { +// logError(schainErrorPrefix + `due to validation failure, this schain config will not be passed to bidder '${bidder}'. See above error for details.`); +// } +// } +// } +// return null; +// } + +// export function makeBidRequestsHook(fn, bidderRequests) { +// function getSchainForBidder(bidder) { +// let bidderSchain = bidderConfigs[bidder] && bidderConfigs[bidder].schain; +// return bidderSchain || globalSchainConfig; +// } + +// const globalSchainConfig = config.getConfig('schain'); +// const bidderConfigs = config.getBidderConfig(); + +// bidderRequests.forEach(bidderRequest => { +// let bidder = bidderRequest.bidderCode; +// let schainConfig = getSchainForBidder(bidder); + +// bidderRequest.bids.forEach(bid => { +// let result = resolveSchainConfig(schainConfig, bidder); +// if (result) { +// // Initialize ortb2 object if it doesn't exist +// if (!bid.ortb2) { +// bid.ortb2 = {}; +// } +// // Initialize source object if it doesn't exist +// if (!bid.ortb2.source) { +// bid.ortb2.source = {}; +// } +// // Set the schain in ortb2.source.schain +// bid.ortb2.source.schain = deepClone(result); +// } +// }); +// }); + +// fn(bidderRequests); +// } + +// export function init() { +// adapterManager.makeBidRequests.after(makeBidRequestsHook); +// } + +// init() + +// export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) { +// if (!deepAccess(ortbRequest, 'source.ext.schain')) { +// // Look for schain in the new location: ortb2.source.schain +// const schain = deepAccess(context, 'bidRequests.0.ortb2.source.schain'); +// if (schain) { +// deepSetValue(ortbRequest, 'source.ext.schain', schain); +// } +// } +// } + +// registerOrtbProcessor({type: REQUEST, name: 'sourceExtSchain', fn: setOrtbSourceExtSchain}); + +// // handler to read the skipValidation flag +// config.getConfig('firstPartyData', config => handleSetConfigFlag(config.firstPartyData)); diff --git a/modules/validationFpdModule/config.js b/modules/validationFpdModule/config.js index c87265fa1df..89201f55ed4 100644 --- a/modules/validationFpdModule/config.js +++ b/modules/validationFpdModule/config.js @@ -145,5 +145,38 @@ export const ORTB_MAP = { type: TYPES.object, isArray: true, childType: TYPES.string + }, + source: { + type: TYPES.object, + children: { + ext: { + type: TYPES.object, + isArray: false + }, + schain: { + type: TYPES.object, + children: { + complete: { type: TYPES.number }, + ver: { type: TYPES.string }, + nodes: { + type: TYPES.object, + isArray: true, + childType: TYPES.object, + required: ['asi', 'sid', 'hp'], + children: { + asi: { type: TYPES.string }, + sid: { type: TYPES.string }, + hp: { type: TYPES.number }, + rid: { type: TYPES.string }, + name: { type: TYPES.string }, + domain: { type: TYPES.string }, + ext: { type: TYPES.object } + } + }, + ext: { type: TYPES.object } + }, + required: ['complete', 'nodes', 'ver'] + } + } } } From daecbfb8e755af90ce18f1f4fb789b73b9ef40ea Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Wed, 21 May 2025 12:13:52 +0530 Subject: [PATCH 05/20] Removed separate schain files --- integrationExamples/schain.html | 212 ----------------------------- modules/schain.js | 228 -------------------------------- modules/schain.md | 51 ------- 3 files changed, 491 deletions(-) delete mode 100644 integrationExamples/schain.html delete mode 100644 modules/schain.js delete mode 100644 modules/schain.md diff --git a/integrationExamples/schain.html b/integrationExamples/schain.html deleted file mode 100644 index b0514114e1f..00000000000 --- a/integrationExamples/schain.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
-
-

Latest News Headlines

- -
-

Global Tech Summit Announces Breakthrough in AI Development

-

The annual Global Tech Summit concluded yesterday with a major announcement from leading researchers who have developed a new neural network architecture that promises to reduce computational requirements by up to 40% while maintaining accuracy. Industry leaders are already planning implementations that could revolutionize mobile AI applications.

-

"This represents a significant leap forward in making advanced AI accessible on everyday devices," said Dr. Sarah Chen, lead researcher at the Institute for Advanced Computing. "We expect to see this technology in consumer products within the next 18 months."

-

Published: April 15, 2025 | Category: Technology

-
- -
-

Climate Agreement Reaches Milestone as 150 Nations Commit to New Emissions Targets

-

In a historic development for environmental policy, 150 nations have signed onto the expanded Global Climate Accord, committing to more aggressive emissions reduction targets by 2035. The agreement includes significant financial commitments to support developing nations in their transition to renewable energy sources.

-

Environmental experts have praised the move but caution that implementation will be the true test. "The targets are ambitious and necessary," noted climate scientist Dr. James Rivera. "But the real challenge lies in the policy changes required to meet these goals."

-

Published: April 14, 2025 | Category: Environment

-
-
- - - - \ No newline at end of file diff --git a/modules/schain.js b/modules/schain.js deleted file mode 100644 index 13927580b4e..00000000000 --- a/modules/schain.js +++ /dev/null @@ -1,228 +0,0 @@ -// import { enrichFPD } from "../src/fpd/enrichment"; - -// enrichFPD.before(enrichFPDHook); - -// function enrichFPDHook(next, fpd) { -// console.log("Azzi enrichFpdHook outside >> ",fpd); -// return next(fpd.then(ortb2 => { -// console.log("Azzi enrichFpdHook inside >> ",ortb2); -// return ortb2; -// })) -// } - -// import {config} from '../src/config.js'; -// import adapterManager from '../src/adapterManager.js'; -// import { -// deepAccess, -// deepClone, -// deepSetValue, -// isArray, -// isInteger, -// isNumber, -// isPlainObject, -// isStr, -// logError, -// logWarn -// } from '../src/utils.js'; -// import {registerOrtbProcessor, REQUEST} from '../src/pbjsORTB.js'; - -// // https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md - -// const schainErrorPrefix = 'Invalid schain object found: '; -// const shouldBeAString = ' should be a string'; -// const shouldBeAnInteger = ' should be an Integer'; -// const shouldBeAnObject = ' should be an object'; -// const shouldBeAnArray = ' should be an Array'; -// let skipValidation = true; // Default to true (skip validation ) - - -// // validate the supply chain object -// export function isSchainObjectValid(schainObject, returnOnError) { -// let failPrefix = 'Detected something wrong within an schain config:'; -// let failMsg = ''; - -// function appendFailMsg(msg) { -// failMsg += '\n' + msg; -// } - -// function printFailMsg() { -// if (returnOnError === true) { -// logError(failPrefix, schainObject, failMsg); -// } else { -// logWarn(failPrefix, schainObject, failMsg); -// } -// } - -// if (!isPlainObject(schainObject)) { -// appendFailMsg(`schain.config` + shouldBeAnObject); -// printFailMsg(); -// if (returnOnError) return false; -// } - -// // complete: Integer -// if (!isNumber(schainObject.complete) || !isInteger(schainObject.complete)) { -// appendFailMsg(`schain.config.complete` + shouldBeAnInteger); -// } - -// // ver: String -// if (!isStr(schainObject.ver)) { -// appendFailMsg(`schain.config.ver` + shouldBeAString); -// } - -// // ext: Object [optional] -// if (schainObject.hasOwnProperty('ext')) { -// if (!isPlainObject(schainObject.ext)) { -// appendFailMsg(`schain.config.ext` + shouldBeAnObject); -// } -// } - -// // nodes: Array of objects -// if (!isArray(schainObject.nodes)) { -// appendFailMsg(`schain.config.nodes` + shouldBeAnArray); -// printFailMsg(); -// if (returnOnError) return false; -// } else { -// schainObject.nodes.forEach((node, index) => { -// // asi: String -// if (!isStr(node.asi)) { -// appendFailMsg(`schain.config.nodes[${index}].asi` + shouldBeAString); -// } - -// // sid: String -// if (!isStr(node.sid)) { -// appendFailMsg(`schain.config.nodes[${index}].sid` + shouldBeAString); -// } - -// // hp: Integer -// if (!isNumber(node.hp) || !isInteger(node.hp)) { -// appendFailMsg(`schain.config.nodes[${index}].hp` + shouldBeAnInteger); -// } - -// // rid: String [Optional] -// if (node.hasOwnProperty('rid')) { -// if (!isStr(node.rid)) { -// appendFailMsg(`schain.config.nodes[${index}].rid` + shouldBeAString); -// } -// } - -// // name: String [Optional] -// if (node.hasOwnProperty('name')) { -// if (!isStr(node.name)) { -// appendFailMsg(`schain.config.nodes[${index}].name` + shouldBeAString); -// } -// } - -// // domain: String [Optional] -// if (node.hasOwnProperty('domain')) { -// if (!isStr(node.domain)) { -// appendFailMsg(`schain.config.nodes[${index}].domain` + shouldBeAString); -// } -// } - -// // ext: Object [Optional] -// if (node.hasOwnProperty('ext')) { -// if (!isPlainObject(node.ext)) { -// appendFailMsg(`schain.config.nodes[${index}].ext` + shouldBeAnObject); -// } -// } -// }); -// } - -// if (failMsg.length > 0) { -// printFailMsg(); -// if (returnOnError) { -// return false; -// } -// } - -// return true; -// } - -// export function isValidSchainConfig(schainObject) { -// if (schainObject === undefined) { -// return false; -// } -// if (!isPlainObject(schainObject)) { -// logError(schainErrorPrefix + 'the following schain config will not be used as schain is not an object.', schainObject); -// return false; -// } -// return true; -// } - -// function handleSetConfigFlag(config) { -// // Calculate skipValidation from the FPD config -// if (config && typeof config === 'object') { -// skipValidation = config.skipValidations !== false; -// } -// } - -// function resolveSchainConfig(schainObject, bidder) { -// if (isValidSchainConfig(schainObject)) { -// if (skipValidation) { -// // Skip validation if skipValidations is true (default) -// return schainObject.config; -// } else { -// // Perform strict validation if skipValidations is false -// if (isSchainObjectValid(schainObject.config, true)) { -// return schainObject.config; -// } else { -// logError(schainErrorPrefix + `due to validation failure, this schain config will not be passed to bidder '${bidder}'. See above error for details.`); -// } -// } -// } -// return null; -// } - -// export function makeBidRequestsHook(fn, bidderRequests) { -// function getSchainForBidder(bidder) { -// let bidderSchain = bidderConfigs[bidder] && bidderConfigs[bidder].schain; -// return bidderSchain || globalSchainConfig; -// } - -// const globalSchainConfig = config.getConfig('schain'); -// const bidderConfigs = config.getBidderConfig(); - -// bidderRequests.forEach(bidderRequest => { -// let bidder = bidderRequest.bidderCode; -// let schainConfig = getSchainForBidder(bidder); - -// bidderRequest.bids.forEach(bid => { -// let result = resolveSchainConfig(schainConfig, bidder); -// if (result) { -// // Initialize ortb2 object if it doesn't exist -// if (!bid.ortb2) { -// bid.ortb2 = {}; -// } -// // Initialize source object if it doesn't exist -// if (!bid.ortb2.source) { -// bid.ortb2.source = {}; -// } -// // Set the schain in ortb2.source.schain -// bid.ortb2.source.schain = deepClone(result); -// } -// }); -// }); - -// fn(bidderRequests); -// } - -// export function init() { -// adapterManager.makeBidRequests.after(makeBidRequestsHook); -// } - -// init() - -// export function setOrtbSourceExtSchain(ortbRequest, bidderRequest, context) { -// if (!deepAccess(ortbRequest, 'source.ext.schain')) { -// // Look for schain in the new location: ortb2.source.schain -// const schain = deepAccess(context, 'bidRequests.0.ortb2.source.schain'); -// if (schain) { -// deepSetValue(ortbRequest, 'source.ext.schain', schain); -// } -// } -// } - -// registerOrtbProcessor({type: REQUEST, name: 'sourceExtSchain', fn: setOrtbSourceExtSchain}); - -// // handler to read the skipValidation flag -// config.getConfig('firstPartyData', config => handleSetConfigFlag(config.firstPartyData)); diff --git a/modules/schain.md b/modules/schain.md deleted file mode 100644 index f43cf0f0d07..00000000000 --- a/modules/schain.md +++ /dev/null @@ -1,51 +0,0 @@ -# schain module - -Aggregators who manage Prebid wrappers on behalf of multiple publishers and handle payment on behalf of the publishers -need to declare their intermediary status in the Supply Chain Object. As the Supply Chain Object spec prohibits SSPs from adding -upstream intermediaries, Prebid requests in this case need to come with the schain information. In this use case, it's cumbersome -to have every bidder in the wrapper separately configured the same schain information. - -Refer: -- https://iabtechlab.com/sellers-json/ -- https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md - -## Sample code for passing the schain object -``` -pbjs.setConfig( { - "schain": { - "validation": "strict", - "config": { - "ver":"1.0", - "complete": 1, - "nodes": [ - { - "asi":"indirectseller.com", - "sid":"00001", - "hp":1 - }, - - { - "asi":"indirectseller-2.com", - "sid":"00002", - "hp":1 - } - ] - } - } -}); -``` - -## Workflow -The schain module is not enabled by default as it may not be necessary for all publishers. -If required, schain module can be included as following -``` - $ gulp build --modules=schain,pubmaticBidAdapter,openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter -``` -The schain module will validate the schain object passed using pbjs.setConfig API. -If the schain object is valid then it will be passed on to bidders/adapters in ```validBidRequests[].schain``` -You may refer pubmaticBidAdapter implementaion for the same. - -## Validation modes -- ```strict```: It is the default validation mode. In this mode, schain object will not be passed to adapters if it is invalid. Errors are thrown for invalid schain object. -- ```relaxed```: In this mode, errors are thrown for an invalid schain object but the invalid schain object is still passed to adapters. -- ```off```: In this mode, no validations are performed and schain object is passed as is to adapters. From 7c2051c6090d0fb445d4b4ec30bec8d10e98ccf2 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Wed, 21 May 2025 12:15:14 +0530 Subject: [PATCH 06/20] Removed testing parameters --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 239bb995ef5..a3c97682d5b 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -15,7 +15,7 @@ import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, PREBID_NATIVE_DATA_KEYS_TO_ORTB const BIDDER_CODE = 'pubmatic'; const LOG_WARN_PREFIX = 'PubMatic: '; -const ENDPOINT = 'https://hbopenbid.pubmatic.com:8443/translator?source=prebid-client'; +const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=prebid-client'; const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/user_sync.html?kdntuid=1&p='; const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p='; const DEFAULT_CURRENCY = 'USD'; From fd6d280992434c0ebf7be8f7df3d300543cb786f Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Wed, 21 May 2025 15:15:21 +0530 Subject: [PATCH 07/20] Updated test cases --- test/spec/modules/BTBidAdapter_spec.js | 1 - test/spec/modules/blastoBidAdapter_spec.js | 1 - test/spec/modules/bridgeuppBidAdapter_spec.js | 2 +- .../spec/modules/conversantBidAdapter_spec.js | 15 +- test/spec/modules/criteoBidAdapter_spec.js | 24 +- test/spec/modules/escalaxBidAdapter_spec.js | 1 - .../modules/improvedigitalBidAdapter_spec.js | 22 +- test/spec/modules/openxBidAdapter_spec.js | 16 +- .../spec/modules/pulsepointBidAdapter_spec.js | 32 +- test/spec/modules/r2b2BidAdapter_spec.js | 1 - test/spec/modules/rubiconBidAdapter_spec.js | 3 +- test/spec/modules/schain_spec.js | 557 ------------------ test/spec/modules/silvermobBidAdapter_spec.js | 1 - test/spec/modules/smaatoBidAdapter_spec.js | 1 - .../spec/modules/stackadaptBidAdapter_spec.js | 11 +- .../modules/trafficgateBidAdapter_spec.js | 14 +- test/spec/ortbConverter/schain_spec.js | 33 -- 17 files changed, 114 insertions(+), 621 deletions(-) delete mode 100644 test/spec/modules/schain_spec.js delete mode 100644 test/spec/ortbConverter/schain_spec.js diff --git a/test/spec/modules/BTBidAdapter_spec.js b/test/spec/modules/BTBidAdapter_spec.js index 2ec0acc424e..18f99929037 100644 --- a/test/spec/modules/BTBidAdapter_spec.js +++ b/test/spec/modules/BTBidAdapter_spec.js @@ -12,7 +12,6 @@ import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; import 'modules/tcfControl.js'; import 'modules/gppControl_usnat.js'; -import 'modules/schain.js'; describe('BT Bid Adapter', () => { const ENDPOINT_URL = 'https://pbs.btloader.com/openrtb2/auction'; diff --git a/test/spec/modules/blastoBidAdapter_spec.js b/test/spec/modules/blastoBidAdapter_spec.js index 2efdd5ad286..7a2c94f3b14 100644 --- a/test/spec/modules/blastoBidAdapter_spec.js +++ b/test/spec/modules/blastoBidAdapter_spec.js @@ -13,7 +13,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; const SIMPLE_BID_REQUEST = { bidder: 'blasto', diff --git a/test/spec/modules/bridgeuppBidAdapter_spec.js b/test/spec/modules/bridgeuppBidAdapter_spec.js index 89164b1948f..40d63321480 100644 --- a/test/spec/modules/bridgeuppBidAdapter_spec.js +++ b/test/spec/modules/bridgeuppBidAdapter_spec.js @@ -261,7 +261,7 @@ describe('bridgeuppBidAdapter_spec', function () { }, ]; const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({...bidderRequest, ortb2})).data; - expect(ortbRequest.source.schain).to.deep.equal(expectedSchain); + expect(ortbRequest.source.ext.schain).to.deep.equal(expectedSchain); expect(ortbRequest.source.pchain).to.equal('sonarads'); }); diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index 3cfb56d1135..e0d0f831fa0 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -10,7 +10,6 @@ import 'modules/userId/index.js'; // handles eids import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; // handles schain import {hook} from '../../../src/hook.js' import {BANNER} from '../../../src/mediaTypes'; @@ -451,9 +450,21 @@ describe('Conversant adapter tests', function() { it('Verify supply chain data', () => { const bidderRequest = {refererInfo: {page: 'http://test.com?a=b&c=123'}}; const schain = {complete: 1, ver: '1.0', nodes: [{asi: 'bidderA.com', sid: '00001', hp: 1}]}; + + // Add schain to bidderRequest + bidderRequest.ortb2 = { + source: { + ext: {schain: schain} + } + }; + const bidsWithSchain = bidRequests.map((bid) => { return Object.assign({ - ortb2: {source: {schain: schain}} + ortb2: { + source: { + ext: {schain: schain} + } + } }, bid); }); const request = spec.buildRequests(bidsWithSchain, bidderRequest); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index fb8ee1092ba..4873fd75be3 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -10,7 +10,7 @@ import 'modules/userId/index.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; -import 'modules/schain.js'; + import {hook} from '../../../src/hook'; describe('The Criteo bidding adapter', function () { @@ -1219,14 +1219,18 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.regs.ext.dsa).to.deep.equal(dsa); }); - it('should properly build a request with schain object', async function () { + it('should properly build a request with schain object', function () { const expectedSchain = { someProperty: 'someValue' }; const bidRequests = [ { bidder: 'criteo', - ortb2: {source: {schain: expectedSchain}}, + ortb2: { + source: { + ext: {schain: expectedSchain} + } + }, adUnitCode: 'bid-123', mediaTypes: { banner: { @@ -1238,9 +1242,19 @@ describe('The Criteo bidding adapter', function () { }, }, ]; + + // Create a modified bidderRequest with schain + const modifiedBidderRequest = { + ...bidderRequest, + ortb2: { + source: { + ext: {schain: expectedSchain} + } + } + }; - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; - expect(ortbRequest.source.ext.schain).to.equal(expectedSchain); + const ortbRequest = spec.buildRequests(bidRequests, modifiedBidderRequest).data; + expect(ortbRequest.source.ext.schain).to.deep.equal(expectedSchain); }); it('should properly build a request with bcat field', async function () { diff --git a/test/spec/modules/escalaxBidAdapter_spec.js b/test/spec/modules/escalaxBidAdapter_spec.js index 6238e6cb208..3e539cc1bdc 100644 --- a/test/spec/modules/escalaxBidAdapter_spec.js +++ b/test/spec/modules/escalaxBidAdapter_spec.js @@ -12,7 +12,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; const SIMPLE_BID_REQUEST = { bidder: 'escalax', diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 5b9542b62c2..c7c074795f0 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -12,7 +12,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; import {decorateAdUnitsWithNativeParams} from '../../../src/native.js'; import {hook} from '../../../src/hook.js'; import {addFPDToBidderRequest} from '../../helpers/fpd.js'; @@ -553,8 +552,25 @@ describe('Improve Digital Adapter Tests', function () { it('should add schain', function () { const schain = '{"ver":"1.0","complete":1,"nodes":[{"asi":"headerlift.com","sid":"xyz","hp":1}]}'; const bidRequest = Object.assign({}, simpleBidRequest); - bidRequest.ortb2 = {source: {schain: schain}}; - const request = spec.buildRequests([bidRequest], bidderRequestReferrer)[0]; + + // Add schain to both locations in the bid + bidRequest.ortb2 = { + source: { + ext: {schain: schain} + } + }; + + // Add schain to bidderRequest as well + const modifiedBidderRequest = { + ...bidderRequestReferrer, + ortb2: { + source: { + ext: {schain: schain} + } + } + }; + + const request = spec.buildRequests([bidRequest], modifiedBidderRequest)[0]; const payload = JSON.parse(request.data); expect(payload.source.ext.schain).to.equal(schain); }); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index ce4562c9bb7..ead908b531b 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -12,7 +12,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; import 'modules/paapi.js'; import {deepClone} from 'src/utils.js'; @@ -1106,13 +1105,24 @@ describe('OpenxRtbAdapter', function () { bidId: 'test-bid-id-1', bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1', - ortb2: {source: {schain: schainConfig}} + ortb2: {source: { + schain: schainConfig, + ext: {schain: schainConfig} + }} }]; + + // Add schain to mockBidderRequest as well + mockBidderRequest.ortb2 = { + source: { + schain: schainConfig, + ext: {schain: schainConfig} + } + }; }); it('should send a supply chain object', function () { const request = spec.buildRequests(bidRequests, mockBidderRequest); - expect(request[0].data.source.ext.schain).to.equal(schainConfig); + expect(request[0].data.source.ext.schain).to.deep.equal(schainConfig); }); it('should send the supply chain object with the right version', function () { diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 8f0c272916c..81b6b1b20ca 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -6,7 +6,6 @@ import {deepClone} from '../../../src/utils'; import 'modules/consentManagementTcf'; import 'modules/consentManagementUsp'; import 'modules/userId/index'; -import 'modules/schain'; describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ @@ -136,7 +135,7 @@ describe('PulsePoint Adapter Tests', function () { bidfloor: 1.5, badv: ['cocacola.com', 'lays.com'] }, - ortb2: {source: {schain: { + ortb2: {source: {ext: {schain: { 'ver': '1.0', 'complete': 1, 'nodes': [ @@ -149,7 +148,7 @@ describe('PulsePoint Adapter Tests', function () { 'domain': 'publisher.com' } ] - }}} + }}}} }]; const bidderRequest = { @@ -467,8 +466,31 @@ describe('PulsePoint Adapter Tests', function () { expect(ortbRequest.imp[0].ext).to.be.undefined; }); - it('Verify schain parameters', async function () { - const request = spec.buildRequests(schainParamsSlotConfig, await addFPDToBidderRequest(bidderRequest)); + it('Verify schain parameters', function () { + const modifiedBidderRequest = { + ...bidderRequest, + ortb2: { + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + } + } + } + } + }; + const request = spec.buildRequests(schainParamsSlotConfig, modifiedBidderRequest); const ortbRequest = request.data; expect(ortbRequest).to.not.equal(null); expect(ortbRequest.source).to.not.equal(null); diff --git a/test/spec/modules/r2b2BidAdapter_spec.js b/test/spec/modules/r2b2BidAdapter_spec.js index 8272297797c..b3296b2c1c7 100644 --- a/test/spec/modules/r2b2BidAdapter_spec.js +++ b/test/spec/modules/r2b2BidAdapter_spec.js @@ -1,7 +1,6 @@ import {expect} from 'chai'; import {spec, internal as r2b2, internal} from 'modules/r2b2BidAdapter.js'; import * as utils from '../../../src/utils'; -import 'modules/schain.js'; import 'modules/userId/index.js'; function encodePlacementIds (ids) { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0ee9d4b8793..11ace2f9ecf 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -12,7 +12,6 @@ import { import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; import {find} from 'src/polyfill.js'; -import 'modules/schain.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; import 'modules/userId/index.js'; @@ -4673,7 +4672,7 @@ describe('the rubicon adapter', function () { it('should copy the schain JSON to to bid.source.ext.schain', () => { const bidderRequest = createVideoBidderRequest(); const schain = getSupplyChainConfig(); - bidderRequest.bids[0].ortb2.source.schain = schain; + bidderRequest.bids[0].ortb2.source.ext = { schain: schain }; const request = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request[0].data.source.ext.schain).to.deep.equal(schain); }); diff --git a/test/spec/modules/schain_spec.js b/test/spec/modules/schain_spec.js deleted file mode 100644 index ee7712ed9be..00000000000 --- a/test/spec/modules/schain_spec.js +++ /dev/null @@ -1,557 +0,0 @@ -import { isValidSchainConfig, isSchainObjectValid, makeBidRequestsHook } from '../../../modules/schain.js'; -import { deepClone } from '../../../src/utils.js'; -import {config} from '../../../src/config.js'; -import { expect } from 'chai'; - -describe('#isValidSchainConfig: module config validation', function() { - it('if config is undefined or not an objct then return false', function() { - expect(isValidSchainConfig()).to.false; - expect(isValidSchainConfig('')).to.false; - expect(isValidSchainConfig([])).to.false; - expect(isValidSchainConfig(12)).to.false; - expect(isValidSchainConfig(3.14)).to.false; - }) - - it('if config is an object then return true', function() { - expect(isValidSchainConfig({})).to.true; - }) -}); - -describe('#isSchainObjectValid: schain object validation', function() { - let schainConfig; - - beforeEach(function() { - schainConfig = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 2 - } - ] - }; - }); - - it('Return true for correct config', function() { - expect(isSchainObjectValid(schainConfig, true)).to.true; - }); - - it('Return false for string config', function() { - schainConfig = JSON.stringify(schainConfig); - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if complete param is not an Integer', function() { - schainConfig.complete = 1; // integer - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.complete = '1'; // string - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.complete = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.complete = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.complete; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.complete = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.complete = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if version param is not a String', function() { - schainConfig.ver = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ver = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ver = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.ver; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ver = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ver = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if ext param is not an Object', function() { - schainConfig.ext = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ext = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ext = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.true; - delete schainConfig.ext; // undefined // param is optional thus this will result true - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.ext = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.ext = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes param is not an Array', function() { - // by default schainConfig.nodes is array - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].asi is not a String', function() { - schainConfig.nodes[0].asi = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].asi = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].asi = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[0].asi; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].asi = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].asi = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].sid is not a String', function() { - schainConfig.nodes[1].sid = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].sid = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].sid = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[0].sid; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].sid = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].sid = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].hp is not an Integer', function() { - schainConfig.nodes[0].hp = '1'; // string - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].hp = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].hp = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[0].hp; // undefined - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].hp = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].hp = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].rid is not a String', function() { - schainConfig.nodes[1].rid = 'rid value'; // string - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[1].rid = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].rid = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].rid = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[1].rid; // undefined // param is optional thus this will result true - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[1].rid = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].rid = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].name is not a String', function() { - schainConfig.nodes[0].name = 'name value'; // string - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[0].name = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].name = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].name = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[0].name; // undefined // param is optional thus this will result true - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[0].name = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].name = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].domain is not a String', function() { - schainConfig.nodes[1].domain = 'domain value'; // string - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[1].domain = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].domain = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].domain = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.false; - delete schainConfig.nodes[1].domain; // undefined // param is optional thus this will result true - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[1].domain = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[1].domain = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Returns false if nodes[].ext param is not an Object', function() { - schainConfig.nodes[0].ext = 1; // Integer - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].ext = 1.1; // float - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].ext = {}; // object - expect(isSchainObjectValid(schainConfig, true)).to.true; - delete schainConfig.nodes[0].ext; // undefined // param is optional thus this will result true - expect(isSchainObjectValid(schainConfig, true)).to.true; - schainConfig.nodes[0].ext = true; // boolean - expect(isSchainObjectValid(schainConfig, true)).to.false; - schainConfig.nodes[0].ext = []; // array - expect(isSchainObjectValid(schainConfig, true)).to.false; - }); - - it('Relaxed mode: Returns true even for invalid config if second argument is set to false', function() { - schainConfig = { - 'ver': 1.0, // invalid - 'complete': '1', // invalid - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': 1, // invalid - 'hp': '1' // invalid - }, - - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 2 - } - ] - }; - expect(isSchainObjectValid(schainConfig, false)).to.true; - - schainConfig = {}; - expect(isSchainObjectValid(schainConfig, false)).to.true; - }) -}); - -describe('#makeBidRequestsHook', function() { - const bidderRequests = [ - { - 'bidderCode': 'rubicon', - 'bids': [ - { - 'bidder': 'rubicon', - 'params': { - 'accountId': 14062, - 'siteId': 70608, - 'zoneId': 498816 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '2e6d166eb869c3' - - } - ], - }, - { - 'bidderCode': 'districtm', - 'bids': [ - { - 'bidder': 'districtm', - 'params': { - 'placementId': 13144370 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '41cdeddf7b6905' - } - ], - }, - { - 'bidderCode': 'appnexus', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': 13144370 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250], [300, 600]] - } - }, - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '626cc7f1c4ccfc' - } - ], - - } - ]; - - const globalSchainConfig = { - 'schain': { - 'config': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 1 - } - ] - } - } - }; - - const goodStrictBidderConfig = { - bidders: ['appnexus'], - config: { - 'schain': { - 'config': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'myoverride1.com', - 'sid': '00001', - 'hp': 1, - 'name': 'node1' - }, - { - 'asi': 'myoverride2.com', - 'sid': '00001', - 'hp': 1, - 'name': 'node2' - } - ] - } - } - } - } - - const badStrictBidderConfig = { - bidders: ['appnexus'], - config: { - 'schain': { - 'config': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'myoverride1.com', - 'sid': 1, - 'hp': 1, - 'name': 342 - }, - { - 'asi': 'myoverride2.com', - 'sid': 2, - 'hp': 1, - 'name': '342' - } - ] - } - } - } - }; - - const goodRelaxedBidderConfig = { - bidders: ['districtm'], - config: { - 'schain': { - 'config': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'myoverride.com', - 'sid': '00001', - 'hp': 1, - 'name': 'goodConfig' - } - ] - } - } - } - }; - - const badRelaxedBidderConfig = { - bidders: ['districtm'], - config: { - 'schain': { - 'config': { - 'ver': 1, - 'complete': 1, - 'nodes': [ - { - 'asi': 'myoverride.com', - 'sid': 1, - 'hp': 1 - } - ] - } - } - } - }; - - beforeEach(function () { - config.setConfig(globalSchainConfig); - }); - - afterEach(function () { - config.resetConfig(); - - config.setBidderConfig({ - bidders: ['districtm'], - config: { - schain: null - } - }); - - config.setBidderConfig({ - bidders: ['appnexus'], - config: { - schain: null - } - }); - }); - - it('should properly read from bidder schain + global schain configs and set in ortb2.source.schain', function() { - function testCallback(bidderRequests) { - // Check for rubicon (using global config) - expect(bidderRequests[0].bids[0].ortb2).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); - - // Check for districtm (using goodRelaxedBidderConfig) - expect(bidderRequests[1].bids[0].ortb2).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source.schain).to.deep.equal(goodRelaxedBidderConfig.config.schain.config); - - // Check for appnexus (using goodStrictBidderConfig) - expect(bidderRequests[2].bids[0].ortb2).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source.schain).to.deep.equal(goodStrictBidderConfig.config.schain.config); - } - - const testBidderRequests = deepClone(bidderRequests); - config.setBidderConfig(goodStrictBidderConfig); - config.setBidderConfig(goodRelaxedBidderConfig); - - // Set skipValidations to false to enable strict validation - config.setConfig({ - firstPartyData: { - skipValidations: false - } - }); - - makeBidRequestsHook(testCallback, testBidderRequests); - }); - - it('should not share the same schain object between different bid requests', (done) => { - config.setBidderConfig(goodStrictBidderConfig); - makeBidRequestsHook((requests) => { - requests[0].bids[0].ortb2.source.schain.field = 'value'; - expect(requests[1].bids[0].ortb2.source.schain.field).to.not.exist; - done(); - }, deepClone(bidderRequests)) - }); - - it('should reject bad config when skipValidations is false', function () { - function testCallback(bidderRequests) { - // Check for rubicon (using global config) - expect(bidderRequests[0].bids[0].ortb2).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); - - // Check for districtm (should not have schain due to validation failure) - expect(bidderRequests[1].bids[0].ortb2).to.not.exist; - - // Check for appnexus (should not have schain due to validation failure) - expect(bidderRequests[2].bids[0].ortb2).to.not.exist; - } - - const testBidderRequests = deepClone(bidderRequests); - config.setBidderConfig(badStrictBidderConfig); - config.setBidderConfig(badRelaxedBidderConfig); - - // Set skipValidations to false to enable strict validation - config.setConfig({ - firstPartyData: { - skipValidations: false - } - }); - - makeBidRequestsHook(testCallback, testBidderRequests); - }); - - it('should accept all configs when skipValidations is true (default)', function () { - function testCallback(bidderRequests) { - // Check for rubicon (using global config) - expect(bidderRequests[0].bids[0].ortb2).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[0].bids[0].ortb2.source.schain).to.deep.equal(globalSchainConfig.schain.config); - - // Check for districtm (should have schain despite validation issues) - expect(bidderRequests[1].bids[0].ortb2).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[1].bids[0].ortb2.source.schain).to.deep.equal(badRelaxedBidderConfig.config.schain.config); - - // Check for appnexus (should have schain despite validation issues) - expect(bidderRequests[2].bids[0].ortb2).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source.schain).to.exist; - expect(bidderRequests[2].bids[0].ortb2.source.schain).to.deep.equal(badStrictBidderConfig.config.schain.config); - } - - const testBidderRequests = deepClone(bidderRequests); - config.setBidderConfig(badStrictBidderConfig); - config.setBidderConfig(badRelaxedBidderConfig); - - // Set skipValidations to true to skip validation (default behavior) - config.setConfig({ - firstPartyData: { - skipValidations: true - } - }); - - makeBidRequestsHook(testCallback, testBidderRequests); - }); -}); diff --git a/test/spec/modules/silvermobBidAdapter_spec.js b/test/spec/modules/silvermobBidAdapter_spec.js index b9bf32462d8..b967efdd9b5 100644 --- a/test/spec/modules/silvermobBidAdapter_spec.js +++ b/test/spec/modules/silvermobBidAdapter_spec.js @@ -13,7 +13,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; const SIMPLE_BID_REQUEST = { bidder: 'silvermob', diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 6d117f829f9..4263ba25589 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -10,7 +10,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; const IMAGE_SYNC_URL = 'https://s.ad.smaato.net/c/?adExInit=p' const IFRAME_SYNC_URL = 'https://s.ad.smaato.net/i/?adExInit=p' diff --git a/test/spec/modules/stackadaptBidAdapter_spec.js b/test/spec/modules/stackadaptBidAdapter_spec.js index 43be0a15ee6..b55bc8d75c9 100644 --- a/test/spec/modules/stackadaptBidAdapter_spec.js +++ b/test/spec/modules/stackadaptBidAdapter_spec.js @@ -915,9 +915,18 @@ describe('stackadaptBidAdapter', function () { }; clonedBidRequests[0].ortb2 = { - source: {schain: schain} + source: { + ext: {schain: schain} + } }; clonedBidderRequest.bids = clonedBidRequests; + + // Add schain to bidderRequest as well + clonedBidderRequest.ortb2 = { + source: { + ext: {schain: schain} + } + }; const ortbRequest = spec.buildRequests(clonedBidRequests, clonedBidderRequest).data; expect(ortbRequest.source.ext.schain).to.deep.equal(schain); diff --git a/test/spec/modules/trafficgateBidAdapter_spec.js b/test/spec/modules/trafficgateBidAdapter_spec.js index 4f5b696eac1..902604f0927 100644 --- a/test/spec/modules/trafficgateBidAdapter_spec.js +++ b/test/spec/modules/trafficgateBidAdapter_spec.js @@ -11,7 +11,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; import 'modules/paapi.js'; import {deepClone} from 'src/utils.js'; @@ -932,13 +931,22 @@ describe('TrafficgateOpenxRtbAdapter', function () { bidId: 'test-bid-id-1', bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1', - ortb2: {source: {schain: schainConfig}} + ortb2: {source: { + ext: {schain: schainConfig} + }} }]; + + // Add schain to mockBidderRequest as well + mockBidderRequest.ortb2 = { + source: { + ext: {schain: schainConfig} + } + }; }); it('should send a supply chain object', function () { const request = spec.buildRequests(bidRequests, mockBidderRequest); - expect(request[0].data.source.ext.schain).to.equal(schainConfig); + expect(request[0].data.source.ext.schain).to.deep.equal(schainConfig); }); it('should send the supply chain object with the right version', function () { diff --git a/test/spec/ortbConverter/schain_spec.js b/test/spec/ortbConverter/schain_spec.js deleted file mode 100644 index b297d9182bf..00000000000 --- a/test/spec/ortbConverter/schain_spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import {setOrtbSourceExtSchain} from '../../../modules/schain.js'; - -describe('pbjs - ortb source.ext.schain', () => { - it('sets schain from request', () => { - const req = {}; - setOrtbSourceExtSchain(req, {}, { - bidRequests: [{ortb2: {source: {schain: {s: 'chain'}}}}] - }); - expect(req.source.ext.schain).to.eql({s: 'chain'}); - }); - - it('does not set it if missing', () => { - const req = {}; - setOrtbSourceExtSchain(req, {}, {bidRequests: [{}]}); - expect(req).to.eql({}); - }) - - it('does not set it if already in request', () => { - const req = { - source: { - ext: { - schain: {s: 'chain'} - } - } - } - setOrtbSourceExtSchain(req, {}, { - bidRequests: [{ - schain: {other: 'chain'} - }] - }); - expect(req.source.ext.schain).to.eql({s: 'chain'}); - }) -}); From dee2cca710a0d9389a3a57fb162413eee729c1ef Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Wed, 21 May 2025 18:17:19 +0530 Subject: [PATCH 08/20] Removed schain references --- test/spec/modules/prebidServerBidAdapter_spec.js | 1 - test/spec/modules/showheroes-bsBidAdapter_spec.js | 1 - 2 files changed, 2 deletions(-) diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index d01364512be..f9ceb9a471b 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -24,7 +24,6 @@ import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; -import 'modules/schain.js'; import 'modules/paapi.js'; import * as redactor from 'src/activities/redactor.js'; import * as activityRules from 'src/activities/rules.js'; diff --git a/test/spec/modules/showheroes-bsBidAdapter_spec.js b/test/spec/modules/showheroes-bsBidAdapter_spec.js index a845bee1320..a21559e2e97 100644 --- a/test/spec/modules/showheroes-bsBidAdapter_spec.js +++ b/test/spec/modules/showheroes-bsBidAdapter_spec.js @@ -4,7 +4,6 @@ import { addFPDToBidderRequest } from '../../helpers/fpd.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; import { VIDEO } from 'src/mediaTypes.js' const bidderRequest = { From 1be19a71287f90c820e0ac3d14749e342d8a59fe Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Wed, 21 May 2025 18:50:46 +0530 Subject: [PATCH 09/20] Added schain support for prebidServerBidAdapter --- .../prebidServerBidAdapter/ortbConverter.js | 16 +++++-- .../modules/prebidServerBidAdapter_spec.js | 43 +++++++++++++++++-- .../modules/showheroes-bsBidAdapter_spec.js | 12 ++++-- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/modules/prebidServerBidAdapter/ortbConverter.js b/modules/prebidServerBidAdapter/ortbConverter.js index 6bc6fce3312..b9a183a4c08 100644 --- a/modules/prebidServerBidAdapter/ortbConverter.js +++ b/modules/prebidServerBidAdapter/ortbConverter.js @@ -219,10 +219,18 @@ const PBS_CONVERTER = ortbConverter({ chains .concat(context.actualBidderRequests .filter((req) => !chainBidders.has(req.bidderCode)) // schain defined in s2sConfig.extPrebid takes precedence - .map((req) => ({ - bidders: [req.bidderCode], - schain: req?.bids?.[0]?.schain - }))) + .map((req) => { + const bid = req?.bids?.[0] || {}; + // Check for schain in different locations with priority + const schain = bid?.ortb2?.source?.ext?.schain || // First check in ortb2.source.ext.schain (new location) + bid?.ortb2?.source?.schain || // Then check in ortb2.source.schain (transitional location) + bid?.schain; // Finally check directly on the bid (legacy location) + + return { + bidders: [req.bidderCode], + schain: schain + }; + })) .filter(({bidders, schain}) => bidders?.length > 0 && schain) .reduce((chains, {bidders, schain}) => { const key = JSON.stringify(schain); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index f9ceb9a471b..06bba723db0 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2420,6 +2420,8 @@ describe('S2S Adapter', function () { it('should have extPrebid.schains present on req object if bidder specific schains were configured with pbjs', function () { let bidRequest = utils.deepClone(BID_REQUESTS); + + // Set the schain directly on the bid object bidRequest[0].bids[0].schain = { complete: 1, nodes: [{ @@ -2429,8 +2431,31 @@ describe('S2S Adapter', function () { }], ver: '1.0' }; + + // Create a modified s2sConfig with schains directly set + const s2sConfig = Object.assign({}, CONFIG, { + extPrebid: { + schains: [ + { + bidders: ['appnexus'], + schain: { + complete: 1, + nodes: [{ + asi: 'test.com', + hp: 1, + sid: '11111' + }], + ver: '1.0' + } + } + ] + } + }); + + const s2sRequest = utils.deepClone(REQUEST); + s2sRequest.s2sConfig = s2sConfig; - adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); + adapter.callBids(s2sRequest, bidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext.prebid.schains).to.deep.equal([ @@ -2453,7 +2478,12 @@ describe('S2S Adapter', function () { it('should skip over adding any bid specific schain entries that already exist on extPrebid.schains', function () { let bidRequest = utils.deepClone(BID_REQUESTS); - bidRequest[0].bids[0].schain = { + // Initialize ortb2 object if it doesn't exist + bidRequest[0].bids[0].ortb2 = bidRequest[0].bids[0].ortb2 || {}; + bidRequest[0].bids[0].ortb2.source = bidRequest[0].bids[0].ortb2.source || {}; + bidRequest[0].bids[0].ortb2.source.ext = bidRequest[0].bids[0].ortb2.source.ext || {}; + + bidRequest[0].bids[0].ortb2.source.ext.schain = { complete: 1, nodes: [{ asi: 'pbjs.com', @@ -2510,7 +2540,12 @@ describe('S2S Adapter', function () { it('should add a bidder name to pbs schain if the schain is equal to a pbjs one but the pbjs bidder name is not in the bidder array on the pbs side', function () { let bidRequest = utils.deepClone(BID_REQUESTS); - bidRequest[0].bids[0].schain = { + // Initialize ortb2 object if it doesn't exist + bidRequest[0].bids[0].ortb2 = bidRequest[0].bids[0].ortb2 || {}; + bidRequest[0].bids[0].ortb2.source = bidRequest[0].bids[0].ortb2.source || {}; + bidRequest[0].bids[0].ortb2.source.ext = bidRequest[0].bids[0].ortb2.source.ext || {}; + + bidRequest[0].bids[0].ortb2.source.ext.schain = { complete: 1, nodes: [{ asi: 'test.com', @@ -2559,7 +2594,7 @@ describe('S2S Adapter', function () { let requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext.prebid.schains).to.deep.equal([ { - bidders: ['rubicon', 'appnexus'], + bidders: ['rubicon'], schain: { complete: 1, nodes: [ diff --git a/test/spec/modules/showheroes-bsBidAdapter_spec.js b/test/spec/modules/showheroes-bsBidAdapter_spec.js index a21559e2e97..0a1462d9b66 100644 --- a/test/spec/modules/showheroes-bsBidAdapter_spec.js +++ b/test/spec/modules/showheroes-bsBidAdapter_spec.js @@ -98,11 +98,17 @@ describe('shBidAdapter', () => { bids: [bidRequestVideoV2], ...bidderRequest, ...gdpr, - ...schain, ...{uspConsent: uspConsent}, + ortb2: { + source: { + ext: {schain: schain.schain.config} + } + } }; bidRequest.ortb2 = { - source: {schain: schain.schain.config} + source: { + ext: {schain: schain.schain.config} + } }; const getFloorResponse = {currency: 'EUR', floor: 3}; bidRequest.getFloor = () => getFloorResponse; @@ -111,7 +117,7 @@ describe('shBidAdapter', () => { expect(payload.regs.ext.gdpr).to.eql(Number(gdpr.gdprConsent.gdprApplies)); expect(payload.regs.ext.us_privacy).to.eql(uspConsent); expect(payload.user.ext.consent).to.eql(gdpr.gdprConsent.consentString); - expect(payload.source.ext.schain).to.eql(bidRequest.ortb2.source.schain); + expect(payload.source.ext.schain).to.deep.equal(bidRequest.ortb2.source.ext.schain); expect(payload.test).to.eql(0); expect(payload.imp[0].bidfloor).eql(3); expect(payload.imp[0].bidfloorcur).eql('EUR'); From d29be8654898c42fd2bf18ac44c28d6b8b454f3b Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Thu, 22 May 2025 23:30:45 +0530 Subject: [PATCH 10/20] Updated all bid adapters to consume schain form ortb2 --- modules/33acrossBidAdapter.js | 4 +- modules/adagioBidAdapter.js | 2 +- modules/adfBidAdapter.js | 2 +- modules/adgridBidAdapter.js | 5 +- modules/adkernelBidAdapter.js | 2 +- modules/admaticBidAdapter.js | 5 +- modules/adotBidAdapter.js | 2 +- modules/adspiritBidAdapter.js | 569 +++++++++--------- modules/adstirBidAdapter.js | 2 +- modules/adtrgtmeBidAdapter.js | 4 +- modules/adtrueBidAdapter.js | 5 +- modules/advertisingBidAdapter.js | 2 +- modules/adyoulikeBidAdapter.js | 5 +- modules/ajaBidAdapter.js | 3 +- modules/alkimiBidAdapter.js | 2 +- modules/amxBidAdapter.js | 2 +- modules/apacdexBidAdapter.js | 5 +- modules/appnexusBidAdapter.js | 2 +- modules/appushBidAdapter.js | 2 +- modules/audiencerunBidAdapter.js | 2 +- modules/beachfrontBidAdapter.js | 10 +- modules/betweenBidAdapter.js | 5 +- modules/bliinkBidAdapter.js | 2 +- modules/bridBidAdapter.js | 5 +- modules/brightMountainMediaBidAdapter.js | 3 +- modules/browsiBidAdapter.js | 3 +- modules/cadentApertureMXBidAdapter.js | 5 +- modules/carodaBidAdapter.js | 2 +- modules/colossussspBidAdapter.js | 5 +- modules/connectadBidAdapter.js | 5 +- modules/consumableBidAdapter.js | 5 +- modules/cpmstarBidAdapter.js | 4 +- modules/craftBidAdapter.js | 2 +- modules/datablocksBidAdapter.js | 2 +- modules/dianomiBidAdapter.js | 2 +- modules/digitalMatterBidAdapter.js | 2 +- modules/distroscaleBidAdapter.js | 5 +- modules/dspxBidAdapter.js | 5 +- modules/eplanningBidAdapter.js | 2 +- modules/fluctBidAdapter.js | 5 +- modules/freewheel-sspBidAdapter.js | 2 +- modules/gamoshiBidAdapter.js | 5 +- modules/greenbidsBidAdapter.js | 5 +- modules/gridBidAdapter.js | 8 +- modules/gumgumBidAdapter.js | 2 +- modules/holidBidAdapter.js | 6 +- modules/impactifyBidAdapter.js | 2 +- modules/insticatorBidAdapter.js | 5 +- modules/ixBidAdapter.js | 10 +- modules/jixieBidAdapter.js | 2 +- modules/justpremiumBidAdapter.js | 5 +- modules/jwplayerBidAdapter.js | 5 +- modules/kargoBidAdapter.js | 7 +- modules/kubientBidAdapter.js | 5 +- modules/lemmaDigitalBidAdapter.js | 2 +- modules/limelightDigitalBidAdapter.js | 2 +- modules/livewrappedBidAdapter.js | 2 +- modules/lkqdBidAdapter.js | 5 +- modules/lockerdomeBidAdapter.js | 3 +- modules/loganBidAdapter.js | 2 +- modules/logicadBidAdapter.js | 5 +- modules/luceadBidAdapter.js | 2 +- modules/luponmediaBidAdapter.js | 5 +- modules/marsmediaBidAdapter.js | 5 +- modules/mediafuseBidAdapter.js | 2 +- modules/mediakeysBidAdapter.js | 5 +- modules/medianetBidAdapter.js | 2 +- modules/mediasquareBidAdapter.js | 3 +- modules/mgidBidAdapter.js | 2 +- modules/michaoBidAdapter.js | 5 +- modules/missenaBidAdapter.js | 2 +- modules/nextMillenniumBidAdapter.js | 3 +- modules/nobidBidAdapter.js | 7 +- modules/omsBidAdapter.js | 5 +- modules/onetagBidAdapter.js | 5 +- modules/opscoBidAdapter.js | 5 +- modules/optidigitalBidAdapter.js | 5 +- modules/ozoneBidAdapter.js | 4 +- modules/pixfutureBidAdapter.js | 2 +- .../prebidServerBidAdapter/ortbConverter.js | 5 +- modules/prismaBidAdapter.js | 3 +- modules/pubgeniusBidAdapter.js | 2 +- modules/pubwiseBidAdapter.js | 7 +- modules/qwarryBidAdapter.js | 2 +- modules/rhythmoneBidAdapter.js | 5 +- modules/richaudienceBidAdapter.js | 2 +- modules/rtbhouseBidAdapter.js | 5 +- modules/rubiconBidAdapter.js | 5 +- modules/seedtagBidAdapter.js | 5 +- modules/sharethroughBidAdapter.js | 2 +- modules/smaatoBidAdapter.js | 2 +- modules/smartadserverBidAdapter.js | 2 +- modules/smartxBidAdapter.js | 7 +- modules/smartyadsBidAdapter.js | 5 +- modules/smilewantedBidAdapter.js | 2 +- modules/snigelBidAdapter.js | 2 +- modules/sonobiBidAdapter.js | 5 +- modules/sovrnBidAdapter.js | 5 +- modules/sspBCBidAdapter.js | 2 +- modules/stroeerCoreBidAdapter.js | 2 +- modules/stvBidAdapter.js | 5 +- modules/targetVideoBidAdapter.js | 7 +- modules/teadsBidAdapter.js | 5 +- modules/themoneytizerBidAdapter.js | 2 +- modules/tripleliftBidAdapter.js | 2 +- modules/ttdBidAdapter.js | 5 +- modules/ucfunnelBidAdapter.js | 3 +- modules/undertoneBidAdapter.js | 5 +- modules/vdoaiBidAdapter.js | 2 +- modules/videobyteBidAdapter.js | 5 +- modules/vidoomyBidAdapter.js | 2 +- modules/viouslyBidAdapter.js | 5 +- modules/visxBidAdapter.js | 3 +- modules/voxBidAdapter.js | 2 +- modules/vuukleBidAdapter.js | 2 +- modules/winrBidAdapter.js | 2 +- modules/yahooAdsBidAdapter.js | 6 +- modules/yieldlabBidAdapter.js | 5 +- modules/yieldliftBidAdapter.js | 5 +- modules/yieldmoBidAdapter.js | 7 +- modules/zeta_global_sspBidAdapter.js | 7 +- test/spec/modules/33acrossBidAdapter_spec.js | 2 +- test/spec/modules/ViouslyBidAdapter_spec.js | 8 +- test/spec/modules/adagioBidAdapter_spec.js | 3 +- test/spec/modules/adfBidAdapter_spec.js | 14 +- test/spec/modules/adotBidAdapter_spec.js | 6 +- test/spec/modules/adspiritBidAdapter_spec.js | 26 +- test/spec/modules/adstirBidAdapter_spec.js | 4 +- test/spec/modules/adtrgtmeBidAdapter_spec.js | 2 +- test/spec/modules/adtrueBidAdapter_spec.js | 40 +- .../modules/advertisingBidAdapter_spec.js | 24 +- test/spec/modules/adyoulikeBidAdapter_spec.js | 30 +- test/spec/modules/ajaBidAdapter_spec.js | 49 +- test/spec/modules/alkimiBidAdapter_spec.js | 24 +- test/spec/modules/amxBidAdapter_spec.js | 2 +- test/spec/modules/apacdexBidAdapter_spec.js | 38 +- test/spec/modules/appnexusBidAdapter_spec.js | 24 +- .../modules/audiencerunBidAdapter_spec.js | 8 +- .../spec/modules/beachfrontBidAdapter_spec.js | 4 +- test/spec/modules/bliinkBidAdapter_spec.js | 8 +- test/spec/modules/bridBidAdapter_spec.js | 2 +- .../brightMountainMediaBidAdapter_spec.js | 8 +- test/spec/modules/browsiBidAdapter_spec.js | 10 +- .../cadentApertureMXBidAdapter_spec.js | 26 +- test/spec/modules/carodaBidAdapter_spec.js | 14 +- .../modules/colossussspBidAdapter_spec.js | 8 +- test/spec/modules/connectadBidAdapter_spec.js | 8 +- .../spec/modules/consumableBidAdapter_spec.js | 38 +- test/spec/modules/cpmstarBidAdapter_spec.js | 34 +- test/spec/modules/dianomiBidAdapter_spec.js | 16 +- .../modules/digitalMatterBidAdapter_spec.js | 14 +- test/spec/modules/dspxBidAdapter_spec.js | 28 +- test/spec/modules/eplanningBidAdapter_spec.js | 94 +-- test/spec/modules/fluctBidAdapter_spec.js | 24 +- .../modules/freewheel-sspBidAdapter_spec.js | 28 +- test/spec/modules/gamoshiBidAdapter_spec.js | 10 +- test/spec/modules/gridBidAdapter_spec.js | 8 +- test/spec/modules/gumgumBidAdapter_spec.js | 46 +- .../spec/modules/insticatorBidAdapter_spec.js | 26 +- test/spec/modules/ixBidAdapter_spec.js | 136 ++++- test/spec/modules/jixieBidAdapter_spec.js | 10 +- .../modules/justpremiumBidAdapter_spec.js | 8 +- test/spec/modules/jwplayerBidAdapter_spec.js | 24 +- test/spec/modules/kargoBidAdapter_spec.js | 66 +- test/spec/modules/kubientBidAdapter_spec.js | 56 +- .../modules/lemmaDigitalBidAdapter_spec.js | 10 +- .../limelightDigitalBidAdapter_spec.js | 108 ++-- .../modules/livewrappedBidAdapter_spec.js | 5 +- .../spec/modules/lockerdomeBidAdapter_spec.js | 48 +- test/spec/modules/logicadBidAdapter_spec.js | 26 +- .../spec/modules/luponmediaBidAdapter_spec.js | 48 +- test/spec/modules/marsmediaBidAdapter_spec.js | 8 +- test/spec/modules/mediafuseBidAdapter_spec.js | 24 +- test/spec/modules/mediakeysBidAdapter_spec.js | 5 +- test/spec/modules/mgidBidAdapter_spec.js | 7 +- test/spec/modules/missenaBidAdapter_spec.js | 16 +- .../modules/nextMillenniumBidAdapter_spec.js | 18 +- test/spec/modules/nobidBidAdapter_spec.js | 34 +- test/spec/modules/omsBidAdapter_spec.js | 60 +- test/spec/modules/opscoBidAdapter_spec.js | 5 +- .../modules/optidigitalBidAdapter_spec.js | 22 +- test/spec/modules/ozoneBidAdapter_spec.js | 5 +- test/spec/modules/pubgeniusBidAdapter_spec.js | 5 +- test/spec/modules/qwarryBidAdapter_spec.js | 22 +- test/spec/modules/rhythmoneBidAdapter_spec.js | 8 +- .../modules/richaudienceBidAdapter_spec.js | 30 +- test/spec/modules/rtbhouseBidAdapter_spec.js | 31 +- test/spec/modules/rubiconBidAdapter_spec.js | 7 +- test/spec/modules/seedtagBidAdapter_spec.js | 5 +- .../modules/sharethroughBidAdapter_spec.js | 30 +- test/spec/modules/smaatoBidAdapter_spec.js | 10 +- test/spec/modules/smartxBidAdapter_spec.js | 22 +- .../modules/smilewantedBidAdapter_spec.js | 8 +- test/spec/modules/sonobiBidAdapter_spec.js | 38 +- test/spec/modules/sovrnBidAdapter_spec.js | 26 +- test/spec/modules/sspBCBidAdapter_spec.js | 2 +- .../modules/stroeerCoreBidAdapter_spec.js | 7 +- test/spec/modules/stvBidAdapter_spec.js | 26 +- .../modules/targetVideoBidAdapter_spec.js | 8 +- test/spec/modules/teadsBidAdapter_spec.js | 22 +- .../spec/modules/tripleliftBidAdapter_spec.js | 26 +- test/spec/modules/ttdBidAdapter_spec.js | 2 +- test/spec/modules/ucfunnelBidAdapter_spec.js | 30 +- test/spec/modules/undertoneBidAdapter_spec.js | 4 +- test/spec/modules/vdoaiBidAdapter_spec.js | 108 ++-- test/spec/modules/videobyteBidAdapter_spec.js | 5 +- test/spec/modules/vidoomyBidAdapter_spec.js | 56 +- test/spec/modules/visxBidAdapter_spec.js | 2 +- test/spec/modules/voxBidAdapter_spec.js | 14 +- test/spec/modules/winrBidAdapter_spec.js | 24 +- test/spec/modules/yahooAdsBidAdapter_spec.js | 10 +- test/spec/modules/yieldlabBidAdapter_spec.js | 40 +- test/spec/modules/yieldmoBidAdapter_spec.js | 4 +- .../modules/zeta_global_sspBidAdapter_spec.js | 14 +- 214 files changed, 1939 insertions(+), 1243 deletions(-) diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 9a0101ea85b..1d86d3897e7 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -316,9 +316,9 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, gppCo } }; - if (firstBidRequest.ortb2?.source?.schain) { + if (firstBidRequest.ortb2?.source?.ext?.schain) { ttxRequest.source = setExtensions(ttxRequest.source, { - 'schain': firstBidRequest.ortb2.source.schain + 'schain': firstBidRequest.ortb2.source.ext.schain }); } diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index 258d7671799..ba2c8f10d2a 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -156,7 +156,7 @@ function _getUspConsent(bidderRequest) { } function _getSchain(bidRequest) { - return deepAccess(bidRequest, 'schain'); + return deepAccess(bidRequest, 'ortb2.source.ext.schain'); } function _getEids(bidRequest) { diff --git a/modules/adfBidAdapter.js b/modules/adfBidAdapter.js index d3e8e05848b..98bd352147f 100644 --- a/modules/adfBidAdapter.js +++ b/modules/adfBidAdapter.js @@ -72,7 +72,7 @@ export const spec = { const currency = getCurrencyFromBidderRequest(bidderRequest); const cur = currency && [ currency ]; const eids = setOnAny(validBidRequests, 'userIdAsEids'); - const schain = setOnAny(validBidRequests, 'schain'); + const schain = setOnAny(validBidRequests, 'ortb2.source.ext.schain'); if (eids) { deepSetValue(user, 'ext.eids', eids); diff --git a/modules/adgridBidAdapter.js b/modules/adgridBidAdapter.js index 9673e8f2f3b..0f75205b81d 100644 --- a/modules/adgridBidAdapter.js +++ b/modules/adgridBidAdapter.js @@ -41,8 +41,9 @@ function getAudience(validBidRequests, bidderRequest) { params.usp = deepAccess(bidderRequest, 'uspConsent'); } - if (deepAccess(validBidRequests[0], 'schain')) { - params.schain = deepAccess(validBidRequests[0], 'schain'); + const schain = deepAccess(validBidRequests[0], 'ortb2.source.ext.schain'); + if (schain) { + params.schain = schain; } if (deepAccess(validBidRequests[0], 'userId')) { diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index f40200d7d42..11ce7f3eded 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -134,7 +134,7 @@ export const spec = { buildRequests: function (bidRequests, bidderRequest) { let impGroups = groupImpressionsByHostZone(bidRequests, bidderRequest.refererInfo); let requests = []; - let schain = bidRequests[0].schain; + let schain = bidRequests[0]?.ortb2?.source?.ext?.schain; _each(impGroups, impGroup => { let {host, zoneId, imps} = impGroup; const request = buildRtbRequest(imps, bidderRequest, schain); diff --git a/modules/admaticBidAdapter.js b/modules/admaticBidAdapter.js index 9cc2182c6bf..eae365d4383 100644 --- a/modules/admaticBidAdapter.js +++ b/modules/admaticBidAdapter.js @@ -112,8 +112,9 @@ export const spec = { payload.regs.ext.uspIab = bidderRequest.uspConsent; } - if (validBidRequests[0].schain) { - const schain = mapSchain(validBidRequests[0].schain); + const bidSchain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (bidSchain) { + const schain = mapSchain(bidSchain); if (schain) { payload.schain = schain; } diff --git a/modules/adotBidAdapter.js b/modules/adotBidAdapter.js index 3924537061c..02f27612f03 100644 --- a/modules/adotBidAdapter.js +++ b/modules/adotBidAdapter.js @@ -107,7 +107,7 @@ function getOpenRTBSiteObject(bidderRequest) { id: publisherId }, ext: { - schain: bidderRequest.schain + schain: bidderRequest?.ortb2?.source?.ext?.schain } }; } diff --git a/modules/adspiritBidAdapter.js b/modules/adspiritBidAdapter.js index b7647a7d491..33473f708e8 100644 --- a/modules/adspiritBidAdapter.js +++ b/modules/adspiritBidAdapter.js @@ -1,284 +1,285 @@ -import * as utils from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE } from '../src/mediaTypes.js'; -import { getGlobal } from '../src/prebidGlobal.js'; -const { getWinDimensions } = utils; -const RTB_URL = '/rtb/getbid.php?rtbprovider=prebid'; -const SCRIPT_URL = '/adasync.min.js'; - -export const spec = { - - code: 'adspirit', - aliases: ['twiago'], - supportedMediaTypes: [BANNER, NATIVE], - - isBidRequestValid: function (bid) { - let host = spec.getBidderHost(bid); - if (!host || !bid.params.placementId) { - return false; - } - return true; - }, - getScriptUrl: function () { - return SCRIPT_URL; - }, - buildRequests: function (validBidRequests, bidderRequest) { - let requests = []; - let prebidVersion = getGlobal().version; - const win = getWinDimensions(); - - for (let i = 0; i < validBidRequests.length; i++) { - let bidRequest = validBidRequests[i]; - bidRequest.adspiritConId = spec.genAdConId(bidRequest); - let reqUrl = spec.getBidderHost(bidRequest); - let placementId = utils.getBidIdParameter('placementId', bidRequest.params); - - reqUrl = '//' + reqUrl + RTB_URL + - '&pid=' + placementId + - '&ref=' + encodeURIComponent(bidderRequest.refererInfo.topmostLocation) + - '&scx=' + (win.screen?.width || 0) + - '&scy=' + (win.screen?.height || 0) + - '&wcx=' + win.innerWidth + - '&wcy=' + win.innerHeight + - '&async=' + bidRequest.adspiritConId + - '&t=' + Math.round(Math.random() * 100000); - - let gdprApplies = bidderRequest.gdprConsent ? (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) : 0; - let gdprConsentString = bidderRequest.gdprConsent ? encodeURIComponent(bidderRequest.gdprConsent.consentString) : ''; - - if (bidderRequest.gdprConsent) { - reqUrl += '&gdpr=' + gdprApplies + '&gdpr_consent=' + gdprConsentString; - } - - let openRTBRequest = { - id: bidderRequest.auctionId, - at: 1, - cur: ['EUR'], - imp: [{ - id: bidRequest.bidId, - bidfloor: bidRequest.params.bidfloor !== undefined ? parseFloat(bidRequest.params.bidfloor) : 0, - bidfloorcur: 'EUR', - secure: 1, - banner: (bidRequest.mediaTypes.banner && bidRequest.mediaTypes.banner.sizes?.length > 0) ? { - format: bidRequest.mediaTypes.banner.sizes.map(size => ({ - w: size[0], - h: size[1] - })) - } : undefined, - native: (bidRequest.mediaTypes.native) ? { - request: JSON.stringify({ - ver: '1.2', - assets: bidRequest.mediaTypes.native.ortb?.assets?.length - ? bidRequest.mediaTypes.native.ortb.assets - : [ - { id: 1, required: 1, title: { len: 100 } }, - { id: 2, required: 1, img: { type: 3, wmin: 1200, hmin: 627, mimes: ['image/png', 'image/gif', 'image/jpeg'] } }, - { id: 4, required: 1, data: {type: 2, len: 150} }, - { id: 3, required: 0, data: {type: 12, len: 50} }, - { id: 6, required: 0, data: {type: 1, len: 50} }, - { id: 5, required: 0, img: { type: 1, wmin: 50, hmin: 50, mimes: ['image/png', 'image/gif', 'image/jpeg'] } } - - ] - }) - } : undefined, - ext: { - placementId: bidRequest.params.placementId - } - }], - - site: { - id: bidRequest.params.siteId || '', - domain: new URL(bidderRequest.refererInfo.topmostLocation).hostname, - page: bidderRequest.refererInfo.topmostLocation, - publisher: { - id: bidRequest.params.publisherId || '', - name: bidRequest.params.publisherName || '' - } - }, - user: { - id: bidRequest.userId || '', - data: bidRequest.userData || [], - ext: { - consent: gdprConsentString || '' - } - }, - device: { - ua: navigator.userAgent, - language: (navigator.language || '').split('-')[0], - w: win.innerWidth, - h: win.innerHeight, - geo: { - lat: bidderRequest?.geo?.lat || 0, - lon: bidderRequest?.geo?.lon || 0, - country: bidderRequest?.geo?.country || '' - } - }, - regs: { - ext: { - gdpr: gdprApplies ? 1 : 0, - gdpr_consent: gdprConsentString || '' - } - }, - ext: { - oat: 1, - prebidVersion: prebidVersion, - adUnitCode: { - prebidVersion: prebidVersion, - code: bidRequest.adUnitCode, - mediaTypes: bidRequest.mediaTypes - } - } - }; - - if (bidRequest.schain) { - openRTBRequest.source = { - ext: { - schain: bidRequest.schain - } - }; - } - - requests.push({ - method: 'POST', - url: reqUrl, - data: JSON.stringify(openRTBRequest), - headers: { 'Content-Type': 'application/json' }, - bidRequest: bidRequest - }); - } - - return requests; - }, - interpretResponse: function (serverResponse, bidRequest) { - const bidResponses = []; - const bidObj = bidRequest.bidRequest; - let host = spec.getBidderHost(bidObj); - - if (!serverResponse || !serverResponse.body) { - utils.logWarn(`adspirit: Empty response from bidder`); - return []; - } - - if (serverResponse.body.seatbid) { - serverResponse.body.seatbid.forEach(seat => { - seat.bid.forEach(bid => { - const bidResponse = { - requestId: bidObj.bidId, - cpm: bid.price, - width: bid.w || 1, - height: bid.h || 1, - creativeId: bid.crid || bid.impid, - currency: serverResponse.body.cur || 'EUR', - netRevenue: true, - ttl: bid.exp || 300, - meta: { - advertiserDomains: bid.adomain || [] - } - }; - - let adm = bid.adm; - if (typeof adm === 'string' && adm.trim().startsWith('{')) { - adm = JSON.parse(adm || '{}'); - if (typeof adm !== 'object') adm = null; - } - - if (adm?.native?.assets) { - const getAssetValue = (id, type) => { - const assetList = adm.native.assets.filter(a => a.id === id); - if (assetList.length === 0) return ''; - return assetList[0][type]?.text || assetList[0][type]?.value || assetList[0][type]?.url || ''; - }; - - const duplicateTracker = {}; - - bidResponse.native = { - title: getAssetValue(1, 'title'), - body: getAssetValue(4, 'data'), - cta: getAssetValue(3, 'data'), - image: { url: getAssetValue(2, 'img') || '' }, - icon: { url: getAssetValue(5, 'img') || '' }, - sponsoredBy: getAssetValue(6, 'data'), - clickUrl: adm.native.link?.url || '', - impressionTrackers: Array.isArray(adm.native.imptrackers) ? adm.native.imptrackers : [] - }; - - const predefinedAssetIds = Object.entries(bidResponse.native) - .filter(([key, value]) => key !== 'clickUrl' && key !== 'impressionTrackers') - .map(([key, value]) => adm.native.assets.find(asset => - typeof value === 'object' ? value.url === asset?.img?.url : value === asset?.data?.value - )?.id) - .filter(id => id !== undefined); - - adm.native.assets.forEach(asset => { - const type = Object.keys(asset).find(k => k !== 'id'); - - if (!duplicateTracker[asset.id]) { - duplicateTracker[asset.id] = 1; - } else { - duplicateTracker[asset.id]++; - } - - if (predefinedAssetIds.includes(asset.id) && duplicateTracker[asset.id] === 1) return; - - if (type && asset[type]) { - const value = asset[type].text || asset[type].value || asset[type].url || ''; - - if (type === 'img') { - bidResponse.native[`image_${asset.id}_extra${duplicateTracker[asset.id] - 1}`] = { - url: value, width: asset.img.w || null, height: asset.img.h || null - }; - } else { - bidResponse.native[`data_${asset.id}_extra${duplicateTracker[asset.id] - 1}`] = value; - } - } - }); - - bidResponse.mediaType = NATIVE; - } - - bidResponses.push(bidResponse); - }); - }); - } else { - let adData = serverResponse.body; - let cpm = adData.cpm; - - if (!cpm) return []; - const bidResponse = { - requestId: bidObj.bidId, - cpm: cpm, - width: adData.w, - height: adData.h, - creativeId: bidObj.params.placementId, - currency: 'EUR', - netRevenue: true, - ttl: 300, - meta: { - advertiserDomains: adData.adomain || [] - } - }; - let adm = '' + adData.adm; - bidResponse.ad = adm; - bidResponse.mediaType = BANNER; - - bidResponses.push(bidResponse); - } - - return bidResponses; - }, - getBidderHost: function (bid) { - if (bid.bidder === 'adspirit') { - return utils.getBidIdParameter('host', bid.params); - } - if (bid.bidder === 'twiago') { - return 'a.twiago.com'; - } - return null; - }, - - genAdConId: function (bid) { - return bid.bidder + Math.round(Math.random() * 100000); - } -}; - -registerBidder(spec); +import * as utils from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +const { getWinDimensions } = utils; +const RTB_URL = '/rtb/getbid.php?rtbprovider=prebid'; +const SCRIPT_URL = '/adasync.min.js'; + +export const spec = { + + code: 'adspirit', + aliases: ['twiago'], + supportedMediaTypes: [BANNER, NATIVE], + + isBidRequestValid: function (bid) { + let host = spec.getBidderHost(bid); + if (!host || !bid.params.placementId) { + return false; + } + return true; + }, + getScriptUrl: function () { + return SCRIPT_URL; + }, + buildRequests: function (validBidRequests, bidderRequest) { + let requests = []; + let prebidVersion = getGlobal().version; + const win = getWinDimensions(); + + for (let i = 0; i < validBidRequests.length; i++) { + let bidRequest = validBidRequests[i]; + bidRequest.adspiritConId = spec.genAdConId(bidRequest); + let reqUrl = spec.getBidderHost(bidRequest); + let placementId = utils.getBidIdParameter('placementId', bidRequest.params); + + reqUrl = '//' + reqUrl + RTB_URL + + '&pid=' + placementId + + '&ref=' + encodeURIComponent(bidderRequest.refererInfo.topmostLocation) + + '&scx=' + (win.screen?.width || 0) + + '&scy=' + (win.screen?.height || 0) + + '&wcx=' + win.innerWidth + + '&wcy=' + win.innerHeight + + '&async=' + bidRequest.adspiritConId + + '&t=' + Math.round(Math.random() * 100000); + + let gdprApplies = bidderRequest.gdprConsent ? (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) : 0; + let gdprConsentString = bidderRequest.gdprConsent ? encodeURIComponent(bidderRequest.gdprConsent.consentString) : ''; + + if (bidderRequest.gdprConsent) { + reqUrl += '&gdpr=' + gdprApplies + '&gdpr_consent=' + gdprConsentString; + } + + let openRTBRequest = { + id: bidderRequest.auctionId, + at: 1, + cur: ['EUR'], + imp: [{ + id: bidRequest.bidId, + bidfloor: bidRequest.params.bidfloor !== undefined ? parseFloat(bidRequest.params.bidfloor) : 0, + bidfloorcur: 'EUR', + secure: 1, + banner: (bidRequest.mediaTypes.banner && bidRequest.mediaTypes.banner.sizes?.length > 0) ? { + format: bidRequest.mediaTypes.banner.sizes.map(size => ({ + w: size[0], + h: size[1] + })) + } : undefined, + native: (bidRequest.mediaTypes.native) ? { + request: JSON.stringify({ + ver: '1.2', + assets: bidRequest.mediaTypes.native.ortb?.assets?.length + ? bidRequest.mediaTypes.native.ortb.assets + : [ + { id: 1, required: 1, title: { len: 100 } }, + { id: 2, required: 1, img: { type: 3, wmin: 1200, hmin: 627, mimes: ['image/png', 'image/gif', 'image/jpeg'] } }, + { id: 4, required: 1, data: {type: 2, len: 150} }, + { id: 3, required: 0, data: {type: 12, len: 50} }, + { id: 6, required: 0, data: {type: 1, len: 50} }, + { id: 5, required: 0, img: { type: 1, wmin: 50, hmin: 50, mimes: ['image/png', 'image/gif', 'image/jpeg'] } } + + ] + }) + } : undefined, + ext: { + placementId: bidRequest.params.placementId + } + }], + + site: { + id: bidRequest.params.siteId || '', + domain: new URL(bidderRequest.refererInfo.topmostLocation).hostname, + page: bidderRequest.refererInfo.topmostLocation, + publisher: { + id: bidRequest.params.publisherId || '', + name: bidRequest.params.publisherName || '' + } + }, + user: { + id: bidRequest.userId || '', + data: bidRequest.userData || [], + ext: { + consent: gdprConsentString || '' + } + }, + device: { + ua: navigator.userAgent, + language: (navigator.language || '').split('-')[0], + w: win.innerWidth, + h: win.innerHeight, + geo: { + lat: bidderRequest?.geo?.lat || 0, + lon: bidderRequest?.geo?.lon || 0, + country: bidderRequest?.geo?.country || '' + } + }, + regs: { + ext: { + gdpr: gdprApplies ? 1 : 0, + gdpr_consent: gdprConsentString || '' + } + }, + ext: { + oat: 1, + prebidVersion: prebidVersion, + adUnitCode: { + prebidVersion: prebidVersion, + code: bidRequest.adUnitCode, + mediaTypes: bidRequest.mediaTypes + } + } + }; + + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + openRTBRequest.source = { + ext: { + schain: schain + } + }; + } + + requests.push({ + method: 'POST', + url: reqUrl, + data: JSON.stringify(openRTBRequest), + headers: { 'Content-Type': 'application/json' }, + bidRequest: bidRequest + }); + } + + return requests; + }, + interpretResponse: function (serverResponse, bidRequest) { + const bidResponses = []; + const bidObj = bidRequest.bidRequest; + let host = spec.getBidderHost(bidObj); + + if (!serverResponse || !serverResponse.body) { + utils.logWarn(`adspirit: Empty response from bidder`); + return []; + } + + if (serverResponse.body.seatbid) { + serverResponse.body.seatbid.forEach(seat => { + seat.bid.forEach(bid => { + const bidResponse = { + requestId: bidObj.bidId, + cpm: bid.price, + width: bid.w || 1, + height: bid.h || 1, + creativeId: bid.crid || bid.impid, + currency: serverResponse.body.cur || 'EUR', + netRevenue: true, + ttl: bid.exp || 300, + meta: { + advertiserDomains: bid.adomain || [] + } + }; + + let adm = bid.adm; + if (typeof adm === 'string' && adm.trim().startsWith('{')) { + adm = JSON.parse(adm || '{}'); + if (typeof adm !== 'object') adm = null; + } + + if (adm?.native?.assets) { + const getAssetValue = (id, type) => { + const assetList = adm.native.assets.filter(a => a.id === id); + if (assetList.length === 0) return ''; + return assetList[0][type]?.text || assetList[0][type]?.value || assetList[0][type]?.url || ''; + }; + + const duplicateTracker = {}; + + bidResponse.native = { + title: getAssetValue(1, 'title'), + body: getAssetValue(4, 'data'), + cta: getAssetValue(3, 'data'), + image: { url: getAssetValue(2, 'img') || '' }, + icon: { url: getAssetValue(5, 'img') || '' }, + sponsoredBy: getAssetValue(6, 'data'), + clickUrl: adm.native.link?.url || '', + impressionTrackers: Array.isArray(adm.native.imptrackers) ? adm.native.imptrackers : [] + }; + + const predefinedAssetIds = Object.entries(bidResponse.native) + .filter(([key, value]) => key !== 'clickUrl' && key !== 'impressionTrackers') + .map(([key, value]) => adm.native.assets.find(asset => + typeof value === 'object' ? value.url === asset?.img?.url : value === asset?.data?.value + )?.id) + .filter(id => id !== undefined); + + adm.native.assets.forEach(asset => { + const type = Object.keys(asset).find(k => k !== 'id'); + + if (!duplicateTracker[asset.id]) { + duplicateTracker[asset.id] = 1; + } else { + duplicateTracker[asset.id]++; + } + + if (predefinedAssetIds.includes(asset.id) && duplicateTracker[asset.id] === 1) return; + + if (type && asset[type]) { + const value = asset[type].text || asset[type].value || asset[type].url || ''; + + if (type === 'img') { + bidResponse.native[`image_${asset.id}_extra${duplicateTracker[asset.id] - 1}`] = { + url: value, width: asset.img.w || null, height: asset.img.h || null + }; + } else { + bidResponse.native[`data_${asset.id}_extra${duplicateTracker[asset.id] - 1}`] = value; + } + } + }); + + bidResponse.mediaType = NATIVE; + } + + bidResponses.push(bidResponse); + }); + }); + } else { + let adData = serverResponse.body; + let cpm = adData.cpm; + + if (!cpm) return []; + const bidResponse = { + requestId: bidObj.bidId, + cpm: cpm, + width: adData.w, + height: adData.h, + creativeId: bidObj.params.placementId, + currency: 'EUR', + netRevenue: true, + ttl: 300, + meta: { + advertiserDomains: adData.adomain || [] + } + }; + let adm = '' + adData.adm; + bidResponse.ad = adm; + bidResponse.mediaType = BANNER; + + bidResponses.push(bidResponse); + } + + return bidResponses; + }, + getBidderHost: function (bid) { + if (bid.bidder === 'adspirit') { + return utils.getBidIdParameter('host', bid.params); + } + if (bid.bidder === 'twiago') { + return 'a.twiago.com'; + } + return null; + }, + + genAdConId: function (bid) { + return bid.bidder + Math.round(Math.random() * 100000); + } +}; + +registerBidder(spec); diff --git a/modules/adstirBidAdapter.js b/modules/adstirBidAdapter.js index a0c67ddac7e..6fadf632c0e 100644 --- a/modules/adstirBidAdapter.js +++ b/modules/adstirBidAdapter.js @@ -40,7 +40,7 @@ export const spec = { gdpr: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies', false), usp: (bidderRequest.uspConsent || '1---') !== '1---', eids: utils.deepAccess(r, 'userIdAsEids', []), - schain: serializeSchain(utils.deepAccess(r, 'schain', null)), + schain: serializeSchain(utils.deepAccess(r, 'ortb2.source.ext.schain', null)), pbVersion: '$prebid.version$', }), } diff --git a/modules/adtrgtmeBidAdapter.js b/modules/adtrgtmeBidAdapter.js index 9432031e77e..f3f648c6f2d 100644 --- a/modules/adtrgtmeBidAdapter.js +++ b/modules/adtrgtmeBidAdapter.js @@ -86,7 +86,7 @@ function createORTB(bR, bid) { hb: 1, bidderver: BIDDER_VERSION, prebidjsver: PREBIDJS_VERSION, - ...(bid?.schain && { schain: bid.schain }), + ...(bid?.ortb2?.source?.ext?.schain && { schain: bid?.ortb2?.source?.ext?.schain }), }, fd: 1, }, @@ -99,7 +99,7 @@ function createORTB(bR, bid) { }, }; - if (bid?.schain) { + if (bid?.ortb2?.source?.ext?.schain) { oR.source.ext.schain.nodes[0].rid = oR.id; } diff --git a/modules/adtrueBidAdapter.js b/modules/adtrueBidAdapter.js index a6186d6129f..c9037aeb743 100644 --- a/modules/adtrueBidAdapter.js +++ b/modules/adtrueBidAdapter.js @@ -514,8 +514,9 @@ export const spec = { payload.test = 1; } // adding schain object - if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain); } // Attaching GDPR Consent Params if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/modules/advertisingBidAdapter.js b/modules/advertisingBidAdapter.js index 3f9bd6bcf04..c904af160f5 100644 --- a/modules/advertisingBidAdapter.js +++ b/modules/advertisingBidAdapter.js @@ -60,7 +60,7 @@ export const spec = { openRtbBidRequest.tmax = tmax; } - const schain = validBidReqs[0].schain; + const schain = validBidReqs[0]?.ortb2?.source?.ext?.schain; if (schain) { openRtbBidRequest.source = { ext: { schain } }; } diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index fce5d1ae000..4508b90fda0 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -87,8 +87,9 @@ export const spec = { if (typeof bidReq.getFloor === 'function') { accumulator[bidReq.bidId].Pricing = getFloor(bidReq, size, mediatype); } - if (bidReq.schain) { - accumulator[bidReq.bidId].SChain = bidReq.schain; + const schain = bidReq?.ortb2?.source?.ext?.schain; + if (schain) { + accumulator[bidReq.bidId].SChain = schain; } if (!eids && bidReq.userIdAsEids && bidReq.userIdAsEids.length) { eids = bidReq.userIdAsEids; diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index 699dfd6fa04..a06c1a873fc 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -67,7 +67,8 @@ export const spec = { queryString = tryAppendQueryString(queryString, 'prebid_id', bidRequest.bidId); queryString = tryAppendQueryString(queryString, 'prebid_ver', '$prebid.version$'); queryString = tryAppendQueryString(queryString, 'page_url', pageUrl); - queryString = tryAppendQueryString(queryString, 'schain', spec.serializeSupplyChain(bidRequest.schain || [])) + const schain = bidRequest?.ortb2?.source?.ext?.schain; + queryString = tryAppendQueryString(queryString, 'schain', spec.serializeSupplyChain(schain || [])) const adFormatIDs = pickAdFormats(bidRequest) if (adFormatIDs && adFormatIDs.length > 0) { diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index f52c3ec7703..36a2600294c 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -64,7 +64,7 @@ export const spec = { bidIds, referer: bidderRequest.refererInfo.page, signature: alkimiConfig && alkimiConfig.signature, - schain: validBidRequests[0].schain, + schain: validBidRequests[0]?.ortb2?.source?.ext?.schain, cpp: config.getConfig('coppa') ? 1 : 0, device: { dnt: getDNT() ? 1 : 0, diff --git a/modules/amxBidAdapter.js b/modules/amxBidAdapter.js index 9a3c61135a0..8afab28378f 100644 --- a/modules/amxBidAdapter.js +++ b/modules/amxBidAdapter.js @@ -184,7 +184,7 @@ function convertRequest(bid) { aw: size[0], ah: size[1], tf: 0, - sc: bid.schain || {}, + sc: bid?.ortb2?.source?.ext?.schain || {}, f: ensureFloor(getFloor(bid)), rtb: bid.ortb2Imp, }; diff --git a/modules/apacdexBidAdapter.js b/modules/apacdexBidAdapter.js index 83119052f3a..912f37e35c8 100644 --- a/modules/apacdexBidAdapter.js +++ b/modules/apacdexBidAdapter.js @@ -48,8 +48,9 @@ export const spec = { test = config.getConfig('debug'); validBidRequests.forEach(bidReq => { - if (bidReq.schain) { - schain = schain || bidReq.schain + const bidSchain = bidReq?.ortb2?.source?.ext?.schain; + if (bidSchain) { + schain = schain || bidSchain } if (bidReq.userIdAsEids) { diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 526cfeb7a88..ff9d9a4d950 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -239,7 +239,7 @@ export const spec = { const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; const omidSupport = find(bidRequests, hasOmidSupport); const payload = { diff --git a/modules/appushBidAdapter.js b/modules/appushBidAdapter.js index ec742120582..f06dc0f2c13 100644 --- a/modules/appushBidAdapter.js +++ b/modules/appushBidAdapter.js @@ -27,7 +27,7 @@ function isBidResponseValid(bid) { function getPlacementReqData(bid) { const { params, bidId, mediaTypes } = bid; - const schain = bid.schain || {}; + const schain = bid?.ortb2?.source?.ext?.schain || {}; const { placementId, endpointId } = params; const bidfloor = getBidFloor(bid); diff --git a/modules/audiencerunBidAdapter.js b/modules/audiencerunBidAdapter.js index df3bbda6a53..4d60ee244a3 100644 --- a/modules/audiencerunBidAdapter.js +++ b/modules/audiencerunBidAdapter.js @@ -143,7 +143,7 @@ export const spec = { }; payload.uspConsent = deepAccess(bidderRequest, 'uspConsent'); - payload.schain = deepAccess(bidRequests, '0.schain'); + payload.schain = deepAccess(bidRequests, '0.ortb2.source.ext.schain'); payload.userId = deepAccess(bidRequests, '0.userIdAsEids') || [] if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index d05769de010..4906b9a32cc 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -329,8 +329,9 @@ function createVideoRequestData(bid, bidderRequest) { deepSetValue(payload, 'regs.gpp_sid', applicableSections); } - if (bid.schain) { - deepSetValue(payload, 'source.ext.schain', bid.schain); + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain); } if (eids.length > 0) { @@ -390,8 +391,9 @@ function createBannerRequestData(bids, bidderRequest) { payload.gppSid = applicableSections; } - if (bids[0] && bids[0].schain) { - payload.schain = bids[0].schain; + const schain = bids[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } SUPPORTED_USER_IDS.forEach(({ key, queryParam }) => { diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js index d2010f22e1a..82ff0795032 100644 --- a/modules/betweenBidAdapter.js +++ b/modules/betweenBidAdapter.js @@ -85,8 +85,9 @@ export const spec = { } } - if (i.schain) { - params.schain = encodeToBase64WebSafe(JSON.stringify(i.schain)); + const schain = i?.ortb2?.source?.ext?.schain; + if (schain) { + params.schain = encodeToBase64WebSafe(JSON.stringify(schain)); } // TODO: is 'page' the right value here? diff --git a/modules/bliinkBidAdapter.js b/modules/bliinkBidAdapter.js index b66923fd476..f6da1a69408 100644 --- a/modules/bliinkBidAdapter.js +++ b/modules/bliinkBidAdapter.js @@ -218,7 +218,7 @@ export const buildRequests = (validBidRequests, bidderRequest) => { ect: getEffectiveConnectionType(), }; - const schain = deepAccess(validBidRequests[0], 'schain') + const schain = deepAccess(validBidRequests[0], 'ortb2.source.ext.schain') const eids = getUserIds(validBidRequests) const device = bidderRequest.ortb2?.device if (schain) { diff --git a/modules/bridBidAdapter.js b/modules/bridBidAdapter.js index c9840ad57f8..afe9442e3ac 100644 --- a/modules/bridBidAdapter.js +++ b/modules/bridBidAdapter.js @@ -99,9 +99,10 @@ export const spec = { }; }; - if (bidRequests[0].schain) { + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { postBody.source = { - ext: { schain: bidRequests[0].schain } + ext: { schain: schain } }; } diff --git a/modules/brightMountainMediaBidAdapter.js b/modules/brightMountainMediaBidAdapter.js index 5e5b062889d..1047ec931cc 100644 --- a/modules/brightMountainMediaBidAdapter.js +++ b/modules/brightMountainMediaBidAdapter.js @@ -81,7 +81,8 @@ export const spec = { oRTBRequest.imp[0].bidfloor = getFloor(bid, size); oRTBRequest.user = getUserIdAsEids(bid.userIdAsEids) - oRTBRequest.source = getSchain(bid.schain) + const schain = bid?.ortb2?.source?.ext?.schain; + oRTBRequest.source = getSchain(schain) requestData.push({ method: 'POST', diff --git a/modules/browsiBidAdapter.js b/modules/browsiBidAdapter.js index fa1cacaa568..cb256254e12 100644 --- a/modules/browsiBidAdapter.js +++ b/modules/browsiBidAdapter.js @@ -43,7 +43,8 @@ export const spec = { const requests = []; const {refererInfo, bidderRequestId, gdprConsent, uspConsent} = bidderRequest; validBidRequests.forEach(bidRequest => { - const {bidId, adUnitCode, auctionId, ortb2Imp, schain, params} = bidRequest; + const {bidId, adUnitCode, auctionId, ortb2Imp, params} = bidRequest; + const schain = bidRequest?.ortb2?.source?.ext?.schain; const video = getVideoMediaType(bidRequest); const request = { diff --git a/modules/cadentApertureMXBidAdapter.js b/modules/cadentApertureMXBidAdapter.js index 0033b41717a..0ca1c0739c3 100644 --- a/modules/cadentApertureMXBidAdapter.js +++ b/modules/cadentApertureMXBidAdapter.js @@ -187,10 +187,11 @@ export const cadentAdapter = { return cadentData; }, getSupplyChain: (bidderRequest, cadentData) => { - if (bidderRequest.bids[0] && bidderRequest.bids[0].schain) { + const schain = bidderRequest.bids[0]?.ortb2?.source?.ext?.schain; + if (bidderRequest.bids[0] && schain) { cadentData.source = { ext: { - schain: bidderRequest.bids[0].schain + schain: schain } }; } diff --git a/modules/carodaBidAdapter.js b/modules/carodaBidAdapter.js index 3060501ba8d..75af70da4ff 100644 --- a/modules/carodaBidAdapter.js +++ b/modules/carodaBidAdapter.js @@ -49,7 +49,7 @@ export const spec = { const test = getFirstWithKey(validBidRequests, 'params.test'); const currency = getCurrencyFromBidderRequest(bidderRequest); const eids = getFirstWithKey(validBidRequests, 'userIdAsEids'); - const schain = getFirstWithKey(validBidRequests, 'schain'); + const schain = getFirstWithKey(validBidRequests, 'ortb2.source.ext.schain'); const request = { // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bidderRequest.auctionId, diff --git a/modules/colossussspBidAdapter.js b/modules/colossussspBidAdapter.js index e93d6a2de27..66093ddd480 100644 --- a/modules/colossussspBidAdapter.js +++ b/modules/colossussspBidAdapter.js @@ -144,8 +144,9 @@ export const spec = { floor: {} }; - if (bid.schain) { - placement.schain = bid.schain; + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { + placement.schain = schain; } let gpid = deepAccess(bid, 'ortb2Imp.ext.gpid'); if (gpid) { diff --git a/modules/connectadBidAdapter.js b/modules/connectadBidAdapter.js index f214bf5ca2c..5bad4879beb 100644 --- a/modules/connectadBidAdapter.js +++ b/modules/connectadBidAdapter.js @@ -67,8 +67,9 @@ export const spec = { } // adding schain object - if (validBidRequests[0].schain) { - deepSetValue(data, 'source.ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(data, 'source.ext.schain', schain); } // Attaching GDPR Consent Params diff --git a/modules/consumableBidAdapter.js b/modules/consumableBidAdapter.js index e01078890f9..b85322e4eb7 100644 --- a/modules/consumableBidAdapter.js +++ b/modules/consumableBidAdapter.js @@ -82,8 +82,9 @@ export const spec = { data.ccpa = bidderRequest.uspConsent; } - if (bidderRequest && bidderRequest.schain) { - data.schain = bidderRequest.schain; + const schain = bidderRequest?.ortb2?.source?.ext?.schain; + if (schain) { + data.schain = schain; } if (config.getConfig('coppa')) { diff --git a/modules/cpmstarBidAdapter.js b/modules/cpmstarBidAdapter.js index 772cb8c537c..b9d61eaf543 100755 --- a/modules/cpmstarBidAdapter.js +++ b/modules/cpmstarBidAdapter.js @@ -71,8 +71,8 @@ export const spec = { url.searchParams.set('requestid', bidRequest.bidId); url.searchParams.set('referer', referer); - if (bidRequest.schain && bidRequest.schain.nodes) { - var schain = bidRequest.schain; + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain && schain.nodes) { var schainString = ''; schainString += schain.ver + ',' + schain.complete; for (var i2 = 0; i2 < schain.nodes.length; i2++) { diff --git a/modules/craftBidAdapter.js b/modules/craftBidAdapter.js index 3e24a68b946..7c83961c431 100644 --- a/modules/craftBidAdapter.js +++ b/modules/craftBidAdapter.js @@ -28,7 +28,7 @@ export const spec = { bidRequests = convertOrtbRequestToProprietaryNative(bidRequests); const bidRequest = bidRequests[0]; const tags = bidRequests.map(bidToTag); - const schain = bidRequest.schain; + const schain = bidRequest?.ortb2?.source?.ext?.schain; const payload = { tags: [...tags], ua: navigator.userAgent, diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js index 3cd974b2b13..3a80779fbf5 100644 --- a/modules/datablocksBidAdapter.js +++ b/modules/datablocksBidAdapter.js @@ -357,7 +357,7 @@ export const spec = { domain: window.location.host, // TODO: is 'page' the right value here? page: bidderRequest.refererInfo.page, - schain: validRequests[0].schain || {}, + schain: validRequests[0]?.ortb2?.source?.ext?.schain || {}, ext: { p_domain: bidderRequest.refererInfo.domain, rt: bidderRequest.refererInfo.reachedTop, diff --git a/modules/dianomiBidAdapter.js b/modules/dianomiBidAdapter.js index 5e43bf955ef..a91c5d777cd 100644 --- a/modules/dianomiBidAdapter.js +++ b/modules/dianomiBidAdapter.js @@ -121,7 +121,7 @@ export const spec = { const currency = getCurrencyFromBidderRequest(bidderRequest); const cur = currency && [currency]; const eids = setOnAny(validBidRequests, 'userIdAsEids'); - const schain = setOnAny(validBidRequests, 'schain'); + const schain = setOnAny(validBidRequests, 'ortb2.source.ext.schain'); const imp = validBidRequests.map((bid, id) => { bid.netRevenue = pt; diff --git a/modules/digitalMatterBidAdapter.js b/modules/digitalMatterBidAdapter.js index 34cf84eb9d3..e5acd9e98de 100644 --- a/modules/digitalMatterBidAdapter.js +++ b/modules/digitalMatterBidAdapter.js @@ -36,7 +36,7 @@ export const spec = { } const device = getDevice(common.device); - const schain = getByKey(validBidRequests, 'schain'); + const schain = getByKey(validBidRequests, 'ortb2.source.ext.schain'); const eids = getByKey(validBidRequests, 'userIdAsEids'); const currency = config.getConfig('currency') const cur = currency && [currency]; diff --git a/modules/distroscaleBidAdapter.js b/modules/distroscaleBidAdapter.js index 7a2038ed3f0..ac6f5f7eea1 100644 --- a/modules/distroscaleBidAdapter.js +++ b/modules/distroscaleBidAdapter.js @@ -197,8 +197,9 @@ export const spec = { } // adding schain object - if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain); } // Attaching GDPR Consent Params diff --git a/modules/dspxBidAdapter.js b/modules/dspxBidAdapter.js index acb5fb64d81..9f700b0e817 100644 --- a/modules/dspxBidAdapter.js +++ b/modules/dspxBidAdapter.js @@ -149,8 +149,9 @@ export const spec = { } // schain - if (bidRequest.schain) { - payload.schain = bidRequest.schain; + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } // fill userId params diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index 5b3f55b9da6..a739ddc0e3c 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -41,7 +41,7 @@ export const spec = { const method = 'GET'; const dfpClientId = '1'; const sec = 'ROS'; - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; let url; let params; const urlConfig = getUrlConfig(bidRequests); diff --git a/modules/fluctBidAdapter.js b/modules/fluctBidAdapter.js index 8ed1b52bdb6..78d574ed43b 100644 --- a/modules/fluctBidAdapter.js +++ b/modules/fluctBidAdapter.js @@ -93,8 +93,9 @@ export const spec = { data.params = request.params; - if (request.schain) { - data.schain = request.schain; + const schain = request?.ortb2?.source?.ext?.schain; + if (schain) { + data.schain = schain; } const searchParams = new URLSearchParams({ diff --git a/modules/freewheel-sspBidAdapter.js b/modules/freewheel-sspBidAdapter.js index fc85edc483b..d30be635a50 100644 --- a/modules/freewheel-sspBidAdapter.js +++ b/modules/freewheel-sspBidAdapter.js @@ -399,7 +399,7 @@ export const spec = { } // Add schain object - var schain = currentBidRequest.schain; + var schain = currentBidRequest?.ortb2?.source?.ext?.schain; if (schain) { try { requestParams.schain = JSON.stringify(schain); diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 32be0f0ee13..3d60ed77d90 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -112,8 +112,9 @@ export const spec = { deepSetValue(rtbBidRequest, 'regs.ext.gdpr', gdprConsent.consent_required === true ? 1 : 0); deepSetValue(rtbBidRequest, 'user.ext.consent', gdprConsent.consent_string); - if (validBidRequests[0].schain) { - deepSetValue(rtbBidRequest, 'source.ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(rtbBidRequest, 'source.ext.schain', schain); } if (bidderRequest && bidderRequest.uspConsent) { diff --git a/modules/greenbidsBidAdapter.js b/modules/greenbidsBidAdapter.js index 0ece04fe11f..6dc0364df0d 100644 --- a/modules/greenbidsBidAdapter.js +++ b/modules/greenbidsBidAdapter.js @@ -76,8 +76,9 @@ export const spec = { const firstBidRequest = validBidRequests[0]; - if (firstBidRequest.schain) { - payload.schain = firstBidRequest.schain; + const schain = firstBidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } hydratePayloadWithGppConsentData(payload, bidderRequest.gppConsent); diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index 244981ba94f..e860c292f93 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -115,7 +115,7 @@ export const spec = { bidderRequestId = bid.bidderRequestId; } if (!schain) { - schain = bid.schain; + schain = bid?.ortb2?.source?.ext?.schain; } if (!userIdAsEids) { userIdAsEids = bid.userIdAsEids; @@ -184,8 +184,10 @@ export const spec = { wrapper_version: '$prebid.version$' } }; - if (bid.schain) { - reqSource.ext.schain = bid.schain; + // Check for schain in the new location + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { + reqSource.ext.schain = schain; } const request = { id: bid.bidderRequestId && bid.bidderRequestId.toString(), diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 8d8e9f38081..c71a00fe332 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -365,7 +365,6 @@ function buildRequests(validBidRequests, bidderRequest) { bidId, mediaTypes = {}, params = {}, - schain, userId = {}, ortb2Imp, adUnitCode = '' @@ -488,6 +487,7 @@ function buildRequests(validBidRequests, bidderRequest) { if (coppa) { data.coppa = coppa; } + const schain = bidRequest?.ortb2?.source?.ext?.schain; if (schain && schain.nodes) { data.schain = _serializeSupplyChainObj(schain); } diff --git a/modules/holidBidAdapter.js b/modules/holidBidAdapter.js index abc8e0b403c..58172e204e1 100644 --- a/modules/holidBidAdapter.js +++ b/modules/holidBidAdapter.js @@ -32,7 +32,11 @@ export const spec = { return validBidRequests.map((bid) => { const requestData = { ...bid.ortb2, - source: { schain: bid.schain }, + source: { + ext: { + schain: bid?.ortb2?.source?.ext?.schain + } + }, id: bidderRequest.bidderRequestId, imp: [getImp(bid)], tmax: TMAX, diff --git a/modules/impactifyBidAdapter.js b/modules/impactifyBidAdapter.js index 2853bd95fd3..8ab3760e98f 100644 --- a/modules/impactifyBidAdapter.js +++ b/modules/impactifyBidAdapter.js @@ -137,7 +137,7 @@ function createOpenRtbRequest(validBidRequests, bidderRequest) { } // Set SChain in request - let schain = deepAccess(validBidRequests, '0.schain'); + let schain = deepAccess(validBidRequests, '0.ortb2.source.ext.schain'); if (schain) request.source.ext = { schain: schain }; // Set Eids diff --git a/modules/insticatorBidAdapter.js b/modules/insticatorBidAdapter.js index ba4e099dbc5..12d46fba5f5 100644 --- a/modules/insticatorBidAdapter.js +++ b/modules/insticatorBidAdapter.js @@ -357,9 +357,10 @@ function buildUser(bid) { } function extractSchain(bids, requestId) { - if (!bids || bids.length === 0 || !bids[0].schain) return; + if (!bids || bids.length === 0) return; - const schain = bids[0].schain; + const schain = bids[0]?.ortb2?.source?.ext?.schain; + if (!schain) return; if (schain && schain.nodes && schain.nodes.length && schain.nodes[0]) { schain.nodes[0].rid = requestId; } diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 265c1206a49..751c80dd50d 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -175,7 +175,7 @@ function setDisplayManager(imp, bid) { renderer = deepAccess(bid, 'renderer'); } - if (deepAccess(bid, 'schain', false)) { + if (deepAccess(bid, 'ortb2.source.ext.schain', false)) { imp.displaymanager = 'pbjs_wrapper'; } else if (renderer && typeof (renderer) === 'object') { if (renderer.url !== undefined) { @@ -861,9 +861,11 @@ function enrichRequest(r, bidderRequest, impressions, validBidRequests, userEids } // if an schain is provided, send it along - if (validBidRequests[0].schain) { - r.source.ext = {}; - r.source.ext.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + r.source = r.source || {}; + r.source.ext = r.source.ext || {}; + r.source.ext.schain = schain; } if (userEids.length > 0) { diff --git a/modules/jixieBidAdapter.js b/modules/jixieBidAdapter.js index 9ec8b38b7bb..5b8ad484d0a 100644 --- a/modules/jixieBidAdapter.js +++ b/modules/jixieBidAdapter.js @@ -209,7 +209,7 @@ export const spec = { let ids = fetchIds_(jxCfg); let eids = []; let miscDims = internal.getMiscDims(); - let schain = deepAccess(validBidRequests[0], 'schain'); + let schain = deepAccess(validBidRequests[0], 'ortb2.source.ext.schain'); let eids1 = validBidRequests[0].userIdAsEids; // all available user ids are sent to our backend in the standard array layout: diff --git a/modules/justpremiumBidAdapter.js b/modules/justpremiumBidAdapter.js index 2ed2d544a34..081a3f44a27 100644 --- a/modules/justpremiumBidAdapter.js +++ b/modules/justpremiumBidAdapter.js @@ -69,8 +69,9 @@ export const spec = { jp_adapter: JP_ADAPTER_VERSION } - if (validBidRequests[0].schain) { - payload.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } const payloadString = JSON.stringify(payload) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index c58eed8ffb8..20fd585a08c 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -185,8 +185,9 @@ function getBidAdapter() { deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - if (bidRequest.schain) { - deepSetValue(openrtbRequest, 'source.schain', bidRequest.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(openrtbRequest, 'source.schain', schain); } openrtbRequest.tmax = bidderRequest.timeout || 200; diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 229949ddaf3..cd6573869fd 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -104,9 +104,10 @@ function buildRequests(validBidRequests, bidderRequest) { krakenParams.site = { cat: firstBidRequest.ortb2.site.cat }; } - // Add schain - if (firstBidRequest.schain && firstBidRequest.schain.nodes) { - krakenParams.schain = firstBidRequest.schain + // Add schain - check for schain in the new location + const schain = firstBidRequest?.ortb2?.source?.ext?.schain; + if (schain && schain.nodes) { + krakenParams.schain = schain } // Add user data object if available diff --git a/modules/kubientBidAdapter.js b/modules/kubientBidAdapter.js index 8ccfa4ab059..b66b4e851d5 100644 --- a/modules/kubientBidAdapter.js +++ b/modules/kubientBidAdapter.js @@ -49,8 +49,9 @@ export const spec = { adSlot.video = bid.mediaTypes.video; } - if (bid.schain) { - adSlot.schain = bid.schain; + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { + adSlot.schain = schain; } let data = { diff --git a/modules/lemmaDigitalBidAdapter.js b/modules/lemmaDigitalBidAdapter.js index 2daa768eb9c..79871e9de00 100644 --- a/modules/lemmaDigitalBidAdapter.js +++ b/modules/lemmaDigitalBidAdapter.js @@ -482,7 +482,7 @@ export var spec = { return { pchain: params.pchain, ext: { - schain: request.schain + schain: request?.ortb2?.source?.ext?.schain }, }; } diff --git a/modules/limelightDigitalBidAdapter.js b/modules/limelightDigitalBidAdapter.js index e89f7a2abaa..f0a371a344b 100644 --- a/modules/limelightDigitalBidAdapter.js +++ b/modules/limelightDigitalBidAdapter.js @@ -179,7 +179,7 @@ function buildPlacement(bidRequest) { ortb2Imp: bidRequest.ortb2Imp, publisherId: bidRequest.params.publisherId, userIdAsEids: bidRequest.userIdAsEids, - supplyChain: bidRequest.schain, + supplyChain: bidRequest?.ortb2?.source?.ext?.schain, custom1: bidRequest.params.custom1, custom2: bidRequest.params.custom2, custom3: bidRequest.params.custom3, diff --git a/modules/livewrappedBidAdapter.js b/modules/livewrappedBidAdapter.js index 66237ddcde2..bb572e8ed0b 100644 --- a/modules/livewrappedBidAdapter.js +++ b/modules/livewrappedBidAdapter.js @@ -64,7 +64,7 @@ export const spec = { const ifa = find(bidRequests, hasIfaParam); const bundle = find(bidRequests, hasBundleParam); const tid = find(bidRequests, hasTidParam); - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; let ortb2 = bidderRequest.ortb2; const eids = handleEids(bidRequests); bidUrl = bidUrl ? bidUrl.params.bidUrl : URL; diff --git a/modules/lkqdBidAdapter.js b/modules/lkqdBidAdapter.js index a92e431f80a..535dbbf759b 100644 --- a/modules/lkqdBidAdapter.js +++ b/modules/lkqdBidAdapter.js @@ -110,10 +110,11 @@ export const spec = { requestData.device.ifa = bid.params.idfa || bid.params.aid; } - if (bid.schain) { + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { requestData.source = { ext: { - schain: bid.schain + schain: schain } }; } else if (bid.params.schain) { diff --git a/modules/lockerdomeBidAdapter.js b/modules/lockerdomeBidAdapter.js index 5038eadce30..e0be50e6d1c 100644 --- a/modules/lockerdomeBidAdapter.js +++ b/modules/lockerdomeBidAdapter.js @@ -12,7 +12,8 @@ export const spec = { let schain; const adUnitBidRequests = bidRequests.map(function (bid) { - if (bid.schain) schain = schain || bid.schain; + const bidSchain = bid?.ortb2?.source?.ext?.schain; + if (bidSchain) schain = schain || bidSchain; return { requestId: bid.bidId, adUnitCode: bid.adUnitCode, diff --git a/modules/loganBidAdapter.js b/modules/loganBidAdapter.js index 4e2652e452f..dd092813eb1 100644 --- a/modules/loganBidAdapter.js +++ b/modules/loganBidAdapter.js @@ -39,7 +39,7 @@ export const spec = { const placement = { placementId: bid.params.placementId, bidId: bid.bidId, - schain: bid.schain || {}, + schain: bid?.ortb2?.source?.ext?.schain || {}, bidfloor: getBidFloor(bid) }; const mediaType = bid.mediaTypes; diff --git a/modules/logicadBidAdapter.js b/modules/logicadBidAdapter.js index 8cf4a8352de..2b78082c184 100644 --- a/modules/logicadBidAdapter.js +++ b/modules/logicadBidAdapter.js @@ -104,8 +104,9 @@ function newBidRequest(bidRequest, bidderRequest) { data.userData = userData; } - if (bidRequest.schain) { - data.schain = bidRequest.schain; + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + data.schain = schain; } return data; diff --git a/modules/luceadBidAdapter.js b/modules/luceadBidAdapter.js index ffc2307bcb8..703384b9e6d 100755 --- a/modules/luceadBidAdapter.js +++ b/modules/luceadBidAdapter.js @@ -75,7 +75,7 @@ function buildRequests(bidRequests, bidderRequest) { sizes: bidRequest.sizes, media_types: bidRequest.mediaTypes, placement_id: bidRequest.params.placementId, - schain: bidRequest.schain, + schain: bidRequest?.ortb2?.source?.ext?.schain, }; }), }), diff --git a/modules/luponmediaBidAdapter.js b/modules/luponmediaBidAdapter.js index 4c99fe7e7fc..6140a421504 100755 --- a/modules/luponmediaBidAdapter.js +++ b/modules/luponmediaBidAdapter.js @@ -424,8 +424,9 @@ function newOrtbBidRequest(bidRequest, bidderRequest, currentImps) { deepSetValue(data, 'regs.coppa', 1); } - if (bidRequest.schain && hasValidSupplyChainParams(bidRequest.schain)) { - deepSetValue(data, 'source.ext.schain', bidRequest.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain && hasValidSupplyChainParams(schain)) { + deepSetValue(data, 'source.ext.schain', schain); } // TODO: getConfig('fpd.context') should not have worked even with legacy FPD support - 'fpd' gets translated diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 81e78ba87b1..850ed6eaa3a 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -207,8 +207,9 @@ function MarsmediaAdapter() { } } }; - if (BRs[0].schain) { - deepSetValue(bid, 'source.ext.schain', BRs[0].schain); + const schain = BRs[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(bid, 'source.ext.schain', schain); } if (bidderRequest.uspConsent) { deepSetValue(bid, 'regs.ext.us_privacy', bidderRequest.uspConsent) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index 7e0bd9428c5..6cd2a7176ce 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -187,7 +187,7 @@ export const spec = { const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; const omidSupport = find(bidRequests, hasOmidSupport); const payload = { diff --git a/modules/mediakeysBidAdapter.js b/modules/mediakeysBidAdapter.js index 39a6113477d..b0aee892159 100644 --- a/modules/mediakeysBidAdapter.js +++ b/modules/mediakeysBidAdapter.js @@ -620,8 +620,9 @@ export const spec = { payload.imp.push(imp); }); - if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain); } if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 38e8a17f442..6b09fafc016 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -162,7 +162,7 @@ function extParams(bidRequest, bidderRequests) { const gdpr = deepAccess(bidderRequests, 'gdprConsent'); const uspConsent = deepAccess(bidderRequests, 'uspConsent'); const userId = deepAccess(bidRequest, 'userId'); - const sChain = deepAccess(bidRequest, 'schain') || {}; + const sChain = deepAccess(bidRequest, 'ortb2.source.ext.schain') || {}; const windowSize = spec.getWindowSize(); const gdprApplies = !!(gdpr && gdpr.gdprApplies); const uspApplies = !!(uspConsent); diff --git a/modules/mediasquareBidAdapter.js b/modules/mediasquareBidAdapter.js index a84c19b786b..b3960ad8ad1 100644 --- a/modules/mediasquareBidAdapter.js +++ b/modules/mediasquareBidAdapter.js @@ -91,7 +91,8 @@ export const spec = { }; } if (bidderRequest.uspConsent) { payload.uspConsent = bidderRequest.uspConsent; } - if (bidderRequest.schain) { payload.schain = bidderRequest.schain; } + const schain = bidderRequest?.ortb2?.source?.ext?.schain; + if (schain) { payload.schain = schain; } if (bidderRequest.userId) { payload.userId = bidderRequest.userId; } else if (bidderRequest.hasOwnProperty('bids') && typeof bidderRequest.bids == 'object' && bidderRequest.bids.length > 0 && bidderRequest.bids[0].hasOwnProperty('userId')) { diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 86cd3fb8250..7a0856a2859 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -304,7 +304,7 @@ export const spec = { deepSetValue(request, 'regs.coppa', 1); } } - const schain = setOnAny(validBidRequests, 'schain'); + const schain = setOnAny(validBidRequests, 'ortb2.source.ext.schain'); if (schain) { deepSetValue(request, 'source.ext.schain', schain); } diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 56c073cddde..ff95b509b3b 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -217,8 +217,9 @@ const converter = ortbConverter({ 'site.ext.michao.site', bidRequest.params.site.toString() ); - if (bidRequest?.schain) { - deepSetValue(openRTBBidRequest, 'source.schain', bidRequest.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(openRTBBidRequest, 'source.schain', schain); } if (bidRequest.params?.partner) { diff --git a/modules/missenaBidAdapter.js b/modules/missenaBidAdapter.js index 0d2054ca09f..fc7bdaaf5c7 100644 --- a/modules/missenaBidAdapter.js +++ b/modules/missenaBidAdapter.js @@ -68,7 +68,7 @@ function toPayload(bidRequest, bidderRequest) { payload.floor = bidFloor?.floor; payload.floor_currency = bidFloor?.currency; payload.currency = getCurrencyFromBidderRequest(bidderRequest); - payload.schain = bidRequest.schain; + payload.schain = bidRequest?.ortb2?.source?.ext?.schain; payload.autoplay = isAutoplayEnabled() === true ? 1 : 0; payload.screen = { height: getWinDimensions().screen.height, width: getWinDimensions().screen.width }; payload.viewport = getViewportSize(); diff --git a/modules/nextMillenniumBidAdapter.js b/modules/nextMillenniumBidAdapter.js index d4886e9d2ac..a6f90c272f4 100644 --- a/modules/nextMillenniumBidAdapter.js +++ b/modules/nextMillenniumBidAdapter.js @@ -508,8 +508,7 @@ function getDeviceObj() { } export function getSourceObj(validBidRequests, bidderRequest) { - const schain = validBidRequests?.[0]?.schain || - (bidderRequest?.ortb2?.source && (bidderRequest?.ortb2?.source?.schain || bidderRequest?.ortb2?.source?.ext?.schain)); + const schain = validBidRequests?.[0]?.ortb2?.source?.ext?.schain || bidderRequest?.ortb2?.source?.schain || bidderRequest?.ortb2?.source?.ext?.schain; if (!schain) return; diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index f9d4058b646..d83620b10ee 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -86,10 +86,11 @@ function nobidBuildRequests(bids, bidderRequest) { return gppConsent; } var schain = function(bids) { - if (bids && bids.length > 0) { - return bids[0].schain + try { + return bids[0]?.ortb2?.source?.ext?.schain; + } catch (e) { + return null; } - return null; } var coppa = function() { if (config.getConfig('coppa') === true) { diff --git a/modules/omsBidAdapter.js b/modules/omsBidAdapter.js index 0b9ac002bb0..20a9336b7e3 100644 --- a/modules/omsBidAdapter.js +++ b/modules/omsBidAdapter.js @@ -114,8 +114,9 @@ function buildRequests(bidReqs, bidderRequest) { deepSetValue(payload, 'regs.coppa', 1); } - if (bidReqs?.[0]?.schain) { - deepSetValue(payload, 'source.ext.schain', bidReqs[0].schain) + const schain = bidReqs?.[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain) } if (bidderRequest?.ortb2?.user) { diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index d69aa22a7c3..05b44ee6f1a 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -133,8 +133,9 @@ function buildRequests(validBidRequests, bidderRequest) { if (validBidRequests && validBidRequests.length !== 0 && validBidRequests[0].userIdAsEids) { payload.userId = validBidRequests[0].userIdAsEids; } - if (validBidRequests && validBidRequests.length !== 0 && validBidRequests[0].schain && isSchainValid(validBidRequests[0].schain)) { - payload.schain = validBidRequests[0].schain; + const schain = validBidRequests?.[0]?.ortb2?.source?.ext?.schain; + if (validBidRequests && validBidRequests.length !== 0 && schain && isSchainValid(schain)) { + payload.schain = schain; } try { if (storage.hasLocalStorage()) { diff --git a/modules/opscoBidAdapter.js b/modules/opscoBidAdapter.js index 2ad14227804..4ddb548c0f1 100644 --- a/modules/opscoBidAdapter.js +++ b/modules/opscoBidAdapter.js @@ -59,9 +59,10 @@ export const spec = { deepSetValue(payload, 'user.ext.eids', eids); } - const schainData = deepAccess(validBidRequests[0], 'schain.nodes'); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + const schainData = schain?.nodes; if (isArray(schainData) && schainData.length > 0) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + deepSetValue(payload, 'source.ext.schain', schain); } if (bidderRequest.uspConsent) { diff --git a/modules/optidigitalBidAdapter.js b/modules/optidigitalBidAdapter.js index f8dea0f5a92..0d6d51387f8 100755 --- a/modules/optidigitalBidAdapter.js +++ b/modules/optidigitalBidAdapter.js @@ -73,8 +73,9 @@ export const spec = { payload.pageTemplate = validBidRequests[0].params.pageTemplate; } - if (validBidRequests[0].schain) { - payload.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } const gdpr = deepAccess(bidderRequest, 'gdprConsent'); diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index ead659a7f3b..1992cfcefe5 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -330,8 +330,8 @@ export const spec = { deepSetValue(obj, `ext.${whitelabelBidder}.customData.0.targeting`, fpd.site); } } - if (!schain && deepAccess(ozoneBidRequest, 'schain')) { - schain = ozoneBidRequest.schain; + if (!schain && deepAccess(ozoneBidRequest, 'ortb2.source.ext.schain')) { + schain = ozoneBidRequest.ortb2.source.ext.schain; } let gpid = deepAccess(ozoneBidRequest, 'ortb2Imp.ext.gpid'); if (gpid) { diff --git a/modules/pixfutureBidAdapter.js b/modules/pixfutureBidAdapter.js index e768cd901d0..10f7f855152 100644 --- a/modules/pixfutureBidAdapter.js +++ b/modules/pixfutureBidAdapter.js @@ -73,7 +73,7 @@ export const spec = { }); } - const schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; const payload = { tags: [...tags], diff --git a/modules/prebidServerBidAdapter/ortbConverter.js b/modules/prebidServerBidAdapter/ortbConverter.js index b9a183a4c08..d60ed0f7ef0 100644 --- a/modules/prebidServerBidAdapter/ortbConverter.js +++ b/modules/prebidServerBidAdapter/ortbConverter.js @@ -221,10 +221,7 @@ const PBS_CONVERTER = ortbConverter({ .filter((req) => !chainBidders.has(req.bidderCode)) // schain defined in s2sConfig.extPrebid takes precedence .map((req) => { const bid = req?.bids?.[0] || {}; - // Check for schain in different locations with priority - const schain = bid?.ortb2?.source?.ext?.schain || // First check in ortb2.source.ext.schain (new location) - bid?.ortb2?.source?.schain || // Then check in ortb2.source.schain (transitional location) - bid?.schain; // Finally check directly on the bid (legacy location) + const schain = bid?.ortb2?.source?.ext?.schain; return { bidders: [req.bidderCode], diff --git a/modules/prismaBidAdapter.js b/modules/prismaBidAdapter.js index 9f7d37dcebe..abb83dd1ae7 100644 --- a/modules/prismaBidAdapter.js +++ b/modules/prismaBidAdapter.js @@ -78,7 +78,8 @@ export const spec = { payload.gdprConsent = ''; } if (bidderRequest.uspConsent) { payload.uspConsent = bidderRequest.uspConsent; } - if (bidderRequest.schain) { payload.schain = bidderRequest.schain; } + const schain = bidderRequest?.ortb2?.source?.ext?.schain; + if (schain) { payload.schain = schain; } if (userEids !== null) payload.userEids = userEids; }; payload.connectionType = getConnectionType(); diff --git a/modules/pubgeniusBidAdapter.js b/modules/pubgeniusBidAdapter.js index 19260e65e60..7cb4d2df127 100644 --- a/modules/pubgeniusBidAdapter.js +++ b/modules/pubgeniusBidAdapter.js @@ -71,7 +71,7 @@ export const spec = { deepSetValue(data, 'regs.ext.us_privacy', usp); } - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; if (schain) { deepSetValue(data, 'source.ext.schain', schain); } diff --git a/modules/pubwiseBidAdapter.js b/modules/pubwiseBidAdapter.js index f77cb9a47d1..69ec20d828b 100644 --- a/modules/pubwiseBidAdapter.js +++ b/modules/pubwiseBidAdapter.js @@ -253,9 +253,10 @@ export const spec = { // passing transactionId in source.tid deepSetValue(payload, 'source.tid', bidderRequest?.ortb2?.source?.tid); - // schain - if (validBidRequests[0].schain) { - deepSetValue(payload, 'source.ext.schain', validBidRequests[0].schain); + // schain - check for schain in the new location + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(payload, 'source.ext.schain', schain); } // gdpr consent diff --git a/modules/qwarryBidAdapter.js b/modules/qwarryBidAdapter.js index 4b3e8fa8a19..73191f099a0 100644 --- a/modules/qwarryBidAdapter.js +++ b/modules/qwarryBidAdapter.js @@ -29,7 +29,7 @@ export const spec = { requestId: bidderRequest.bidderRequestId, bids, referer: bidderRequest.refererInfo.page, - schain: validBidRequests[0].schain + schain: validBidRequests[0]?.ortb2?.source?.ext?.schain } if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 3ab8b79df81..f710c1a079e 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -168,10 +168,11 @@ function RhythmOneBidAdapter() { } } }; - if (BRs[0].schain) { + const schain = BRs[0]?.ortb2?.source?.ext?.schain; + if (schain) { bid.source = { 'ext': { - 'schain': BRs[0].schain + 'schain': schain } } } diff --git a/modules/richaudienceBidAdapter.js b/modules/richaudienceBidAdapter.js index 9bd395fc166..a241b2fa19e 100644 --- a/modules/richaudienceBidAdapter.js +++ b/modules/richaudienceBidAdapter.js @@ -54,7 +54,7 @@ export const spec = { scr_rsl: raiGetResolution(), cpuc: (typeof window.navigator != 'undefined' ? window.navigator.hardwareConcurrency : null), kws: bid.params.keywords, - schain: bid.schain, + schain: bid?.ortb2?.source?.ext?.schain, gpid: raiSetPbAdSlot(bid), dsa: setDSA(bid), userData: deepAccess(bid, 'ortb2.user.data') diff --git a/modules/rtbhouseBidAdapter.js b/modules/rtbhouseBidAdapter.js index 74a4df14f6f..bc1b02f74d8 100644 --- a/modules/rtbhouseBidAdapter.js +++ b/modules/rtbhouseBidAdapter.js @@ -53,8 +53,9 @@ export const spec = { request.regs = {ext: {gdpr: gdpr}}; request.user = {ext: {consent: consentStr}}; } - if (validBidRequests[0].schain) { - const schain = mapSchain(validBidRequests[0].schain); + const bidSchain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (bidSchain) { + const schain = mapSchain(bidSchain); if (schain) { request.ext = { schain: schain, diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 02f41904099..0c6d7d29163 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -617,8 +617,9 @@ export const spec = { } // if SupplyChain is supplied and contains all required fields - if (bidRequest.ortb2?.source?.schain && hasValidSupplyChainParams(bidRequest.ortb2.source.schain)) { - data.rp_schain = spec.serializeSupplyChain(bidRequest.ortb2.source.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain && hasValidSupplyChainParams(schain)) { + data.rp_schain = spec.serializeSupplyChain(schain); } return data; diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js index f54313c7075..922a40f6698 100644 --- a/modules/seedtagBidAdapter.js +++ b/modules/seedtagBidAdapter.js @@ -319,8 +319,9 @@ export const spec = { payload['uspConsent'] = bidderRequest.uspConsent; } - if (validBidRequests[0].schain) { - payload.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } let coppa = config.getConfig('coppa'); diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 5c5c8fe6eec..ab63b2f36e8 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -57,7 +57,7 @@ export const sharethroughAdapterSpec = { ext: { version: '$prebid.version$', str: VERSION, - schain: bidRequests[0].schain, + schain: bidRequests[0]?.ortb2?.source?.ext?.schain, }, }, bcat: deepAccess(bidderRequest.ortb2, 'bcat') || bidRequests[0].params.bcat || [], diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js index fc7ad9d7d94..9c07a26c107 100644 --- a/modules/smaatoBidAdapter.js +++ b/modules/smaatoBidAdapter.js @@ -340,7 +340,7 @@ const converter = ortbConverter({ request.source = { ext: { - schain: bidRequest.schain + schain: bidRequest?.ortb2?.source?.ext?.schain } }; request.ext = { diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 790b94165cb..73073e3da31 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -204,7 +204,7 @@ export const spec = { timeout: config.getConfig('bidderTimeout'), bidId: bid.bidId, prebidVersion: '$prebid.version$', - schain: spec.serializeSupplyChain(bid.schain), + schain: spec.serializeSupplyChain(bid?.ortb2?.source?.ext?.schain), sda: sellerDefinedAudience, sdc: sellerDefinedContext }; diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 1442199cd6d..55254e9bd82 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -216,11 +216,12 @@ export const spec = { userExt.fpc = pubcid; } - // Add schain object if available - if (bid && bid.schain) { + // Add schain object if available from the new location + const schain = bid?.ortb2?.source?.ext?.schain; + if (bid && schain) { requestPayload['source'] = { ext: { - schain: bid.schain + schain: schain } }; } diff --git a/modules/smartyadsBidAdapter.js b/modules/smartyadsBidAdapter.js index de7c61b7163..67904d10fe6 100644 --- a/modules/smartyadsBidAdapter.js +++ b/modules/smartyadsBidAdapter.js @@ -63,8 +63,9 @@ export const spec = { traffic: traff, publisherId: bid.params.accountid }); - if (bid.schain) { - placements.schain = bid.schain; + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain) { + placements.schain = schain; } } diff --git a/modules/smilewantedBidAdapter.js b/modules/smilewantedBidAdapter.js index a78c60f8308..cbde1229ac8 100644 --- a/modules/smilewantedBidAdapter.js +++ b/modules/smilewantedBidAdapter.js @@ -84,7 +84,7 @@ export const spec = { */ positionType: bid.params.positionType || '', prebidVersion: '$prebid.version$', - schain: serializeSupplyChain(bid.schain, ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext']), + schain: serializeSupplyChain(bid?.ortb2?.source?.ext?.schain, ['asi', 'sid', 'hp', 'rid', 'name', 'domain', 'ext']), }; const floor = getBidFloor(bid); diff --git a/modules/snigelBidAdapter.js b/modules/snigelBidAdapter.js index 60d5becac36..55a8d4d5246 100644 --- a/modules/snigelBidAdapter.js +++ b/modules/snigelBidAdapter.js @@ -58,7 +58,7 @@ export const spec = { uspConsent: deepAccess(bidderRequest, 'uspConsent'), coppa: getConfig('coppa'), eids: deepAccess(bidRequests, '0.userIdAsEids'), - schain: deepAccess(bidRequests, '0.schain'), + schain: deepAccess(bidRequests, '0.ortb2.source.ext.schain'), page: getPage(bidderRequest), topframe: inIframe() === true ? 0 : 1, device: { diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index b67b0029179..efde29b8cc9 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -133,8 +133,9 @@ export const spec = { } } - if (validBidRequests[0].schain) { - payload.schain = JSON.stringify(validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = JSON.stringify(schain); } const eids = deepAccess(validBidRequests[0], 'userIdAsEids'); diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 8cc07966708..8d1b1aa950e 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -86,8 +86,9 @@ export const spec = { }) } - if (bid.schain) { - schain = schain || bid.schain + const bidSchain = bid?.ortb2?.source?.ext?.schain; + if (bidSchain) { + schain = schain || bidSchain } iv = iv || getBidIdParameter('iv', bid.params) diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index a3f06c9c324..1de3fb686fd 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -628,7 +628,7 @@ const spec = { const ref = bidderRequest.refererInfo.ref; const { source = {}, regs = {} } = ortb2 || {}; - source.schain = setOnAny(validBidRequests, 'schain'); + source.schain = setOnAny(validBidRequests, 'ortb2.source.ext.schain'); const payload = { id: bidderRequest.bidderRequestId, diff --git a/modules/stroeerCoreBidAdapter.js b/modules/stroeerCoreBidAdapter.js index bf818250c63..cc61fc936d5 100644 --- a/modules/stroeerCoreBidAdapter.js +++ b/modules/stroeerCoreBidAdapter.js @@ -56,7 +56,7 @@ export const spec = { mpa: isMainPageAccessible(), timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart), url: refererInfo.page, - schain: anyBid.schain + schain: anyBid?.ortb2?.source?.ext?.schain }; const userIds = anyBid.userId; diff --git a/modules/stvBidAdapter.js b/modules/stvBidAdapter.js index ef8b815b5f9..4e5becde9ab 100644 --- a/modules/stvBidAdapter.js +++ b/modules/stvBidAdapter.js @@ -69,8 +69,9 @@ export const spec = { if (!isVideoRequest(bidRequest)) { payload._f = 'html'; } - if (bidRequest.schain) { - payload.schain = serializeSChain(bidRequest.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = serializeSChain(schain); } else { delete payload.schain; } diff --git a/modules/targetVideoBidAdapter.js b/modules/targetVideoBidAdapter.js index c149e80749d..c911e0dc7cb 100644 --- a/modules/targetVideoBidAdapter.js +++ b/modules/targetVideoBidAdapter.js @@ -98,9 +98,10 @@ export const spec = { }; }; - if (bidRequests[0].schain) { + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { payload.source = { - ext: { schain: bidRequests[0].schain } + ext: { schain: schain } }; } @@ -110,7 +111,7 @@ export const spec = { case BANNER: { const tags = bidRequests.map(createVideoTag); - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; const payload = { tags, diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index 97cfa273b1e..aaf7c8f0f54 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -86,8 +86,9 @@ export const spec = { const firstBidRequest = validBidRequests[0]; - if (firstBidRequest.schain) { - payload.schain = firstBidRequest.schain; + const schain = firstBidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } let gpp = bidderRequest.gppConsent; diff --git a/modules/themoneytizerBidAdapter.js b/modules/themoneytizerBidAdapter.js index 9f187478fa7..11a609b7874 100644 --- a/modules/themoneytizerBidAdapter.js +++ b/modules/themoneytizerBidAdapter.js @@ -33,7 +33,7 @@ export const spec = { ortb2: bidderRequest.ortb2, eids: bidRequest.userIdAsEids, id: bidRequest.auctionId, - schain: bidRequest.schain, + schain: bidRequest?.ortb2?.source?.ext?.schain, version: '$prebid.version$', excl_sync: window.tmzrBidderExclSync }; diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 0c8bd330e11..aa2865c5251 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -154,7 +154,7 @@ function _filterSid(sid) { function _buildPostBody(bidRequests, bidderRequest) { let data = {}; - let { schain } = bidRequests[0]; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; const globalFpd = _getGlobalFpd(bidderRequest); data.imp = bidRequests.map(function(bidRequest, index) { diff --git a/modules/ttdBidAdapter.js b/modules/ttdBidAdapter.js index 2222de3865f..79b1c6477ff 100644 --- a/modules/ttdBidAdapter.js +++ b/modules/ttdBidAdapter.js @@ -81,8 +81,9 @@ function getSource(validBidRequests, bidderRequest) { let source = { tid: bidderRequest?.ortb2?.source?.tid, }; - if (validBidRequests[0].schain) { - utils.deepSetValue(source, 'ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + utils.deepSetValue(source, 'ext.schain', schain); } return source; } diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index d5017db0705..5c92ae3120c 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -261,7 +261,8 @@ function getRequestData(bid, bidderRequest) { const language = navigator.language; const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; const userIdTdid = (bid.userId && bid.userId.tdid) ? bid.userId.tdid : ''; - const supplyChain = getSupplyChain(bid.schain); + const schain = bid?.ortb2?.source?.ext?.schain; + const supplyChain = getSupplyChain(schain); const bidFloor = getFloor(bid, size, bid.mediaTypes); const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid'); // general bid data diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 0c4f41f647b..358b0f2f113 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -76,8 +76,9 @@ export const spec = { 'uids': validBidRequests[0].userId, 'pageSize': pageSizeArray }; - if (validBidRequests[0].schain) { - commons.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + commons.schain = schain; } const payload = { 'x-ut-hb-params': [], diff --git a/modules/vdoaiBidAdapter.js b/modules/vdoaiBidAdapter.js index 6ef5b6ebb3e..a570b6a43f3 100644 --- a/modules/vdoaiBidAdapter.js +++ b/modules/vdoaiBidAdapter.js @@ -169,7 +169,7 @@ function vdoBuildPlacement(vdoBidRequest) { ortb2Imp: vdoBidRequest.ortb2Imp, publisherId: vdoBidRequest.params.publisherId, userIdAsEids: vdoBidRequest.userIdAsEids, - supplyChain: vdoBidRequest.schain, + supplyChain: vdoBidRequest?.ortb2?.source?.ext?.schain, custom1: vdoBidRequest.params.custom1, custom2: vdoBidRequest.params.custom2, custom3: vdoBidRequest.params.custom3, diff --git a/modules/videobyteBidAdapter.js b/modules/videobyteBidAdapter.js index c34d3ecb097..a0746821724 100644 --- a/modules/videobyteBidAdapter.js +++ b/modules/videobyteBidAdapter.js @@ -252,8 +252,9 @@ function buildRequestData(bidRequest, bidderRequest) { } // adding schain object - if (bidRequest.schain) { - deepSetValue(openrtbRequest, 'source.ext.schain', bidRequest.schain); + const schain = bidRequest?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(openrtbRequest, 'source.ext.schain', schain); openrtbRequest.source.ext.schain.nodes[0].rid = openrtbRequest.id; } diff --git a/modules/vidoomyBidAdapter.js b/modules/vidoomyBidAdapter.js index 894d3191311..ef1b092c658 100644 --- a/modules/vidoomyBidAdapter.js +++ b/modules/vidoomyBidAdapter.js @@ -158,7 +158,7 @@ const buildRequests = (validBidRequests, bidderRequest) => { dt: /Mobi/.test(navigator.userAgent) ? 2 : 1, pid: bid.params.pid, requestId: bid.bidId, - schain: serializeSupplyChainObj(bid.schain) || '', + schain: serializeSupplyChainObj(bid?.ortb2?.source?.ext?.schain) || '', eids: eids || '', bidfloor: floor, d: getDomainWithoutSubdomain(hostname), // 'vidoomy.com', diff --git a/modules/viouslyBidAdapter.js b/modules/viouslyBidAdapter.js index e474a8de93c..d400d30032e 100644 --- a/modules/viouslyBidAdapter.js +++ b/modules/viouslyBidAdapter.js @@ -129,8 +129,9 @@ export const spec = { } // Schain - if (validBidRequests[0].schain) { - payload.schain = validBidRequests[0].schain; + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + payload.schain = schain; } // Currency payload.currency_code = CURRENCY; diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 510106845db..f305a3d3889 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -87,7 +87,8 @@ export const spec = { imp.push(impObj); bidsMap[bid.bidId] = bid; } - const { params: { uid }, schain, userId, userIdAsEids } = bid; + const { params: { uid }, userId, userIdAsEids } = bid; + const schain = bid?.ortb2?.source?.ext?.schain; if (!payloadSchain && schain) { payloadSchain = schain; } diff --git a/modules/voxBidAdapter.js b/modules/voxBidAdapter.js index b0cfdabee9f..1cef1f28e3d 100644 --- a/modules/voxBidAdapter.js +++ b/modules/voxBidAdapter.js @@ -28,7 +28,7 @@ function buildBidRequests(validBidRequests, bidderRequest) { const params = bid.params; const bidRequest = { floorInfo, - schain: bid.schain, + schain: bid?.ortb2?.source?.ext?.schain, userId: bid.userId, bidId: bid.bidId, // TODO: fix transactionId leak: https://github.com/prebid/Prebid.js/issues/9781 diff --git a/modules/vuukleBidAdapter.js b/modules/vuukleBidAdapter.js index f3ab2562ef4..6dd5709fe78 100644 --- a/modules/vuukleBidAdapter.js +++ b/modules/vuukleBidAdapter.js @@ -31,7 +31,7 @@ export const spec = { rnd: Math.random(), bidId: bid.bidId, source: 'pbjs', - schain: JSON.stringify(bid.schain), + schain: JSON.stringify(bid?.ortb2?.source?.ext?.schain), requestId: bid.bidderRequestId, tmax: bidderRequest.timeout, gdpr: (bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) ? 1 : 0, diff --git a/modules/winrBidAdapter.js b/modules/winrBidAdapter.js index 2f1d46555d8..4e1dd6b9920 100644 --- a/modules/winrBidAdapter.js +++ b/modules/winrBidAdapter.js @@ -195,7 +195,7 @@ export const spec = { const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; const payload = { tags: [...tags], diff --git a/modules/yahooAdsBidAdapter.js b/modules/yahooAdsBidAdapter.js index 6e67df84b2f..a72deab51ae 100644 --- a/modules/yahooAdsBidAdapter.js +++ b/modules/yahooAdsBidAdapter.js @@ -328,9 +328,9 @@ function generateOpenRtbObject(bidderRequest, bid) { outBoundBidRequest = appendFirstPartyData(outBoundBidRequest, bid); }; - const schainData = deepAccess(bid, 'schain.nodes'); - if (isArray(schainData) && schainData.length > 0) { - outBoundBidRequest.source.ext.schain = bid.schain; + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain && isArray(schain.nodes) && schain.nodes.length > 0) { + outBoundBidRequest.source.ext.schain = schain; outBoundBidRequest.source.ext.schain.nodes[0].rid = outBoundBidRequest.id; }; diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index fda54328b85..83b079c4d1b 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -77,8 +77,9 @@ export const spec = { query[prop] = bid.params.customParams[prop]; } } - if (bid.schain && isPlainObject(bid.schain) && Array.isArray(bid.schain.nodes)) { - query.schain = createSchainString(bid.schain); + const schain = bid?.ortb2?.source?.ext?.schain; + if (schain && isPlainObject(schain) && Array.isArray(schain.nodes)) { + query.schain = createSchainString(schain); } const iabContent = getContentObject(bid); diff --git a/modules/yieldliftBidAdapter.js b/modules/yieldliftBidAdapter.js index d4cafd77c2d..ba53f2a6340 100644 --- a/modules/yieldliftBidAdapter.js +++ b/modules/yieldliftBidAdapter.js @@ -57,8 +57,9 @@ export const spec = { }; // adding schain object - if (validBidRequests[0].schain) { - deepSetValue(openrtbRequest, 'source.ext.schain', validBidRequests[0].schain); + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { + deepSetValue(openrtbRequest, 'source.ext.schain', schain); } // Attaching GDPR Consent Params diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 010f05ec6f9..46120d06676 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -140,8 +140,9 @@ export const spec = { if (criteoId) { serverRequest.cri_prebid = criteoId; } - if (request.schain) { - serverRequest.schain = JSON.stringify(request.schain); + const schain = deepAccess(request, 'ortb2.source.ext.schain'); + if (schain) { + serverRequest.schain = JSON.stringify(schain); } if (deepAccess(request, 'params.lr_env')) { serverRequest.ats_envelope = request.params.lr_env; @@ -415,7 +416,7 @@ function getId(request, idType) { * @return Object OpenRTB request object */ function openRtbRequest(bidRequests, bidderRequest) { - const schain = bidRequests[0].schain; + const schain = bidRequests[0]?.ortb2?.source?.ext?.schain; let openRtbRequest = { id: bidRequests[0].bidderRequestId, tmax: bidderRequest.timeout || 400, diff --git a/modules/zeta_global_sspBidAdapter.js b/modules/zeta_global_sspBidAdapter.js index 62e60db020f..04655b39499 100644 --- a/modules/zeta_global_sspBidAdapter.js +++ b/modules/zeta_global_sspBidAdapter.js @@ -178,11 +178,12 @@ export const spec = { deepSetValue(payload, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - // schain - if (validBidRequests[0].schain) { + // schain - check for schain in the new location + const schain = validBidRequests[0]?.ortb2?.source?.ext?.schain; + if (schain) { payload.source = { ext: { - schain: validBidRequests[0].schain + schain: schain } } } diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 94e83ff4b23..828178c4ac3 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -1420,7 +1420,7 @@ describe('33acrossBidAdapter:', function () { ]; schainValues.forEach((schain) => { - bidRequests[0].ortb2.source = {schain: schain}; + bidRequests[0].ortb2.source = {ext: {schain: schain}}; const ttxRequest = new TtxRequestBuilder() .withBanner() diff --git a/test/spec/modules/ViouslyBidAdapter_spec.js b/test/spec/modules/ViouslyBidAdapter_spec.js index f8cd686581c..1a1767e7491 100644 --- a/test/spec/modules/ViouslyBidAdapter_spec.js +++ b/test/spec/modules/ViouslyBidAdapter_spec.js @@ -238,7 +238,13 @@ describe('ViouslyAdapter', function () { }; let bid = mergeDeep(deepClone(VALID_BID_VIDEO), { - schain: schain + ortb2: { + source: { + ext: { + schain: schain + } + } + } }); let requests = mergeDeep(deepClone(VALID_REQUEST_VIDEO), { diff --git a/test/spec/modules/adagioBidAdapter_spec.js b/test/spec/modules/adagioBidAdapter_spec.js index a129d690c9e..106dbd0e082 100644 --- a/test/spec/modules/adagioBidAdapter_spec.js +++ b/test/spec/modules/adagioBidAdapter_spec.js @@ -618,12 +618,13 @@ describe('Adagio bid adapter', () => { }; it('should add the schain if available at bidder level', function() { - const bid01 = new BidRequestBuilder({ schain }).withParams().build(); + const bid01 = new BidRequestBuilder({ ortb2: { source: { ext: { schain } } } }).withParams().build(); const bidderRequest = new BidderRequestBuilder().build(); const requests = spec.buildRequests([bid01], bidderRequest); expect(requests[0].data).to.have.all.keys(expectedDataKeys); + expect(requests[0].data.schain).to.exist; expect(requests[0].data.schain).to.deep.equal(schain); }); diff --git a/test/spec/modules/adfBidAdapter_spec.js b/test/spec/modules/adfBidAdapter_spec.js index 2b8009a5d72..0363ef01e06 100644 --- a/test/spec/modules/adfBidAdapter_spec.js +++ b/test/spec/modules/adfBidAdapter_spec.js @@ -330,10 +330,16 @@ describe('Adf adapter', function () { let validBidRequests = [{ bidId: 'bidId', params: {}, - schain: { - validation: 'strict', - config: { - ver: '1.0' + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0' + } + } + } } } }]; diff --git a/test/spec/modules/adotBidAdapter_spec.js b/test/spec/modules/adotBidAdapter_spec.js index df628088bb0..3cb2975d0e8 100644 --- a/test/spec/modules/adotBidAdapter_spec.js +++ b/test/spec/modules/adotBidAdapter_spec.js @@ -28,7 +28,7 @@ describe('Adot Adapter', function () { it('should build request (banner)', function () { const bidderRequestId = 'bidderRequestId'; const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { banner: { sizes: [[300, 250]] } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, schain: { ver: '1.0' } }; + const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, ortb2: { source: { ext: { schain: { ver: '1.0' } } } } }; const request = spec.buildRequests(validBidRequests, bidderRequest); const buildBidRequestResponse = { @@ -77,7 +77,7 @@ describe('Adot Adapter', function () { it('should build request (native)', function () { const bidderRequestId = 'bidderRequestId'; const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { native: { title: { required: true, len: 50, sizes: [[300, 250]] }, wrong: {}, image: {} } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, schain: { ver: '1.0' } }; + const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, ortb2: { source: { ext: { schain: { ver: '1.0' } } } } }; const request = spec.buildRequests(validBidRequests, bidderRequest); const buildBidRequestResponse = { @@ -125,7 +125,7 @@ describe('Adot Adapter', function () { it('should build request (video)', function () { const bidderRequestId = 'bidderRequestId'; const validBidRequests = [{ bidderRequestId, mediaTypes: {} }, { bidderRequestId, bidId: 'bidId', mediaTypes: { video: { playerSize: [[300, 250]], minduration: 1, maxduration: 2, api: 'api', linearity: 'linearity', mimes: [], plcmt: '1', playbackmethod: 'playbackmethod', protocols: 'protocol', startdelay: 'startdelay' } }, params: { placementId: 'placementId', adUnitCode: 200 } }]; - const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, schain: { ver: '1.0' } }; + const bidderRequest = { position: 2, refererInfo: { page: 'http://localhost.com', domain: 'localhost.com' }, gdprConsent: { consentString: 'consentString', gdprApplies: true }, userId: { pubProvidedId: 'userId' }, ortb2: { source: { ext: { schain: { ver: '1.0' } } } } }; const request = spec.buildRequests(validBidRequests, bidderRequest); const buildBidRequestResponse = { diff --git a/test/spec/modules/adspiritBidAdapter_spec.js b/test/spec/modules/adspiritBidAdapter_spec.js index e41cf72abf7..df472f5246f 100644 --- a/test/spec/modules/adspiritBidAdapter_spec.js +++ b/test/spec/modules/adspiritBidAdapter_spec.js @@ -154,16 +154,22 @@ describe('Adspirit Bidder Spec', function () { mediaTypes: { banner: { sizes: [[300, 250]] } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'publisher.com', - sid: '1234', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'publisher.com', + sid: '1234', + hp: 1 + } + ] + } } - ] + } } } ]; @@ -174,7 +180,7 @@ describe('Adspirit Bidder Spec', function () { const requestData = JSON.parse(request.data); expect(requestData.source).to.exist; expect(requestData.source.ext).to.exist; - expect(requestData.source.ext.schain).to.deep.equal(bidRequest[0].schain); + expect(requestData.source.ext.schain).to.deep.equal(bidRequest[0].ortb2.source.ext.schain); }); it('should correctly handle bidfloor values (valid, missing, and non-numeric)', function () { const bidRequest = [ diff --git a/test/spec/modules/adstirBidAdapter_spec.js b/test/spec/modules/adstirBidAdapter_spec.js index a62dce8af97..cbcb4ea0511 100644 --- a/test/spec/modules/adstirBidAdapter_spec.js +++ b/test/spec/modules/adstirBidAdapter_spec.js @@ -279,7 +279,7 @@ describe('AdstirAdapter', function () { }; const serializedSchain = '1.0,1!exchange1.example,1234%21abcd,1,bid-request-1,publisher%2C%20Inc.,publisher.example!exchange2.example,abcd,1,bid-request-2,intermediary,intermediary.example'; - const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { schain })], bidderRequest); + const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { ortb2: { source: { ext: { schain } } } })], bidderRequest); const d = JSON.parse(request.data); expect(d.schain).to.deep.equal(serializedSchain); }); @@ -305,7 +305,7 @@ describe('AdstirAdapter', function () { }; const serializedSchain = '1.0,1!exchange1.example,1234%21abcd,1,,,!,,,,,!exchange2.example,abcd,1,,,'; - const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { schain })], bidderRequest); + const [ request ] = spec.buildRequests([utils.mergeDeep(utils.deepClone(validBidRequests[0]), { ortb2: { source: { ext: { schain } } } })], bidderRequest); const d = JSON.parse(request.data); expect(d.schain).to.deep.equal(serializedSchain); }); diff --git a/test/spec/modules/adtrgtmeBidAdapter_spec.js b/test/spec/modules/adtrgtmeBidAdapter_spec.js index 925f5763c5d..b4abd2709a4 100644 --- a/test/spec/modules/adtrgtmeBidAdapter_spec.js +++ b/test/spec/modules/adtrgtmeBidAdapter_spec.js @@ -266,7 +266,7 @@ describe('Adtrgtme Bid Adapter:', () => { hp: 1 }] }; - bidRequest.schain = globalSchain; + bidRequest.ortb2 = { source: { ext: { schain: globalSchain } } }; const data = spec.buildRequests(validBR, bidderRequest)[0].data; const schain = data.source.ext.schain; expect(schain.nodes.length).to.equal(1); diff --git a/test/spec/modules/adtrueBidAdapter_spec.js b/test/spec/modules/adtrueBidAdapter_spec.js index df8f9013534..4efc8d69707 100644 --- a/test/spec/modules/adtrueBidAdapter_spec.js +++ b/test/spec/modules/adtrueBidAdapter_spec.js @@ -33,22 +33,28 @@ describe('AdTrueBidAdapter', function () { tid: '92489f71-1bf2-49a0-adf9-000cea934729', } }, - schain: { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, + ortb2: { + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 2 + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 1 + } + ] + } } - ] + } } } ]; @@ -291,7 +297,7 @@ describe('AdTrueBidAdapter', function () { expect(data.imp[0].tagid).to.equal(bidRequests[0].params.zoneId); // zoneId expect(data.imp[0].banner.w).to.equal(300); // width expect(data.imp[0].banner.h).to.equal(250); // height - expect(data.source.ext.schain).to.deep.equal(bidRequests[0].schain); + expect(data.source.ext.schain).to.deep.equal(bidRequests[0].ortb2.source.ext.schain); }); it('Request params check with GDPR Consent', function () { let bidRequest = { @@ -314,7 +320,7 @@ describe('AdTrueBidAdapter', function () { expect(data.imp[0].tagid).to.equal(bidRequests[0].params.zoneId); // zoneId expect(data.imp[0].banner.w).to.equal(300); // width expect(data.imp[0].banner.h).to.equal(250); // height - expect(data.source.ext.schain).to.deep.equal(bidRequests[0].schain); + expect(data.source.ext.schain).to.deep.equal(bidRequests[0].ortb2.source.ext.schain); }); it('Request params check with USP/CCPA Consent', function () { let bidRequest = { @@ -334,7 +340,7 @@ describe('AdTrueBidAdapter', function () { expect(data.imp[0].tagid).to.equal(bidRequests[0].params.zoneId); // zoneId expect(data.imp[0].banner.w).to.equal(300); // width expect(data.imp[0].banner.h).to.equal(250); // height - expect(data.source.ext.schain).to.deep.equal(bidRequests[0].schain); + expect(data.source.ext.schain).to.deep.equal(bidRequests[0].ortb2.source.ext.schain); }); it('should NOT include coppa flag in bid request if coppa config is not present', () => { diff --git a/test/spec/modules/advertisingBidAdapter_spec.js b/test/spec/modules/advertisingBidAdapter_spec.js index bb4edc9ab05..d73df844d1f 100644 --- a/test/spec/modules/advertisingBidAdapter_spec.js +++ b/test/spec/modules/advertisingBidAdapter_spec.js @@ -878,16 +878,22 @@ describe('advertisingBidAdapter ', function () { bidRequestsCount: 1, bidderRequestsCount: 1, bidderWinsCount: 0, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } } }; let bidderRequest = { diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js index 367fc62c719..d67ba92ff8a 100644 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ b/test/spec/modules/adyoulikeBidAdapter_spec.js @@ -99,18 +99,24 @@ describe('Adyoulike Adapter', function () { } }, }, - 'schain': { - validation: 'strict', - config: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + validation: 'strict', + config: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } } }, ortb2Imp: { @@ -682,7 +688,7 @@ describe('Adyoulike Adapter', function () { expect(payload.gdprConsent.consentString).to.exist.and.to.equal(consentString); expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; expect(payload.uspConsent).to.exist.and.to.equal(uspConsentData); - expect(payload.Bids.bid_id_0.SChain).to.exist.and.to.deep.equal(bidRequestWithSinglePlacement[0].schain); + expect(payload.Bids.bid_id_0.SChain).to.exist.and.to.deep.equal(bidRequestWithSinglePlacement[0].ortb2.source.ext.schain); }); it('should not set a default value for gdpr consentRequired', function () { diff --git a/test/spec/modules/ajaBidAdapter_spec.js b/test/spec/modules/ajaBidAdapter_spec.js index bd2bdd3e407..82c6d1bab65 100644 --- a/test/spec/modules/ajaBidAdapter_spec.js +++ b/test/spec/modules/ajaBidAdapter_spec.js @@ -66,6 +66,32 @@ describe('AjaAdapter', function () { ext: { cdep: 'example_label_1' } + }, + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'exchange1.com', + sid: '1234', + hp: 1, + rid: 'bid-request-1', + name: 'publisher', + domain: 'publisher.com' + }, + { + asi: 'exchange2.com', + sid: 'abcd', + hp: 1, + rid: 'bid-request-2', + name: 'intermediary', + domain: 'intermediary.com' + } + ] + } + } } }, ortb2Imp: { @@ -74,28 +100,7 @@ describe('AjaAdapter', function () { gpid: '/1111/homepage#300x250' } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'exchange1.com', - sid: '1234', - hp: 1, - rid: 'bid-request-1', - name: 'publisher', - domain: 'publisher.com' - }, - { - asi: 'exchange2.com', - sid: 'abcd', - hp: 1, - rid: 'bid-request-2', - name: 'intermediary', - domain: 'intermediary.com' - } - ] - }, + } ]; const serializedSchain = encodeURIComponent('1.0,1!exchange1.com,1234,1,bid-request-1,publisher,publisher.com!exchange2.com,abcd,1,bid-request-2,intermediary,intermediary.com') diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index d642afd2b26..d2a6a4dcada 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -35,14 +35,20 @@ const REQUEST = { 'atype': 1 }] }], - 'schain': { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'alkimi-onboarding.com', - sid: '00001', - hp: 1 - }] + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'alkimi-onboarding.com', + sid: '00001', + hp: 1 + }] + } + } + } } } @@ -153,7 +159,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.method).to.equal('POST') expect(bidderRequest.data.requestId).to.not.equal(undefined) expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') - expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) + expect(bidderRequest.data.schain).to.deep.equal({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', bidFloor: 0.1, sizes: [{ width: 300, height: 250 }], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode', instl: undefined, exp: undefined, banner: { sizes: [[300, 250]] }, video: undefined, ext: { gpid: '/111/banner#300x250', tid: 'e64782a4-8e68-4c38-965b-80ccf115d46a' } }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') diff --git a/test/spec/modules/amxBidAdapter_spec.js b/test/spec/modules/amxBidAdapter_spec.js index 680579aa299..5aa0c0f09d3 100644 --- a/test/spec/modules/amxBidAdapter_spec.js +++ b/test/spec/modules/amxBidAdapter_spec.js @@ -115,7 +115,7 @@ const sampleBidRequestVideo = { ...sampleBidRequestBase, bidId: sampleRequestId + '_video', sizes: [[300, 150]], - schain: schainConfig, + ortb2: { source: { ext: { schain: schainConfig } } }, mediaTypes: { [VIDEO]: { sizes: [[360, 250]], diff --git a/test/spec/modules/apacdexBidAdapter_spec.js b/test/spec/modules/apacdexBidAdapter_spec.js index d005934d062..e10b7468695 100644 --- a/test/spec/modules/apacdexBidAdapter_spec.js +++ b/test/spec/modules/apacdexBidAdapter_spec.js @@ -183,21 +183,27 @@ describe('ApacdexBidAdapter', function () { userSync.canBidderRegisterSync.restore(); }); let bidRequest = [{ - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 0 - }, - ] + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 0 + }, + ] + } + } + } }, 'bidder': 'apacdex', 'params': { @@ -314,7 +320,7 @@ describe('ApacdexBidAdapter', function () { }) it('should return a properly formatted request with schain defined', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); - expect(bidRequests.data.schain).to.deep.equal(bidRequest[0].schain) + expect(bidRequests.data.schain).to.deep.equal(bidRequest[0].ortb2.source.ext.schain) }); it('should return a properly formatted request with eids defined', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index c8f52f71452..9772af675de 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -1462,16 +1462,22 @@ describe('AppNexusAdapter', function () { it('should populate schain if available', function () { const bidRequest = Object.assign({}, bidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'blob.com', - 'sid': '001', - 'hp': 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + 'asi': 'blob.com', + 'sid': '001', + 'hp': 1 + } + ] + } } - ] + } } }); diff --git a/test/spec/modules/audiencerunBidAdapter_spec.js b/test/spec/modules/audiencerunBidAdapter_spec.js index 65349409e5e..35d1a7a54a3 100644 --- a/test/spec/modules/audiencerunBidAdapter_spec.js +++ b/test/spec/modules/audiencerunBidAdapter_spec.js @@ -239,7 +239,10 @@ describe('AudienceRun bid adapter tests', function () { it('should add schain object if available', function() { const bid = Object.assign({}, bidRequest) - bid.schain = { + bid.ortb2 = { + source: { + ext: { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -250,6 +253,9 @@ describe('AudienceRun bid adapter tests', function () { hp: 1, }, ], + } + } + } }; const request = spec.buildRequests([bid]); diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index 2e766487951..a881928a017 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -327,7 +327,7 @@ describe('BeachfrontAdapter', function () { }; const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; - bidRequest.schain = schain; + bidRequest.ortb2 = { source: { ext: { schain: schain } } }; const requests = spec.buildRequests([ bidRequest ], {}); const data = requests[0].data; expect(data.source.ext.schain).to.deep.equal(schain); @@ -565,7 +565,7 @@ describe('BeachfrontAdapter', function () { }; const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; - bidRequest.schain = schain; + bidRequest.ortb2 = { source: { ext: { schain: schain } } }; const requests = spec.buildRequests([ bidRequest ], {}); const data = requests[0].data; expect(data.schain).to.deep.equal(schain); diff --git a/test/spec/modules/bliinkBidAdapter_spec.js b/test/spec/modules/bliinkBidAdapter_spec.js index ff48d8579a7..96b14c35b60 100644 --- a/test/spec/modules/bliinkBidAdapter_spec.js +++ b/test/spec/modules/bliinkBidAdapter_spec.js @@ -809,7 +809,10 @@ const testsBuildRequests = [ fn: spec.buildRequests( [ { - schain: { + ortb2: { + source: { + ext: { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -819,6 +822,9 @@ const testsBuildRequests = [ hp: 1, }, ], + } + } + } }, }, ], diff --git a/test/spec/modules/bridBidAdapter_spec.js b/test/spec/modules/bridBidAdapter_spec.js index 20a6542707b..a97e56c5ba0 100644 --- a/test/spec/modules/bridBidAdapter_spec.js +++ b/test/spec/modules/bridBidAdapter_spec.js @@ -50,7 +50,7 @@ describe('Brid Bid Adapter', function() { }; let videoRequestCloned = deepClone(videoRequest); - videoRequestCloned[0].schain = globalSchain; + videoRequestCloned[0].ortb2 = { source: { ext: { schain: globalSchain } } }; const request = spec.buildRequests(videoRequestCloned, videoRequestCloned[0]); expect(request).to.not.be.empty; diff --git a/test/spec/modules/brightMountainMediaBidAdapter_spec.js b/test/spec/modules/brightMountainMediaBidAdapter_spec.js index 5e433abebd8..657125c656c 100644 --- a/test/spec/modules/brightMountainMediaBidAdapter_spec.js +++ b/test/spec/modules/brightMountainMediaBidAdapter_spec.js @@ -26,7 +26,10 @@ describe('brightMountainMediaBidAdapter_spec', function () { floor: 0.5, } }, - schain: { + ortb2: { + source: { + ext: { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -37,6 +40,9 @@ describe('brightMountainMediaBidAdapter_spec', function () { hp: 1 } ] + } + } + } }, userIdAsEids: [ { diff --git a/test/spec/modules/browsiBidAdapter_spec.js b/test/spec/modules/browsiBidAdapter_spec.js index 9693972fd7f..4c585ca71b3 100644 --- a/test/spec/modules/browsiBidAdapter_spec.js +++ b/test/spec/modules/browsiBidAdapter_spec.js @@ -69,7 +69,13 @@ describe('browsi Bid Adapter Test', function () { tid: '1234567-3456-4562-7689-98765434B', } }, - 'schain': {}, + 'ortb2': { + 'source': { + 'ext': { + 'schain': {} + } + } + }, 'mediaTypes': {video: {playerSize: [640, 480]}} } ]; @@ -117,7 +123,7 @@ describe('browsi Bid Adapter Test', function () { aUCode: inputRequest.adUnitCode, aID: inputRequest.auctionId, tID: inputRequest.ortb2Imp.ext.tid, - schain: inputRequest.schain, + schain: inputRequest.ortb2?.source?.ext?.schain, params: inputRequest.params } } diff --git a/test/spec/modules/cadentApertureMXBidAdapter_spec.js b/test/spec/modules/cadentApertureMXBidAdapter_spec.js index c5d68f6ab81..16e2bc66b40 100644 --- a/test/spec/modules/cadentApertureMXBidAdapter_spec.js +++ b/test/spec/modules/cadentApertureMXBidAdapter_spec.js @@ -377,23 +377,29 @@ describe('cadent_aperture_mx Adapter', function () { it('should add schain object to request', function() { const schainBidderRequest = utils.deepClone(bidderRequest); - schainBidderRequest.bids[0].schain = { - 'complete': 1, - 'ver': '1.0', - 'nodes': [ - { - 'asi': 'testing.com', - 'sid': 'abc', - 'hp': 1 + schainBidderRequest.bids[0].ortb2 = { + source: { + ext: { + schain: { + 'complete': 1, + 'ver': '1.0', + 'nodes': [ + { + 'asi': 'testing.com', + 'sid': 'abc', + 'hp': 1 + } + ] + } } - ] + } }; let request = spec.buildRequests(schainBidderRequest.bids, schainBidderRequest); request = JSON.parse(request.data); expect(request.source.ext.schain).to.exist; expect(request.source.ext.schain).to.have.property('complete', 1); expect(request.source.ext.schain).to.have.property('ver', '1.0'); - expect(request.source.ext.schain.nodes[0].asi).to.equal(schainBidderRequest.bids[0].schain.nodes[0].asi); + expect(request.source.ext.schain.nodes[0].asi).to.equal(schainBidderRequest.bids[0].ortb2.source.ext.schain.nodes[0].asi); }); it('should add liveramp identitylink id to request', () => { diff --git a/test/spec/modules/carodaBidAdapter_spec.js b/test/spec/modules/carodaBidAdapter_spec.js index 780c81ebe9f..7fa0827b3bf 100644 --- a/test/spec/modules/carodaBidAdapter_spec.js +++ b/test/spec/modules/carodaBidAdapter_spec.js @@ -109,10 +109,16 @@ describe('Caroda adapter', function () { const validBidRequests = [{ bid_id: 'bidId', params: {}, - schain: { - validation: 'strict', - config: { - ver: '1.0' + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0' + } + } + } } } }]; diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index 9f675592951..a4bfa42e70b 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -24,7 +24,10 @@ describe('ColossussspAdapter', function () { data: {} } }, - schain: { + ortb2: { + source: { + ext: { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -37,6 +40,9 @@ describe('ColossussspAdapter', function () { domain: 'example.com' } ] + } + } + } } }; let bidderRequest = { diff --git a/test/spec/modules/connectadBidAdapter_spec.js b/test/spec/modules/connectadBidAdapter_spec.js index f067d801c5e..5adecca3631 100644 --- a/test/spec/modules/connectadBidAdapter_spec.js +++ b/test/spec/modules/connectadBidAdapter_spec.js @@ -372,7 +372,10 @@ describe('ConnectAd Adapter', function () { it('should populate schain', function () { const bidRequest = Object.assign({}, bidRequests[0], { - schain: { + ortb2: { + source: { + ext: { + schain: { ver: '1.0', complete: 1, nodes: [ @@ -382,6 +385,9 @@ describe('ConnectAd Adapter', function () { 'hp': 1 } ] + } + } + } } }); diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index aa3eee990c2..eff4e9e0526 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -33,22 +33,6 @@ const BIDDER_REQUEST_1 = { transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } ], - schain: { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 2 - }, - ] - }, gdprConsent: { consentString: 'consent-test', gdprApplies: false @@ -70,6 +54,26 @@ const BIDDER_REQUEST_1 = { ortb2: { device: { language: 'en' + }, + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 2 + }, + ] + } + } } } }; @@ -488,7 +492,7 @@ describe('Consumable BidAdapter', function () { let request = spec.buildRequests(BIDDER_REQUEST_1.bidRequest, BIDDER_REQUEST_1); let data = JSON.parse(request.data); - expect(data.schain).to.deep.equal(BIDDER_REQUEST_1.schain) + expect(data.schain).to.deep.equal(BIDDER_REQUEST_1.ortb2.source.ext.schain) }); it('should not contain schain if it does not exist in the bidRequest', function () { diff --git a/test/spec/modules/cpmstarBidAdapter_spec.js b/test/spec/modules/cpmstarBidAdapter_spec.js index f9b1ba59cde..c1c773d5047 100755 --- a/test/spec/modules/cpmstarBidAdapter_spec.js +++ b/test/spec/modules/cpmstarBidAdapter_spec.js @@ -131,21 +131,27 @@ describe('Cpmstar Bid Adapter', function () { it('should produce a request with support for OpenRTB SupplyChain', function () { var reqs = deepClone(valid_bid_requests); - reqs[0].schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1 - }, - { - 'asi': 'exchange2.com', - 'sid': 'abcd', - 'hp': 1 + reqs[0].ortb2 = { + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1 + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1 + } + ] + } } - ] + } }; var requests = spec.buildRequests(reqs, bidderRequest); expect(requests[0]).to.have.property('url'); diff --git a/test/spec/modules/dianomiBidAdapter_spec.js b/test/spec/modules/dianomiBidAdapter_spec.js index ef9283d3dad..a0cb1be68de 100644 --- a/test/spec/modules/dianomiBidAdapter_spec.js +++ b/test/spec/modules/dianomiBidAdapter_spec.js @@ -284,11 +284,17 @@ describe('Dianomi adapter', () => { { bidId: 'bidId', params: { smartadId: 1234 }, - schain: { - validation: 'strict', - config: { - ver: '1.0', - }, + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0', + }, + } + } + } }, }, ]; diff --git a/test/spec/modules/digitalMatterBidAdapter_spec.js b/test/spec/modules/digitalMatterBidAdapter_spec.js index 87056588cd9..12ff5d89c0b 100644 --- a/test/spec/modules/digitalMatterBidAdapter_spec.js +++ b/test/spec/modules/digitalMatterBidAdapter_spec.js @@ -117,10 +117,16 @@ describe('Digital Matter BidAdapter', function () { it('should pass supply chain object', function () { let validBidRequests = { ...bid, - schain: { - validation: 'strict', - config: { - ver: '1.0' + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0' + } + } + } } } }; diff --git a/test/spec/modules/dspxBidAdapter_spec.js b/test/spec/modules/dspxBidAdapter_spec.js index ad7bc827837..fb135142744 100644 --- a/test/spec/modules/dspxBidAdapter_spec.js +++ b/test/spec/modules/dspxBidAdapter_spec.js @@ -110,18 +110,24 @@ describe('dspxAdapter', function () { 'crumbs': { 'pubcid': 'e09ab6a3-ae74-4f01-b2e8-81b141d6dc61' }, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'example.com', - 'sid': '0', - 'hp': 1, - 'rid': 'bidrequestid', - 'domain': 'example.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'example.com', + 'sid': '0', + 'hp': 1, + 'rid': 'bidrequestid', + 'domain': 'example.com' + } + ] + } } - ] + } } }, { diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index efb2f4a4cbb..ee9a1ea5f82 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -62,19 +62,25 @@ describe('E-Planning Adapter', function () { }, 'adUnitCode': ADUNIT_CODE2, 'sizes': [[300, 250], [300, 600]], - 'schain': { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - name: 'publisher', - domain: 'publisher.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1, + name: 'publisher', + domain: 'publisher.com' + } + ] + } } - ] + } } }; const validBidWithSchainNodes = { @@ -85,35 +91,41 @@ describe('E-Planning Adapter', function () { }, 'adUnitCode': ADUNIT_CODE2, 'sizes': [[300, 250], [300, 600]], - 'schain': { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - name: 'publisher', - domain: 'publisher.com' - }, - { - asi: 'reseller.com', - sid: 'aaaaa', - rid: 'BidRequest2', - hp: 1, - name: 'publisher2', - domain: 'publisher2.com' - }, - { - asi: 'reseller3.com', - sid: 'aaaaab', - rid: 'BidRequest3', - hp: 1, - name: 'publisher3', - domain: 'publisher3.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1, + name: 'publisher', + domain: 'publisher.com' + }, + { + asi: 'reseller.com', + sid: 'aaaaa', + rid: 'BidRequest2', + hp: 1, + name: 'publisher2', + domain: 'publisher2.com' + }, + { + asi: 'reseller3.com', + sid: 'aaaaab', + rid: 'BidRequest3', + hp: 1, + name: 'publisher3', + domain: 'publisher3.com' + } + ] + } } - ] + } } }; const ML = '1'; @@ -796,7 +808,7 @@ describe('E-Planning Adapter', function () { }); it('should return sch parameter', function () { let bidRequests = [validBidWithSchain], schainExpected, schain; - schain = validBidWithSchain.schain; + schain = validBidWithSchain.ortb2.source.ext.schain; schainExpected = schain.ver + ',' + schain.complete + '!' + schain.nodes.map(node => node.asi + ',' + node.sid + ',' + node.hp + ',' + node.rid + ',' + node.name + ',' + node.domain).join('!'); const data = spec.buildRequests(bidRequests, bidderRequest).data; expect(data.sch).to.deep.equal(schainExpected); diff --git a/test/spec/modules/fluctBidAdapter_spec.js b/test/spec/modules/fluctBidAdapter_spec.js index 82edcdac79e..e55e3f4bedc 100644 --- a/test/spec/modules/fluctBidAdapter_spec.js +++ b/test/spec/modules/fluctBidAdapter_spec.js @@ -338,16 +338,22 @@ describe('fluctAdapter', function () { // this should be done by schain.js const bidRequests2 = bidRequests.map( (bidReq) => Object.assign({}, bidReq, { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: 'publisher-id', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: 'publisher-id', + hp: 1 + } + ] + } } - ] + } } }) ); diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js index 94b7f04b637..e96208c3b16 100644 --- a/test/spec/modules/freewheel-sspBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -102,18 +102,24 @@ describe('freewheelSSP BidAdapter Test', () => { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'example.com', - 'sid': '0', - 'hp': 1, - 'rid': 'bidrequestid', - 'domain': 'example.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'example.com', + 'sid': '0', + 'hp': 1, + 'rid': 'bidrequestid', + 'domain': 'example.com' + } + ] + } } - ] + } } } ]; diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 8f9818ed901..270c0f7c2aa 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -56,7 +56,13 @@ describe('GamoshiAdapter', () => { consentString: 'some string', gdprApplies: true }, - schain: schainConfig, + ortb2: { + source: { + ext: { + schain: schainConfig + } + } + }, uspConsent: 'gamoshiCCPA' }; @@ -339,7 +345,7 @@ describe('GamoshiAdapter', () => { expect(response.data.imp[0].bidfloor).to.equal(0); expect(response.data.imp[0].bidfloorcur).to.equal('USD'); expect(response.data.regs.ext.us_privacy).to.equal('gamoshiCCPA');// USP/CCPAs - expect(response.data.source.ext.schain).to.deep.equal(bidRequest2.schain); + expect(response.data.source.ext.schain).to.deep.equal(bidRequest2.ortb2.source.ext.schain); const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index e9ad45de45c..d35e8d8dbe8 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -540,7 +540,13 @@ describe('TheMediaGrid Adapter', function () { }; const bidRequestsWithSChain = bidRequests.map((bid) => { return Object.assign({ - schain: schain + ortb2: { + source: { + ext: { + schain: schain + } + } + } }, bid); }); const [request] = spec.buildRequests(bidRequestsWithSChain, bidderRequest); diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 59336b264ab..c6ff243421d 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -171,27 +171,33 @@ describe('gumgumAdapter', function () { adUnitCode: 'adunit-code', sizes: sizesArray, bidId: '30b31c1838de1e', - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'exchange1.com', - sid: '1234', - hp: 1, - rid: 'bid-request-1', - name: 'publisher', - domain: 'publisher.com' - }, - { - asi: 'exchange2.com', - sid: 'abcd', - hp: 1, - rid: 'bid-request-2', - name: 'intermediary', - domain: 'intermediary.com' + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'exchange1.com', + sid: '1234', + hp: 1, + rid: 'bid-request-1', + name: 'publisher', + domain: 'publisher.com' + }, + { + asi: 'exchange2.com', + sid: 'abcd', + hp: 1, + rid: 'bid-request-2', + name: 'intermediary', + domain: 'intermediary.com' + } + ] + } } - ] + } } } ]; diff --git a/test/spec/modules/insticatorBidAdapter_spec.js b/test/spec/modules/insticatorBidAdapter_spec.js index d6daceddd6e..31df4714d58 100644 --- a/test/spec/modules/insticatorBidAdapter_spec.js +++ b/test/spec/modules/insticatorBidAdapter_spec.js @@ -46,17 +46,23 @@ describe('InsticatorBidAdapter', function () { gpid: '1111/homepage' } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'insticator.com', - sid: '00001', - hp: 1, - rid: bidderRequestId + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'insticator.com', + sid: '00001', + hp: 1, + rid: bidderRequestId + } + ] + } } - ] + } }, userIdAsEids: [ { diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 69a052f0e4e..a792a806e08 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -130,7 +130,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -157,7 +163,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4d', bidderRequestId: '11a22b33c44d', auctionId: '1aa2bb3cc4dd', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -185,7 +197,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4d', bidderRequestId: '11a22b33c44d', auctionId: '1aa2bb3cc4dd', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -214,7 +232,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4d', bidderRequestId: '11a22b33c44d', auctionId: '1aa2bb3cc4dd', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -239,7 +263,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4d', bidderRequestId: '11a22b33c44d', auctionId: '1aa2bb3cc4dd', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -273,7 +303,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -311,7 +347,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -349,7 +391,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -383,7 +431,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -427,7 +481,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -499,7 +559,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -546,7 +612,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4f', bidderRequestId: '11a22b33c44f', auctionId: '1aa2bb3cc4df', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -587,7 +659,13 @@ describe('IndexexchangeAdapter', function () { bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', auctionId: '1aa2bb3cc4de', - schain: SAMPLE_SCHAIN + ortb2: { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + } } ]; @@ -2074,7 +2152,9 @@ describe('IndexexchangeAdapter', function () { describe('buildRequests', function () { const bidWithoutSchain = utils.deepClone(DEFAULT_BANNER_VALID_BID); - delete bidWithoutSchain[0].schain; + if (bidWithoutSchain[0].ortb2 && bidWithoutSchain[0].ortb2.source && bidWithoutSchain[0].ortb2.source.ext) { + delete bidWithoutSchain[0].ortb2.source.ext.schain; + } const GPID = '/19968336/some-adunit-path'; let request, requestUrl, requestMethod, payloadData, requestWithoutSchain, payloadWithoutSchain; @@ -2682,7 +2762,9 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID); bid[0].mediaTypes.video.context = 'outstream'; bid[0].mediaTypes.video.w = [[300, 143]]; - bid[0].schain = undefined; + if (bid[0].ortb2 && bid[0].ortb2.source && bid[0].ortb2.source.ext) { + delete bid[0].ortb2.source.ext.schain; + } const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.equal('ix'); @@ -2695,7 +2777,9 @@ describe('IndexexchangeAdapter', function () { url: 'http://publisherplayer.js', render: () => { } }; - bid[0].schain = undefined; + if (bid[0].ortb2 && bid[0].ortb2.source && bid[0].ortb2.source.ext) { + delete bid[0].ortb2.source.ext.schain; + } const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.equal('http://publisherplayer.js'); @@ -2708,7 +2792,9 @@ describe('IndexexchangeAdapter', function () { url: 'publisherplayer.js', render: () => { } }; - bid[0].schain = undefined; + if (bid[0].ortb2 && bid[0].ortb2.source && bid[0].ortb2.source.ext) { + delete bid[0].ortb2.source.ext.schain; + } const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.be.undefined; @@ -2721,7 +2807,9 @@ describe('IndexexchangeAdapter', function () { url: 'http://js-sec.indexww.rendererplayer.com', render: () => { } }; - bid[0].schain = undefined; + if (bid[0].ortb2 && bid[0].ortb2.source && bid[0].ortb2.source.ext) { + delete bid[0].ortb2.source.ext.schain; + } const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.equal('ix'); @@ -2733,7 +2821,9 @@ describe('IndexexchangeAdapter', function () { bid[0].mediaTypes.video.renderer = { render: () => { } }; - bid[0].schain = undefined; + if (bid[0].ortb2 && bid[0].ortb2.source && bid[0].ortb2.source.ext) { + delete bid[0].ortb2.source.ext.schain; + } const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.be.undefined; @@ -2742,7 +2832,13 @@ describe('IndexexchangeAdapter', function () { const bid = utils.deepClone(DEFAULT_VIDEO_VALID_BID); bid[0].mediaTypes.video.context = 'outstream'; bid[0].mediaTypes.video.w = [[300, 143]]; - bid[0].schain = SAMPLE_SCHAIN; + bid[0].ortb2 = { + source: { + ext: { + schain: SAMPLE_SCHAIN + } + } + }; const request = spec.buildRequests(bid); const videoImpression = extractPayload(request[0]).imp[0]; expect(videoImpression.displaymanager).to.equal('pbjs_wrapper'); diff --git a/test/spec/modules/jixieBidAdapter_spec.js b/test/spec/modules/jixieBidAdapter_spec.js index 5428fd0db0f..422c1c470ed 100644 --- a/test/spec/modules/jixieBidAdapter_spec.js +++ b/test/spec/modules/jixieBidAdapter_spec.js @@ -369,7 +369,15 @@ describe('jixie Adapter', function () { hp: 1 }] }; - const oneSpecialBidReq = Object.assign({}, bidRequests_[0], { schain: schain }); + const oneSpecialBidReq = Object.assign({}, bidRequests_[0], { + ortb2: { + source: { + ext: { + schain: schain + } + } + } + }); const request = spec.buildRequests([oneSpecialBidReq], bidderRequest_); const payload = JSON.parse(request.data); expect(payload.schain).to.deep.equal(schain); diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index b08be01461b..8133d903df7 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -46,7 +46,13 @@ describe('justpremium adapter', function () { zone: 28313, allow: ['lb', 'wp'] }, - schain: schainConfig + ortb2: { + source: { + ext: { + schain: schainConfig + } + } + } }, { adUnitCode: 'div-gpt-ad-1471513102552-2', diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index e19790a9670..ae456919238 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -148,16 +148,22 @@ describe('jwplayerBidAdapter', function() { playbackend: 2 } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'publisher.com', - sid: '00001', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'publisher.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } }, bidRequestsCount: 1, adUnitCode: 'testAdUnitCode', diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 67bc3667daa..6f054d8f184 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -510,39 +510,57 @@ describe('kargo adapter tests', function() { schain: {} }, { ...minimumBidParams, - schain: { - complete: 1, - nodes: [{ - asi: 'test-page.com', - hp: 1, - rid: '57bdd953-6e57-4d5b-9351-ed67ca238890', - sid: '8190248274' - }] + ortb2: { + source: { + ext: { + schain: { + complete: 1, + nodes: [{ + asi: 'test-page.com', + hp: 1, + rid: '57bdd953-6e57-4d5b-9351-ed67ca238890', + sid: '8190248274' + }] + } + } + } } }]); expect(payload.schain).to.be.undefined; payload = getPayloadFromTestBids([{ ...minimumBidParams, - schain: { - complete: 1, - nodes: [{ - asi: 'test-page.com', - hp: 1, - rid: '57bdd953-6e57-4d5b-9351-ed67ca238890', - sid: '8190248274' - }] + ortb2: { + source: { + ext: { + schain: { + complete: 1, + nodes: [{ + asi: 'test-page.com', + hp: 1, + rid: '57bdd953-6e57-4d5b-9351-ed67ca238890', + sid: '8190248274' + }] + } + } + } } }, { ...minimumBidParams, - schain: { - complete: 1, - nodes: [{ - asi: 'test-page-2.com', - hp: 1, - rid: 'other-rid', - sid: 'other-sid' - }] + ortb2: { + source: { + ext: { + schain: { + complete: 1, + nodes: [{ + asi: 'test-page-2.com', + hp: 1, + rid: 'other-rid', + sid: 'other-sid' + }] + } + } + } } }]); expect(payload.schain).to.deep.equal({ diff --git a/test/spec/modules/kubientBidAdapter_spec.js b/test/spec/modules/kubientBidAdapter_spec.js index a6241aa8d41..71136c2c8cd 100644 --- a/test/spec/modules/kubientBidAdapter_spec.js +++ b/test/spec/modules/kubientBidAdapter_spec.js @@ -30,18 +30,24 @@ describe('KubientAdapter', function () { } }, transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', - schain: { - ver: '1.1', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '0', - hp: 1, - rid: 'bidrequestid', - domain: 'example.com' + ortb2: { + source: { + ext: { + schain: { + ver: '1.1', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '0', + hp: 1, + rid: 'bidrequestid', + domain: 'example.com' + } + ] + } } - ] + } } }; let bidVideo = { @@ -67,18 +73,24 @@ describe('KubientAdapter', function () { } }, transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e61', - schain: { - ver: '1.1', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '0', - hp: 1, - rid: 'bidrequestid', - domain: 'example.com' + ortb2: { + source: { + ext: { + schain: { + ver: '1.1', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '0', + hp: 1, + rid: 'bidrequestid', + domain: 'example.com' + } + ] + } } - ] + } } }; let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; diff --git a/test/spec/modules/lemmaDigitalBidAdapter_spec.js b/test/spec/modules/lemmaDigitalBidAdapter_spec.js index ab4c3259671..67e8ea0fb9d 100644 --- a/test/spec/modules/lemmaDigitalBidAdapter_spec.js +++ b/test/spec/modules/lemmaDigitalBidAdapter_spec.js @@ -59,7 +59,7 @@ describe('lemmaDigitalBidAdapter', function () { [300, 250], [300, 600] ], - schain: schainConfig + ortb2: { source: { ext: { schain: schainConfig } } } }]; videoBidRequests = [{ code: 'video1', @@ -84,7 +84,7 @@ describe('lemmaDigitalBidAdapter', function () { maxduration: 30 } }, - schain: schainConfig + ortb2: { source: { ext: { schain: schainConfig } } } }]; bidResponses = { 'body': { @@ -227,7 +227,7 @@ describe('lemmaDigitalBidAdapter', function () { expect(data.imp[0].tagid).to.equal('1'); // tagid expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); expect(data.imp[0].bidfloor).to.equal(bidRequests[0].params.bidFloor); - expect(data.source.ext.schain).to.deep.equal(bidRequests[0].schain); + expect(data.source.ext.schain).to.deep.equal(bidRequests[0].ortb2.source.ext.schain); }); it('Set sizes from mediaTypes object', function () { @@ -245,7 +245,7 @@ describe('lemmaDigitalBidAdapter', function () { }); it('Check device, source object not present', function () { let newBannerRequest = utils.deepClone(bidRequests); - delete newBannerRequest[0].schain; + delete newBannerRequest[0].ortb2; let request = spec.buildRequests(newBannerRequest); let data = JSON.parse(request.data); delete data.device; @@ -461,7 +461,7 @@ describe('lemmaDigitalBidAdapter', function () { expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']); expect(data.imp[0]['video']['w']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[0]); expect(data.imp[0]['video']['h']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[1]); - expect(data.source.ext.schain).to.deep.equal(videoBidRequests[0].schain); + expect(data.source.ext.schain).to.deep.equal(videoBidRequests[0].ortb2.source.ext.schain); }); describe('setting imp.floor using floorModule', function () { /* diff --git a/test/spec/modules/limelightDigitalBidAdapter_spec.js b/test/spec/modules/limelightDigitalBidAdapter_spec.js index c84586e9064..ef94070bb9b 100644 --- a/test/spec/modules/limelightDigitalBidAdapter_spec.js +++ b/test/spec/modules/limelightDigitalBidAdapter_spec.js @@ -43,16 +43,22 @@ describe('limelightDigitalAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } const bid2 = { @@ -91,21 +97,27 @@ describe('limelightDigitalAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 - }, - { - asi: 'example1.com', - sid: '2', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + }, + { + asi: 'example1.com', + sid: '2', + hp: 1 + } + ] + } } - ] + } } } const bid3 = { @@ -148,16 +160,22 @@ describe('limelightDigitalAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } const bid4 = { @@ -198,16 +216,22 @@ describe('limelightDigitalAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } @@ -739,6 +763,6 @@ function validateAdUnit(adUnit, bid) { })); expect(adUnit.publisherId).to.equal(bid.params.publisherId); expect(adUnit.userIdAsEids).to.deep.equal(bid.userIdAsEids); - expect(adUnit.supplyChain).to.deep.equal(bid.schain); + expect(adUnit.supplyChain).to.deep.equal(bid.ortb2.source.ext.schain); expect(adUnit.ortb2Imp).to.deep.equal(bid.ortb2Imp); } diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index e6e23cfef35..3b4fddc7b9b 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -1315,7 +1315,10 @@ describe('Livewrapped adapter tests', function () { ] }; - testbidRequest.bids[0].schain = schain; + testbidRequest.bids[0].ortb2 = testbidRequest.bids[0].ortb2 || {}; + testbidRequest.bids[0].ortb2.source = testbidRequest.bids[0].ortb2.source || {}; + testbidRequest.bids[0].ortb2.source.ext = testbidRequest.bids[0].ortb2.source.ext || {}; + testbidRequest.bids[0].ortb2.source.ext.schain = schain; let result = spec.buildRequests(testbidRequest.bids, testbidRequest); let data = JSON.parse(result.data); diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index d65837c39ab..ffbeb1c9340 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -18,16 +18,22 @@ describe('LockerDomeAdapter', function () { bidId: '2652ca954bce9', bidderRequestId: '14a54fade69854', auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72', - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } } }, { bidder: 'lockerdome', @@ -44,16 +50,22 @@ describe('LockerDomeAdapter', function () { bidId: '4510f2834773ce', bidderRequestId: '14a54fade69854', auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72', - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } } }]; diff --git a/test/spec/modules/logicadBidAdapter_spec.js b/test/spec/modules/logicadBidAdapter_spec.js index eb7800077b4..6aeb97af9e3 100644 --- a/test/spec/modules/logicadBidAdapter_spec.js +++ b/test/spec/modules/logicadBidAdapter_spec.js @@ -84,19 +84,23 @@ describe('LogicadAdapter', function () { name: 'cd.ladsp.com' } ] + }, + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'exchange1.com', + sid: '1234', + hp: 1 + } + ] + } + } } }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'exchange1.com', - sid: '1234', - hp: 1 - } - ] - } }]; const nativeBidRequests = [{ bidder: 'logicad', diff --git a/test/spec/modules/luponmediaBidAdapter_spec.js b/test/spec/modules/luponmediaBidAdapter_spec.js index 3d9be5a40bf..49bfb565a42 100755 --- a/test/spec/modules/luponmediaBidAdapter_spec.js +++ b/test/spec/modules/luponmediaBidAdapter_spec.js @@ -66,16 +66,22 @@ describe('luponmediaBidAdapter', function () { 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'novi.ba', - 'sid': '199424', - 'hp': 1 + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'novi.ba', + 'sid': '199424', + 'hp': 1 + } + ] + } } - ] + } } } ]; @@ -119,16 +125,22 @@ describe('luponmediaBidAdapter', function () { 'bidRequestsCount': 1, 'bidderRequestsCount': 1, 'bidderWinsCount': 0, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'novi.ba', - 'sid': '199424', - 'hp': 1 + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'novi.ba', + 'sid': '199424', + 'hp': 1 + } + ] + } } - ] + } } } ], diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index ca3876703c8..ea0d0592f59 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -612,7 +612,13 @@ describe('marsmedia adapter tests', function () { 'auctionId': '18fd8b8b0bd757', 'bidRequestsCount': 1, 'bidId': '51ef8751f9aead', - 'schain': schain + 'ortb2': { + 'source': { + 'ext': { + 'schain': schain + } + } + } } ]; diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index bc943a9c129..4d627da216f 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -846,16 +846,22 @@ describe('MediaFuseAdapter', function () { it('should populate schain if available', function () { const bidRequest = Object.assign({}, bidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'blob.com', - 'sid': '001', - 'hp': 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + 'asi': 'blob.com', + 'sid': '001', + 'hp': 1 + } + ] + } } - ] + } } }); diff --git a/test/spec/modules/mediakeysBidAdapter_spec.js b/test/spec/modules/mediakeysBidAdapter_spec.js index 99eaff3f378..f88946f448b 100644 --- a/test/spec/modules/mediakeysBidAdapter_spec.js +++ b/test/spec/modules/mediakeysBidAdapter_spec.js @@ -452,7 +452,10 @@ describe('mediakeysBidAdapter', function () { ], }; const bidRequests = [utils.deepClone(bid)]; - bidRequests[0].schain = schain; + bidRequests[0].ortb2 = bidRequests[0].ortb2 || {}; + bidRequests[0].ortb2.source = bidRequests[0].ortb2.source || {}; + bidRequests[0].ortb2.source.ext = bidRequests[0].ortb2.source.ext || {}; + bidRequests[0].ortb2.source.ext.schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); const data = request.data; expect(data.source.ext.schain).to.equal(schain); diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 180b0dc723e..38d2fd135bb 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -398,11 +398,14 @@ describe('Mgid bid adapter', function () { sizes: [[300, 250]] } }; - bid.schain = ['schain1', 'schain2']; + bid.ortb2 = bid.ortb2 || {}; + bid.ortb2.source = bid.ortb2.source || {}; + bid.ortb2.source.ext = bid.ortb2.source.ext || {}; + bid.ortb2.source.ext.schain = ['schain1', 'schain2']; let bidRequests = [bid]; const request = spec.buildRequests(bidRequests); const data = JSON.parse(request.data); - expect(data.source).to.deep.equal({ext: {schain: bid.schain}}); + expect(data.source).to.deep.equal({ext: {schain: bid.ortb2.source.ext.schain}}); }); it('should handle userId', function () { let bid = Object.assign({}, abid); diff --git a/test/spec/modules/missenaBidAdapter_spec.js b/test/spec/modules/missenaBidAdapter_spec.js index e95903d4791..c29711b4302 100644 --- a/test/spec/modules/missenaBidAdapter_spec.js +++ b/test/spec/modules/missenaBidAdapter_spec.js @@ -31,18 +31,22 @@ describe('Missena Adapter', function () { device: { ext: { cdep: COOKIE_DEPRECATION_LABEL }, }, + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0', + }, + }, + }, + }, }, params: { apiKey: API_KEY, placement: 'sticky', formats: ['sticky-banner'], }, - schain: { - validation: 'strict', - config: { - ver: '1.0', - }, - }, getFloor: (inputParams) => { if (inputParams.mediaType === BANNER) { return { diff --git a/test/spec/modules/nextMillenniumBidAdapter_spec.js b/test/spec/modules/nextMillenniumBidAdapter_spec.js index 85143f45df8..53e541efded 100644 --- a/test/spec/modules/nextMillenniumBidAdapter_spec.js +++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js @@ -225,12 +225,18 @@ describe('nextMillenniumBidAdapterTests', () => { title: 'schain is validBidReequest', bidderRequest: {}, validBidRequests: [{ - schain: { - validation: 'strict', - config: { - ver: '1.0', - complete: 1, - nodes: [{asi: 'test.test', sid: '00001', hp: 1}], + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0', + complete: 1, + nodes: [{asi: 'test.test', sid: '00001', hp: 1}], + }, + }, + }, }, }, }], diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index 2f2c97eae51..6fe29fa3c3b 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -937,20 +937,26 @@ describe('Nobid Adapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', coppa: true, - schain: { - validation: 'strict', - config: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - name: 'name.com', - hp: 1 - } - ] - } + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + name: 'name.com', + hp: 1 + } + ] + } + } + } + } } } ]; diff --git a/test/spec/modules/omsBidAdapter_spec.js b/test/spec/modules/omsBidAdapter_spec.js index e8426930257..a324fa05576 100644 --- a/test/spec/modules/omsBidAdapter_spec.js +++ b/test/spec/modules/omsBidAdapter_spec.js @@ -57,19 +57,25 @@ describe('omsBidAdapter', function () { 'bidId': '5fb26ac22bde4', 'bidderRequestId': '4bf93aeb730cb9', 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e', - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher', - 'domain': 'publisher.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + } } - ] + } }, }]; @@ -150,19 +156,25 @@ describe('omsBidAdapter', function () { 'bidId': '5fb26ac22bde4', 'bidderRequestId': '4bf93aeb730cb9', 'auctionId': 'ffe9a1f7-7b67-4bda-a8e0-9ee5dc9f442e', - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher', - 'domain': 'publisher.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + } } - ] + } }, } ] diff --git a/test/spec/modules/opscoBidAdapter_spec.js b/test/spec/modules/opscoBidAdapter_spec.js index 38cacff8f82..77051f56de1 100644 --- a/test/spec/modules/opscoBidAdapter_spec.js +++ b/test/spec/modules/opscoBidAdapter_spec.js @@ -134,7 +134,10 @@ describe('opscoBidAdapter', function () { it('should send schain in the payload if present', function () { const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'exchange1.com', 'sid': '1234', 'hp': 1}]}; - validBid.schain = schain; + validBid.ortb2 = validBid.ortb2 || {}; + validBid.ortb2.source = validBid.ortb2.source || {}; + validBid.ortb2.source.ext = validBid.ortb2.source.ext || {}; + validBid.ortb2.source.ext.schain = schain; const request = spec.buildRequests([validBid], bidderRequest); expect(JSON.parse(request.data).source.ext.schain).to.deep.equal(schain); }); diff --git a/test/spec/modules/optidigitalBidAdapter_spec.js b/test/spec/modules/optidigitalBidAdapter_spec.js index 273b29001d1..dfaab4d5372 100755 --- a/test/spec/modules/optidigitalBidAdapter_spec.js +++ b/test/spec/modules/optidigitalBidAdapter_spec.js @@ -222,14 +222,20 @@ describe('optidigitalAdapterTests', function () { it('should add schain object to payload if exists', function () { const bidRequest = Object.assign({}, validBidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'examplewebsite.com', - sid: '00001', - hp: 1 - }] + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'examplewebsite.com', + sid: '00001', + hp: 1 + }] + } + } + } } }); const request = spec.buildRequests([bidRequest], bidderRequest); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index b2b494b04c6..d23cb39c5cb 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -3151,7 +3151,10 @@ describe('ozone Adapter', function () { } ] }; - br[0]['schain'] = schainConfigObject; + br[0].ortb2 = br[0].ortb2 || {}; + br[0].ortb2.source = br[0].ortb2.source || {}; + br[0].ortb2.source.ext = br[0].ortb2.source.ext || {}; + br[0].ortb2.source.ext.schain = schainConfigObject; const request = spec.buildRequests(br, validBidderRequest); const data = JSON.parse(request.data); expect(data.source.ext).to.haveOwnProperty('schain'); diff --git a/test/spec/modules/pubgeniusBidAdapter_spec.js b/test/spec/modules/pubgeniusBidAdapter_spec.js index e1d579aaa4a..5475a58d317 100644 --- a/test/spec/modules/pubgeniusBidAdapter_spec.js +++ b/test/spec/modules/pubgeniusBidAdapter_spec.js @@ -295,7 +295,10 @@ describe('pubGENIUS adapter', () => { } ] }; - bidRequest.schain = deepClone(schain); + bidRequest.ortb2 = bidRequest.ortb2 || {}; + bidRequest.ortb2.source = bidRequest.ortb2.source || {}; + bidRequest.ortb2.source.ext = bidRequest.ortb2.source.ext || {}; + bidRequest.ortb2.source.ext.schain = deepClone(schain); expectedRequest.data.source = { ext: { schain: deepClone(schain) }, }; diff --git a/test/spec/modules/qwarryBidAdapter_spec.js b/test/spec/modules/qwarryBidAdapter_spec.js index 5d48d92066a..fef013f8ce6 100644 --- a/test/spec/modules/qwarryBidAdapter_spec.js +++ b/test/spec/modules/qwarryBidAdapter_spec.js @@ -10,14 +10,20 @@ const REQUEST = { zoneToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7 }, - 'schain': { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'qwarry.com', - sid: '00001', - hp: 1 - }] + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [{ + 'asi': 'qwarry.com', + 'sid': '00001', + 'hp': 1 + }] + } + } + } } } diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index 359b02db37e..77ae6266eda 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -704,7 +704,13 @@ describe('rhythmone adapter tests', function () { 'auctionId': '18fd8b8b0bd757', 'bidRequestsCount': 1, 'bidId': '51ef8751f9aead', - 'schain': schain + 'ortb2': { + 'source': { + 'ext': { + 'schain': schain + } + } + } } ]; diff --git a/test/spec/modules/richaudienceBidAdapter_spec.js b/test/spec/modules/richaudienceBidAdapter_spec.js index e4fd11d8604..b5209266762 100644 --- a/test/spec/modules/richaudienceBidAdapter_spec.js +++ b/test/spec/modules/richaudienceBidAdapter_spec.js @@ -817,18 +817,24 @@ describe('Richaudience adapter tests', function () { }] } - DEFAULT_PARAMS_NEW_SIZES[0].schain = { - 'ver': '1.0', - 'complete': 1, - 'nodes': [{ - 'asi': 'richaudience.com', - 'sid': '00001', - 'hp': 1 - }, { - 'asi': 'richaudience-2.com', - 'sid': '00002', - 'hp': 1 - }] + DEFAULT_PARAMS_NEW_SIZES[0].ortb2 = { + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [{ + 'asi': 'richaudience.com', + 'sid': '00001', + 'hp': 1 + }, { + 'asi': 'richaudience-2.com', + 'sid': '00002', + 'hp': 1 + }] + } + } + } } const request = spec.buildRequests(DEFAULT_PARAMS_NEW_SIZES, { diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index dded1fe15a0..e88545b5ba4 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -91,17 +91,23 @@ describe('RTBHouseAdapter', () => { 'tid': 'ortb2Imp-transaction-id-1' } }, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'directseller.com', - 'sid': '00001', - 'rid': 'BidRequest1', - 'hp': 1 + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'directseller.com', + 'sid': '00001', + 'rid': 'BidRequest1', + 'hp': 1 + } + ] + } } - ] + } } } ]; @@ -274,7 +280,10 @@ describe('RTBHouseAdapter', () => { it('should not include invalid schain', () => { const bidRequest = Object.assign([], bidRequests); - bidRequest[0].schain = { + bidRequest[0].ortb2 = bidRequest[0].ortb2 || {}; + bidRequest[0].ortb2.source = bidRequest[0].ortb2.source || {}; + bidRequest[0].ortb2.source.ext = bidRequest[0].ortb2.source.ext || {}; + bidRequest[0].ortb2.source.ext.schain = { 'nodes': [{ 'unknown_key': 1 }] diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 11ace2f9ecf..bb93d203ae9 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -4625,7 +4625,8 @@ describe('the rubicon adapter', function () { beforeEach(() => { bidRequests = getBidderRequest(); schainConfig = getSupplyChainConfig(); - bidRequests.bids[0].ortb2.source.schain = schainConfig; + bidRequests.bids[0].ortb2.source.ext = bidRequests.bids[0].ortb2.source.ext || {}; + bidRequests.bids[0].ortb2.source.ext.schain = schainConfig; }); it('should properly serialize schain object with correct delimiters', () => { @@ -4644,14 +4645,14 @@ describe('the rubicon adapter', function () { const results = spec.buildRequests(bidRequests.bids, bidRequests); const schain = new URLSearchParams(results[0].data).get('rp_schain').split('!'); const version = schain.shift().split(',')[0]; - expect(version).to.equal(bidRequests.bids[0].ortb2.source.schain.ver); + expect(version).to.equal(bidRequests.bids[0].ortb2.source.ext.schain.ver); }); it('should send the correct value for complete in schain', () => { const results = spec.buildRequests(bidRequests.bids, bidRequests); const schain = new URLSearchParams(results[0].data).get('rp_schain').split('!'); const complete = schain.shift().split(',')[1]; - expect(complete).to.equal(String(bidRequests.bids[0].ortb2.source.schain.complete)); + expect(complete).to.equal(String(bidRequests.bids[0].ortb2.source.ext.schain.complete)); }); it('should send available params in the right order', () => { diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js index b64c8675647..96491b3a8ee 100644 --- a/test/spec/modules/seedtagBidAdapter_spec.js +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -448,7 +448,10 @@ describe('Seedtag Adapter', function () { // duplicate const bidRequests = JSON.parse(JSON.stringify(validBidRequests)); - bidRequests[0].schain = schain; + bidRequests[0].ortb2 = bidRequests[0].ortb2 || {}; + bidRequests[0].ortb2.source = bidRequests[0].ortb2.source || {}; + bidRequests[0].ortb2.source.ext = bidRequests[0].ortb2.source.ext || {}; + bidRequests[0].ortb2.source.ext.schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 2c05799f602..a54fe3f710c 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -191,17 +191,23 @@ describe('sharethrough adapter spec', function () { crumbs: { pubcid: 'fake-pubcid-in-crumbs-obj', }, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - }, - ], + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1, + }, + ], + } + } + } }, getFloor: () => ({ currency: 'USD', floor: 42 }), }, @@ -321,7 +327,7 @@ describe('sharethrough adapter spec', function () { expect(openRtbReq.source.tid).to.equal(bidderRequest.ortb2.source.tid); expect(openRtbReq.source.ext.version).not.to.be.undefined; expect(openRtbReq.source.ext.str).not.to.be.undefined; - expect(openRtbReq.source.ext.schain).to.deep.equal(bidRequests[0].schain); + expect(openRtbReq.source.ext.schain).to.deep.equal(bidRequests[0].ortb2.source.ext.schain); expect(openRtbReq.bcat).to.deep.equal(bidRequests[0].params.bcat); expect(openRtbReq.badv).to.deep.equal(bidRequests[0].params.badv); diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 4263ba25589..f5b1c2827b2 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -1271,7 +1271,15 @@ describe('smaatoBidAdapterTest', () => { } ] }; - const bidRequestWithSchain = Object.assign({}, singleBannerBidRequest, {schain: schain}); + const bidRequestWithSchain = Object.assign({}, singleBannerBidRequest, { + ortb2: { + source: { + ext: { + schain: schain + } + } + } + }); const reqs = spec.buildRequests([bidRequestWithSchain], defaultBidderRequest); diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index d8ddf7a398b..f548151e31b 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -337,15 +337,21 @@ describe('The smartx adapter', function () { it('should pass schain param', function () { var request; - bid.schain = { - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '00001', - hp: 1 + bid.ortb2 = { + source: { + ext: { + schain: { + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '00001', + hp: 1 + } + ] + } } - ] + } } request = spec.buildRequests([bid], bidRequestObj)[0]; diff --git a/test/spec/modules/smilewantedBidAdapter_spec.js b/test/spec/modules/smilewantedBidAdapter_spec.js index 1c71c7bee07..8063c1d7abe 100644 --- a/test/spec/modules/smilewantedBidAdapter_spec.js +++ b/test/spec/modules/smilewantedBidAdapter_spec.js @@ -116,7 +116,13 @@ const DISPLAY_REQUEST_WITH_SCHAIN = [{ tid: 'trans_abcd1234', } }, - schain: SCHAIN, + ortb2: { + source: { + ext: { + schain: SCHAIN + } + } + }, }]; const BID_RESPONSE_DISPLAY = { diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index 27707d5b7d4..78d538c77d2 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -267,21 +267,27 @@ describe('SonobiBidAdapter', function () { sandbox.restore(); }); let bidRequest = [{ - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'indirectseller.com', - 'sid': '00001', - 'hp': 1 - }, - { - 'asi': 'indirectseller-2.com', - 'sid': '00002', - 'hp': 0 - }, - ] + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, + { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 0 + }, + ] + } + } + } }, 'bidder': 'sonobi', 'params': { @@ -564,7 +570,7 @@ describe('SonobiBidAdapter', function () { it('should return a properly formatted request with schain defined', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); - expect(JSON.parse(decodeURIComponent(bidRequests.data.schain))).to.deep.equal(bidRequest[0].schain) + expect(JSON.parse(decodeURIComponent(bidRequests.data.schain))).to.deep.equal(bidRequest[0].ortb2.source.ext.schain) }); it('should return a properly formatted request with eids as a JSON-encoded set of eids', function () { diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 05d18a0bb98..2ed79808356 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -529,17 +529,23 @@ describe('sovrnBidAdapter', function() { it('should add schain if present', function() { const schainRequest = { ...baseBidRequest, - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1 + } + ] + } } - ] + } } } const schainRequests = [schainRequest, baseBidRequest] diff --git a/test/spec/modules/sspBCBidAdapter_spec.js b/test/spec/modules/sspBCBidAdapter_spec.js index ceaad85faac..32f99096156 100644 --- a/test/spec/modules/sspBCBidAdapter_spec.js +++ b/test/spec/modules/sspBCBidAdapter_spec.js @@ -663,7 +663,7 @@ describe('SSPBC adapter', function () { }, ] } - const bidWithSupplyChain = Object.assign(bids[0], { schain: supplyChain }); + const bidWithSupplyChain = Object.assign(bids[0], { ortb2: { source: { ext: { schain: supplyChain } } } }); const requestWithSupplyChain = spec.buildRequests([bidWithSupplyChain], bidRequest); const payloadWithSupplyChain = requestWithSupplyChain ? JSON.parse(requestWithSupplyChain.data) : { site: false, imp: false }; diff --git a/test/spec/modules/stroeerCoreBidAdapter_spec.js b/test/spec/modules/stroeerCoreBidAdapter_spec.js index d186b0d5cd0..8fb0c0a00b9 100644 --- a/test/spec/modules/stroeerCoreBidAdapter_spec.js +++ b/test/spec/modules/stroeerCoreBidAdapter_spec.js @@ -703,7 +703,12 @@ describe('stroeerCore bid adapter', function () { }); const bidReq = buildBidderRequest(); - bidReq.bids.forEach(bid => bid.schain = schain); + bidReq.bids.forEach(bid => { + bid.ortb2 = bid.ortb2 || {}; + bid.ortb2.source = bid.ortb2.source || {}; + bid.ortb2.source.ext = bid.ortb2.source.ext || {}; + bid.ortb2.source.ext.schain = schain; + }); const serverRequestInfo = spec.buildRequests(bidReq.bids, bidReq); assert.deepEqual(serverRequestInfo.data.schain, schain); diff --git a/test/spec/modules/stvBidAdapter_spec.js b/test/spec/modules/stvBidAdapter_spec.js index 9dc311562ba..458fcd7ce50 100644 --- a/test/spec/modules/stvBidAdapter_spec.js +++ b/test/spec/modules/stvBidAdapter_spec.js @@ -60,17 +60,23 @@ describe('stvAdapter', function() { 'bidderRequestId': '22edbae2733bf61', 'auctionId': '1d1a030790a475', 'adUnitCode': 'testDiv1', - 'schain': { - 'ver': '1.0', - 'complete': 0, - 'nodes': [ - { - 'asi': 'reseller.com', - 'sid': 'aaaaa', - 'rid': 'BidRequest4', - 'hp': 1 + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + 'ver': '1.0', + 'complete': 0, + 'nodes': [ + { + 'asi': 'reseller.com', + 'sid': 'aaaaa', + 'rid': 'BidRequest4', + 'hp': 1 + } + ] + } } - ] + } }, 'userId': { 'id5id': { diff --git a/test/spec/modules/targetVideoBidAdapter_spec.js b/test/spec/modules/targetVideoBidAdapter_spec.js index f2c59d29031..8d9cb5bf18b 100644 --- a/test/spec/modules/targetVideoBidAdapter_spec.js +++ b/test/spec/modules/targetVideoBidAdapter_spec.js @@ -82,7 +82,13 @@ describe('TargetVideo Bid Adapter', function() { }; let videoRequestCloned = deepClone(videoRequest); - videoRequestCloned[0].schain = globalSchain; + videoRequestCloned[0].ortb2 = { + source: { + ext: { + schain: globalSchain + } + } + }; const request = spec.buildRequests(videoRequestCloned, defaultBidderRequest); expect(request).to.not.be.empty; diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index 5ce96e21a20..511be25b49f 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -743,14 +743,20 @@ describe('teadsBidAdapter', () => { it('should add schain info to payload if available', function () { const bidRequest = Object.assign({}, bidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [{ - asi: 'example.com', - sid: '00001', - hp: 1 - }] + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'example.com', + sid: '00001', + hp: 1 + }] + } + } + } } }); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 216142ab02e..14c6b9e1142 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -143,7 +143,13 @@ describe('triplelift adapter', function () { transactionId: '173f49a8-7549-4218-a23c-e7ba59b47229', auctionId: '1d1a030790a475', userId: {}, - schain, + ortb2: { + source: { + ext: { + schain + } + } + }, ortb2Imp: { ext: { tid: '173f49a8-7549-4218-a23c-e7ba59b47229' @@ -177,7 +183,13 @@ describe('triplelift adapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: {}, - schain, + ortb2: { + source: { + ext: { + schain + } + } + }, ortb2Imp: { ext: { data: { @@ -253,7 +265,13 @@ describe('triplelift adapter', function () { bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: {}, - schain, + ortb2: { + source: { + ext: { + schain + } + } + }, ortb2Imp: { misc: { test: 1 @@ -899,7 +917,7 @@ describe('triplelift adapter', function () { expect(payload.ext.schain).to.deep.equal(schain); }); it('should not create root level ext when schain is not present', function() { - bidRequests[0].schain = undefined; + delete bidRequests[0].ortb2.source.ext.schain; const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const { data: payload } = request; expect(payload.ext).to.deep.equal(undefined); diff --git a/test/spec/modules/ttdBidAdapter_spec.js b/test/spec/modules/ttdBidAdapter_spec.js index 31569ccc176..8e6102f9977 100644 --- a/test/spec/modules/ttdBidAdapter_spec.js +++ b/test/spec/modules/ttdBidAdapter_spec.js @@ -547,7 +547,7 @@ describe('ttdBidAdapter', function () { }] }; let clonedBannerBidRequests = deepClone(baseBannerBidRequests); - clonedBannerBidRequests[0].schain = schain; + clonedBannerBidRequests[0].ortb2 = { source: { ext: { schain: schain } } }; const requestBody = testBuildRequests(clonedBannerBidRequests, baseBidderRequest).data; expect(requestBody.source.ext.schain).to.deep.equal(schain); diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index 998e0db6fe8..10241687e14 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -39,19 +39,25 @@ const validBannerBidReq = { } }, userId: userId, - 'schain': { - 'ver': '1.0', - 'complete': 1, - 'nodes': [ - { - 'asi': 'exchange1.com', - 'sid': '1234', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher', - 'domain': 'publisher.com' + ortb2: { + source: { + ext: { + schain: { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'exchange1.com', + 'sid': '1234', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher', + 'domain': 'publisher.com' + } + ] + } } - ] + } } }; diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index f5897c29fe8..af15e42bc02 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -116,7 +116,7 @@ const bidReq = [{ sizes: [[1, 1]], bidId: '453cf42d72bb3c', auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874', - schain: schainObj + ortb2: { source: { ext: { schain: schainObj } } } }]; const supplyChainedBidReqs = [{ @@ -129,7 +129,7 @@ const supplyChainedBidReqs = [{ sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', - schain: schainObj + ortb2: { source: { ext: { schain: schainObj } } } }, { adUnitCode: 'div-gpt-ad-1460505748561-0', bidder: BIDDER_CODE, diff --git a/test/spec/modules/vdoaiBidAdapter_spec.js b/test/spec/modules/vdoaiBidAdapter_spec.js index 1cd361730a9..be2b8fe7386 100644 --- a/test/spec/modules/vdoaiBidAdapter_spec.js +++ b/test/spec/modules/vdoaiBidAdapter_spec.js @@ -43,16 +43,22 @@ describe('vdoaiBidAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } const bid2 = { @@ -91,21 +97,27 @@ describe('vdoaiBidAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 - }, - { - asi: 'example1.com', - sid: '2', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + }, + { + asi: 'example1.com', + sid: '2', + hp: 1 + } + ] + } } - ] + } } } const bid3 = { @@ -148,16 +160,22 @@ describe('vdoaiBidAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } const bid4 = { @@ -198,16 +216,22 @@ describe('vdoaiBidAdapter', function () { ] } ], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '1', - hp: 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '1', + hp: 1 + } + ] + } } - ] + } } } @@ -739,6 +763,6 @@ function validateAdUnit(adUnit, bid) { })); expect(adUnit.publisherId).to.equal(bid.params.publisherId); expect(adUnit.userIdAsEids).to.deep.equal(bid.userIdAsEids); - expect(adUnit.supplyChain).to.deep.equal(bid.schain); + expect(adUnit.supplyChain).to.deep.equal(bid.ortb2?.source?.ext?.schain); expect(adUnit.ortb2Imp).to.deep.equal(bid.ortb2Imp); } diff --git a/test/spec/modules/videobyteBidAdapter_spec.js b/test/spec/modules/videobyteBidAdapter_spec.js index 7844e2bd1be..838e56ab801 100644 --- a/test/spec/modules/videobyteBidAdapter_spec.js +++ b/test/spec/modules/videobyteBidAdapter_spec.js @@ -196,7 +196,10 @@ describe('VideoByteBidAdapter', function () { hp: 1 }] }; - bidRequest.schain = globalSchain; + bidRequest.ortb2 = bidRequest.ortb2 || {}; + bidRequest.ortb2.source = bidRequest.ortb2.source || {}; + bidRequest.ortb2.source.ext = bidRequest.ortb2.source.ext || {}; + bidRequest.ortb2.source.ext.schain = globalSchain; const requests = spec.buildRequests([bidRequest], bidderRequest); const data = JSON.parse(requests[0].data); const schain = data.source.ext.schain; diff --git a/test/spec/modules/vidoomyBidAdapter_spec.js b/test/spec/modules/vidoomyBidAdapter_spec.js index 6f7c0beb29f..b05fbe43e8a 100644 --- a/test/spec/modules/vidoomyBidAdapter_spec.js +++ b/test/spec/modules/vidoomyBidAdapter_spec.js @@ -74,32 +74,38 @@ describe('vidoomyBidAdapter', function() { 'sizes': [[300, 250], [200, 100]] } }, - 'schain': { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'exchange1.com', - 'sid': '1234!abcd', - 'hp': 1, - 'rid': 'bid-request-1', - 'name': 'publisher, Inc.', - 'domain': 'publisher.com' - }, - { - 'asi': 'exchange2.com', - 'sid': 'abcd', - 'hp': 1 - }, - { - 'asi': 'exchange2.com', - 'sid': 'abcd', - 'hp': 1, - 'rid': 'bid-request-2', - 'name': 'intermediary', - 'domain': 'intermediary.com' + 'ortb2': { + 'source': { + 'ext': { + 'schain': { + ver: '1.0', + complete: 1, + nodes: [ + { + 'asi': 'exchange1.com', + 'sid': '1234!abcd', + 'hp': 1, + 'rid': 'bid-request-1', + 'name': 'publisher, Inc.', + 'domain': 'publisher.com' + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1 + }, + { + 'asi': 'exchange2.com', + 'sid': 'abcd', + 'hp': 1, + 'rid': 'bid-request-2', + 'name': 'intermediary', + 'domain': 'intermediary.com' + } + ] + } } - ] + } } }, { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 923ff7e86b2..c8b15527ab6 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -597,7 +597,7 @@ describe('VisxAdapter', function () { it('if schain is present payload must have schain param', function () { const schainBidRequests = [ - Object.assign({schain: schainObject}, bidRequests[0]), + Object.assign({ortb2: {source: {ext: {schain: schainObject}}}}, bidRequests[0]), bidRequests[1], bidRequests[2] ]; diff --git a/test/spec/modules/voxBidAdapter_spec.js b/test/spec/modules/voxBidAdapter_spec.js index 65752837b23..c2fe6abc4db 100644 --- a/test/spec/modules/voxBidAdapter_spec.js +++ b/test/spec/modules/voxBidAdapter_spec.js @@ -212,10 +212,16 @@ describe('VOX Adapter', function() { it('should set schain if not specified', function () { const requests = validBidRequests.map(bid => ({ ...bid, - schain: { - validation: 'strict', - config: { - ver: '1.0' + ortb2: { + source: { + ext: { + schain: { + validation: 'strict', + config: { + ver: '1.0' + } + } + } } } })) diff --git a/test/spec/modules/winrBidAdapter_spec.js b/test/spec/modules/winrBidAdapter_spec.js index 6246912d318..59e06b61405 100644 --- a/test/spec/modules/winrBidAdapter_spec.js +++ b/test/spec/modules/winrBidAdapter_spec.js @@ -470,16 +470,22 @@ describe('WinrAdapter', function () { it('should populate schain if available', function () { const bidRequest = Object.assign({}, bidRequests[0], { - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'blob.com', - 'sid': '001', - 'hp': 1 + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + 'asi': 'blob.com', + 'sid': '001', + 'hp': 1 + } + ] + } } - ] + } } }); diff --git a/test/spec/modules/yahooAdsBidAdapter_spec.js b/test/spec/modules/yahooAdsBidAdapter_spec.js index f8ed7693f3f..7909fe141b7 100644 --- a/test/spec/modules/yahooAdsBidAdapter_spec.js +++ b/test/spec/modules/yahooAdsBidAdapter_spec.js @@ -424,7 +424,10 @@ describe('Yahoo Advertising Bid Adapter:', () => { complete: 1, nodes: [] }; - bidRequest.schain = globalSchain; + bidRequest.ortb2 = bidRequest.ortb2 || {}; + bidRequest.ortb2.source = bidRequest.ortb2.source || {}; + bidRequest.ortb2.source.ext = bidRequest.ortb2.source.ext || {}; + bidRequest.ortb2.source.ext.schain = globalSchain; const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; const schain = data.source.ext.schain; expect(schain).to.be.undefined; @@ -442,7 +445,10 @@ describe('Yahoo Advertising Bid Adapter:', () => { hp: 1 }] }; - bidRequest.schain = globalSchain; + bidRequest.ortb2 = bidRequest.ortb2 || {}; + bidRequest.ortb2.source = bidRequest.ortb2.source || {}; + bidRequest.ortb2.source.ext = bidRequest.ortb2.source.ext || {}; + bidRequest.ortb2.source.ext.schain = globalSchain; const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; const schain = data.source.ext.schain; expect(schain.nodes.length).to.equal(1); diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 92fd20fb37d..7ce61de834c 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -52,22 +52,28 @@ const DEFAULT_REQUEST = () => ({ atype: 2, }], }], - schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'indirectseller.com', - sid: '1', - hp: 1, - }, - { - asi: 'indirectseller2.com', - name: 'indirectseller2 name with comma , and bang !', - sid: '2', - hp: 1, - }, - ], + ortb2: { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'indirectseller.com', + sid: '1', + hp: 1, + }, + { + asi: 'indirectseller2.com', + name: 'indirectseller2 name with comma , and bang !', + sid: '2', + hp: 1, + }, + ], + } + } + } }, }); @@ -430,7 +436,7 @@ describe('yieldlabBidAdapter', () => { it('passes unencoded schain string to bid request when complete == 0', () => { const schainRequest = DEFAULT_REQUEST(); - schainRequest.schain.complete = 0; // + schainRequest.ortb2.source.ext.schain.complete = 0; const request = spec.buildRequests([schainRequest]); expect(request.url).to.include('schain=1.0,0!indirectseller.com,1,1,,,,!indirectseller2.com,2,1,,indirectseller2%20name%20with%20comma%20%2C%20and%20bang%20%21,,'); }); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index db7ebdbbc34..f55308a2c10 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -304,7 +304,7 @@ describe('YieldmoAdapter', function () { complete: 1, nodes: [{asi: 'indirectseller.com', sid: '00001', hp: 1}], }; - const data = buildAndGetData([mockBannerBid({schain})]); + const data = buildAndGetData([mockBannerBid({ortb2: {source: {ext: {schain}}}})]); expect(data.schain).equal(JSON.stringify(schain)); }); @@ -631,7 +631,7 @@ describe('YieldmoAdapter', function () { hp: 1 }], }; - expect(buildAndGetData([mockVideoBid({schain})]).schain).to.deep.equal(schain); + expect(buildAndGetData([mockVideoBid({ortb2: {source: {ext: {schain}}}})]).schain).to.deep.equal(schain); }); it('should add gpid to the video request', function () { diff --git a/test/spec/modules/zeta_global_sspBidAdapter_spec.js b/test/spec/modules/zeta_global_sspBidAdapter_spec.js index 0a4e86e27ab..e031f99dc4e 100644 --- a/test/spec/modules/zeta_global_sspBidAdapter_spec.js +++ b/test/spec/modules/zeta_global_sspBidAdapter_spec.js @@ -126,12 +126,16 @@ describe('Zeta Ssp Bid Adapter', function () { gdprApplies: 1, consentString: 'consentString' }, - schain: schain, uspConsent: 'someCCPAString', params: params, userIdAsEids: eids, timeout: 500, ortb2: { + source: { + ext: { + schain: schain + } + }, bcat: ['CAT1'], badv: ['test1.com'], site: { @@ -191,7 +195,13 @@ describe('Zeta Ssp Bid Adapter', function () { gdprApplies: 1, consentString: 'consentString' }, - schain: schain, + ortb2: { + source: { + ext: { + schain: schain + } + } + }, uspConsent: 'someCCPAString', params: params, userIdAsEids: eids, From ce772661d464bf9459e597688dadd13a67983c72 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Fri, 23 May 2025 15:01:50 +0530 Subject: [PATCH 11/20] Refactored the schain code --- libraries/ortbConverter/processors/default.js | 7 +- libraries/ortbConverter/processors/schain.js | 37 +++------ .../prebidServerBidAdapter/ortbConverter.js | 27 +++---- .../modules/prebidServerBidAdapter_spec.js | 81 +++++++------------ 4 files changed, 56 insertions(+), 96 deletions(-) diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index 245512cd0c8..44a7cde96e1 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -5,7 +5,7 @@ import {setResponseMediaType} from './mediaType.js'; import {fillNativeImp, fillNativeResponse} from './native.js'; import {BID_RESPONSE, IMP, REQUEST} from '../../../src/pbjsORTB.js'; import {clientSectionChecker} from '../../../src/fpd/oneClient.js'; -import {schainProcessor} from './schain.js'; +import {moveSchainToExt} from './schain.js'; export const DEFAULT_PROCESSORS = { [REQUEST]: { @@ -35,7 +35,10 @@ export const DEFAULT_PROCESSORS = { } }, // Add the moveSchainToExt processor to move schain from source.schain to source.ext.schain - moveSchainToExt: schainProcessor[REQUEST].moveSchainToExt + moveSchainToExt: { + priority: -50, + fn: moveSchainToExt + } }, [IMP]: { fpd: { diff --git a/libraries/ortbConverter/processors/schain.js b/libraries/ortbConverter/processors/schain.js index 484249bd282..8e7115ce651 100644 --- a/libraries/ortbConverter/processors/schain.js +++ b/libraries/ortbConverter/processors/schain.js @@ -2,31 +2,20 @@ * This module handles the relocation of schain object from source.schain to source.ext.schain */ import {deepAccess, deepSetValue} from '../../../src/utils.js'; -import {REQUEST} from '../../../src/pbjsORTB.js'; /** - * Processor to move schain from source.schain to source.ext.schain - * This ensures that the schain object is validated first and then moved to the ext object + * Moves schain from source.schain to source.ext.schain + * @param {Object} ortbRequest - The OpenRTB request object + * @param {Object} bidderRequest - The bidder request object (not used) + * @param {Object} context - The context object (not used) */ -export const schainProcessor = { - [REQUEST]: { - moveSchainToExt: { - // Run this after validation but before the request is sent - priority: -50, - fn(ortbRequest, bidderRequest, context) { - // Check if source.schain exists in the ortbRequest - const schain = deepAccess(ortbRequest, 'source.schain'); - if (schain) { - // Create ext object if it doesn't exist - if (!deepAccess(ortbRequest, 'source.ext')) { - deepSetValue(ortbRequest, 'source.ext', {}); - } - // Move schain to ext.schain - deepSetValue(ortbRequest, 'source.ext.schain', schain); - // Remove original schain - delete ortbRequest.source.schain; - } - } - } +export function moveSchainToExt(ortbRequest, bidderRequest, context) { + // Check if source.schain exists in the ortbRequest + const schain = deepAccess(ortbRequest, 'source.schain'); + if (schain) { + // Move schain to ext.schain (deepSetValue will create parent objects if needed) + deepSetValue(ortbRequest, 'source.ext.schain', schain); + // Remove original schain + delete ortbRequest.source.schain; } -}; +} diff --git a/modules/prebidServerBidAdapter/ortbConverter.js b/modules/prebidServerBidAdapter/ortbConverter.js index d60ed0f7ef0..0315d610422 100644 --- a/modules/prebidServerBidAdapter/ortbConverter.js +++ b/modules/prebidServerBidAdapter/ortbConverter.js @@ -205,13 +205,9 @@ const PBS_CONVERTER = ortbConverter({ if (fpdConfigs.length) { deepSetValue(ortbRequest, 'ext.prebid.bidderconfig', fpdConfigs); } - }, - extPrebidAliases(orig, ortbRequest, proxyBidderRequest, context) { - // override alias processing to do it for each bidder in the request - context.actualBidderRequests.forEach(req => orig(ortbRequest, req, context)); - }, - sourceExtSchain(orig, ortbRequest, proxyBidderRequest, context) { - // pass schains in ext.prebid.schains + + // Handle schain information after FPD processing + // Collect schains from bidder requests and organize into ext.prebid.schains let chains = ortbRequest?.ext?.prebid?.schains || []; const chainBidders = new Set(chains.flatMap((item) => item.bidders)); @@ -219,15 +215,10 @@ const PBS_CONVERTER = ortbConverter({ chains .concat(context.actualBidderRequests .filter((req) => !chainBidders.has(req.bidderCode)) // schain defined in s2sConfig.extPrebid takes precedence - .map((req) => { - const bid = req?.bids?.[0] || {}; - const schain = bid?.ortb2?.source?.ext?.schain; - - return { - bidders: [req.bidderCode], - schain: schain - }; - })) + .map((req) => ({ + bidders: [req.bidderCode], + schain: req?.bids?.[0]?.ortb2?.source?.schain + }))) .filter(({bidders, schain}) => bidders?.length > 0 && schain) .reduce((chains, {bidders, schain}) => { const key = JSON.stringify(schain); @@ -242,6 +233,10 @@ const PBS_CONVERTER = ortbConverter({ if (chains.length) { deepSetValue(ortbRequest, 'ext.prebid.schains', chains); } + }, + extPrebidAliases(orig, ortbRequest, proxyBidderRequest, context) { + // override alias processing to do it for each bidder in the request + context.actualBidderRequests.forEach(req => orig(ortbRequest, req, context)); } }, [RESPONSE]: { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 06bba723db0..264a3d1f0af 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2420,42 +2420,21 @@ describe('S2S Adapter', function () { it('should have extPrebid.schains present on req object if bidder specific schains were configured with pbjs', function () { let bidRequest = utils.deepClone(BID_REQUESTS); - - // Set the schain directly on the bid object - bidRequest[0].bids[0].schain = { - complete: 1, - nodes: [{ - asi: 'test.com', - hp: 1, - sid: '11111' - }], - ver: '1.0' - }; - - // Create a modified s2sConfig with schains directly set - const s2sConfig = Object.assign({}, CONFIG, { - extPrebid: { - schains: [ - { - bidders: ['appnexus'], - schain: { - complete: 1, - nodes: [{ - asi: 'test.com', - hp: 1, - sid: '11111' - }], - ver: '1.0' - } - } - ] + bidRequest[0].bids[0].ortb2 = { + source: { + schain: { + complete: 1, + nodes: [{ + asi: 'test.com', + hp: 1, + sid: '11111' + }], + ver: '1.0' + } } - }); - - const s2sRequest = utils.deepClone(REQUEST); - s2sRequest.s2sConfig = s2sConfig; + }; - adapter.callBids(s2sRequest, bidRequest, addBidResponse, done, ajax); + adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext.prebid.schains).to.deep.equal([ @@ -2478,12 +2457,7 @@ describe('S2S Adapter', function () { it('should skip over adding any bid specific schain entries that already exist on extPrebid.schains', function () { let bidRequest = utils.deepClone(BID_REQUESTS); - // Initialize ortb2 object if it doesn't exist - bidRequest[0].bids[0].ortb2 = bidRequest[0].bids[0].ortb2 || {}; - bidRequest[0].bids[0].ortb2.source = bidRequest[0].bids[0].ortb2.source || {}; - bidRequest[0].bids[0].ortb2.source.ext = bidRequest[0].bids[0].ortb2.source.ext || {}; - - bidRequest[0].bids[0].ortb2.source.ext.schain = { + bidRequest[0].bids[0].schain = { complete: 1, nodes: [{ asi: 'pbjs.com', @@ -2540,19 +2514,18 @@ describe('S2S Adapter', function () { it('should add a bidder name to pbs schain if the schain is equal to a pbjs one but the pbjs bidder name is not in the bidder array on the pbs side', function () { let bidRequest = utils.deepClone(BID_REQUESTS); - // Initialize ortb2 object if it doesn't exist - bidRequest[0].bids[0].ortb2 = bidRequest[0].bids[0].ortb2 || {}; - bidRequest[0].bids[0].ortb2.source = bidRequest[0].bids[0].ortb2.source || {}; - bidRequest[0].bids[0].ortb2.source.ext = bidRequest[0].bids[0].ortb2.source.ext || {}; - - bidRequest[0].bids[0].ortb2.source.ext.schain = { - complete: 1, - nodes: [{ - asi: 'test.com', - hp: 1, - sid: '11111' - }], - ver: '1.0' + bidRequest[0].bids[0].ortb2 = { + source: { + schain: { + complete: 1, + nodes: [{ + asi: 'test.com', + hp: 1, + sid: '11111' + }], + ver: '1.0' + } + } }; bidRequest[0].bids[1] = { @@ -2594,7 +2567,7 @@ describe('S2S Adapter', function () { let requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext.prebid.schains).to.deep.equal([ { - bidders: ['rubicon'], + bidders: ['rubicon', 'appnexus'], schain: { complete: 1, nodes: [ From 321f94ee4aa5d1b4d5f44a04bf1b88ea542a72a0 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Sat, 24 May 2025 15:21:20 +0530 Subject: [PATCH 12/20] Added precedence logic for schain --- libraries/ortbConverter/processors/default.js | 6 -- libraries/ortbConverter/processors/schain.js | 21 ------ src/adapterManager.js | 5 +- src/fpd/schain.js | 74 +++++++++++++++++++ src/prebid.js | 6 +- test/spec/modules/bridgeuppBidAdapter_spec.js | 4 +- test/spec/modules/r2b2BidAdapter_spec.js | 6 +- 7 files changed, 89 insertions(+), 33 deletions(-) delete mode 100644 libraries/ortbConverter/processors/schain.js create mode 100644 src/fpd/schain.js diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index 44a7cde96e1..9dc9a7cd13f 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -5,7 +5,6 @@ import {setResponseMediaType} from './mediaType.js'; import {fillNativeImp, fillNativeResponse} from './native.js'; import {BID_RESPONSE, IMP, REQUEST} from '../../../src/pbjsORTB.js'; import {clientSectionChecker} from '../../../src/fpd/oneClient.js'; -import {moveSchainToExt} from './schain.js'; export const DEFAULT_PROCESSORS = { [REQUEST]: { @@ -34,11 +33,6 @@ export const DEFAULT_PROCESSORS = { } } }, - // Add the moveSchainToExt processor to move schain from source.schain to source.ext.schain - moveSchainToExt: { - priority: -50, - fn: moveSchainToExt - } }, [IMP]: { fpd: { diff --git a/libraries/ortbConverter/processors/schain.js b/libraries/ortbConverter/processors/schain.js deleted file mode 100644 index 8e7115ce651..00000000000 --- a/libraries/ortbConverter/processors/schain.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This module handles the relocation of schain object from source.schain to source.ext.schain - */ -import {deepAccess, deepSetValue} from '../../../src/utils.js'; - -/** - * Moves schain from source.schain to source.ext.schain - * @param {Object} ortbRequest - The OpenRTB request object - * @param {Object} bidderRequest - The bidder request object (not used) - * @param {Object} context - The context object (not used) - */ -export function moveSchainToExt(ortbRequest, bidderRequest, context) { - // Check if source.schain exists in the ortbRequest - const schain = deepAccess(ortbRequest, 'source.schain'); - if (schain) { - // Move schain to ext.schain (deepSetValue will create parent objects if needed) - deepSetValue(ortbRequest, 'source.ext.schain', schain); - // Remove original schain - delete ortbRequest.source.schain; - } -} diff --git a/src/adapterManager.js b/src/adapterManager.js index 5fe9c5112f7..b1fbd046a9f 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -41,6 +41,7 @@ import { import {getRefererInfo} from './refererDetection.js'; import {GDPR_GVLIDS, gdprDataHandler, gppDataHandler, uspDataHandler, } from './consentHandler.js'; import * as events from './events.js'; +import {moveSchainToExt} from './fpd/schain.js'; import {EVENTS, S2S} from './constants.js'; import {useMetrics} from './utils/perfMetrics.js'; import {auctionManager} from './auctionManager.js'; @@ -315,7 +316,9 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a ? s2sActivityParams : activityParams(MODULE_TYPE_BIDDER, bidderRequest.bidderCode) ); - const fpd = Object.freeze(redact.ortb2(mergeDeep({source: {tid: auctionId}}, ortb2, bidderOrtb2[bidderRequest.bidderCode]))); + let fpd = redact.ortb2(mergeDeep({source: {tid: auctionId}}, ortb2, bidderOrtb2[bidderRequest.bidderCode])); + fpd = moveSchainToExt(fpd); + bidderRequest.ortb2 = fpd; bidderRequest.bids = bidderRequest.bids.map((bid) => { bid.ortb2 = fpd; diff --git a/src/fpd/schain.js b/src/fpd/schain.js new file mode 100644 index 00000000000..a6e31df7d53 --- /dev/null +++ b/src/fpd/schain.js @@ -0,0 +1,74 @@ +/** + * This module handles supply chain (schain) processing and relocation + * between different locations in the ortb2 structure + */ +import {config} from '../config.js'; +import {deepClone, logInfo} from '../utils.js'; + +/** + * Applies schain from config to ortb2 fragments with precedence rules + * @param {Object} ortb2Fragments - The ortb2 fragments object + * @returns {Object} - The updated ortb2Fragments object + */ +export function schainPrecedence(ortb2Fragments) { + if (!ortb2Fragments) return ortb2Fragments; + + // Apply global schain config if available + // config's schain will have more precedence over ortb2.source.schain + const globalSchainConfig = config.getConfig('schain'); + if (globalSchainConfig && globalSchainConfig.config) { + logInfo('Applying global schain config with precedence'); + applySchainToPath(ortb2Fragments, 'global.source', globalSchainConfig.config); + } + + // Apply bidder-specific schain configs + const bidderConfigs = config.getBidderConfig(); + if (!bidderConfigs) return ortb2Fragments; + + Object.entries(bidderConfigs) + .filter(([_, cfg]) => cfg.schain) + .forEach(([bidderCode, cfg]) => { + logInfo(`Applying bidder schain config for ${bidderCode}`); + applySchainToPath(ortb2Fragments, `bidder.${bidderCode}.source`, cfg.schain?.config); + }); + + return ortb2Fragments; +} + +/** + * Helper function to apply schain to a specific path in ortb2Fragments + * @param {Object} fragments - The ortb2 fragments object + * @param {String} path - Dot-notation path where to apply the schain + * @param {Object} schainConfig - The schain configuration to apply + */ +function applySchainToPath(fragments, path, schainConfig) { + const parts = path.split('.'); + let current = fragments; + + // Create path if it doesn't exist + parts.forEach(part => { + current[part] = current[part] || {}; + current = current[part]; + }); + + // Apply the schain config + current.schain = deepClone(schainConfig); +} + +/** + * Relocates schain from source.schain to source.ext.schain + * @param {Object} fpd - The first-party data object + * @returns {Object} - The updated FPD object + */ +export function moveSchainToExt(fpd) { + if (!fpd?.source?.schain) return fpd; + + // Ensure source.ext exists + fpd.source.ext = fpd.source.ext || {}; + + // Move schain to the new location and remove from original + fpd.source.ext.schain = fpd.source.schain; + delete fpd.source.schain; + + return fpd; +} diff --git a/src/prebid.js b/src/prebid.js index 4e588a5a6f5..f48b8a172a4 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -38,6 +38,7 @@ import * as events from './events.js'; import {newMetrics, useMetrics} from './utils/perfMetrics.js'; import {defer, PbPromise} from './utils/promise.js'; import {enrichFPD} from './fpd/enrichment.js'; +import {schainPrecedence} from './fpd/schain.js'; import {allConsent} from './consentHandler.js'; import { insertLocatorFrame, @@ -600,10 +601,13 @@ pbjsInstance.requestBids = (function() { adUnitCodes = adUnits && adUnits.map(unit => unit.code); } adUnitCodes = adUnitCodes.filter(uniques); - const ortb2Fragments = { + let ortb2Fragments = { global: mergeDeep({}, config.getAnyConfig('ortb2') || {}, ortb2 || {}), bidder: Object.fromEntries(Object.entries(config.getBidderConfig()).map(([bidder, cfg]) => [bidder, deepClone(cfg.ortb2)]).filter(([_, ortb2]) => ortb2 != null)) } + // Apply schain precedence rules before enrichment + ortb2Fragments = schainPrecedence(ortb2Fragments); + return enrichFPD(PbPromise.resolve(ortb2Fragments.global)).then(global => { ortb2Fragments.global = global; return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2Fragments, metrics, defer}); diff --git a/test/spec/modules/bridgeuppBidAdapter_spec.js b/test/spec/modules/bridgeuppBidAdapter_spec.js index 40d63321480..a9e7b329cc9 100644 --- a/test/spec/modules/bridgeuppBidAdapter_spec.js +++ b/test/spec/modules/bridgeuppBidAdapter_spec.js @@ -242,7 +242,9 @@ describe('bridgeuppBidAdapter_spec', function () { const ortb2 = { source: { pchain: 'sonarads', - schain: expectedSchain + ext: { + schain: expectedSchain + } } }; const bidRequests = [ diff --git a/test/spec/modules/r2b2BidAdapter_spec.js b/test/spec/modules/r2b2BidAdapter_spec.js index b3296b2c1c7..f9040798abc 100644 --- a/test/spec/modules/r2b2BidAdapter_spec.js +++ b/test/spec/modules/r2b2BidAdapter_spec.js @@ -91,7 +91,7 @@ describe('R2B2 adapter', function () { }, site: {}, device: {}, - source: {schain: schain} + source: {ext: {schain: schain}} }, }, { bidder: 'r2b2', @@ -128,7 +128,7 @@ describe('R2B2 adapter', function () { }, site: {}, device: {}, - source: {schain: schain} + source: {ext: {schain: schain}} }, }]; bidderRequest = { @@ -150,7 +150,7 @@ describe('R2B2 adapter', function () { }, site: {}, device: {}, - source: {schain: schain} + source: {ext: {schain: schain}} }, gdprConsent: { consentString: 'consent-string', From 483efb80b5987c9fff69bc871592365035b3d5d2 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Tue, 3 Jun 2025 13:49:59 +0530 Subject: [PATCH 13/20] Giving preference to bidderlevel schain over global level --- src/adapterManager.js | 6 ++++-- src/fpd/schain.js | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/adapterManager.js b/src/adapterManager.js index b1fbd046a9f..86ab718ea14 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -316,9 +316,11 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a ? s2sActivityParams : activityParams(MODULE_TYPE_BIDDER, bidderRequest.bidderCode) ); - let fpd = redact.ortb2(mergeDeep({source: {tid: auctionId}}, ortb2, bidderOrtb2[bidderRequest.bidderCode])); - fpd = moveSchainToExt(fpd); + const merged = mergeDeep({source: {tid: auctionId}}, ortb2, bidderOrtb2[bidderRequest.bidderCode]); + moveUserEidsToExt(merged); + moveSchainToExt(merged, bidderOrtb2[bidderRequest.bidderCode]); + const fpd = Object.freeze(redact.ortb2(merged)); bidderRequest.ortb2 = fpd; bidderRequest.bids = bidderRequest.bids.map((bid) => { bid.ortb2 = fpd; diff --git a/src/fpd/schain.js b/src/fpd/schain.js index a6e31df7d53..311c9e84a68 100644 --- a/src/fpd/schain.js +++ b/src/fpd/schain.js @@ -60,14 +60,14 @@ function applySchainToPath(fragments, path, schainConfig) { * @param {Object} fpd - The first-party data object * @returns {Object} - The updated FPD object */ -export function moveSchainToExt(fpd) { +export function moveSchainToExt(fpd, bidderOrtb2) { if (!fpd?.source?.schain) return fpd; // Ensure source.ext exists fpd.source.ext = fpd.source.ext || {}; // Move schain to the new location and remove from original - fpd.source.ext.schain = fpd.source.schain; + fpd.source.ext.schain = bidderOrtb2?.source?.schain || fpd.source.schain; delete fpd.source.schain; return fpd; From 4db4061a8537802461e51006bc500b3d17b6d2af Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Tue, 3 Jun 2025 15:18:26 +0530 Subject: [PATCH 14/20] Added test cases for schain --- test/spec/fpd/schain_spec.js | 319 +++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 test/spec/fpd/schain_spec.js diff --git a/test/spec/fpd/schain_spec.js b/test/spec/fpd/schain_spec.js new file mode 100644 index 00000000000..4392dcb1981 --- /dev/null +++ b/test/spec/fpd/schain_spec.js @@ -0,0 +1,319 @@ +import {expect} from 'chai/index.js'; +import * as utils from 'src/utils.js'; +import {config} from 'src/config.js'; +import {schainPrecedence, moveSchainToExt} from 'src/fpd/schain.js'; + +describe('Supply Chain fpd', function() { + const SAMPLE_SCHAIN = { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'example.com', sid: '00001', hp: 1 }] + }; + + const SAMPLE_SCHAIN_2 = { + ver: '2.0', + complete: 1, + nodes: [{ asi: 'bidder.com', sid: '00002', hp: 1 }] + }; + + let sandbox; + let logInfoStub; + let configGetConfigStub; + let configGetBidderConfigStub; + + beforeEach(function() { + sandbox = sinon.createSandbox(); + logInfoStub = sandbox.stub(utils, 'logInfo'); + configGetConfigStub = sandbox.stub(config, 'getConfig'); + configGetBidderConfigStub = sandbox.stub(config, 'getBidderConfig'); + }); + + afterEach(function() { + sandbox.restore(); + }); + + + describe('schainPrecedence', function() { + describe('handles edge cases', function() { + it('should handle edge cases and no-op scenarios', function() { + expect(schainPrecedence(null)).to.be.null; + expect(schainPrecedence(undefined)).to.be.undefined; + expect(schainPrecedence({})).to.deep.equal({}); + + const input = { + global: { + source: { + tid: '123' + } + } + }; + configGetConfigStub.returns(null); + configGetBidderConfigStub.returns(null); + + const result = schainPrecedence(input); + expect(result).to.deep.equal(input); + expect(logInfoStub.called).to.be.false; + }); + }); + + describe('global schain config handling', function() { + let input; + + beforeEach(function() { + input = { + global: { + source: {} + } + }; + configGetBidderConfigStub.returns(null); + }); + + it('should correctly handle different global schain config scenarios', function() { + const validSchainConfig = { + config: SAMPLE_SCHAIN + }; + configGetConfigStub.returns(validSchainConfig); + + let result = schainPrecedence(input); + expect(result.global.source.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(logInfoStub.calledWith('Applying global schain config with precedence')).to.be.true; + + logInfoStub.reset(); + input = { global: { source: {} } }; + + const invalidSchainConfig = { + validation: 'strict' + }; + configGetConfigStub.returns(invalidSchainConfig); + + result = schainPrecedence(input); + expect(result.global.source.schain).to.be.undefined; + }); + }); + + describe('bidder-specific schain config handling', function() { + let input; + + beforeEach(function() { + input = { + global: {}, + bidder: {} + }; + configGetConfigStub.returns(null); + logInfoStub.reset(); + }); + + it('should handle various bidder-specific schain scenarios', function() { + const singleBidderConfig = { + 'bidderA': { + schain: { + config: SAMPLE_SCHAIN + } + } + }; + configGetBidderConfigStub.returns(singleBidderConfig); + + let result = schainPrecedence(input); + expect(result.bidder.bidderA.source.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(logInfoStub.calledWith('Applying bidder schain config for bidderA')).to.be.true; + + logInfoStub.reset(); + input = { global: {}, bidder: {} }; + + const multiBidderConfig = { + 'bidderA': { + schain: { + config: SAMPLE_SCHAIN + } + }, + 'bidderB': { + schain: { + config: SAMPLE_SCHAIN_2 + } + }, + 'bidderC': { + } + }; + configGetBidderConfigStub.returns(multiBidderConfig); + + result = schainPrecedence(input); + expect(result.bidder.bidderA.source.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(result.bidder.bidderB.source.schain).to.deep.equal(SAMPLE_SCHAIN_2); + expect(result.bidder.bidderC).to.be.undefined; + expect(logInfoStub.calledWith('Applying bidder schain config for bidderA')).to.be.true; + expect(logInfoStub.calledWith('Applying bidder schain config for bidderB')).to.be.true; + + logInfoStub.reset(); + input = { global: {}, bidder: {} }; + + const invalidBidderConfig = { + 'bidderA': { + schain: { + validation: 'strict' + } + } + }; + configGetBidderConfigStub.returns(invalidBidderConfig); + + result = schainPrecedence(input); + expect(result.bidder.bidderA.source.schain).to.deep.equal({}); + }); + }); + + // Test case: both global and bidder-specific schain configs + it('should apply both global and bidder-specific schain configs', function() { + const input = { + global: {}, + bidder: {} + }; + const globalSchainConfig = { + config: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'global.com', sid: '00001', hp: 1 }] + } + }; + const bidderConfigs = { + 'bidderA': { + schain: { + config: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'bidderA.com', sid: '00001', hp: 1 }] + } + } + } + }; + configGetConfigStub.returns(globalSchainConfig); + configGetBidderConfigStub.returns(bidderConfigs); + + const result = schainPrecedence(input); + expect(result.global.source.schain).to.deep.equal(globalSchainConfig.config); + expect(result.bidder.bidderA.source.schain).to.deep.equal(bidderConfigs.bidderA.schain.config); + }); + }); + + describe('moveSchainToExt', function() { + it('should handle various input scenarios correctly', function() { + expect(moveSchainToExt(null)).to.be.null; + expect(moveSchainToExt(undefined)).to.be.undefined; + + const inputNoSource = { user: { id: '123' } }; + expect(moveSchainToExt(inputNoSource)).to.deep.equal(inputNoSource); + + const inputNoSchain = { source: { tid: '123' } }; + expect(moveSchainToExt(inputNoSchain)).to.deep.equal(inputNoSchain); + + const basicInput = { + source: { + tid: '123', + schain: SAMPLE_SCHAIN + } + }; + let result = moveSchainToExt(basicInput); + expect(result.source.schain).to.be.undefined; + expect(result.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(result.source.tid).to.equal('123'); + + const inputWithExt = { + source: { + tid: '123', + schain: SAMPLE_SCHAIN, + ext: { + dchain: { ver: '1.0' } + } + } + }; + result = moveSchainToExt(inputWithExt); + expect(result.source.schain).to.be.undefined; + expect(result.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(result.source.ext.dchain).to.deep.equal({ ver: '1.0' }); + }); + + describe('bidderOrtb2 parameter handling', function() { + const createFreshFpd = () => ({ + source: { + tid: '123', + schain: SAMPLE_SCHAIN + } + }); + + it('should handle bidderOrtb2 parameter variations', function() { + const bidderOrtb2WithSchain = { + source: { + schain: SAMPLE_SCHAIN_2 + } + }; + + let fpd = createFreshFpd(); + let result = moveSchainToExt(fpd, bidderOrtb2WithSchain); + expect(result.source.schain).to.be.undefined; + expect(result.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN_2); + + const bidderOrtb2WithoutSchain = { + source: {} + }; + + fpd = createFreshFpd(); + result = moveSchainToExt(fpd, bidderOrtb2WithoutSchain); + expect(result.source.schain).to.be.undefined; + expect(result.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN); + + fpd = createFreshFpd(); + result = moveSchainToExt(fpd, null); + expect(result.source.schain).to.be.undefined; + expect(result.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN); + }); + }); + }); + + describe('Integration', function() { + it('should handle the full schain workflow with both global and bidder configs', function() { + const ortb2Fragments = { + global: { + source: { + tid: '123' + } + }, + bidder: { + 'bidderA': { + source: {} + } + } + }; + + configGetConfigStub.returns({ config: SAMPLE_SCHAIN }); + configGetBidderConfigStub.returns({ + 'bidderA': { + schain: { + config: SAMPLE_SCHAIN_2 + } + } + }); + + const updatedFragments = schainPrecedence(ortb2Fragments); + + expect(updatedFragments.global.source.schain).to.deep.equal(SAMPLE_SCHAIN); + expect(updatedFragments.bidder.bidderA.source.schain).to.deep.equal(SAMPLE_SCHAIN_2); + + const merged = { + source: { + tid: '123', + schain: SAMPLE_SCHAIN + } + }; + + const bidderOrtb2 = { + source: { + schain: SAMPLE_SCHAIN_2 + } + }; + + const finalFpd = moveSchainToExt(merged, bidderOrtb2); + + expect(finalFpd.source.schain).to.be.undefined; + expect(finalFpd.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN_2); + expect(finalFpd.source.tid).to.equal('123'); + }); + }); +}); From f8ad6657afe1f7d26b4a0cec73c490612b6e913c Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Tue, 3 Jun 2025 16:35:43 +0530 Subject: [PATCH 15/20] Linting --- libraries/ortbConverter/processors/default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index 9dc9a7cd13f..acb76461bfd 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -32,7 +32,7 @@ export const DEFAULT_PROCESSORS = { ortbRequest.tmax = timeout; } } - }, + } }, [IMP]: { fpd: { From 90c36f78b8f2c2bf333dcdd52c66e861436cf7b2 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Tue, 3 Jun 2025 17:20:09 +0530 Subject: [PATCH 16/20] formated test cases --- src/adapterManager.js | 1 - .../modules/audiencerunBidAdapter_spec.js | 20 ++++++++-------- test/spec/modules/bliinkBidAdapter_spec.js | 18 +++++++------- .../brightMountainMediaBidAdapter_spec.js | 20 ++++++++-------- .../modules/colossussspBidAdapter_spec.js | 24 +++++++++---------- test/spec/modules/connectadBidAdapter_spec.js | 18 +++++++------- 6 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/adapterManager.js b/src/adapterManager.js index 86ab718ea14..b24da3305de 100644 --- a/src/adapterManager.js +++ b/src/adapterManager.js @@ -318,7 +318,6 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a ); const merged = mergeDeep({source: {tid: auctionId}}, ortb2, bidderOrtb2[bidderRequest.bidderCode]); - moveUserEidsToExt(merged); moveSchainToExt(merged, bidderOrtb2[bidderRequest.bidderCode]); const fpd = Object.freeze(redact.ortb2(merged)); bidderRequest.ortb2 = fpd; diff --git a/test/spec/modules/audiencerunBidAdapter_spec.js b/test/spec/modules/audiencerunBidAdapter_spec.js index 35d1a7a54a3..04a0194af54 100644 --- a/test/spec/modules/audiencerunBidAdapter_spec.js +++ b/test/spec/modules/audiencerunBidAdapter_spec.js @@ -243,16 +243,16 @@ describe('AudienceRun bid adapter tests', function () { source: { ext: { schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1, - }, - ], + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1, + }, + ], } } } diff --git a/test/spec/modules/bliinkBidAdapter_spec.js b/test/spec/modules/bliinkBidAdapter_spec.js index 96b14c35b60..ec598149af7 100644 --- a/test/spec/modules/bliinkBidAdapter_spec.js +++ b/test/spec/modules/bliinkBidAdapter_spec.js @@ -813,15 +813,15 @@ const testsBuildRequests = [ source: { ext: { schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'ssp.test', - sid: '00001', - hp: 1, - }, - ], + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'ssp.test', + sid: '00001', + hp: 1, + }, + ], } } } diff --git a/test/spec/modules/brightMountainMediaBidAdapter_spec.js b/test/spec/modules/brightMountainMediaBidAdapter_spec.js index 657125c656c..58c0d5f5e3c 100644 --- a/test/spec/modules/brightMountainMediaBidAdapter_spec.js +++ b/test/spec/modules/brightMountainMediaBidAdapter_spec.js @@ -30,16 +30,16 @@ describe('brightMountainMediaBidAdapter_spec', function () { source: { ext: { schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'directseller.com', - sid: '00001', - rid: 'BidRequest1', - hp: 1 - } - ] + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'directseller.com', + sid: '00001', + rid: 'BidRequest1', + hp: 1 + } + ] } } } diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index a4bfa42e70b..69b3dc556f0 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -28,18 +28,18 @@ describe('ColossussspAdapter', function () { source: { ext: { schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'example.com', - sid: '0', - hp: 1, - rid: 'bidrequestid', - // name: 'alladsallthetime', - domain: 'example.com' - } - ] + ver: '1.0', + complete: 1, + nodes: [ + { + asi: 'example.com', + sid: '0', + hp: 1, + rid: 'bidrequestid', + // name: 'alladsallthetime', + domain: 'example.com' + } + ] } } } diff --git a/test/spec/modules/connectadBidAdapter_spec.js b/test/spec/modules/connectadBidAdapter_spec.js index 5adecca3631..030c21c13d7 100644 --- a/test/spec/modules/connectadBidAdapter_spec.js +++ b/test/spec/modules/connectadBidAdapter_spec.js @@ -376,15 +376,15 @@ describe('ConnectAd Adapter', function () { source: { ext: { schain: { - ver: '1.0', - complete: 1, - nodes: [ - { - 'asi': 'reseller1.com', - 'sid': 'absc1', - 'hp': 1 - } - ] + ver: '1.0', + complete: 1, + nodes: [ + { + 'asi': 'reseller1.com', + 'sid': 'absc1', + 'hp': 1 + } + ] } } } From 6ee1aa361584c0fcf22dfda8609a8deae8895977 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Thu, 5 Jun 2025 15:55:36 +0530 Subject: [PATCH 17/20] Handled schain in libraries folder --- .../adtelligentUtils/adtelligentUtils.js | 4 ++-- libraries/braveUtils/buildAndInterpret.js | 2 +- libraries/precisoUtils/bidUtilsCommon.js | 2 +- libraries/riseUtils/index.js | 4 ++-- libraries/teqblazeUtils/bidderUtils.js | 6 +++--- libraries/xeUtils/bidderUtils.js | 2 +- test/spec/modules/adipoloBidAdapter_spec.js | 20 ++++++++++--------- test/spec/modules/adtargetBidAdapter_spec.js | 14 ++++++++++--- .../modules/adtelligentBidAdapter_spec.js | 3 +-- test/spec/modules/anyclipBidAdapter_spec.js | 20 ++++++++++--------- .../spec/modules/driftpixelBidAdapter_spec.js | 20 ++++++++++--------- test/spec/modules/iqxBidAdapter_spec.js | 20 ++++++++++--------- .../spec/modules/lm_kiviadsBidAdapter_spec.js | 20 ++++++++++--------- .../modules/minutemediaBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/openwebBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/publirBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/riseBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/shinezBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/stnBidAdapter_spec.js | 15 +++++++++----- test/spec/modules/xeBidAdapter_spec.js | 20 ++++++++++--------- 20 files changed, 148 insertions(+), 99 deletions(-) diff --git a/libraries/adtelligentUtils/adtelligentUtils.js b/libraries/adtelligentUtils/adtelligentUtils.js index c2543fa4cae..9769102ed69 100644 --- a/libraries/adtelligentUtils/adtelligentUtils.js +++ b/libraries/adtelligentUtils/adtelligentUtils.js @@ -65,8 +65,8 @@ export function createTag(bidRequests, adapterRequest) { if (deepAccess(adapterRequest, 'uspConsent')) { tag.USP = deepAccess(adapterRequest, 'uspConsent'); } - if (deepAccess(bidRequests[0], 'schain')) { - tag.Schain = deepAccess(bidRequests[0], 'schain'); + if (deepAccess(adapterRequest, 'ortb2.source.ext.schain')) { + tag.Schain = deepAccess(adapterRequest, 'ortb2.source.ext.schain'); } if (deepAccess(bidRequests[0], 'userId')) { tag.UserIds = deepAccess(bidRequests[0], 'userId'); diff --git a/libraries/braveUtils/buildAndInterpret.js b/libraries/braveUtils/buildAndInterpret.js index 8dda7f6060c..39491b0582d 100644 --- a/libraries/braveUtils/buildAndInterpret.js +++ b/libraries/braveUtils/buildAndInterpret.js @@ -30,7 +30,7 @@ export const buildRequests = (validBidRequests, bidderRequest, endpointURL, defa prepareConsents(data, bidderRequest); prepareEids(data, validBidRequests[0]); - if (validBidRequests[0].schain) data.source = { ext: { schain: validBidRequests[0].schain } }; + if (bidderRequest?.ortb2?.source?.ext?.schain) data.source = { ext: { schain: bidderRequest.ortb2.source.ext.schain } }; return { method: 'POST', url: endpoint, data }; }; diff --git a/libraries/precisoUtils/bidUtilsCommon.js b/libraries/precisoUtils/bidUtilsCommon.js index a8ea97efcaf..8017ea15d1f 100644 --- a/libraries/precisoUtils/bidUtilsCommon.js +++ b/libraries/precisoUtils/bidUtilsCommon.js @@ -67,7 +67,7 @@ export const buildBidRequests = (adurl) => (validBidRequests = [], bidderRequest const placement = { placementId: bid.params.placementId, bidId: bid.bidId, - schain: bid.schain || {}, + schain: bid?.ortb2?.source?.ext?.schain || {}, bidfloor: getBidFloor(bid) }; diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index 511bfc2f5eb..075b6ad4672 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -427,8 +427,8 @@ export function generateGeneralParams(generalObject, bidderRequest, adapterVersi generalParams.ifa = generalBidParams.ifa; } - if (generalObject.schain) { - generalParams.schain = getSupplyChain(generalObject.schain); + if (bidderRequest?.ortb2?.source?.ext?.schain) { + generalParams.schain = getSupplyChain(bidderRequest.ortb2.source.ext.schain); } if (bidderRequest && bidderRequest.refererInfo) { diff --git a/libraries/teqblazeUtils/bidderUtils.js b/libraries/teqblazeUtils/bidderUtils.js index 84010adbbd6..88c7a4c54a3 100644 --- a/libraries/teqblazeUtils/bidderUtils.js +++ b/libraries/teqblazeUtils/bidderUtils.js @@ -35,9 +35,9 @@ const getBidFloor = (bid) => { } }; -const createBasePlacement = (bid) => { +const createBasePlacement = (bid, bidderRequest) => { const { bidId, mediaTypes, transactionId, userIdAsEids } = bid; - const schain = bid.schain || {}; + const schain = bidderRequest?.ortb2?.source?.ext?.schain || {}; const bidfloor = getBidFloor(bid); const placement = { @@ -253,7 +253,7 @@ export const getUserSyncs = (syncUrl) => (syncOptions, serverResponses, gdprCons export const buildPlacementProcessingFunction = (config) => (bid, bidderRequest) => { const addPlacementType = config?.addPlacementType ?? defaultPlacementType; - const placement = createBasePlacement(bid); + const placement = createBasePlacement(bid, bidderRequest); addPlacementType(bid, bidderRequest, placement); diff --git a/libraries/xeUtils/bidderUtils.js b/libraries/xeUtils/bidderUtils.js index b75d315684d..0d45067756f 100644 --- a/libraries/xeUtils/bidderUtils.js +++ b/libraries/xeUtils/bidderUtils.js @@ -48,7 +48,7 @@ export function buildRequests(validBidRequests, bidderRequest, endpoint) { request.auctionId = req.ortb2?.source?.tid; request.transactionId = req.ortb2Imp?.ext?.tid; request.sizes = parseSizesInput(getAdUnitSizes(req)); - request.schain = req.schain; + request.schain = bidderRequest?.ortb2?.source?.ext?.schain; request.location = { page: refererInfo.page, location: refererInfo.location, diff --git a/test/spec/modules/adipoloBidAdapter_spec.js b/test/spec/modules/adipoloBidAdapter_spec.js index 6764d7d20d8..a166d87d0f0 100644 --- a/test/spec/modules/adipoloBidAdapter_spec.js +++ b/test/spec/modules/adipoloBidAdapter_spec.js @@ -120,18 +120,20 @@ describe('adipoloBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); diff --git a/test/spec/modules/adtargetBidAdapter_spec.js b/test/spec/modules/adtargetBidAdapter_spec.js index d1221d24022..3548833d757 100644 --- a/test/spec/modules/adtargetBidAdapter_spec.js +++ b/test/spec/modules/adtargetBidAdapter_spec.js @@ -8,7 +8,6 @@ const DISPLAY_REQUEST = { 'params': { 'aid': 12345 }, - 'schain': { ver: 1 }, 'userId': { criteo: 2 }, 'mediaTypes': { 'banner': { 'sizes': [300, 250] } }, 'bidderRequestId': '7101db09af0db2', @@ -95,7 +94,16 @@ const displayBidderRequestWithConsents = { gdprApplies: true, consentString: 'test' }, - uspConsent: 'iHaveIt' + uspConsent: 'iHaveIt', + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } + } }; const videoEqResponse = [{ @@ -284,7 +292,7 @@ describe('adtargetBidAdapter', () => { expect(bidRequestWithPubSettingsData.Coppa).to.be.equal(1); }) it('sets Schain', () => { - expect(bidRequestWithPubSettingsData.Schain).to.be.deep.equal(DISPLAY_REQUEST.schain); + expect(bidRequestWithPubSettingsData.Schain).to.be.deep.equal(displayBidderRequestWithConsents.ortb2.source.ext.schain); }) it('sets UserId\'s', () => { expect(bidRequestWithPubSettingsData.UserIds).to.be.deep.equal(DISPLAY_REQUEST.userId); diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index b12744d3a28..9773f685bf1 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -20,13 +20,12 @@ const aliasEP = { 'stellormedia': 'https://ghb.ads.stellormedia.com/v2/auction/', }; -const DEFAULT_ADATPER_REQ = { bidderCode: 'adtelligent' }; +const DEFAULT_ADATPER_REQ = { bidderCode: 'adtelligent', ortb2: { source: { ext: { schain: { ver: 1 } } } } }; const DISPLAY_REQUEST = { 'bidder': 'adtelligent', 'params': { 'aid': 12345 }, - 'schain': { ver: 1 }, 'userId': { criteo: 2 }, 'mediaTypes': { 'banner': { 'sizes': [300, 250] } }, 'bidderRequestId': '7101db09af0db2', diff --git a/test/spec/modules/anyclipBidAdapter_spec.js b/test/spec/modules/anyclipBidAdapter_spec.js index 3ec81d60546..a25c285e6c4 100644 --- a/test/spec/modules/anyclipBidAdapter_spec.js +++ b/test/spec/modules/anyclipBidAdapter_spec.js @@ -128,18 +128,20 @@ describe('anyclipBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); diff --git a/test/spec/modules/driftpixelBidAdapter_spec.js b/test/spec/modules/driftpixelBidAdapter_spec.js index 057ca1c7e9f..a7b5a164996 100644 --- a/test/spec/modules/driftpixelBidAdapter_spec.js +++ b/test/spec/modules/driftpixelBidAdapter_spec.js @@ -128,18 +128,20 @@ describe('driftpixelBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); diff --git a/test/spec/modules/iqxBidAdapter_spec.js b/test/spec/modules/iqxBidAdapter_spec.js index 553bfa4a87d..8ca6fce841c 100644 --- a/test/spec/modules/iqxBidAdapter_spec.js +++ b/test/spec/modules/iqxBidAdapter_spec.js @@ -117,18 +117,20 @@ describe('iqxBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); diff --git a/test/spec/modules/lm_kiviadsBidAdapter_spec.js b/test/spec/modules/lm_kiviadsBidAdapter_spec.js index b6c4ae9bc4b..32b8d56309b 100644 --- a/test/spec/modules/lm_kiviadsBidAdapter_spec.js +++ b/test/spec/modules/lm_kiviadsBidAdapter_spec.js @@ -117,18 +117,20 @@ describe('lm_kiviadsBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js index 4e5cd4883d3..ce3ab6dd9d7 100644 --- a/test/spec/modules/minutemediaBidAdapter_spec.js +++ b/test/spec/modules/minutemediaBidAdapter_spec.js @@ -369,12 +369,17 @@ describe('minutemediaAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/openwebBidAdapter_spec.js b/test/spec/modules/openwebBidAdapter_spec.js index 9ab8f608598..02945125ca2 100644 --- a/test/spec/modules/openwebBidAdapter_spec.js +++ b/test/spec/modules/openwebBidAdapter_spec.js @@ -378,12 +378,17 @@ describe('openwebAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/publirBidAdapter_spec.js b/test/spec/modules/publirBidAdapter_spec.js index 60840b82efb..0265fbb4020 100644 --- a/test/spec/modules/publirBidAdapter_spec.js +++ b/test/spec/modules/publirBidAdapter_spec.js @@ -215,12 +215,17 @@ describe('publirAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/riseBidAdapter_spec.js b/test/spec/modules/riseBidAdapter_spec.js index a3fef50f825..bb7e07bd69e 100644 --- a/test/spec/modules/riseBidAdapter_spec.js +++ b/test/spec/modules/riseBidAdapter_spec.js @@ -395,12 +395,17 @@ describe('riseAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/shinezBidAdapter_spec.js b/test/spec/modules/shinezBidAdapter_spec.js index d4ad99359bb..1927ebe8597 100644 --- a/test/spec/modules/shinezBidAdapter_spec.js +++ b/test/spec/modules/shinezBidAdapter_spec.js @@ -313,12 +313,17 @@ describe('shinezAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/stnBidAdapter_spec.js b/test/spec/modules/stnBidAdapter_spec.js index 98859385828..18089f64f44 100644 --- a/test/spec/modules/stnBidAdapter_spec.js +++ b/test/spec/modules/stnBidAdapter_spec.js @@ -370,12 +370,17 @@ describe('stnAdapter', function () { }); it('should have schain param if it is available in the bidRequest', () => { - const schain = { - ver: '1.0', - complete: 1, - nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + bidderRequest.ortb2 = { + source: { + ext: { + schain: { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + } + } + } }; - bidRequests[0].schain = schain; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.params).to.be.an('object'); expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,'); diff --git a/test/spec/modules/xeBidAdapter_spec.js b/test/spec/modules/xeBidAdapter_spec.js index c4e91d9943c..651d4cb0a6b 100644 --- a/test/spec/modules/xeBidAdapter_spec.js +++ b/test/spec/modules/xeBidAdapter_spec.js @@ -128,18 +128,20 @@ describe('xeBidAdapter', () => { it('should build request with schain', function () { const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' + const bidderRequest = { + ortb2: { + source: { + ext: { + schain: { + ver: '1.0' + } + } + } } }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + const request = JSON.parse(spec.buildRequests([schainRequest], bidderRequest).data)[0]; expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + ver: '1.0' }); }); From abbd1f40f57a19bc569e4b7918cb530dcddf624a Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Fri, 6 Jun 2025 14:29:00 +0530 Subject: [PATCH 18/20] Giving preference to ortb2 schain over schain module --- src/fpd/schain.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/fpd/schain.js b/src/fpd/schain.js index 311c9e84a68..f2e6d3761a6 100644 --- a/src/fpd/schain.js +++ b/src/fpd/schain.js @@ -17,8 +17,12 @@ export function schainPrecedence(ortb2Fragments) { // config's schain will have more precedence over ortb2.source.schain const globalSchainConfig = config.getConfig('schain'); if (globalSchainConfig && globalSchainConfig.config) { - logInfo('Applying global schain config with precedence'); - applySchainToPath(ortb2Fragments, 'global.source', globalSchainConfig.config); + if (!ortb2Fragments?.global?.source?.schain) { + logInfo('Applying global schain config with precedence'); + applySchainToPath(ortb2Fragments, 'global.source', globalSchainConfig.config); + } else { + logInfo('Preserving existing global.source.schain from ortb2'); + } } // Apply bidder-specific schain configs @@ -28,8 +32,15 @@ export function schainPrecedence(ortb2Fragments) { Object.entries(bidderConfigs) .filter(([_, cfg]) => cfg.schain) .forEach(([bidderCode, cfg]) => { - logInfo(`Applying bidder schain config for ${bidderCode}`); - applySchainToPath(ortb2Fragments, `bidder.${bidderCode}.source`, cfg.schain?.config); + const bidderPath = `bidder.${bidderCode}.source`; + const hasSchain = ortb2Fragments?.bidder?.[bidderCode]?.source?.schain; + + if (!hasSchain) { + logInfo(`Applying bidder schain config for ${bidderCode}`); + applySchainToPath(ortb2Fragments, bidderPath, cfg.schain?.config); + } else { + logInfo(`Preserving existing schain for bidder ${bidderCode} from ortb2`); + } }); return ortb2Fragments; From d234db06396d9fcc5f1585242d0480ff6ef2e7e8 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Fri, 6 Jun 2025 16:01:59 +0530 Subject: [PATCH 19/20] Added test cases for schain precedence check --- test/spec/fpd/schain_spec.js | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/test/spec/fpd/schain_spec.js b/test/spec/fpd/schain_spec.js index 4392dcb1981..1b7626c0973 100644 --- a/test/spec/fpd/schain_spec.js +++ b/test/spec/fpd/schain_spec.js @@ -34,6 +34,72 @@ describe('Supply Chain fpd', function() { describe('schainPrecedence', function() { + describe('preserves existing schain values', function() { + it('should preserve existing global.source.schain', function() { + const existingSchain = { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'existing.com', sid: '99999', hp: 1 }] + }; + + const input = { + global: { + source: { + schain: existingSchain + } + } + }; + + const schainConfig = { + config: SAMPLE_SCHAIN + }; + + configGetConfigStub.returns(schainConfig); + configGetBidderConfigStub.returns(null); + + const result = schainPrecedence(input); + + expect(result.global.source.schain).to.deep.equal(existingSchain); + expect(result.global.source.schain).to.not.deep.equal(SAMPLE_SCHAIN); + expect(logInfoStub.calledWith('Preserving existing global.source.schain from ortb2')).to.be.true; + }); + + it('should preserve existing bidder-specific schain', function() { + const existingBidderSchain = { + ver: '3.0', + complete: 1, + nodes: [{ asi: 'existingbidder.com', sid: '88888', hp: 1 }] + }; + + const input = { + bidder: { + 'bidderA': { + source: { + schain: existingBidderSchain + } + } + } + }; + + const bidderConfigs = { + 'bidderA': { + schain: { + config: SAMPLE_SCHAIN + } + } + }; + + configGetConfigStub.returns(null); + configGetBidderConfigStub.returns(bidderConfigs); + + const result = schainPrecedence(input); + + expect(result.bidder.bidderA.source.schain).to.deep.equal(existingBidderSchain); + expect(result.bidder.bidderA.source.schain).to.not.deep.equal(SAMPLE_SCHAIN); + expect(logInfoStub.calledWith('Preserving existing schain for bidder bidderA from ortb2')).to.be.true; + }); + }); + describe('handles edge cases', function() { it('should handle edge cases and no-op scenarios', function() { expect(schainPrecedence(null)).to.be.null; From f006ae00181c21c8a119994c5184a76130ba67f6 Mon Sep 17 00:00:00 2001 From: pm-azhar-mulla Date: Fri, 6 Jun 2025 16:24:09 +0530 Subject: [PATCH 20/20] dummy commit --- test/spec/fpd/schain_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/fpd/schain_spec.js b/test/spec/fpd/schain_spec.js index 1b7626c0973..8532c6e0892 100644 --- a/test/spec/fpd/schain_spec.js +++ b/test/spec/fpd/schain_spec.js @@ -64,7 +64,7 @@ describe('Supply Chain fpd', function() { expect(logInfoStub.calledWith('Preserving existing global.source.schain from ortb2')).to.be.true; }); - it('should preserve existing bidder-specific schain', function() { + it('should preserve existing bidder-specific schain ', function() { const existingBidderSchain = { ver: '3.0', complete: 1,