Skip to content

Commit

Permalink
Add Video Reach adapter (#3766)
Browse files Browse the repository at this point in the history
* Add Video Reach adapter

* Add Video Reach adapter

* Add Video Reach adapter
  • Loading branch information
VideoReach authored and robertrmartinez committed May 7, 2019
1 parent 10ec9a5 commit 7406f1a
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 0 deletions.
97 changes: 97 additions & 0 deletions modules/videoreachBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {registerBidder} from '../src/adapters/bidderFactory';
const utils = require('../src/utils');
const BIDDER_CODE = 'videoreach';
const ENDPOINT_URL = '//a.videoreach.de/hb/';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: ['banner'],

isBidRequestValid: function(bid) {
return !!(bid.params.TagId);
},

buildRequests: function(validBidRequests, bidderRequest) {
var data = {
referrer: utils.getTopWindowUrl(),
data: validBidRequests.map(function(bid) {
return {
TagId: utils.getValue(bid.params, 'TagId'),
bidId: utils.getBidIdParameter('bidId', bid),
bidderRequestId: utils.getBidIdParameter('bidderRequestId', bid),
auctionId: utils.getBidIdParameter('auctionId', bid),
transactionId: utils.getBidIdParameter('transactionId', bid)
}
})
};

if (bidderRequest && bidderRequest.gdprConsent) {
data.gdpr = {
consent_string: bidderRequest.gdprConsent.consentString,
consent_required: bidderRequest.gdprConsent.gdprApplies
};
}

return {
method: 'POST',
url: ENDPOINT_URL,
data: JSON.stringify(data)
};
},

interpretResponse: function(serverResponse) {
const bidResponses = [];
serverResponse = serverResponse.body;

if (serverResponse.responses) {
serverResponse.responses.forEach(function (bid) {
const bidResponse = {
cpm: bid.cpm,
width: bid.width,
height: bid.height,
currency: bid.currency,
netRevenue: true,
ttl: bid.ttl,
ad: bid.ad,
requestId: bid.bidId,
creativeId: bid.creativeId
};
bidResponses.push(bidResponse);
});
}
return bidResponses;
},

getUserSyncs: function(syncOptions, responses, gdprConsent) {
const syncs = [];

if (syncOptions.pixelEnabled && responses.length) {
const SyncPixels = responses[0].body.responses[0].sync;

let params = '';
if (gdprConsent && typeof gdprConsent.consentString === 'string') {
if (typeof gdprConsent.gdprApplies === 'boolean') {
params += 'gdpr=' + gdprConsent.gdprApplies + '&gdpr_consent=' + gdprConsent.consentString;
} else {
params += 'gdpr_consent=' + gdprConsent.consentString;
}
}

var gdpr;
if (SyncPixels) {
SyncPixels.forEach(sync => {
gdpr = (params) ? ((sync.split('?')[1] ? '&' : '?') + params) : '';

syncs.push({
type: 'image',
url: sync + gdpr
});
});
}
}

return syncs;
}
};

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

**Module Name**: Video Reach Bidder Adapter
**Module Type**: Bidder Adapter
**Maintainer**: hello@videoreach.de

# Description

Video Reach Bidder Adapter for Prebid.js.

Use `videoreach` as bidder.

`TagId` ist required.

## AdUnits configuration example
```
var adUnits = [{
code: 'your-slot', //use exactly the same code as your slot div id.
sizes: [[1, 1]],
bids: [{
bidder: 'videoreach',
params: {
TagId: 'XXXXX'
}
}]
}];
```
141 changes: 141 additions & 0 deletions test/spec/modules/videoreachBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import {expect} from 'chai';
import {spec} from 'modules/videoreachBidAdapter';
import {newBidder} from 'src/adapters/bidderFactory';

const ENDPOINT_URL = '//a.videoreach.de/hb/';

describe('videoreachBidAdapter', function () {
describe('isBidRequestValid', function () {
let bid = {
'params': {
'TagId': 'ABCDE'
},
'bidId': '242d506d4e4f15',
'bidderRequestId': '1893a2136a84a2',
'auctionId': '8fb7b1c7-317b-4edf-83f0-c4669a318522',
'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622'
};

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

it('should return false when required params are not passed', function () {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'TagId': ''
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
});

describe('buildRequests', function () {
let bidRequests = [
{
'bidder': 'videoreach',
'params': {
'TagId': 'ABCDE'
},
'adUnitCode': 'adzone',
'auctionId': '8fb7b1c7-317b-4edf-83f0-c4669a318522',
'sizes': [[1, 1]],
'bidId': '242d506d4e4f15',
'bidderRequestId': '1893a2136a84a2',
'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622',
'mediaTypes': {
'banner': {
'sizes': [1, 1]
},
}
}
];

it('send bid request to endpoint', function () {
const request = spec.buildRequests(bidRequests);

expect(request.url).to.equal(ENDPOINT_URL);
expect(request.method).to.equal('POST');
});

it('send bid request with GDPR to endpoint', function () {
let consentString = 'BOEFEAyOEFEAyAHABDENAI4AAAB9vABAASA';

let bidderRequest = {
'gdprConsent': {
'consentString': consentString,
'gdprApplies': true
}
};

const request = spec.buildRequests(bidRequests, bidderRequest);
const payload = JSON.parse(request.data);

expect(payload.gdpr.consent_required).to.exist;
expect(payload.gdpr.consent_string).to.equal(consentString);
});
});

describe('interpretResponse', function () {
let serverResponse =
{
'body': {
'responses': [{
'bidId': '242d506d4e4f15',
'transactionId': '85a2e190-0684-4f95-ad32-6c90757ed622',
'cpm': 10.0,
'width': '1',
'height': '1',
'ad': '<script type="text/javascript" async="true" src="//a.videoreach.de/hb/js/?t=f86fb856-15d0-4591-84eb-0830b38e9cf2"></script>',
'ttl': 360,
'creativeId': '5cb5dc9375c0e',
'netRevenue': true,
'currency': 'EUR',
'sync': ['https:\/\/SYNC_URL']
}]
}
};

it('should handle response', function() {
let expectedResponse = [
{
cpm: 10.0,
width: '1',
height: '1',
currency: 'EUR',
netRevenue: true,
ttl: 360,
ad: '<!-- AD -->',
requestId: '242d506d4e4f15',
creativeId: '5cb5dc9375c0e'
}
];

let result = spec.interpretResponse(serverResponse);
expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0]));
});

it('should handles empty response', function() {
let serverResponse = {
'body': {
'responses': []
}
};

let result = spec.interpretResponse(serverResponse);
expect(result.length).to.equal(0);
});

describe('getUserSyncs', () => {
it('should push user sync images if enabled', () => {
const syncOptions = { pixelEnabled: true };
const syncs = spec.getUserSyncs(syncOptions, [serverResponse]);

expect(syncs[0]).to.deep.equal({
type: 'image',
url: 'https://SYNC_URL'
});
})
});
});
});

0 comments on commit 7406f1a

Please sign in to comment.