Skip to content

Commit

Permalink
Invamia Bid Adapter: add new bid adapter (#6941)
Browse files Browse the repository at this point in the history
* Added invamia bia adapter

* Changed serialization method

* Replaced URLSearchParams in tests as it's not supported by Circle CI

* Delete package-lock.json

* revert changes on package-lock

* Revert "Changed serialization method"

This reverts commit 4fc0ad3

* Changed serialization method

* Cache bid request params in local variable

* Implemented multiple bid support

* Updated tests

Co-authored-by: Andrew Lays <[email protected]>
  • Loading branch information
llays and Andrew Lays authored Jun 9, 2021
1 parent 64586ad commit 99a51e0
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 0 deletions.
88 changes: 88 additions & 0 deletions modules/invamiaBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER} from '../src/mediaTypes.js';

const BIDDER_CODE = 'invamia';
const ENDPOINT_URL = 'https://ad.invamia.com/delivery/impress';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],
/**
* Determines whether or not the given bid request is valid.
*
* @param {BidRequest} bidRequest The bid request params to validate.
* @return boolean True if this is a valid bid request, and false otherwise.
*/
isBidRequestValid: function(bidRequest) {
return !!bidRequest.params.zoneId;
},
/**
* Make a server request from the list of BidRequests.
*
* @param {Array<BidRequest>} validBidRequests an array of bid requests
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests) {
let serverRequests = [];

validBidRequests.forEach(bidRequest => {
const sizes = bidRequest.mediaTypes.banner.sizes;

sizes.forEach(([width, height]) => {
bidRequest.params.requestedSizes = [width, height];

const payload = {
ctype: 'div',
pzoneid: bidRequest.params.zoneId,
width,
height,
};

const payloadString = Object.keys(payload).map(k => k + '=' + encodeURIComponent(payload[k])).join('&');

serverRequests.push({
method: 'GET',
url: ENDPOINT_URL,
data: payloadString,
bidderRequest: bidRequest,
});
});
});

return serverRequests;
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {ServerResponse} serverResponse A successful response from the server.
* @param {BidRequest} bidderRequest A matched bid request for this response.
* @return Array<BidResponse> An array of bids which were nested inside the server.
*/
interpretResponse: function(serverResponse, {bidderRequest}) {
const response = serverResponse.body;
const bidResponses = [];

if (response && response.template && response.template.html) {
const {bidId} = bidderRequest;
const [width, height] = bidderRequest.params.requestedSizes;

const bidResponse = {
requestId: bidId,
cpm: response.hb.cpm,
creativeId: response.banner.hash,
currency: 'USD',
netRevenue: response.hb.netRevenue,
ttl: 600,
ad: response.template.html,
width,
height,
};

bidResponses.push(bidResponse);
}

return bidResponses;
},
}

registerBidder(spec);
30 changes: 30 additions & 0 deletions modules/invamiaBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Overview

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

# Description

Module that connects to Invamia demand sources.

# Test Parameters

```
const adUnits = [{
code: 'test-div',
mediaTypes: {
banner: {
sizes: [[300, 250]],
},
},
bids: [{
bidder: 'invamia',
params: {
zoneId: 379783,
},
}],
}];
```
169 changes: 169 additions & 0 deletions test/spec/modules/invamiaBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import {expect} from 'chai';
import {spec} from 'modules/invamiaBidAdapter.js';

describe('invamia bid adapter tests', function () {
describe('bid requests', function () {
it('should accept valid bid', function () {
const validBid = {
bidder: 'invamia',
params: {zoneId: 123},
};

expect(spec.isBidRequestValid(validBid)).to.equal(true);
});

it('should reject invalid bid', function () {
const invalidBid = {
bidder: 'invamia',
params: {},
};

expect(spec.isBidRequestValid(invalidBid)).to.equal(false);
});

it('should correctly build payload string', function () {
const bidRequests = [{
bidder: 'invamia',
params: {zoneId: 123},
mediaTypes: {
banner: {
sizes: [[300, 250]],
},
},
bidId: '23acc48ad47af5',
auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99',
bidderRequestId: '1c56ad30b9b8ca8',
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
}];
const payload = spec.buildRequests(bidRequests)[0].data;

expect(payload).to.contain('ctype=div');
expect(payload).to.contain('pzoneid=123');
expect(payload).to.contain('width=300');
expect(payload).to.contain('height=250');
});

it('should support multiple bids', function () {
const bidRequests = [{
bidder: 'invamia',
params: {zoneId: 123},
mediaTypes: {
banner: {
sizes: [[300, 250]],
},
},
bidId: '23acc48ad47af5',
auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99',
bidderRequestId: '1c56ad30b9b8ca8',
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
}, {
bidder: 'invamia',
params: {zoneId: 321},
mediaTypes: {
banner: {
sizes: [[728, 90]],
},
},
bidId: '23acc48ad47af52',
auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba992',
bidderRequestId: '1c56ad30b9b8ca82',
transactionId: '92489f71-1bf2-49a0-adf9-000cea9347292',
}];
const payload = spec.buildRequests(bidRequests);

expect(payload).to.be.lengthOf(2);
});

it('should support multiple sizes', function () {
const bidRequests = [{
bidder: 'invamia',
params: {zoneId: 123},
mediaTypes: {
banner: {
sizes: [[300, 250], [300, 600]],
},
},
bidId: '23acc48ad47af5',
auctionId: '0fb4905b-9456-4152-86be-c6f6d259ba99',
bidderRequestId: '1c56ad30b9b8ca8',
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
}];
const payload = spec.buildRequests(bidRequests);

expect(payload).to.be.lengthOf(2);
});
});

describe('bid responses', function () {
it('should return complete bid response', function () {
const serverResponse = {
body: {
banner: {
hash: '1c56ad30b9b8ca8',
},
hb: {
cpm: 0.5,
netRevenue: false,
},
template: {
html: '<ad></ad>',
},
},
};
const bidderRequest = {
bidId: '23acc48ad47af5',
params: {
requestedSizes: [300, 250],
},
};

const bids = spec.interpretResponse(serverResponse, {bidderRequest});

expect(bids).to.be.lengthOf(1);
expect(bids[0].requestId).to.equal('23acc48ad47af5');
expect(bids[0].creativeId).to.equal('1c56ad30b9b8ca8');
expect(bids[0].width).to.equal(300);
expect(bids[0].height).to.equal(250);
expect(bids[0].ttl).to.equal(600);
expect(bids[0].cpm).to.equal(0.5);
expect(bids[0].netRevenue).to.equal(false);
expect(bids[0].currency).to.equal('USD');
});

it('should return empty bid response', function () {
const serverResponse = {
body: {},
};
const bidderRequest = {
bidId: '23acc48ad47af5',
params: {
requestedSizes: [300, 250],
},
};

const bids = spec.interpretResponse(serverResponse, {bidderRequest});

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

it('should return empty bid response 2', function () {
const serverResponse = {
body: {
template: {
html: '',
}
},
};
const bidderRequest = {
bidId: '23acc48ad47af5',
params: {
requestedSizes: [300, 250],
},
};

const bids = spec.interpretResponse(serverResponse, {bidderRequest});

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

0 comments on commit 99a51e0

Please sign in to comment.