Skip to content

Commit

Permalink
Add Content Ignite adapter (#2268)
Browse files Browse the repository at this point in the history
* initial Content Ignite adapter

* revert hello world example

* Fixes for latest prebid standards

* reformatting with modern keywords
  • Loading branch information
jdrucey authored and matthewlane committed Mar 19, 2018
1 parent c314596 commit 28e58ff
Show file tree
Hide file tree
Showing 3 changed files with 331 additions and 0 deletions.
115 changes: 115 additions & 0 deletions modules/contentigniteBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { registerBidder } from 'src/adapters/bidderFactory';
import { config } from 'src/config';
import * as utils from 'src/utils';

const BIDDER_CODE = 'contentignite';

export const spec = {
code: BIDDER_CODE,
pageID: Math.floor(Math.random() * 10e6),

isBidRequestValid: (bid) => {
return !!(bid.params.accountID && bid.params.zoneID);
},

buildRequests: (validBidRequests) => {
let i;
let zoneID;
let bidRequest;
let accountID;
let keyword;
let requestURI;
const serverRequests = [];
const zoneCounters = {};

for (i = 0; i < validBidRequests.length; i++) {
bidRequest = validBidRequests[i];
zoneID = utils.getBidIdParameter('zoneID', bidRequest.params);
accountID = utils.getBidIdParameter('accountID', bidRequest.params);
keyword = utils.getBidIdParameter('keyword', bidRequest.params);

if (!(zoneID in zoneCounters)) {
zoneCounters[zoneID] = 0;
}

requestURI =
location.protocol + '//serve.connectignite.com/adserve/;type=hbr;';
requestURI += `ID=${encodeURIComponent(accountID)};`;
requestURI += `setID=${encodeURIComponent(zoneID)};`;
requestURI += `pid=${spec.pageID};`;
requestURI += `place=${encodeURIComponent(zoneCounters[zoneID])};`;

// append the keyword for targeting if one was passed in
if (keyword !== '') {
requestURI += `kw=${encodeURIComponent(keyword)};`;
}

zoneCounters[zoneID]++;
serverRequests.push({
method: 'GET',
url: requestURI,
data: {},
bidRequest: bidRequest
});
}
return serverRequests;
},

// tslint:disable-next-line:cyclomatic-complexity
interpretResponse: (serverResponse, bidRequest) => {
const bidObj = bidRequest.bidRequest;
const bidResponses = [];
const bidResponse = {};
let isCorrectSize = false;
let isCorrectCPM = true;
let cpm;
let minCPM;
let maxCPM;
let width;
let height;

serverResponse = serverResponse.body;
if (serverResponse && serverResponse.status === 'SUCCESS' && bidObj) {
cpm = serverResponse.cpm;
minCPM = utils.getBidIdParameter('minCPM', bidObj.params);
maxCPM = utils.getBidIdParameter('maxCPM', bidObj.params);
width = parseInt(serverResponse.width);
height = parseInt(serverResponse.height);

// Ensure response CPM is within the given bounds
if (minCPM !== '' && cpm < parseFloat(minCPM)) {
isCorrectCPM = false;
utils.logWarn('ContentIgnite: CPM did not meet minCPM requirements.');
} else if (maxCPM !== '' && cpm > parseFloat(maxCPM)) {
isCorrectCPM = false;
utils.logWarn('ContentIgnite: CPM did not meet maxCPM requirements.');
}

// Ensure that response ad matches one of the placement sizes.
utils._each(bidObj.sizes, (size) => {
if (width === size[0] && height === size[1]) {
isCorrectSize = true;
} else {
utils.logWarn(
'ContentIgnite: Returned ad is of a different size to that requested.'
);
}
});
if (isCorrectCPM && isCorrectSize) {
bidResponse.requestId = bidObj.bidId;
bidResponse.creativeId = serverResponse.placement_id;
bidResponse.cpm = cpm;
bidResponse.width = width;
bidResponse.height = height;
bidResponse.ad = serverResponse.ad_code;
bidResponse.currency = 'USD';
bidResponse.netRevenue = true;
bidResponse.ttl = config.getConfig('_bidderTimeout');
bidResponse.referrer = utils.getTopWindowUrl();
bidResponses.push(bidResponse);
}
}
return bidResponses;
}
};
registerBidder(spec);
30 changes: 30 additions & 0 deletions modules/contentigniteBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Overview

```
Module Name: Content Ignite Bidder Adapter
Module Type: Bidder Adapter
Maintainer: [email protected]
```

# Description

Module that connects to Content Ignites bidder application.

# Test Parameters

```
var adUnits = [{
code: 'display-div',
sizes: [[728, 90]], // a display size
bids: [{
bidder: "contentignite",
params: {
accountID: '168237',
zoneID: '299680',
keyword: 'business', //optional
minCPM: '0.10', //optional
maxCPM: '1.00' //optional
}
}]
}];
```
186 changes: 186 additions & 0 deletions test/spec/modules/contentigniteBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { expect } from 'chai';
import { spec } from '../../../modules/contentigniteBidAdapter';

describe('Content Ignite adapter', () => {
let bidRequests;

beforeEach(() => {
bidRequests = [
{
bidder: 'contentignite',
params: {
accountID: '168237',
zoneID: '299680',
keyword: 'business',
minCPM: '0.10',
maxCPM: '1.00'
},
placementCode: '/19968336/header-bid-tag-1',
sizes: [[728, 90]],
bidId: '23acc48ad47af5',
auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99',
bidderRequestId: '1c56ad30b9b8ca8',
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729'
}
];
});

describe('implementation', () => {
describe('for requests', () => {
it('should accept valid bid', () => {
const validBid = {
bidder: 'contentignite',
params: {
accountID: '168237',
zoneID: '299680'
}
},
isValid = spec.isBidRequestValid(validBid);

expect(isValid).to.equal(true);
});

it('should reject invalid bid', () => {
const invalidBid = {
bidder: 'contentignite',
params: {
accountID: '168237'
}
},
isValid = spec.isBidRequestValid(invalidBid);

expect(isValid).to.equal(false);
});

it('should set the keyword parameter', () => {
const requests = spec.buildRequests(bidRequests),
requestURL = requests[0].url;

expect(requestURL).to.have.string(';kw=business;');
});

it('should increment the count for the same zone', () => {
const bidRequests = [
{
sizes: [[728, 90]],
bidder: 'contentignite',
params: {
accountID: '107878',
zoneID: '86133'
}
},
{
sizes: [[728, 90]],
bidder: 'contentignite',
params: {
accountID: '107878',
zoneID: '86133'
}
}
],
requests = spec.buildRequests(bidRequests),
firstRequest = requests[0].url,
secondRequest = requests[1].url;

expect(firstRequest).to.have.string(';place=0;');
expect(secondRequest).to.have.string(';place=1;');
});
});

describe('bid responses', () => {
it('should return complete bid response', () => {
const serverResponse = {
body: {
status: 'SUCCESS',
account_id: 107878,
zone_id: 86133,
cpm: 0.1,
width: 728,
height: 90,
place: 0,
ad_code:
'<div id="ci_lb_14209"></div> <script type="text/javascript" src="https://connectignite.com/srv/lb/14209/add.js?serve=1" id="cilb-ads"></script>',
tracking_pixels: []
}
},
bids = spec.interpretResponse(serverResponse, {
bidRequest: bidRequests[0]
});

expect(bids).to.be.lengthOf(1);
expect(bids[0].cpm).to.equal(0.1);
expect(bids[0].width).to.equal(728);
expect(bids[0].height).to.equal(90);
expect(bids[0].currency).to.equal('USD');
expect(bids[0].netRevenue).to.equal(true);
expect(bids[0].ad).to.have.length.above(1);
});

it('should return empty bid response', () => {
const serverResponse = {
status: 'NO_ELIGIBLE_ADS',
zone_id: 299680,
width: 728,
height: 90,
place: 0
},
bids = spec.interpretResponse(serverResponse, {
bidRequest: bidRequests[0]
});

expect(bids).to.be.lengthOf(0);
});

it('should return empty bid response on incorrect size', () => {
const serverResponse = {
status: 'SUCCESS',
account_id: 168237,
zone_id: 299680,
cpm: 0.1,
width: 300,
height: 250,
place: 0
},
bids = spec.interpretResponse(serverResponse, {
bidRequest: bidRequests[0]
});

expect(bids).to.be.lengthOf(0);
});

it('should return empty bid response with CPM too low', () => {
const serverResponse = {
status: 'SUCCESS',
account_id: 168237,
zone_id: 299680,
cpm: 0.05,
width: 728,
height: 90,
place: 0
},
bids = spec.interpretResponse(serverResponse, {
bidRequest: bidRequests[0]
});

expect(bids).to.be.lengthOf(0);
});

it('should return empty bid response with CPM too high', () => {
const serverResponse = {
status: 'SUCCESS',
account_id: 168237,
zone_id: 299680,
cpm: 7.0,
width: 728,
height: 90,
place: 0
},
bids = spec.interpretResponse(serverResponse, {
bidRequest: bidRequests[0]
});

expect(bids).to.be.lengthOf(0);
});
});
});
});

0 comments on commit 28e58ff

Please sign in to comment.