Skip to content

Commit

Permalink
Pbadslot phase2 (#5525)
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

* Re-add rubicon analytics without deprecated getTopWindowUrl util

* Cache referrer on auction_init instead of bid_requested

* merged remote master changes

* Send both pbAdSlot and GAM ad unit if in FPD

Co-authored-by: nakamoto <nakamoto_tatsuya@microad.co.jp>
Co-authored-by: Chandra Prakash <chandra.prakash@advangelists.com>
Co-authored-by: Isaac Dettman <idettman@rubiconproject.com>
Co-authored-by: Eric Harper <eharper@rubiconproject.com>
Co-authored-by: TJ Eastmond <teastmond@la-wlandaverde-mac.local>
Co-authored-by: Mark Monday <mmonday@rubiconproject.com>
  • Loading branch information
7 people authored Jul 27, 2020
1 parent 93e1b93 commit ec030f4
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 33 deletions.
11 changes: 10 additions & 1 deletion modules/prebidServerBidAdapter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,16 @@ const OPEN_RTB_PROTOCOL = {
*/
const pbAdSlot = utils.deepAccess(adUnit, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
utils.deepSetValue(imp, 'ext.context.data.adslot', pbAdSlot);
utils.deepSetValue(imp, 'ext.context.data.pbadslot', pbAdSlot);
}

/**
* GAM Ad Unit
* @type {(string|undefined)}
*/
const gamAdUnit = utils.deepAccess(adUnit, 'fpd.context.adServer.adSlot');
if (typeof gamAdUnit === 'string' && gamAdUnit) {
utils.deepSetValue(imp, 'ext.context.data.adslot', gamAdUnit);
}

Object.assign(imp, mediaTypes);
Expand Down
22 changes: 20 additions & 2 deletions modules/rubiconBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,16 @@ export const spec = {
*/
const pbAdSlot = utils.deepAccess(bidRequest, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
utils.deepSetValue(data.imp[0].ext, 'context.data.adslot', pbAdSlot);
utils.deepSetValue(data.imp[0].ext, 'context.data.pbadslot', pbAdSlot);
}

/**
* GAM Ad Unit
* @type {(string|undefined)}
*/
const gamAdUnit = utils.deepAccess(bidRequest, 'fpd.context.adServer.adSlot');
if (typeof gamAdUnit === 'string' && gamAdUnit) {
utils.deepSetValue(data.imp[0].ext, 'context.data.adslot', gamAdUnit);
}

// if storedAuctionResponse has been set, pass SRID
Expand Down Expand Up @@ -593,7 +602,16 @@ export const spec = {
*/
const pbAdSlot = utils.deepAccess(bidRequest, 'fpd.context.pbAdSlot');
if (typeof pbAdSlot === 'string' && pbAdSlot) {
data['tg_i.dfp_ad_unit_code'] = pbAdSlot.replace(/^\/+/, '');
data['tg_i.pbadslot'] = pbAdSlot.replace(/^\/+/, '');
}

/**
* GAM Ad Unit
* @type {(string|undefined)}
*/
const gamAdUnit = utils.deepAccess(bidRequest, 'fpd.context.adServer.adSlot');
if (typeof gamAdUnit === 'string' && gamAdUnit) {
data['tg_i.dfp_ad_unit_code'] = gamAdUnit.replace(/^\/+/, '');
}

// digitrust properties
Expand Down
88 changes: 83 additions & 5 deletions test/spec/modules/prebidServerBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,80 @@ describe('S2S Adapter', function () {
});

describe('pbAdSlot config', function () {
it('should not send \"imp.ext.context.data.pbadslot\" 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.pbadslot');
});

it('should not send \"imp.ext.context.data.pbadslot\" 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.pbadslot');
});

it('should not send \"imp.ext.context.data.pbadslot\" 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.pbadslot');
});

it('should send \"imp.ext.context.data.pbadslot\" 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.pbadslot');
expect(parsedRequestBody.imp[0].ext.context.data.pbadslot).to.equal('/a/b/c');
});
});

describe('GAM ad unit 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';
Expand All @@ -1426,7 +1500,7 @@ describe('S2S Adapter', function () {
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 () {
it('should not send \"imp.ext.context.data.adslot\" if \"fpd.context.adServer.adSlot\" is undefined', function () {
const ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';
const consentConfig = { s2sConfig: ortb2Config };
Expand All @@ -1442,15 +1516,17 @@ describe('S2S Adapter', function () {
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 () {
it('should not send \"imp.ext.context.data.adslot\" if \"fpd.context.adServer.adSlot\" 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: ''
adServer: {
adSlot: ''
}
}
};

Expand All @@ -1462,15 +1538,17 @@ describe('S2S Adapter', function () {
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 () {
it('should send \"imp.ext.context.data.adslot\" if \"fpd.context.adServer.adSlot\" 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'
adServer: {
adSlot: '/a/b/c'
}
}
};

Expand Down
129 changes: 104 additions & 25 deletions test/spec/modules/rubiconBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1364,25 +1364,25 @@ describe('the rubicon adapter', function () {
}
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context\" object is not valid', function () {
it('should not send \"tg_i.pbadslot’\" 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');
expect(data).to.not.have.property('tg_i.pbadslot’');
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" is undefined', function () {
it('should not send \"tg_i.pbadslot’\" 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');
expect(data).to.not.have.property('tg_i.pbadslot’');
});

it('should not send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" value is an empty string', function () {
it('should not send \"tg_i.pbadslot’\" if \"fpd.context.pbAdSlot\" value is an empty string', function () {
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: ''
Expand All @@ -1393,10 +1393,10 @@ describe('the rubicon adapter', function () {
const data = parseQuery(request.data);

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

it('should send \"tg_i.dfp_ad_unit_code\" if \"fpd.context.pbAdSlot\" value is a valid string', function () {
it('should send \"tg_i.pbadslot\" if \"fpd.context.pbAdSlot\" value is a valid string', function () {
bidderRequest.bids[0].fpd = {
context: {
pbAdSlot: 'abc'
Expand All @@ -1406,15 +1406,92 @@ describe('the rubicon adapter', function () {
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.pbadslot');
expect(data['tg_i.pbadslot']).to.equal('abc');
});

it('should send \"tg_i.pbadslot\" 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.pbadslot');
expect(data['tg_i.pbadslot']).to.equal('a/b/c');
});
});

describe('GAM ad unit', 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.adServer.adSlot\" 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.adServer.adSlot\" value is an empty string', function () {
bidderRequest.bids[0].fpd = {
context: {
adServer: {
adSlot: ''
}
}
};

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

Expand Down Expand Up @@ -1839,6 +1916,24 @@ describe('the rubicon adapter', function () {
bidderRequest.auctionStart + 100
);

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

it('should include GAM ad unit in bid request', function () {
createVideoBidderRequest();
bidderRequest.bids[0].fpd = {
context: {
adServer: {
adSlot: '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');
});
Expand All @@ -1856,22 +1951,6 @@ describe('the rubicon adapter', function () {
});
});

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 () {
it('should combine an array of slot url params', function () {
expect(spec.combineSlotUrlParams([])).to.deep.equal({});
Expand Down

0 comments on commit ec030f4

Please sign in to comment.