diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js
index 89506a5659b..0778917efb1 100644
--- a/modules/ixBidAdapter.js
+++ b/modules/ixBidAdapter.js
@@ -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
@@ -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;
@@ -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;
}
@@ -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 = {};
diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md
index 90592f258a6..e99c42408f2 100644
--- a/modules/ixBidAdapter.md
+++ b/modules/ixBidAdapter.md
@@ -29,8 +29,6 @@ Here are examples of both formats.
var adUnits = [{
// ...
- mediaType: 'banner',
-
sizes: [
[300, 250],
[300, 600]
@@ -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
@@ -75,15 +73,10 @@ object are detailed here.
| Key | Scope | Type | Description
| --- | --- | --- | ---
-| 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:
-| 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]`
-| bidFloor | Optional1 | Number | 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.
Examples:
- 10.26 USD => `bidFloor: 10.26`
- 13.41 GBP => `bidFloor: 13.41`
- 600 JPY => `bidFloor: 600`
| N/A
-| bidFloorCur | Optional1 | String | The currency of the bid floor.
Examples:
+| 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]`
+
-
- 1 bidFloor
and bidFloorCur
must
- both be set when a bid floor is being configured.
-
Setup Guide
===========
@@ -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
@@ -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
diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js
index 36b2b0e9629..3bf0fb27280 100644
--- a/test/spec/modules/ixBidAdapter_spec.js
+++ b/test/spec/modules/ixBidAdapter_spec.js
@@ -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;
@@ -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);
@@ -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: {
@@ -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', () => {
@@ -300,7 +414,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '',
currency: 'USD',
- ttl: 60,
+ ttl: 35,
netRevenue: true,
dealId: undefined
}
@@ -321,7 +435,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '',
currency: 'USD',
- ttl: 60,
+ ttl: 35,
netRevenue: true,
dealId: undefined
}
@@ -342,7 +456,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '',
currency: 'JPY',
- ttl: 60,
+ ttl: 35,
netRevenue: true,
dealId: undefined
}
@@ -363,7 +477,7 @@ describe('IndexexchangeAdapter', () => {
height: 250,
ad: '',
currency: 'USD',
- ttl: 60,
+ ttl: 35,
netRevenue: true,
dealId: 'deal'
}