forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(bidrequest): code for making bidrequest * feat(bidresponse): format and return the response * feat(tests): added tests for adapter * feat(docs): added docs for the adapter * refactor(url): changed adserver url * test(user sync): added unit tests for the user syncs * refactor(endpoint): changed endpoint for prebid * refactor(endpoint): changed endpoint for prebid * doc(tagid): mandatory param definition added * fix(imp id): fix for correct impression id * fix(width/height): fix for correct width and height sequence
- Loading branch information
Showing
3 changed files
with
357 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,142 @@ | ||
import {registerBidder} from '../src/adapters/bidderFactory'; | ||
import {BANNER} from '../src/mediaTypes'; | ||
import * as utils from '../src/utils'; | ||
const BIDDER_CODE = 'deepintent'; | ||
const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid'; | ||
const USER_SYNC_URL = 'https://beacon.deepintent.com/usersync.html'; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER], | ||
aliases: [], | ||
|
||
// tagId is mandatory param | ||
isBidRequestValid: bid => { | ||
let valid = false; | ||
if (bid && bid.params && bid.params.tagId) { | ||
if (typeof bid.params.tagId === 'string' || bid.params.tagId instanceof String) { | ||
valid = true; | ||
} | ||
} | ||
return valid; | ||
}, | ||
interpretResponse: function(bidResponse, request) { | ||
let responses = []; | ||
if (bidResponse && bidResponse.body) { | ||
let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : []; | ||
responses = bids.map(bid => formatResponse(bid)) | ||
} | ||
return responses; | ||
}, | ||
buildRequests: function (validBidRequests, bidderRequest) { | ||
const openRtbBidRequest = { | ||
id: utils.generateUUID(), | ||
at: 1, | ||
imp: validBidRequests.map(bid => buildImpression(bid)), | ||
site: buildSite(bidderRequest), | ||
device: buildDevice(), | ||
source: { | ||
fd: 0, | ||
ext: { | ||
type: 2 | ||
} | ||
} | ||
}; | ||
|
||
return { | ||
method: 'POST', | ||
url: BIDDER_ENDPOINT, | ||
data: JSON.stringify(openRtbBidRequest), | ||
options: { | ||
contentType: 'application/json' | ||
} | ||
}; | ||
}, | ||
/** | ||
* Register User Sync. | ||
*/ | ||
getUserSyncs: syncOptions => { | ||
if (syncOptions.iframeEnabled) { | ||
return [{ | ||
type: 'iframe', | ||
url: USER_SYNC_URL | ||
}]; | ||
} | ||
} | ||
|
||
}; | ||
|
||
function formatResponse(bid) { | ||
return { | ||
requestId: bid && bid.impid ? bid.impid : undefined, | ||
cpm: bid && bid.price ? bid.price : 0.0, | ||
width: bid && bid.w ? bid.w : 0, | ||
height: bid && bid.h ? bid.h : 0, | ||
ad: bid && bid.adm ? bid.adm : '', | ||
creativeId: bid && bid.crid ? bid.crid : undefined, | ||
netRevenue: false, | ||
currency: bid && bid.cur ? bid.cur : 'USD', | ||
ttl: 300, | ||
dealId: bid && bid.dealId ? bid.dealId : undefined | ||
} | ||
} | ||
|
||
function buildImpression(bid) { | ||
return { | ||
id: bid.bidId, | ||
tagid: bid.params.tagId || '', | ||
secure: window.location.protocol === 'https' ? 1 : 0, | ||
banner: buildBanner(bid), | ||
ext: bid.params.custom ? bid.params.custom : {} | ||
}; | ||
} | ||
|
||
function buildBanner(bid) { | ||
if (utils.deepAccess(bid, 'mediaTypes.banner')) { | ||
// Get Sizes from MediaTypes Object, Will always take first size, will be overrided by params for exact w,h | ||
if (utils.deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.height && !bid.params.width) { | ||
let sizes = utils.deepAccess(bid, 'mediaTypes.banner.sizes'); | ||
if (utils.isArray(sizes) && sizes.length > 0) { | ||
return { | ||
h: sizes[0][1], | ||
w: sizes[0][0] | ||
} | ||
} | ||
} else { | ||
return { | ||
h: bid.params.height, | ||
w: bid.params.width | ||
} | ||
} | ||
} | ||
} | ||
|
||
function buildSite(bidderRequest) { | ||
let site = {}; | ||
if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { | ||
site.page = bidderRequest.refererInfo.referer; | ||
site.domain = getDomain(bidderRequest.refererInfo.referer); | ||
} | ||
return site; | ||
} | ||
|
||
function getDomain(referer) { | ||
if (referer) { | ||
let domainA = document.createElement('a'); | ||
domainA.href = referer; | ||
return domainA.hostname; | ||
} | ||
} | ||
|
||
function buildDevice() { | ||
return { | ||
ua: navigator.userAgent, | ||
js: 1, | ||
dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack === '1') ? 1 : 0, | ||
h: screen.height, | ||
w: screen.width, | ||
language: navigator.language | ||
} | ||
} | ||
|
||
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,53 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Deepintent Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: prebid@deepintent.com | ||
``` | ||
|
||
# Description | ||
|
||
Deepintent currently supports the BANNER type ads through prebid js | ||
|
||
Module that connects to Deepintent's demand sources. | ||
|
||
# Banner Test Request | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'di_adUnit1', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250]], // a display size, only first one will be picked up since multiple ad sizes are not supported yet | ||
} | ||
} | ||
bids: [ | ||
{ | ||
bidder: 'deepintent', | ||
params: { | ||
tagId: '1300', // Required parameter | ||
w: 300, // Width and Height here will override sizes in mediatype | ||
h: 250, | ||
custom: { // Custom parameters in form of key value pairs | ||
user_min_age: 18 | ||
} | ||
} | ||
} | ||
] | ||
} | ||
]; | ||
``` | ||
|
||
###Recommended User Sync Configuration | ||
|
||
```javascript | ||
pbjs.setConfig({ | ||
userSync: { | ||
iframeEnabled: true, | ||
enabledBidders: ['deepintent'], | ||
syncDelay: 3000 | ||
}}); | ||
|
||
|
||
``` |
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,162 @@ | ||
import {expect} from 'chai'; | ||
import {spec} from 'modules/deepintentBidAdapter'; | ||
import * as utils from '../../../src/utils'; | ||
|
||
describe('Deepintent adapter', function () { | ||
let request; | ||
let bannerResponse; | ||
|
||
beforeEach(function () { | ||
request = [ | ||
{ | ||
bidder: 'deepintent', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250]] | ||
} | ||
}, | ||
params: { | ||
tagId: '100013', | ||
w: 728, | ||
h: 90, | ||
custom: { | ||
user_gender: 'female', | ||
user_max_age: 25 | ||
} | ||
} | ||
} | ||
]; | ||
bannerResponse = { | ||
'body': { | ||
'id': '303e1fae-9677-41e2-9a92-15a23445363f', | ||
'seatbid': [{ | ||
'bid': [{ | ||
'id': '11447bb1-a266-470d-b0d7-8810f5b1b75f', | ||
'impid': 'a7e92b9b-d9db-4de8-9c3f-f90737335445', | ||
'price': 0.6, | ||
'adid': '10001', | ||
'adm': "<span id='deepintent_wrapper_a7e92b9b-d9db-4de8-9c3f-f90737335445' onclick=DeepIntentExecuteClicks('%%CLICK_URL_UNESC%%')><span id='deepintent_wrapper_span_9-1bfd-4764-b4cf-0bb1a74e554e'><a href='https://test-beacon.deepintent.com/click?id=11447bb1-a266-470d-b0d7-8810f5b1b75f&ts=1565252378497&r=http%3A%2F%2Ftest.com' target='_blank'><img src='https://storage.googleapis.com/deepintent-test/adv/10001/asset/a640bcb5c0d5416096290d1c1097a1e9.jpg'></img></a></span><noscript class=\"MOAT-deepintentdisplay440800993657?moatClientLevel1=10001&moatClientLevel2=103389&moatClientLevel3=13665&moatClientSlicer1=washingtonpost.com&zMoatBID=11447bb1-a266-470d-b0d7-8810f5b1b75f&zMoatTIME=1565252378495&zMoatCGRP=530\"></noscript>\r\n<script src=\"https://z.moatads.com/deepintentdisplay440800993657/moatad.js#moatClientLevel1=10001&moatClientLevel2=103389&moatClientLevel3=13665&moatClientSlicer1=washingtonpost.com&zMoatBID=11447bb1-a266-470d-b0d7-8810f5b1b75f&zMoatTIME=1565252378495&zMoatCGRP=530\" type=\"text/javascript\"></script><img src='https://tracking.com' height='0px' width='0px' style='display:none'></img></span><script type='text/javascript'>window.DeepIntentExecuteClicks=window.DeepIntentExecuteClicks||function(e){if(e)for(var n=e.split(','),t=0;t<n.length;t++)(new Image).src=n[t]};</script><img src='https://test-beacon.deepintent.com/impression?id=11447bb1-a266-470d-b0d7-8810f5b1b75f&ts=1565252378497&wp=%%WINNING_PRICE%%' height='0px' width='0px' style='display:none'></img><iframe src='https://cdn.deepintent.com/sync/adx.html' width='0' height='0' style='display:none;'></iframe>", | ||
'adomain': ['deepintent.com'], | ||
'cid': '103389', | ||
'crid': '13665', | ||
'w': 300, | ||
'h': 250, | ||
'dealId': 'dee_12312stdszzsx' | ||
}], | ||
'seat': '10000' | ||
}], | ||
'bidid': '0b08b09f-aaa1-4c14-b1c8-7debb1a7c1cd' | ||
} | ||
} | ||
}); | ||
|
||
describe('validations', function () { | ||
it('validBid : tagId is passed', function () { | ||
let bid = { | ||
bidder: 'deepintent', | ||
params: { | ||
tagId: '1232' | ||
} | ||
}, | ||
isValid = spec.isBidRequestValid(bid); | ||
expect(isValid).to.equals(true); | ||
}); | ||
it('invalidBid : tagId is not passed', function () { | ||
let bid = { | ||
bidder: 'deepintent', | ||
params: { | ||
h: 200, | ||
w: 300 | ||
} | ||
}, | ||
isValid = spec.isBidRequestValid(bid); | ||
expect(isValid).to.equals(false); | ||
}); | ||
it('invalidBid : tagId is not a string', function () { | ||
let bid = { | ||
bidder: 'deepintent', | ||
params: { | ||
tagId: 12345 | ||
} | ||
}, | ||
isValid = spec.isBidRequestValid(bid); | ||
expect(isValid).to.equals(false); | ||
}); | ||
}); | ||
describe('request check', function () { | ||
it('unmutaable bid request check', function () { | ||
let oRequest = utils.deepClone(request), | ||
bidRequest = spec.buildRequests(request); | ||
expect(request).to.deep.equal(oRequest); | ||
}); | ||
it('bidder connection check', function () { | ||
let bRequest = spec.buildRequests(request); | ||
expect(bRequest.url).to.equal('https://prebid.deepintent.com/prebid'); | ||
expect(bRequest.method).to.equal('POST'); | ||
expect(bRequest.options.contentType).to.equal('application/json'); | ||
}); | ||
it('bid request check : Device', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
expect(data.device.ua).to.be.a('string'); | ||
expect(data.device.js).to.equal(1); | ||
expect(data.device.dnt).to.be.a('number'); | ||
expect(data.device.h).to.be.a('number'); | ||
expect(data.device.w).to.be.a('number'); | ||
}); | ||
it('bid request check : Impression', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
expect(data.at).to.equal(1); // auction type | ||
expect(data.imp[0].id).to.equal(request[0].bidId); | ||
expect(data.imp[0].tagid).to.equal('100013'); | ||
}); | ||
it('bid request check : ad size', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
expect(data.imp[0].banner).to.be.a('object'); | ||
expect(data.imp[0].banner.w).to.equal(300); | ||
expect(data.imp[0].banner.h).to.equal(250); | ||
}); | ||
it('bid request check : custom params', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
expect(data.imp[0].ext).to.be.a('object'); | ||
expect(data.imp[0].ext.user_gender).to.equal('female'); | ||
expect(data.imp[0].ext.user_max_age).to.equal(25); | ||
}); | ||
it('bid request check: source params', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
expect(data.source.fd).to.equal(0); | ||
expect(data.source.ext.type).to.equal(2); | ||
}) | ||
}); | ||
describe('user sync check', function () { | ||
it('user sync url check', function () { | ||
let syncOptions = { | ||
iframeEnabled: true | ||
}; | ||
let userSync = spec.getUserSyncs(syncOptions); | ||
expect(userSync).to.be.an('array').with.length.above(0); | ||
expect(userSync[0].type).to.equal('iframe'); | ||
expect(userSync[0].url).to.equal('https://beacon.deepintent.com/usersync.html'); | ||
}); | ||
}); | ||
describe('response check', function () { | ||
it('bid response check: valid bid response', function () { | ||
let bRequest = spec.buildRequests(request); | ||
let data = JSON.parse(bRequest.data); | ||
let bResponse = spec.interpretResponse(bannerResponse, request); | ||
expect(bResponse).to.be.an('array').with.length.above(0); | ||
expect(bResponse[0].requestId).to.equal(bannerResponse.body.seatbid[0].bid[0].impid); | ||
expect(bResponse[0].width).to.equal(bannerResponse.body.seatbid[0].bid[0].w); | ||
expect(bResponse[0].height).to.equal(bannerResponse.body.seatbid[0].bid[0].h); | ||
expect(bResponse[0].currency).to.equal('USD'); | ||
expect(bResponse[0].netRevenue).to.equal(false); | ||
expect(bResponse[0].ttl).to.equal(300); | ||
expect(bResponse[0].creativeId).to.equal(bannerResponse.body.seatbid[0].bid[0].crid); | ||
expect(bResponse[0].dealId).to.equal(bannerResponse.body.seatbid[0].bid[0].dealId); | ||
}); | ||
}) | ||
}); |