Skip to content

Commit

Permalink
New bid adapter for SmileWanted (prebid#3601)
Browse files Browse the repository at this point in the history
* New bid adapter for SmileWanted

- Smilewanted BidAdapter module and test spec added

* Update to correct feedback from PR prebid#3601

- Add comments
- Default value for currencyCode
- replacing "utils.getTopWindowUrl()" with bidderRequest.refererInfo
- Update unit tests

* Delete of the commented spec
  • Loading branch information
MaxSmileWanted authored and jsnellbaker committed Mar 11, 2019
1 parent d00c92a commit 72e0e97
Show file tree
Hide file tree
Showing 3 changed files with 335 additions and 0 deletions.
113 changes: 113 additions & 0 deletions modules/smilewantedBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import * as utils from '../src/utils';
import { config } from '../src/config';
import { registerBidder } from '../src/adapters/bidderFactory';

export const spec = {
code: 'smilewanted',
aliases: ['smile', 'sw'],

/**
* Determines whether or not the given bid request is valid.
*
* @param {object} bid The bid to validate.
* @return boolean True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function(bid) {
return !!(bid.params && bid.params.zoneId);
},

/**
* Make a server request from the list of BidRequests.
*
* @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server.
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests, bidderRequest) {
return validBidRequests.map(bid => {
var payload = {
zoneId: bid.params.zoneId,
currencyCode: config.getConfig('currency.adServerCurrency') || 'EUR',
bidfloor: bid.params.bidfloor || 0.0,
tagId: bid.adUnitCode,
sizes: bid.sizes.map(size => ({
w: size[0],
h: size[1]
})),
transactionId: bid.transactionId,
timeout: config.getConfig('bidderTimeout'),
bidId: bid.bidId,
prebidVersion: '$prebid.version$'
};

if (bidderRequest && bidderRequest.refererInfo) {
payload.pageDomain = bidderRequest.refererInfo.referer || '';
}

if (bidderRequest && bidderRequest.gdprConsent) {
payload.gdpr_consent = bidderRequest.gdprConsent.consentString;
payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side
}
var payloadString = JSON.stringify(payload);
return {
method: 'POST',
url: 'https://prebid.smilewanted.com',
data: payloadString,
};
});
},

/**
* Unpack the response from the server into a list of bids.
*
* @param {*} serverResponse A successful response from the server.
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: function(serverResponse, bidRequest) {
const bidResponses = [];
var response = serverResponse.body;
try {
if (response) {
const bidResponse = {
requestId: JSON.parse(bidRequest.data).bidId,
cpm: response.cpm,
width: response.width,
height: response.height,
creativeId: response.creativeId,
dealId: response.dealId,
currency: response.currency,
netRevenue: response.isNetCpm,
ttl: response.ttl,
adUrl: response.adUrl,
ad: response.ad
};

bidResponses.push(bidResponse);
}
} catch (error) {
utils.logError('Error while parsing smilewanted response', error);
}
return bidResponses;
},

/**
* User syncs.
*
* @param {*} syncOptions Publisher prebid configuration.
* @param {*} serverResponses A successful response from the server.
* @return {Syncs[]} An array of syncs that should be executed.
*/
getUserSyncs: function(syncOptions, serverResponses) {
const syncs = []
if (syncOptions.iframeEnabled && serverResponses.length > 0) {
if (serverResponses[0].body.cSyncUrl === 'https://csync.smilewanted.com') {
syncs.push({
type: 'iframe',
url: serverResponses[0].body.cSyncUrl
});
}
}
return syncs;
}
}

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

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

# Description

To use us as a bidder you must have an account and an active "zoneId" on our SmileWanted platform.

# Test Parameters

## Web
```
var adUnits = [
{
code: 'test-div',
sizes: [[300, 250]],
bids: [
{
bidder: "smilewanted",
params: {
zoneId: 1
}
}
]
}
];
```
191 changes: 191 additions & 0 deletions test/spec/modules/smilewantedBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import { expect } from 'chai';
import { spec } from 'modules/smilewantedBidAdapter';
import { newBidder } from 'src/adapters/bidderFactory';
import { config } from 'src/config';
import * as utils from 'src/utils';
import { requestBidsHook } from 'modules/consentManagement';

// Default params with optional ones
describe('smilewantedBidAdapterTests', function () {
var DEFAULT_PARAMS = [{
adUnitCode: 'sw_300x250',
bidId: '12345',
sizes: [
[300, 250],
[300, 200]
],
bidder: 'smilewanted',
params: {
zoneId: '1234',
bidfloor: 2.50
},
requestId: 'request_abcd1234',
transactionId: 'trans_abcd1234'
}];

var BID_RESPONSE = {
body: {
cpm: 3,
width: 300,
height: 250,
creativeId: 'crea_sw_1',
currency: 'EUR',
isNetCpm: true,
ttl: 300,
adUrl: 'https://www.smilewanted.com',
ad: '< --- sw script --- >',
cSyncUrl: 'https://csync.smilewanted.com'
}
};

it('SmileWanted - Verify build request', function () {
config.setConfig({
'currency': {
'adServerCurrency': 'EUR'
}
});
const request = spec.buildRequests(DEFAULT_PARAMS);
expect(request[0]).to.have.property('url').and.to.equal('https://prebid.smilewanted.com');
expect(request[0]).to.have.property('method').and.to.equal('POST');
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.have.property('zoneId').and.to.equal('1234');
expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR');
expect(requestContent).to.have.property('bidfloor').and.to.equal(2.50);
expect(requestContent).to.have.property('sizes');
expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300);
expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250);
expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300);
expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200);
expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined;
});

it('SmileWanted - Verify build request with referrer', function () {
const request = spec.buildRequests(DEFAULT_PARAMS, {
refererInfo: {
referer: 'http://localhost/Prebid.js/integrationExamples/gpt/hello_world.html'
}
});
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.have.property('pageDomain').and.to.equal('http://localhost/Prebid.js/integrationExamples/gpt/hello_world.html');
});

describe('gdpr tests', function () {
afterEach(function () {
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

it('SmileWanted - Verify build request with GDPR', function () {
config.setConfig({
'currency': {
'adServerCurrency': 'EUR'
},
consentManagement: {
cmp: 'iab',
consentRequired: true,
timeout: 1000,
allowAuctionWithoutConsent: true
}
});
const request = spec.buildRequests(DEFAULT_PARAMS, {
gdprConsent: {
consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA',
gdprApplies: true
}
});
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.have.property('gdpr').and.to.equal(true);
expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA');
});

it('SmileWanted - Verify build request with GDPR without gdprApplies', function () {
config.setConfig({
'currency': {
'adServerCurrency': 'EUR'
},
consentManagement: {
cmp: 'iab',
consentRequired: true,
timeout: 1000,
allowAuctionWithoutConsent: true
}
});
const request = spec.buildRequests(DEFAULT_PARAMS, {
gdprConsent: {
consentString: 'BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA'
}
});
const requestContent = JSON.parse(request[0].data);
expect(requestContent).to.not.have.property('gdpr');
expect(requestContent).to.have.property('gdpr_consent').and.to.equal('BOO_ch7OO_ch7AKABBENA2-AAAAZ97_______9______9uz_Gv_r_f__33e8_39v_h_7_u___m_-zzV4-_lvQV1yPA1OrfArgFA');
});
});

it('SmileWanted - Verify parse response', function () {
const request = spec.buildRequests(DEFAULT_PARAMS);
const bids = spec.interpretResponse(BID_RESPONSE, request[0]);
expect(bids).to.have.lengthOf(1);
const bid = bids[0];
expect(bid.cpm).to.equal(3);
expect(bid.adUrl).to.equal('https://www.smilewanted.com');
expect(bid.ad).to.equal('< --- sw script --- >');
expect(bid.width).to.equal(300);
expect(bid.height).to.equal(250);
expect(bid.creativeId).to.equal('crea_sw_1');
expect(bid.currency).to.equal('EUR');
expect(bid.netRevenue).to.equal(true);
expect(bid.ttl).to.equal(300);
expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId);

expect(function () {
spec.interpretResponse(BID_RESPONSE, {
data: 'invalid Json'
})
}).to.not.throw();
});

it('SmileWanted - Verify bidder code', function () {
expect(spec.code).to.equal('smilewanted');
});

it('SmileWanted - Verify bidder aliases', function () {
expect(spec.aliases).to.have.lengthOf(2);
expect(spec.aliases[0]).to.equal('smile');
expect(spec.aliases[1]).to.equal('sw');
});

it('SmileWanted - Verify if bid request valid', function () {
expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true);
expect(spec.isBidRequestValid({
params: {
zoneId: 1234
}
})).to.equal(true);
});

it('SmileWanted - Verify if params(zoneId) is not passed', function () {
expect(spec.isBidRequestValid({})).to.equal(false);
expect(spec.isBidRequestValid({
params: {}
})).to.equal(false);
});

it('SmileWanted - Verify user sync', function () {
var syncs = spec.getUserSyncs({
iframeEnabled: true
}, [BID_RESPONSE]);
expect(syncs).to.have.lengthOf(1);
expect(syncs[0].type).to.equal('iframe');
expect(syncs[0].url).to.equal('https://csync.smilewanted.com');

syncs = spec.getUserSyncs({
iframeEnabled: false
}, [BID_RESPONSE]);
expect(syncs).to.have.lengthOf(0);

syncs = spec.getUserSyncs({
iframeEnabled: true
}, []);
expect(syncs).to.have.lengthOf(0);
});
});

0 comments on commit 72e0e97

Please sign in to comment.