Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ozone adapter 2.1 - bug fix for multi bids + GDPR parameter handling #3916

Merged
merged 2 commits into from
Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions modules/ozoneBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { Renderer } from '../src/Renderer'
const BIDDER_CODE = 'ozone';

const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction';
const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js'
const OZONE_RENDERER_URL = 'https://prebid.the-ozone-project.com/ozone-renderer.js';

const OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html';
const OZONEVERSION = '2.0.0';
const OZONEVERSION = '2.1.0';

export const spec = {
code: BIDDER_CODE,
Expand Down Expand Up @@ -98,10 +98,17 @@ export const spec = {
if (ozoneRequest.regs.ext.gdpr) {
ozoneRequest.user = {};
ozoneRequest.user.ext = {'consent': bidderRequest.gdprConsent.consentString};
// are we able to make this request?
let vendorConsents = bidderRequest.gdprConsent.vendorData.vendorConsents;
let boolGdprConsentForOzone = vendorConsents[524];
let arrGdprConsents = toFlatArray(bidderRequest.gdprConsent.vendorData.purposeConsents);
ozoneRequest.regs.ext.oz_con = boolGdprConsentForOzone ? 1 : 0;
ozoneRequest.regs.ext.gap = arrGdprConsents;
}
} else {
utils.logInfo('OZONE: WILL NOT ADD GDPR info');
utils.logInfo('OZONE: WILL NOT ADD GDPR info; no bidderRequest.gdprConsent object was present.');
}

ozoneRequest.device = {'w': window.innerWidth, 'h': window.innerHeight};
let tosendtags = validBidRequests.map(ozoneBidRequest => {
var obj = {};
Expand Down Expand Up @@ -226,8 +233,8 @@ export const spec = {
serverResponse.seatbid = injectAdIdsIntoAllBidResponses(serverResponse.seatbid); // we now make sure that each bid in the bidresponse has a unique (within page) adId attribute.
for (let i = 0; i < serverResponse.seatbid.length; i++) {
let sb = serverResponse.seatbid[i];
const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[i]);
for (let j = 0; j < sb.bid.length; j++) {
const {defaultWidth, defaultHeight} = defaultSize(request.bidderRequest.bids[j]); // there should be the same number of bids as requests, so index [j] should always exist.
let thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight);

// from https://github.com/prebid/Prebid.js/pull/1082
Expand Down Expand Up @@ -310,6 +317,13 @@ export function checkDeepArray(Arr) {
}
}
export function defaultSize(thebidObj) {
if (!thebidObj) {
utils.logInfo('defaultSize received empty bid obj! going to return fixed default size');
return {
'defaultHeight': 250,
'defaultWidth': 300
};
}
const {sizes} = thebidObj;
const returnObject = {};
returnObject.defaultWidth = checkDeepArray(sizes)[0];
Expand Down Expand Up @@ -499,5 +513,21 @@ function outstreamRender(bid) {
window.ozoneVideo.outstreamRender(bid);
}

/**
* convert {1: true,
2: true,
3: true,
4: true,
5: true}
to : [1,2,3,4,5]
* @param obj
*/
function toFlatArray(obj) {
let ret = [];
Object.keys(obj).forEach(function(key) { if (obj[key]) { ret.push(parseInt(key)); } });
utils.logInfo('toFlatArray:', obj, 'returning', ret);
return ret;
}

registerBidder(spec);
utils.logInfo('OZONE: ozoneBidAdapter ended');
6 changes: 2 additions & 4 deletions modules/ozoneBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ adUnits = [{
publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */
siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */
placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */
customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */
ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify on the change to remove this property ozoneData from the md file? Was it intentional?

It's still present in the adapter code from what I can tell. It's also present on the prebid.org site (under http://prebid.org/dev-docs/bidders.html#ozone).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was intentional. We'll be submitting a pull request to remove it from the prebid.org documentation shortly.

customData: "[{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}]",/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the value meant to be surrounded by double quotes? It looks like it should be an array of objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

• the quotes around the customData array in the md file have been removed - thanks for flagging. The quotes in the array for 'key2' in the example are intentional as they are meant to be a array of strings.

lotameData: {"key1": "value1", "key2": "value2"} /* optional JSON placeholder for passing Lotame DMP data */
}
}]
Expand Down Expand Up @@ -65,8 +64,7 @@ adUnits = [{
siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */
customData: [{"settings": {}, "targeting": { "key": "value", "key2": ["value1", "value2"]}}]
placementId: '0440440442', /* an ID used to identify the piece of inventory - required - for unruly test use 0440440442. */
customData": [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"],}}] /* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */
ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */
customData: "[{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}]",/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */
lotameData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for passing Lotame DMP data */
video: {
skippable: true, /* optional */
Expand Down
177 changes: 154 additions & 23 deletions test/spec/modules/ozoneBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,97 @@ var validOutstreamResponse = {
}
},
'headers': {}
}
};
var validBidResponse1adWith2Bidders = {
'body': {
'id': '91221f96-b931-4acc-8f05-c2a1186fa5ac',
'seatbid': [
{
'bid': [
{
'id': 'd6198807-7a53-4141-b2db-d2cb754d68ba',
'impid': '2899ec066a91ff8',
'price': 0.36754,
'adm': '<script>removed</script>',
'adid': '134928661',
'adomain': [
'somecompany.com'
],
'iurl': 'https:\/\/ams1-ib.adnxs.com\/cr?id=134928661',
'cid': '8825',
'crid': '134928661',
'cat': [
'IAB8-15',
'IAB8-16',
'IAB8-4',
'IAB8-1',
'IAB8-14',
'IAB8-6',
'IAB8-13',
'IAB8-3',
'IAB8-17',
'IAB8-12',
'IAB8-8',
'IAB8-7',
'IAB8-2',
'IAB8-9',
'IAB8',
'IAB8-11'
],
'w': 300,
'h': 250,
'ext': {
'prebid': {
'type': 'banner'
},
'bidder': {
'appnexus': {
'brand_id': 14640,
'auction_id': 1.8369641905139e+18,
'bidder_id': 2,
'bid_ad_type': 0
}
}
}
}
],
'seat': 'appnexus'
},
{
'bid': [
{
'id': '75665207-a1ca-49db-ba0e-a5e9c7d26f32',
'impid': '37fff511779365a',
'price': 1.046,
'adm': '<div>removed</div>',
'adomain': [
'kx.com'
],
'crid': '13005',
'w': 300,
'h': 250,
'ext': {
'prebid': {
'type': 'banner'
}
}
}
],
'seat': 'openx'
}
],
'ext': {
'responsetimemillis': {
'appnexus': 91,
'openx': 109,
'ozappnexus': 46,
'ozbeeswax': 2,
'pangaea': 91
}
}
},
'headers': {}
};

describe('ozone Adapter', function () {
describe('isBidRequestValid', function () {
Expand Down Expand Up @@ -618,28 +708,6 @@ describe('ozone Adapter', function () {
expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']);
});

it('should add gdpr consent information to the request', function () {
let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==';
let bidderRequest = {
'bidderCode': 'ozone',
'auctionId': '1d1a030790a475',
'bidderRequestId': '22edbae2733bf6',
'timeout': 3000,
'gdprConsent': {
consentString: consentString,
gdprApplies: true
}
};
bidderRequest.bids = validBidRequests;

const request = spec.buildRequests(validBidRequests, bidderRequest);
const payload = JSON.parse(request.data);

expect(payload.user.ext).to.exist;
expect(payload.user.ext.consent).to.exist.and.to.equal(consentString);
expect(payload.regs.ext.gdpr).to.exist.and.to.equal(1);
});

it('should be able to handle non-single requests', function () {
config.setConfig({'ozone': {'singleRequest': false}});
const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest);
Expand All @@ -648,6 +716,63 @@ describe('ozone Adapter', function () {
// need to reset the singleRequest config flag:
config.setConfig({'ozone': {'singleRequest': true}});
});

it('should add gdpr consent information to the request when ozone is true', function () {
let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA==';
let bidderRequest = validBidderRequest;
bidderRequest.gdprConsent = {
consentString: consentString,
gdprApplies: true,
vendorData: {
vendorConsents: {524: true},
purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true}
}
}

const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest);
const payload = JSON.parse(request.data);
expect(payload.regs.ext.gdpr).to.equal(1);
expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1);
expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]);
});

it('should add correct gdpr consent information to the request when user has accepted only some purpose consents', function () {
let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA==';
let bidderRequest = validBidderRequest;
bidderRequest.gdprConsent = {
consentString: consentString,
gdprApplies: true,
vendorData: {
vendorConsents: {524: true},
purposeConsents: {1: true, 4: true, 5: true}
}
}

const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest);
const payload = JSON.parse(request.data);
expect(payload.regs.ext.gdpr).to.equal(1);
expect(payload.regs.ext.oz_con).to.exist.and.to.equal(1);
expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 4, 5]);
});

it('should add gdpr consent information to the request when ozone is false', function () {
let consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA==';
let bidderRequest = validBidderRequest;
bidderRequest.gdprConsent = {
consentString: consentString,
gdprApplies: true,
vendorData: {
vendorConsents: {}, /* 524 is not present */
purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true}
}
};

const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest);
const payload = JSON.parse(request.data);
expect(payload.regs.ext.gdpr).to.equal(1);
expect(payload.regs.ext.oz_con).to.exist.and.to.equal(0);
expect(payload.regs.ext.gap).to.exist.and.to.be.an('array').and.to.eql([1, 2, 3, 4, 5]);
});
});

describe('interpretResponse', function () {
Expand Down Expand Up @@ -690,6 +815,12 @@ describe('ozone Adapter', function () {
const bid = result[0];
expect(bid.renderer).to.be.an.instanceOf(Renderer);
});

it('should correctly parse response where there are more bidders than ad slots', function () {
const request = spec.buildRequests(validBidRequests, validBidderRequest);
const result = spec.interpretResponse(validBidResponse1adWith2Bidders, request);
expect(result.length).to.equal(2);
});
});

describe('userSyncs', function () {
Expand Down