Skip to content

Commit

Permalink
Bidfluence adapter 1.x (#3244)
Browse files Browse the repository at this point in the history
* Bidfluence Adapter 1.x

* Test for Bidfluence Adapter 1.x

* Update to Bidfluence Adapter 1.x

* Update due to test not passing

* Fixed undefined gdpr object and unsupported gdpr vendor

* Removed gdpr vendor line test

* Updated as requested 

Related to prebid/prebid.github.io#1020 (comment)
  • Loading branch information
francescocristallo authored and jsnellbaker committed Nov 5, 2018
1 parent 1110e25 commit 5e1c996
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 0 deletions.
116 changes: 116 additions & 0 deletions modules/bidfluenceBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
const BIDDER_CODE = 'bidfluence';

function stdTimezoneOffset(t) {
const jan = new Date(t.getFullYear(), 0, 1);
const jul = new Date(t.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}
function dst(t) {
return t.getTimezoneOffset() < stdTimezoneOffset(t);
}
function getBdfTz(d) {
let tz = d.getTimezoneOffset();
if (dst(d)) {
tz += 60;
}
return tz.toString();
}
function getUTCDate() {
var m = new Date();
var dateString = m.getUTCFullYear() + '/' +
('0' + (m.getUTCMonth() + 1)).slice(-2) + '/' +
('0' + m.getUTCDate()).slice(-2) + ' ' +
('0' + m.getUTCHours()).slice(-2) + ':' +
('0' + m.getUTCMinutes()).slice(-2) + ':' +
('0' + m.getUTCSeconds()).slice(-2);

return dateString;
}

export const spec = {
code: BIDDER_CODE,
isBidRequestValid: function (bid) {
return !!bid.params.placementId || !!bid.params.publisherId;
},

buildRequests: function (validBidRequests, bidderRequest) {
return validBidRequests.map(bidRequest => {
const params = bidRequest.params;
const sizes = utils.parseSizesInput(bidRequest.sizes)[0];
const width = sizes.split('x')[0];
const height = sizes.split('x')[1];
const refInfo = bidderRequest.refererInfo;
const gdpr = bidderRequest.gdprConsent;
const body = document.getElementsByTagName('body')[0];
const vpW = Math.max(window.innerWidth || body.clientWidth || 0) + 2;
const vpH = Math.max(window.innerHeight || body.clientHeight || 0) + 2;
const sr = screen.height > screen.width ? screen.height + 'x' + screen.width + 'x' + screen.colorDepth : screen.width + 'x' + screen.height + 'x' + screen.colorDepth;

const payload = {
bid: bidRequest.bidId,
v: '1.0',
azr: true,
ck: utils.cookiesAreEnabled(),
tid: params.placementId,
pid: params.publisherId,
rp: params.reservePrice || 0,
re: refInfo ? refInfo.referer : '',
st: refInfo ? refInfo.stack : [],
tz: getBdfTz(new Date()),
sr: sr,
tm: bidderRequest.timeout,
vp: vpW + 'x' + vpH,
sdt: getUTCDate(),
w: width,
h: height,
gdpr: gdpr ? gdpr.gdprApplies : false,
gdprc: gdpr ? gdpr.consentString : ''
};
const payloadString = JSON.stringify(payload);
return {
method: 'POST',
url: `//${payload.pid}.bidfluence.com/Hb`,
data: payloadString,
options: { contentType: 'text/plain' }
};
});
},

interpretResponse: function (serverResponse, bidRequest) {
const bidResponses = [];
const response = serverResponse.body;
const cpm = response.Cpm || 0;

if (cpm > 0) {
const bidResponse = {
requestId: response.BidId,
cpm: cpm,
width: response.Width,
height: response.Height,
creativeId: response.CreativeId,
ad: response.Ad,
currency: 'USD',
netRevenue: true,
ttl: 360
};
bidResponses.push(bidResponse);
}

return bidResponses;
},

getUserSyncs: function (serverResponses) {
if (serverResponses.userSyncs) {
const syncs = serverResponses.UserSyncs.map((sync) => {
return {
type: sync.Type === 'ifr' ? 'iframe' : 'image',
url: sync.Url
};
});
return syncs;
}
}
};
registerBidder(spec);
31 changes: 31 additions & 0 deletions modules/bidfluenceBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Overview

```
Module Name: Bidfluence Adapter
Module Type: Bidder Adapter
Maintainer: integrations@bidfluence.com
prebid_1_0_supported : true
gdpr_supported: true
```

# Description

Bidfluence adapter for prebid.

# Test Parameters

```
var adUnits = [
{
code: 'test-prebid',
sizes: [[300, 250]],
bids: [{
bidder: 'bidfluence',
params: {
placementId: '1000',
publisherId: '1000'
}
}]
}
]
```
111 changes: 111 additions & 0 deletions test/spec/modules/bidfluenceBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { expect } from 'chai';
import { spec } from 'modules/bidfluenceBidAdapter';

const BIDDER_CODE = 'bidfluence';
const PLACEMENT_ID = '1000';
const PUB_ID = '1000';
const CONSENT_STRING = 'DUXDSDFSFWRRR8345F==';

const validBidRequests = [{
'bidder': BIDDER_CODE,
'params': {
'placementId': PLACEMENT_ID,
'publisherId': PUB_ID,
'reservePrice': 0
},
'adUnitCode': 'adunit-code',
'sizes': [[300, 250]],
'bidId': '2b1f23307fb8ef',
'bidderRequestId': '10edf38ec1a719',
'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304'
}];

const bidderRequest = {
'bidderCode': 'bidfluence',
'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304',
'bidderRequestId': '10edf38ec1a719',
'refererInfo': {
'numIframes': 0,
'reachedTop': true,
'referer': 'test',
'stack': ['test']
},
'timeout': 1000,
'gdprConsent': {
'gdprApplies': true,
'consentString': CONSENT_STRING,
'vendorData': ''
}
};

bidderRequest.bids = validBidRequests;

describe('Bidfluence Adapter test', () => {
describe('isBidRequestValid', function () {
it('should return true when required params found', function () {
expect(spec.isBidRequestValid(validBidRequests[0])).to.equal(true);
});
it('should return the right bidder code', function () {
expect(spec.code).to.eql(BIDDER_CODE);
});
});

describe('buildRequests', function () {
const request = spec.buildRequests(validBidRequests, bidderRequest);

it('sends bid request to our endpoint via POST', function () {
expect(request[0].method).to.equal('POST');
});

const payload = JSON.parse(request[0].data);

expect(payload.bid).to.equal(validBidRequests[0].bidId);
expect(payload.azr).to.equal(true);
expect(payload.ck).to.not.be.undefined;
expect(payload.tid).to.equal(PLACEMENT_ID);
expect(payload.pid).to.equal(PUB_ID);
expect(payload.rp).to.be.a('number');
expect(payload.re).to.not.be.undefined;
expect(payload.st).to.not.be.undefined;
expect(payload.tz).to.not.be.undefined;
expect(payload.sr).to.not.be.undefined;
expect(payload.vp).to.not.be.undefined;
expect(payload.sdt).to.not.be.undefined;
expect(payload.w).to.equal('300');
expect(payload.h).to.equal('250');

it('sends gdpr info if exists', function () {
expect(payload.gdpr).to.equal(true);
expect(payload.gdprc).to.equal(CONSENT_STRING);
});
});

describe('interpretResponse', function () {
const response = {
body: {
'CreativeId': '1000',
'Cpm': 0.50,
'Ad': '<div></div>',
'Height': 250,
'Width': 300
}
};

it('should get correct bid response', function () {
const expectedResponse = [{
requestId: response.body.BidId,
cpm: response.body.Cpm,
width: response.body.Width,
height: response.body.Height,
creativeId: response.body.CreativeId,
ad: response.body.Ad,
currency: 'USD',
netRevenue: true,
ttl: 360
}];

let result = spec.interpretResponse(response, { 'bidderRequest': validBidRequests[0] });
expect(result).to.deep.equal(expectedResponse);
});
});
});

0 comments on commit 5e1c996

Please sign in to comment.