Skip to content

Commit

Permalink
Pre-auction filters and pbAdslot support (prebid#4539)
Browse files Browse the repository at this point in the history
* Add microadBidAdapter

* Remove unnecessary encodeURIComponent from microadBidAdapter

* Submit Advangelists Prebid Adapter

* Submit Advangelists Prebid Adapter 1.1

* Correct procudtion endpoint for prebid

* analytics update with wrapper name

* reverted error merge

* update changed default value of netRevenue to true

* add beforeRequestBids event

* add pbAdSlot support to pbs adapter

* update jsdoc comment for on before request bids event

* add pbAdSlot support to rubicon adapter

* added more tests

* update code comment

* add api test, update event to emit from adapterManager

* add multi-bid api test

* added pbAdSlot to rubicon bid adapter video bid request

* added ext to server video path in rp adapter pbAdSlot

* fix for pb video ortb path

* fix for consistency with pb server

* update obj path to fpd.context.pbAdSlot

* add leading slash removal to all outputs of pbAslot

* revert to previous branch reviewed

* revert to previous branch reviewed

* fix merge errors
  • Loading branch information
Isaac A. Dettman authored and harpere committed Jan 15, 2020
1 parent 9c92c16 commit fa13966
Show file tree
Hide file tree
Showing 7 changed files with 434 additions and 0 deletions.
9 changes: 9 additions & 0 deletions modules/prebidServerBidAdapter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,15 @@ const OPEN_RTB_PROTOCOL = {

const imp = { id: adUnit.code, ext, secure: _s2sConfig.secure };

/**
* Prebid AdSlot
* @type {(string|undefined)}
*/
const pbAdSlot = utils.deepAccess(adUnit, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
utils.deepSetValue(imp, 'ext.context.data.adslot', pbAdSlot);
}

Object.assign(imp, mediaTypes);

if (imp.banner || imp.video || imp.native) {
Expand Down
18 changes: 18 additions & 0 deletions modules/rubiconBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ export const spec = {
utils.deepSetValue(data, 'source.ext.schain', bidRequest.schain);
}

/**
* Prebid AdSlot
* @type {(string|undefined)}
*/
const pbAdSlot = utils.deepAccess(bidRequest, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
utils.deepSetValue(data.imp[0].ext, 'context.data.adslot', pbAdSlot);
}

return {
method: 'POST',
url: VIDEO_ENDPOINT,
Expand Down Expand Up @@ -489,6 +498,15 @@ export const spec = {
});
}

/**
* Prebid AdSlot
* @type {(string|undefined)}
*/
const pbAdSlot = utils.deepAccess(bidRequest, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
data['tg_i.dfp_ad_unit_code'] = pbAdSlot.replace(/^\/+/, '');
}

// digitrust properties
const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE');
Object.assign(data, digitrustParams);
Expand Down
7 changes: 7 additions & 0 deletions src/adapterManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels, src})
}

bid = Object.assign({}, bid, getDefinedParams(adUnit, [
'fpd',
'mediaType',
'renderer'
]));
Expand Down Expand Up @@ -174,6 +175,12 @@ export let uspDataHandler = {
};

adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, auctionId, cbTimeout, labels) {
/**
* emit and pass adunits for external modification
* @see {@link https://github.com/prebid/Prebid.js/issues/4149|Issue}
*/
events.emit(CONSTANTS.EVENTS.BEFORE_REQUEST_BIDS, adUnits);

let bidRequests = [];

let bidderCodes = getBidderCodes(adUnits);
Expand Down
1 change: 1 addition & 0 deletions src/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"BID_WON": "bidWon",
"BIDDER_DONE": "bidderDone",
"SET_TARGETING": "setTargeting",
"BEFORE_REQUEST_BIDS": "beforeRequestBids",
"REQUEST_BIDS": "requestBids",
"ADD_AD_UNITS": "addAdUnits",
"AD_RENDER_FAILED" : "adRenderFailed"
Expand Down
74 changes: 74 additions & 0 deletions test/spec/modules/prebidServerBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,80 @@ describe('S2S Adapter', function () {
const parsedRequestBody = JSON.parse(server.requests[0].requestBody);
expect(parsedRequestBody.source.ext.schain).to.deep.equal(schainObject);
})

describe('pbAdSlot config', function () {
it('should not send \"imp.ext.context.data.adslot\" if \"fpd.context\" is undefined', function () {
const ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
const consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);
const bidRequest = utils.deepClone(REQUEST);

adapter.callBids(bidRequest, BID_REQUESTS, addBidResponse, done, ajax);
const parsedRequestBody = JSON.parse(server.requests[0].requestBody);

expect(parsedRequestBody.imp).to.be.a('array');
expect(parsedRequestBody.imp[0]).to.be.a('object');
expect(parsedRequestBody.imp[0]).to.not.have.deep.nested.property('ext.context.data.adslot');
});

it('should not send \"imp.ext.context.data.adslot\" if \"fpd.context.pbAdSlot\" is undefined', function () {
const ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
const consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);
const bidRequest = utils.deepClone(REQUEST);
bidRequest.ad_units[0].fpd = {};

adapter.callBids(bidRequest, BID_REQUESTS, addBidResponse, done, ajax);
const parsedRequestBody = JSON.parse(server.requests[0].requestBody);

expect(parsedRequestBody.imp).to.be.a('array');
expect(parsedRequestBody.imp[0]).to.be.a('object');
expect(parsedRequestBody.imp[0]).to.not.have.deep.nested.property('ext.context.data.adslot');
});

it('should not send \"imp.ext.context.data.adslot\" if \"fpd.context.pbAdSlot\" is empty string', function () {
const ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
const consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);
const bidRequest = utils.deepClone(REQUEST);
bidRequest.ad_units[0].fpd = {
context: {
pbAdSlot: ''
}
};

adapter.callBids(bidRequest, BID_REQUESTS, addBidResponse, done, ajax);
const parsedRequestBody = JSON.parse(server.requests[0].requestBody);

expect(parsedRequestBody.imp).to.be.a('array');
expect(parsedRequestBody.imp[0]).to.be.a('object');
expect(parsedRequestBody.imp[0]).to.not.have.deep.nested.property('ext.context.data.adslot');
});

it('should send \"imp.ext.context.data.adslot\" if \"fpd.context.pbAdSlot\" value is a non-empty string', function () {
const ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
const consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);
const bidRequest = utils.deepClone(REQUEST);
bidRequest.ad_units[0].fpd = {
context: {
pbAdSlot: '/a/b/c'
}
};

adapter.callBids(bidRequest, BID_REQUESTS, addBidResponse, done, ajax);
const parsedRequestBody = JSON.parse(server.requests[0].requestBody);

expect(parsedRequestBody.imp).to.be.a('array');
expect(parsedRequestBody.imp[0]).to.be.a('object');
expect(parsedRequestBody.imp[0]).to.have.deep.nested.property('ext.context.data.adslot');
expect(parsedRequestBody.imp[0].ext.context.data.adslot).to.equal('/a/b/c');
});
});
});

describe('response handler', function () {
Expand Down
103 changes: 103 additions & 0 deletions test/spec/modules/rubiconBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,77 @@ describe('the rubicon adapter', function () {
});
});
})

describe('Prebid AdSlot', function () {
beforeEach(function () {
// enforce that the bid at 0 does not have a 'context' property
if (bidderRequest.bids[0].hasOwnProperty('fpd')) {
delete bidderRequest.bids[0].fpd;
}
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context\" object is not valid', function () {
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const data = parseQuery(request.data);

expect(data).to.be.an('Object');
expect(data).to.not.have.property('tg_i.dfp_ad_unit_code');
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" is undefined', function () {
bidderRequest.bids[0].fpd = {};

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const data = parseQuery(request.data);

expect(data).to.be.an('Object');
expect(data).to.not.have.property('tg_i.dfp_ad_unit_code');
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" value is an empty string', function () {
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: ''
}
};

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const data = parseQuery(request.data);

expect(data).to.be.an('Object');
expect(data).to.not.have.property('tg_i.dfp_ad_unit_code');
});

it('should send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" value is a valid string', function () {
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: 'abc'
}
}

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const data = parseQuery(request.data);

expect(data).to.be.an('Object');
expect(data).to.have.property('tg_i.dfp_ad_unit_code');
expect(data['tg_i.dfp_ad_unit_code']).to.equal('abc');
});

it('should send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" value is a valid string, but all leading slash characters should be removed', function () {
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: '/a/b/c'
}
};

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const data = parseQuery(request.data);

expect(data).to.be.an('Object');
expect(data).to.have.property('tg_i.dfp_ad_unit_code');
expect(data['tg_i.dfp_ad_unit_code']).to.equal('a/b/c');
});
});
});

describe('for video requests', function () {
Expand Down Expand Up @@ -1568,6 +1639,38 @@ describe('the rubicon adapter', function () {
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
expect(request.data.regs.coppa).to.equal(1);
});

it('should include pbAdSlot in bid request', function () {
createVideoBidderRequest();
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: '1234567890'
}
};

sandbox.stub(Date, 'now').callsFake(() =>
bidderRequest.auctionStart + 100
);

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
expect(request.data.imp[0].ext.context.data.adslot).to.equal('1234567890');
});
});

it('should include pbAdSlot in bid request', function () {
createVideoBidderRequest();
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: '1234567890'
}
};

sandbox.stub(Date, 'now').callsFake(() =>
bidderRequest.auctionStart + 100
);

const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
expect(request.data.imp[0].ext.context.data.adslot).to.equal('1234567890');
});

describe('combineSlotUrlParams', function () {
Expand Down
Loading

0 comments on commit fa13966

Please sign in to comment.