diff --git a/modules/adagioRtdProvider.js b/modules/adagioRtdProvider.js index 75562580cd6..16bd8fc2ae2 100644 --- a/modules/adagioRtdProvider.js +++ b/modules/adagioRtdProvider.js @@ -38,6 +38,11 @@ const ADAGIO_BIDDER_CODE = 'adagio'; const GVLID = 617; const SCRIPT_URL = 'https://script.4dex.io/a/latest/adagio.js'; const SESS_DURATION = 30 * 60 * 1000; +export const PLACEMENT_SOURCES = { + ORTB: 'ortb', // implicit default, not used atm. + ADUNITCODE: 'code', + GPID: 'gpid' +}; export const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: SUBMODULE_NAME }); const { logError, logWarn } = prefixLog('AdagioRtdProvider:'); @@ -259,6 +264,7 @@ function onBidRequest(bidderRequest, config, _userConsent) { * @param {*} config */ function onGetBidRequestData(bidReqConfig, callback, config) { + const configParams = deepAccess(config, 'params', {}); const { site: ortb2Site } = bidReqConfig.ortb2Fragments.global; const features = _internal.getFeatures().get(); const ext = { @@ -283,8 +289,26 @@ function onGetBidRequestData(bidReqConfig, callback, config) { const slotPosition = getSlotPosition(adUnit); deepSetValue(ortb2Imp, `ext.data.adg_rtd.adunit_position`, slotPosition); - // We expect `pagetype` `category` are defined in FPD `ortb2.site.ext.data` object. - // `placement` is expected in FPD `adUnits[].ortb2Imp.ext.data` object. (Please note that this `placement` is not related to the oRTB video property.) + // It is expected that the publisher set a `adUnits[].ortb2Imp.ext.data.placement` value. + // Btw, We allow fallback sources to programmatically set this value. + // The source is defined in the `config.params.placementSource` and the possible values are `code` or `gpid`. + // (Please note that this `placement` is not related to the oRTB video property.) + if (!deepAccess(ortb2Imp, 'ext.data.placement')) { + const { placementSource = '' } = configParams; + + switch (placementSource.toLowerCase()) { + case PLACEMENT_SOURCES.ADUNITCODE: + deepSetValue(ortb2Imp, 'ext.data.placement', adUnit.code); + break; + case PLACEMENT_SOURCES.GPID: + deepSetValue(ortb2Imp, 'ext.data.placement', deepAccess(ortb2Imp, 'ext.gpid')); + break; + default: + logWarn('`ortb2Imp.ext.data.placement` is missing and `params.definePlacement` is not set in the config.'); + } + } + + // We expect that `pagetype`, `category`, `placement` are defined in FPD `ortb2.site.ext.data` and `adUnits[].ortb2Imp.ext.data` objects. // Btw, we have to ensure compatibility with publishers that use the "legacy" adagio params at the adUnit.params level. const adagioBid = adUnit.bids.find(bid => _internal.isAdagioBidder(bid.bidder)); if (adagioBid) { @@ -305,9 +329,6 @@ function onGetBidRequestData(bidReqConfig, callback, config) { if (adagioBid.params.placement) { deepSetValue(ortb2Imp, 'ext.data.placement', adagioBid.params.placement); mustWarnOrtb2Imp = true; - } else { - // If the placement is not defined, we fallback to the adUnit code. - deepSetValue(ortb2Imp, 'ext.data.placement', adUnit.code); } } diff --git a/modules/adagioRtdProvider.md b/modules/adagioRtdProvider.md index f05521ec54a..a51137d571f 100644 --- a/modules/adagioRtdProvider.md +++ b/modules/adagioRtdProvider.md @@ -30,6 +30,7 @@ pbjs.setConfig({ params: { organizationId: '1000' // Required. Provided by Adagio site: 'my-site' // Required. Provided by Adagio + placementSource: 'ortb' // Optional. Where to find the "placement" value. Possible values: 'ortb' | 'code' | 'gpid' } }] } diff --git a/test/spec/modules/adagioRtdProvider_spec.js b/test/spec/modules/adagioRtdProvider_spec.js index 2c1612f2e83..ad469d29b37 100644 --- a/test/spec/modules/adagioRtdProvider_spec.js +++ b/test/spec/modules/adagioRtdProvider_spec.js @@ -1,4 +1,9 @@ -import { adagioRtdSubmodule, _internal, storage } from 'modules/adagioRtdProvider.js'; +import { + PLACEMENT_SOURCES, + _internal, + adagioRtdSubmodule, + storage, +} from 'modules/adagioRtdProvider.js'; import * as utils from 'src/utils.js'; import { loadExternalScript } from '../../../src/adloader.js'; import { expect } from 'chai'; @@ -376,6 +381,62 @@ describe('Adagio Rtd Provider', function () { const ortb2ImpExt = bidRequest.adUnits[0].ortb2Imp.ext.data.adg_rtd; expect(ortb2ImpExt.adunit_position).equal(''); }); + + describe('update the ortb2Imp.ext.data.placement if not present', function() { + const config = { + name: SUBMODULE_NAME, + params: { + organizationId: '1000', + site: 'mysite' + } + }; + + it('update the placement value with the adUnit.code value', function() { + const configCopy = utils.deepClone(config); + configCopy.params.placementSource = PLACEMENT_SOURCES.ADUNITCODE; + + const bidRequest = utils.deepClone(bidReqConfig); + + adagioRtdSubmodule.getBidRequestData(bidRequest, cb, configCopy); + expect(bidRequest.adUnits[0]).to.have.property('ortb2Imp'); + expect(bidRequest.adUnits[0].ortb2Imp.ext.data.placement).to.equal('div-gpt-ad-1460505748561-0'); + }); + + it('update the placement value with the gpid value', function() { + const configCopy = utils.deepClone(config); + configCopy.params.placementSource = PLACEMENT_SOURCES.GPID; + + const bidRequest = utils.deepClone(bidReqConfig); + const gpid = '/19968336/header-bid-tag-0' + utils.deepSetValue(bidRequest.adUnits[0], 'ortb2Imp.ext.gpid', gpid) + + adagioRtdSubmodule.getBidRequestData(bidRequest, cb, configCopy); + expect(bidRequest.adUnits[0]).to.have.property('ortb2Imp'); + expect(bidRequest.adUnits[0].ortb2Imp.ext.data.placement).to.equal(gpid); + }); + + it('update the placement value the legacy adUnit[].bids adagio.params.placement value', function() { + const placement = 'placement-value'; + + const configCopy = utils.deepClone(config); + + const bidRequest = utils.deepClone(bidReqConfig); + bidRequest.adUnits[0].bids[0].params.placement = placement; + + adagioRtdSubmodule.getBidRequestData(bidRequest, cb, configCopy); + expect(bidRequest.adUnits[0]).to.have.property('ortb2Imp'); + expect(bidRequest.adUnits[0].ortb2Imp.ext.data.placement).to.equal(placement); + }); + + it('it does not populate `ortb2Imp.ext.data.placement` if no fallback', function() { + const configCopy = utils.deepClone(config); + const bidRequest = utils.deepClone(bidReqConfig); + + adagioRtdSubmodule.getBidRequestData(bidRequest, cb, configCopy); + expect(bidRequest.adUnits[0]).to.have.property('ortb2Imp'); + expect(bidRequest.adUnits[0].ortb2Imp.ext.data.placement).to.not.exist; + }); + }); }); describe('submodule `onBidRequestEvent`', function() {