-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
modules: Implement SmartRTB adapter and spec. (#3575)
* modules: Implement SmartRTB adapter and spec. * Fix for-loop syntax to support IE; refactor getDomain out of exported set.
- Loading branch information
1 parent
90cefb8
commit c0fdf02
Showing
3 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import * as utils from 'src/utils'; | ||
import {registerBidder} from 'src/adapters/bidderFactory'; | ||
const BIDDER_CODE = 'smartrtb'; | ||
|
||
function getDomain () { | ||
if (!utils.inIframe()) { | ||
return window.location.hostname | ||
} | ||
let origins = window.document.location.ancestorOrigins | ||
if (origins && origins.length > 0) { | ||
return origins[origins.length - 1] | ||
} | ||
} | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
aliases: ['smrtb'], | ||
isBidRequestValid: function(bid) { | ||
return (bid.params.pubId !== null && | ||
bid.params.medId !== null && | ||
bid.params.zoneId !== null); | ||
}, | ||
buildRequests: function(validBidRequests, bidderRequest) { | ||
let stack = (bidderRequest.refererInfo && | ||
bidderRequest.refererInfo.stack ? bidderRequest.refererInfo | ||
: []) | ||
|
||
const payload = { | ||
start_time: utils.timestamp(), | ||
tmax: 120, | ||
language: window.navigator.userLanguage || window.navigator.language, | ||
site: { | ||
domain: getDomain(), | ||
iframe: !bidderRequest.refererInfo.reachedTop, | ||
url: stack && stack.length > 0 ? [stack.length - 1] : null, | ||
https: (window.location.protocol === 'https:'), | ||
referrer: bidderRequest.refererInfo.referer | ||
}, | ||
imps: [] | ||
}; | ||
|
||
if (bidderRequest && bidderRequest.gdprConsent) { | ||
payload.gdpr = { | ||
applies: bidderRequest.gdprConsent.gdprApplies, | ||
consent: bidderRequest.gdprConsent.consentString | ||
}; | ||
} | ||
|
||
for (let x = 0; x < validBidRequests.length; x++) { | ||
let req = validBidRequests[x] | ||
|
||
payload.imps.push({ | ||
pub_id: req.params.pubId, | ||
med_id: req.params.medId, | ||
zone_id: req.params.zoneId, | ||
bid_id: req.bidId, | ||
imp_id: req.transactionId, | ||
sizes: req.sizes, | ||
force_bid: req.params.forceBid | ||
}); | ||
} | ||
|
||
return { | ||
method: 'POST', | ||
url: '//pubs.smrtb.com/json/publisher/prebid', | ||
data: JSON.stringify(payload) | ||
}; | ||
}, | ||
interpretResponse: function(serverResponse, bidRequest) { | ||
const bidResponses = []; | ||
let res = serverResponse.body; | ||
if (!res.bids || !res.bids.length) { | ||
return [] | ||
} | ||
|
||
for (let x = 0; x < serverResponse.body.bids.length; x++) { | ||
let bid = serverResponse.body.bids[x] | ||
|
||
bidResponses.push({ | ||
requestId: bid.bid_id, | ||
cpm: bid.cpm, | ||
width: bid.w, | ||
height: bid.h, | ||
ad: bid.html, | ||
ttl: 120, | ||
creativeId: bid.crid, | ||
netRevenue: true, | ||
currency: 'USD' | ||
}) | ||
} | ||
|
||
return bidResponses; | ||
}, | ||
getUserSyncs: function(syncOptions, serverResponses) { | ||
const syncs = [] | ||
if (syncOptions.iframeEnabled) { | ||
syncs.push({ | ||
type: 'iframe', | ||
url: '//ads.smrtb.com/sync' | ||
}); | ||
} else if (syncOptions.pixelEnabled) { | ||
syncs.push({ | ||
type: 'image', | ||
url: '//ads.smrtb.com/sync' | ||
}); | ||
} | ||
return syncs; | ||
} | ||
}; | ||
|
||
registerBidder(spec); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Smart RTB (smrtb.com) Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: evanm@smrtb.com | ||
``` | ||
|
||
# Description | ||
|
||
Prebid adapter for Smart RTB. Requires approval and account setup. | ||
|
||
# Test Parameters | ||
|
||
## Web | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'test-div', | ||
sizes: [[300, 250]], | ||
bids: [ | ||
{ | ||
bidder: "smartrtb", | ||
params: { | ||
pubId: 123, | ||
medId: "m_00a95d003340dbb2fcb8ee668a84fa", | ||
zoneId: "z_261b6c7e7d4d4985393b293cc903d1", | ||
force_bid: true | ||
} | ||
} | ||
] | ||
} | ||
]; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { expect } from 'chai' | ||
import { spec, _getPlatform } from 'modules/smartrtbBidAdapter' | ||
import { newBidder } from 'src/adapters/bidderFactory' | ||
|
||
describe('SmartRTBBidAdapter', function () { | ||
const adapter = newBidder(spec) | ||
|
||
let bidRequest = { | ||
bidId: '123', | ||
transactionId: '456', | ||
sizes: [[ 300, 250 ]], | ||
params: { | ||
pubId: 123, | ||
medId: 'm_00a95d003340dbb2fcb8ee668a84fa', | ||
zoneId: 'z_261b6c7e7d4d4985393b293cc903d1' | ||
} | ||
} | ||
|
||
describe('codes', function () { | ||
it('should return a bidder code of smartrtb', function () { | ||
expect(spec.code).to.equal('smartrtb') | ||
}) | ||
it('should alias smrtb', function () { | ||
expect(spec.aliases.length > 0 && spec.aliases[0] === 'smrtb').to.be.true | ||
}) | ||
}) | ||
|
||
describe('isBidRequestValid', function () { | ||
it('should return true if all params present', function () { | ||
expect(spec.isBidRequestValid(bidRequest)).to.be.true | ||
}) | ||
|
||
it('should return false if any parameter missing', function () { | ||
expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { pubId: null } }))).to.be.false | ||
expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { medId: null } }))).to.be.false | ||
expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { zoneId: null } }))).to.be.false | ||
}) | ||
}) | ||
|
||
describe('buildRequests', function () { | ||
let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) | ||
let rdata | ||
|
||
it('should return request object', function () { | ||
expect(req).to.not.be.null | ||
}) | ||
|
||
it('should build request data', function () { | ||
expect(req.data).to.not.be.null | ||
}) | ||
|
||
it('should include one request', function () { | ||
rdata = JSON.parse(req.data) | ||
expect(rdata.imps.length).to.equal(1) | ||
}) | ||
|
||
it('should include all publisher params', function () { | ||
let r = rdata.imps[0] | ||
expect(r.pub_id !== null && r.med_id !== null && r.zone_id !== null).to.be.true | ||
}) | ||
}) | ||
|
||
describe('interpretResponse', function () { | ||
it('should form compliant bid object response', function () { | ||
let res = { | ||
body: { | ||
bids: [{ | ||
bid_id: '123', | ||
cpm: 1.23, | ||
w: 300, | ||
h: 250, | ||
html: '<b>deadbeef</b>', | ||
crid: 'crid' | ||
}] | ||
} | ||
} | ||
|
||
let ir = spec.interpretResponse(res, bidRequest) | ||
|
||
expect(ir.length).to.equal(1) | ||
|
||
let en = ir[0] | ||
|
||
expect(en.requestId != null && | ||
en.cpm != null && typeof en.cpm === 'number' && | ||
en.width != null && typeof en.width === 'number' && | ||
en.height != null && typeof en.height === 'number' && | ||
en.ad != null && | ||
en.creativeId != null | ||
).to.be.true | ||
}) | ||
}) | ||
|
||
describe('getUserSyncs', function () { | ||
it('should return iframe sync', function () { | ||
let sync = spec.getUserSyncs({ iframeEnabled: true }) | ||
expect(sync.length).to.equal(1) | ||
expect(sync[0].type === 'iframe') | ||
expect(typeof sync[0].url === 'string') | ||
}) | ||
|
||
it('should return pixel sync', function () { | ||
let sync = spec.getUserSyncs({ pixelEnabled: true }) | ||
expect(sync.length).to.equal(1) | ||
expect(sync[0].type === 'image') | ||
expect(typeof sync[0].url === 'string') | ||
}) | ||
}) | ||
}) |