Skip to content

Commit

Permalink
Backward compatible update & reduced TTL (#2744)
Browse files Browse the repository at this point in the history
  • Loading branch information
ix-prebid-support authored and mike-chowla committed Jul 3, 2018
1 parent 79b3fbc commit 204daf8
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 43 deletions.
28 changes: 19 additions & 9 deletions modules/ixBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const BANNER_INSECURE_BID_URL = 'http://as.casalemedia.com/cygnus';
const SUPPORTED_AD_TYPES = [BANNER];
const ENDPOINT_VERSION = 7.2;
const CENT_TO_DOLLAR_FACTOR = 100;
const TIME_TO_LIVE = 60;
const TIME_TO_LIVE = 35;
const NET_REVENUE = true;

// Always start by assuming the protocol is HTTPS. This way, it will work
Expand Down Expand Up @@ -45,9 +45,15 @@ function bidToBannerImp(bid) {
imp.banner.topframe = utils.inIframe() ? 0 : 1;

imp.ext = {};
imp.ext.sid = `${bid.params.size[0]}x${bid.params.size[1]}`;
imp.ext.siteID = bid.params.siteId;

if (bid.params.hasOwnProperty('id') &&
(typeof bid.params.id === 'string' || typeof bid.params.id === 'number')) {
imp.ext.sid = String(bid.params.id);
} else {
imp.ext.sid = `${bid.params.size[0]}x${bid.params.size[1]}`;
}

if (bid.params.hasOwnProperty('bidFloor') && bid.params.hasOwnProperty('bidFloorCur')) {
imp.bidfloor = bid.params.bidFloor;
imp.bidfloorcur = bid.params.bidFloorCur;
Expand Down Expand Up @@ -153,6 +159,14 @@ export const spec = {
return false;
}

if (bid.hasOwnProperty('mediaType') && bid.mediaType !== 'banner') {
return false;
}

if (bid.hasOwnProperty('mediaTypes') && !utils.deepAccess(bid, 'mediaTypes.banner.sizes')) {
return false;
}

if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') {
return false;
}
Expand Down Expand Up @@ -183,13 +197,9 @@ export const spec = {
for (let i = 0; i < validBidRequests.length; i++) {
validBidRequest = validBidRequests[i];

// If the bid request is for banner, then transform the bid request based on banner format.
if (utils.deepAccess(validBidRequest, 'mediaTypes.banner') ||
validBidRequest.mediaType === 'banner' ||
(validBidRequest.mediaType === undefined && utils.deepAccess(validBidRequest, 'mediaTypes.banner') === undefined)) {
bannerImp = bidToBannerImp(validBidRequest);
bannerImps.push(bannerImp);
}
// Transform the bid request based on the banner format.
bannerImp = bidToBannerImp(validBidRequest);
bannerImps.push(bannerImp);
}

const r = {};
Expand Down
25 changes: 10 additions & 15 deletions modules/ixBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ Here are examples of both formats.
var adUnits = [{
// ...

mediaType: 'banner',

sizes: [
[300, 250],
[300, 600]
Expand Down Expand Up @@ -63,7 +61,7 @@ var adUnits = [{
| Type | Support
| --- | ---
| Banner | Fully supported for all IX approved sizes.
| Video | Only in-stream supported.
| Video | Not supported.
| Native | Not supported.

# Bid Parameters
Expand All @@ -75,15 +73,10 @@ object are detailed here.

| Key | Scope | Type | Description
| --- | --- | --- | ---
| siteId | Required | String | <p>An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have.</p><p>Examples:<ul><li>`'3723'`</li><li>`'6482'`</li><li>`'3639'`</li></ul></p>
| size | Required | Number[] | <p>The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`.</p><p>Examples:<ul><li>`[300, 250]`</li><li>`[300, 600]`</li><li>`[728, 90]`</li></ul></p>
| bidFloor | Optional<sup>1</sup> | Number | <p>The minimum bid required to participate in an auction for this ad unit. Assuming the bid floor currency that is set has a main unit (e.g. dollars, pounds) and a sub-unit (e.g. cents, pence), the bid floor should be in decimal-point format. If the currency only has main a unit (e.g. JPY), then the bid floor should be a whole number.</p><p>Examples:<ul><li>10.26 USD => `bidFloor: 10.26`</li><li>13.41 GBP => `bidFloor: 13.41`</li><li>600 JPY => `bidFloor: 600`</li></ul></p> | N/A
| bidFloorCur | Optional<sup>1</sup> | String | <p>The currency of the bid floor.</p><p>Examples:<ul><li>`'USD'`</li><li>`'GBP'`</li><li>`'JPY'`</li></ul></p>
| siteId | Required | String | An IX-specific identifier that is associated with a specific size on this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. Examples: `'3723'`, `'6482'`, `'3639'`
| size | Required | Number[] | The single size associated with the site ID. It should be one of the sizes listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.banner.sizes`. Examples: `[300, 250]`, `[300, 600]`, `[728, 90]`


<p>
<sup>1</sup> <code>bidFloor</code> and <code>bidFloorCur</code> <b>must</b>
both be set when a bid floor is being configured.
</p>

Setup Guide
===========
Expand Down Expand Up @@ -154,7 +147,10 @@ var adUnits = [{
}];
```

Please note that you can re-use the existing `siteId` within the same flex position.
Please note that you can re-use the existing `siteId` within the same flex
position.



##### 2. Include `ixBidAdapter` in your build process

Expand Down Expand Up @@ -246,12 +242,11 @@ the rest will be ignored.

To avoid this situation, ensure that when `pbjs.requestBid` is invoked, that the
number of bid objects (i.e. `adUnits[].bids`) with `adUnits[].bids[].bidder` set
to `'ix'` across all ad units that bids are being requested for does not exceed
20.
to `'ix'` across all ad units that bids are being requested for does not exceed 20.

### Time-To-Live (TTL)

All bids received from IX have a TTL of 60 seconds, after which time they become
All bids received from IX have a TTL of 35 seconds, after which time they become
invalid.

If an invalid bid wins, and its associated ad is rendered, it will not count
Expand Down
152 changes: 133 additions & 19 deletions test/spec/modules/ixBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,65 @@ describe('IndexexchangeAdapter', () => {
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return false when mediaTypes is not banner', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
bid.mediaTypes = {
video: {
sizes: [[300, 250]]
}
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return false when mediaTypes.banner does not have sizes', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
bid.mediaTypes = {
banner: {
size: [[300, 250]]
}
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return false when mediaType is not banner', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
delete bid.params.mediaTypes;
bid.mediaType = 'banne';
bid.sizes = [[300, 250]];
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return false when mediaType is video', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
delete bid.params.mediaTypes;
bid.mediaType = 'video';
bid.sizes = [[300, 250]];
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return false when mediaType is native', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
delete bid.params.mediaTypes;
bid.mediaType = 'native';
bid.sizes = [[300, 250]];
expect(spec.isBidRequestValid(bid)).to.equal(false);
});

it('should return true when mediaType is missing and has sizes', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
delete bid.mediaTypes;
bid.sizes = [[300, 250]];
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return true when mediaType is banner', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
delete bid.mediaTypes;
bid.mediaType = 'banner';
bid.sizes = [[300, 250]];
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return false when there is only bidFloor', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
bid.params.bidFloor = 50;
Expand Down Expand Up @@ -144,6 +203,12 @@ describe('IndexexchangeAdapter', () => {
const requestMethod = request.method;
const query = request.data;

const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID);
delete bidWithoutMediaType[0].mediaTypes;
bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]];
const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType);
const queryWithoutMediaType = requestWithoutMediaType.data;

it('request should be made to IX endpoint with GET method', () => {
expect(requestMethod).to.equal('GET');
expect(requestUrl).to.equal(IX_ENDPOINT);
Expand Down Expand Up @@ -199,6 +264,70 @@ describe('IndexexchangeAdapter', () => {
expect(impression.bidfloorcur).to.equal(bid.params.bidFloorCur);
});

it('payload without mediaType should have correct format and value', () => {
const payload = JSON.parse(queryWithoutMediaType.r);

expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId);
expect(payload.site).to.exist;
expect(payload.site.page).to.exist;
expect(payload.site.page).to.contain('http');
expect(payload.site.ref).to.exist;
expect(payload.site.ref).to.be.a('string');
expect(payload.ext).to.exist;
expect(payload.ext.source).to.equal('prebid');
expect(payload.imp).to.exist;
expect(payload.imp).to.be.an('array');
expect(payload.imp).to.have.lengthOf(1);
});

it('impression without mediaType should have correct format and value', () => {
const impression = JSON.parse(queryWithoutMediaType.r).imp[0];
const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`;

expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId);
expect(impression.banner).to.exist;
expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]);
expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]);
expect(impression.banner.topframe).to.exist;
expect(impression.banner.topframe).to.be.oneOf([0, 1]);
expect(impression.ext).to.exist;
expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString());
expect(impression.ext.sid).to.equal(sidValue);
});

it('impression should have sid if id is configured as number', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
bid.params.id = 50;
const requestBidFloor = spec.buildRequests([bid]);
const impression = JSON.parse(requestBidFloor.data.r).imp[0];

expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId);
expect(impression.banner).to.exist;
expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]);
expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]);
expect(impression.banner.topframe).to.exist;
expect(impression.banner.topframe).to.be.oneOf([0, 1]);
expect(impression.ext).to.exist;
expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString());
expect(impression.ext.sid).to.equal('50');
});

it('impression should have sid if id is configured as string', () => {
const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]);
bid.params.id = 'abc';
const requestBidFloor = spec.buildRequests([bid]);
const impression = JSON.parse(requestBidFloor.data.r).imp[0];
expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId);
expect(impression.banner).to.exist;
expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]);
expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]);
expect(impression.banner.topframe).to.exist;
expect(impression.banner.topframe).to.be.oneOf([0, 1]);
expect(impression.ext).to.exist;
expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString());
expect(impression.ext.sid).to.equal('abc');
});

it('should add first party data to page url in bid request if it exists in config', () => {
config.setConfig({
ix: {
Expand Down Expand Up @@ -272,21 +401,6 @@ describe('IndexexchangeAdapter', () => {

expect(requestStringTimeout.data.t).to.be.undefined;
});

it('should default to assuming media type is banner', () => {
const bidsWithoutMediaType = [
Object.assign({}, DEFAULT_BANNER_VALID_BID[0])
];
delete bidsWithoutMediaType[0].mediaTypes;

const request = spec.buildRequests(bidsWithoutMediaType);
const payload = JSON.parse(request.data.r);

expect(payload.id).to.equal(bidsWithoutMediaType[0].bidderRequestId);
expect(payload.imp).to.exist;
expect(payload.imp).to.be.an('array');
expect(payload.imp).to.have.lengthOf(1);
});
});

describe('interpretResponseBanner', () => {
Expand All @@ -300,7 +414,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '<a target="_blank" href="http://www.indexexchange.com"></a>',
currency: 'USD',
ttl: 60,
ttl: 35,
netRevenue: true,
dealId: undefined
}
Expand All @@ -321,7 +435,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '<a target="_blank" href="http://www.indexexchange.com"></a>',
currency: 'USD',
ttl: 60,
ttl: 35,
netRevenue: true,
dealId: undefined
}
Expand All @@ -342,7 +456,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '<a target="_blank" href="http://www.indexexchange.com"></a>',
currency: 'JPY',
ttl: 60,
ttl: 35,
netRevenue: true,
dealId: undefined
}
Expand All @@ -363,7 +477,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '<a target="_blank" href="http://www.indexexchange.com"></a>',
currency: 'USD',
ttl: 60,
ttl: 35,
netRevenue: true,
dealId: 'deal'
}
Expand Down

0 comments on commit 204daf8

Please sign in to comment.