Skip to content

Commit

Permalink
FreePass Bid Adapter : initial release (prebid#9827)
Browse files Browse the repository at this point in the history
* Add FreePass Bid Adapter

* Add note about FreePass IdSystem

* Unrequire userId

* Add test flag

* Update official maintainer email

* Update official bidder service URL

* No credentials

Client does not need to send credentials

* Add md code type

Trigger ci

* Replace double with single quotes

* Append js to import

* Build mock request in local scope

* Update maintainer email
  • Loading branch information
czarpino committed Jun 21, 2023
1 parent 26142f2 commit 5bfac11
Show file tree
Hide file tree
Showing 3 changed files with 290 additions and 0 deletions.
98 changes: 98 additions & 0 deletions modules/freepassBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {logMessage} from '../src/utils.js';
import {BANNER} from '../src/mediaTypes.js';
import {ortbConverter} from '../libraries/ortbConverter/converter.js'

const BIDDER_SERVICE_URL = 'https://bidding-dsp.ad-m.asia/dsp/api/bid/s/s/freepass';

const converter = ortbConverter({
context: {
netRevenue: true,
ttl: 30
}
});

function prepareUserInfo(user, freepassId) {
let userInfo = user || {};
let extendedUserInfo = userInfo.ext || {};

if (freepassId.userId) {
userInfo.id = freepassId.userId;
}

if (freepassId.commonId) {
extendedUserInfo.fuid = freepassId.commonId;
}
userInfo.ext = extendedUserInfo;

return userInfo;
}

function prepareDeviceInfo(device, freepassId) {
let deviceInfo = device || {};
let extendedDeviceInfo = deviceInfo.ext || {};

extendedDeviceInfo.is_accurate_ip = 0;
if (freepassId.userIp) {
deviceInfo.ip = freepassId.userIp;
extendedDeviceInfo.is_accurate_ip = 1;
}
deviceInfo.ext = extendedDeviceInfo;

return deviceInfo;
}

export const spec = {
code: 'freepass',
supportedMediaTypes: [BANNER],

isBidRequestValid(bid) {
logMessage('Validating bid: ', bid);
return !!bid.adUnitCode;
},

buildRequests(validBidRequests, bidderRequest) {
if (validBidRequests.length === 0) {
logMessage('FreePass BidAdapter has no valid bid requests');
return [];
}

logMessage('FreePass BidAdapter is preparing bid request: ', validBidRequests);
logMessage('FreePass BidAdapter is using bidder request: ', bidderRequest);

const data = converter.toORTB({
bidderRequest: bidderRequest,
bidRequests: validBidRequests,
context: { mediaType: BANNER }
});
logMessage('FreePass BidAdapter interpreted ORTB bid request as ', data);

// Only freepassId is supported
let freepassId = (validBidRequests[0].userId && validBidRequests[0].userId.freepassId) || {};
data.user = prepareUserInfo(data.user, freepassId);
data.device = prepareDeviceInfo(data.device, freepassId);

data.test = validBidRequests[0].test || 0;

logMessage('FreePass BidAdapter augmented ORTB bid request user: ', data.user);
logMessage('FreePass BidAdapter augmented ORTB bid request device: ', data.device);

return {
method: 'POST',
url: BIDDER_SERVICE_URL,
data,
options: { withCredentials: false }
};
},

interpretResponse(serverResponse, bidRequest) {
logMessage('FreePass BidAdapter is interpreting server response: ', serverResponse);
logMessage('FreePass BidAdapter is using bid request: ', bidRequest);
const bids = converter.fromORTB({response: serverResponse.body, request: bidRequest.data}).bids;
logMessage('FreePass BidAdapter interpreted ORTB bids as ', bids);

return bids;
},
};

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

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

# Description

Connects to FreePass service for bids. Only BANNER is currently supported.

This BidAdapter requires the FreePass IdSystem to be configured. Please contact FreePass for proper setup.

# Test Parameters
```javascript
let adUnits = [
{
code: 'ad-banner-1', // ad slot HTML element ID
mediaTypes: {
banner: {
sizes: [[1024, 1024]]
}
},
bids: [{
bidder: 'freepass'
}]
}
];
```

161 changes: 161 additions & 0 deletions test/spec/modules/freepassBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {expect} from 'chai';
import {spec} from 'modules/freepassBidAdapter.js';
import {newBidder} from 'src/adapters/bidderFactory.js';

describe('FreePass adapter', function () {
const adapter = newBidder(spec);
describe('inherited functions', function () {
it('exists and is a function', function () {
expect(adapter.callBids).to.exist.and.to.be.a('function');
});
});

describe('isBidRequestValid', function () {
const bid = {
bidder: 'freepass',
userId: {
freepassId: {
userId: 'fpid'
}
},
adUnitCode: 'adunit-code',
};

it('should return true when required params found', function () {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return false when adUnitCode is missing', function () {
let localBid = Object.assign({}, bid);
delete localBid.adUnitCode;
expect(spec.isBidRequestValid(localBid)).to.equal(false);
});
});

describe('buildRequests', function () {
let bidRequests, bidderRequest;
beforeEach(function () {
bidRequests = [{
'bidder': 'freepass',
'userId': {
'freepassId': {
'userIp': '172.21.0.1',
'userId': '56c4c789-71ce-46f5-989e-9e543f3d5f96',
'commonId': 'commonIdValue'
}
}
}];
bidderRequest = {};
});

it('should return an empty array when no bid requests', function () {
const bidRequest = spec.buildRequests([], bidderRequest);
expect(bidRequest).to.be.an('array');
expect(bidRequest.length).to.equal(0);
});

it('should return a valid bid request object', function () {
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
expect(bidRequest).to.be.an('object');
expect(bidRequest.data).to.be.an('object');
expect(bidRequest.method).to.equal('POST');
expect(bidRequest.url).to.not.equal('');
expect(bidRequest.url).to.not.equal(undefined);
expect(bidRequest.url).to.not.equal(null);
});

it('should add user id to user information', function () {
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
const ortbData = bidRequest.data;
expect(ortbData.user).to.be.an('object');
expect(ortbData.user.id).to.equal('56c4c789-71ce-46f5-989e-9e543f3d5f96');
});

it('should add freepass commonId to extended user information', function () {
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
const ortbData = bidRequest.data;
expect(ortbData.user).to.be.an('object');
expect(ortbData.user.ext).to.be.an('object');
expect(ortbData.user.ext.fuid).to.equal('commonIdValue');
});

it('should skip freepass commonId when not available', function () {
let localBidRequests = [Object.assign({}, bidRequests[0])];
delete localBidRequests[0].userId.freepassId.commonId;
const bidRequest = spec.buildRequests(localBidRequests, bidderRequest);
const ortbData = bidRequest.data;
expect(ortbData.user).to.be.an('object');
expect(ortbData.user.ext).to.be.an('object');
expect(ortbData.user.ext.fuid).to.be.undefined;
});

it('should add IP information to extended device information', function () {
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
const ortbData = bidRequest.data;
expect(ortbData.device).to.be.an('object');
expect(ortbData.device.ip).to.equal('172.21.0.1');
expect(ortbData.device.ext).to.be.an('object');
expect(ortbData.device.ext.is_accurate_ip).to.equal(1);
});

it('should skip IP information when not available', function () {
let localBidRequests = [Object.assign({}, bidRequests[0])];
delete localBidRequests[0].userId.freepassId.userIp;
const bidRequest = spec.buildRequests(localBidRequests, bidderRequest);
const ortbData = bidRequest.data;
expect(ortbData.device).to.be.an('object');
expect(ortbData.device.ip).to.be.undefined;
expect(ortbData.device.ext).to.be.an('object');
expect(ortbData.device.ext.is_accurate_ip).to.equal(0);
});
});

describe('interpretResponse', function () {
let bidRequests, bidderRequest;
beforeEach(function () {
bidRequests = [{
'bidId': '28ffdf2a952532',
'bidder': 'freepass',
'userId': {
'freepassId': {
'userIp': '172.21.0.1',
'userId': '56c4c789-71ce-46f5-989e-9e543f3d5f96',
'commonId': 'commonIdValue'
}
}
}];
bidderRequest = {};
});

const ad = '<iframe src=\'http://127.0.0.1:8081/banner.html?w=300&h=250&cr=0\' width=\'300\' height=\'250\' style=\'border:none;\'></iframe>';
const serverResponse = {
body: {
'cur': 'JPY',
'seatbid': [{
'bid': [{
'impid': '28ffdf2a952532',
'price': 97,
'adm': ad,
'w': 300,
'h': 250,
'crid': 'creative0'
}]
}]
}
};
it('should interpret server response', function () {
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
const bids = spec.interpretResponse(serverResponse, bidRequest);
expect(bids).to.be.an('array');

const bid = bids[0];
expect(bid).to.be.an('object');
expect(bid.currency).to.equal('JPY');
expect(bid.cpm).to.equal(97);
expect(bid.ad).to.equal(ad)
expect(bid.width).to.equal(300);
expect(bid.height).to.equal(250);
expect(bid.creativeId).to.equal('creative0');
});
});
});

0 comments on commit 5bfac11

Please sign in to comment.