-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Viewability #10
Viewability #10
Changes from all commits
91a7caf
4cc1ad8
343c796
0e7ae04
1b5d075
0fd09aa
717ab51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
import { uniques } from 'src/utils'; | ||
import * as utils from 'src/utils'; | ||
|
||
const { registerBidder } = require('../src/adapters/bidderFactory'); | ||
const { config } = require('../src/config'); | ||
|
||
const BIDDER_CODE = '33across'; | ||
const END_POINT = 'https://ssc.33across.com/api/v1/hb'; | ||
const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch&rt=html'; | ||
|
@@ -28,21 +30,28 @@ function _createBidResponse(response) { | |
function _createServerRequest(bidRequest, gdprConsent) { | ||
const ttxRequest = {}; | ||
const params = bidRequest.params; | ||
const element = document.getElementById(bidRequest.adUnitCode); | ||
const sizes = _transformSizes(bidRequest.sizes); | ||
const minSize = _getMinSize(sizes); | ||
|
||
const contributeViewability = ViewabilityContributor( | ||
_getPercentInView(element, window.top, minSize) | ||
); | ||
|
||
/* | ||
* Infer data for the request payload | ||
*/ | ||
ttxRequest.imp = []; | ||
ttxRequest.imp[0] = { | ||
banner: { | ||
format: bidRequest.sizes.map(_getFormatSize) | ||
format: sizes.map(size => Object.assign(size, {ext: {}})) | ||
}, | ||
ext: { | ||
ttx: { | ||
prod: params.productId | ||
} | ||
} | ||
} | ||
}; | ||
ttxRequest.site = { id: params.siteId }; | ||
|
||
// Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and | ||
|
@@ -54,19 +63,18 @@ function _createServerRequest(bidRequest, gdprConsent) { | |
ext: { | ||
consent: gdprConsent.consentString | ||
} | ||
} | ||
}; | ||
ttxRequest.regs = { | ||
ext: { | ||
gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0 | ||
} | ||
} | ||
}; | ||
|
||
// Finally, set the openRTB 'test' param if this is to be a test bid | ||
if (params.test === 1) { | ||
ttxRequest.test = 1; | ||
} | ||
|
||
|
||
/* | ||
* Now construct the full server request | ||
*/ | ||
|
@@ -82,7 +90,7 @@ function _createServerRequest(bidRequest, gdprConsent) { | |
return { | ||
'method': 'POST', | ||
'url': url, | ||
'data': JSON.stringify(ttxRequest), | ||
'data': JSON.stringify(contributeViewability(ttxRequest)), | ||
'options': options | ||
} | ||
} | ||
|
@@ -98,12 +106,111 @@ function _createSync(siteId) { | |
} | ||
} | ||
|
||
function _getFormatSize(sizeArr) { | ||
function _getSize(size) { | ||
return { | ||
w: sizeArr[0], | ||
h: sizeArr[1], | ||
ext: {} | ||
w: parseInt(size[0], 10), | ||
h: parseInt(size[1], 10) | ||
} | ||
} | ||
|
||
function _getMinSize(sizes) { | ||
return sizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min); | ||
} | ||
|
||
function _getBoundingBox(element, { w, h } = {}) { | ||
let { width, height, left, top, right, bottom } = element.getBoundingClientRect(); | ||
|
||
if ((width === 0 || height === 0) && w && h) { | ||
width = w; | ||
height = h; | ||
right = left + w; | ||
bottom = top + h; | ||
} | ||
|
||
return { width, height, left, top, right, bottom }; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate what
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also how do you think we should treat an undefined size? Don't recall how Prebid core treats sizes not being set in the ad unit parameters. If it simply throws errors, should we consider including a check for size in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
function _transformSizes(sizes) { | ||
if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { | ||
return [_getSize(sizes)]; | ||
} | ||
|
||
return sizes.map(_getSize); | ||
} | ||
|
||
function _getIntersectionOfRects(rects) { | ||
const bbox = { | ||
left: rects[0].left, | ||
right: rects[0].right, | ||
top: rects[0].top, | ||
bottom: rects[0].bottom | ||
}; | ||
|
||
for (let i = 1; i < rects.length; ++i) { | ||
bbox.left = Math.max(bbox.left, rects[i].left); | ||
bbox.right = Math.min(bbox.right, rects[i].right); | ||
|
||
if (bbox.left >= bbox.right) { | ||
return null; | ||
} | ||
|
||
bbox.top = Math.max(bbox.top, rects[i].top); | ||
bbox.bottom = Math.min(bbox.bottom, rects[i].bottom); | ||
|
||
if (bbox.top >= bbox.bottom) { | ||
return null; | ||
} | ||
} | ||
|
||
bbox.width = bbox.right - bbox.left; | ||
bbox.height = bbox.bottom - bbox.top; | ||
|
||
return bbox; | ||
} | ||
|
||
function _getPercentInView(element, topWin, { w, h } = {}) { | ||
const elementBoundingBox = _getBoundingBox(element, { w, h }); | ||
|
||
// Obtain the intersection of the element and the viewport | ||
const elementInViewBoundingBox = _getIntersectionOfRects([ { | ||
left: 0, | ||
top: 0, | ||
right: topWin.innerWidth, | ||
bottom: topWin.innerHeight | ||
}, elementBoundingBox ]); | ||
|
||
let elementInViewArea, elementTotalArea; | ||
|
||
if (elementInViewBoundingBox !== null) { | ||
// Some or all of the element is in view | ||
elementInViewArea = elementInViewBoundingBox.width * elementInViewBoundingBox.height; | ||
elementTotalArea = elementBoundingBox.width * elementBoundingBox.height; | ||
|
||
return ((elementInViewArea / elementTotalArea) * 100); | ||
} | ||
|
||
// No overlap between element and the viewport; therefore, the element | ||
// lies completely out of view | ||
return 0; | ||
} | ||
|
||
/** | ||
* Viewability contribution to request.. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting usage of the Contributor Pattern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I see this is the way contributor pattern is implemented in 33xchange which I was using as a reference.
|
||
*/ | ||
function ViewabilityContributor(viewabilityAmount) { | ||
function contributeViewability(ttxRequest) { | ||
const req = Object.assign({}, ttxRequest); | ||
const imp = req.imp = req.imp.map(impItem => Object.assign({}, impItem)); | ||
const banner = imp[0].banner = Object.assign({}, imp[0].banner); | ||
const ext = banner.ext = Object.assign({}, banner.ext); | ||
const ttx = ext.ttx = Object.assign({}, ext.ttx); | ||
|
||
ttx.viewability = { amount: Math.round(viewabilityAmount) }; | ||
|
||
return req; | ||
} | ||
|
||
return contributeViewability; | ||
} | ||
|
||
function isBidRequestValid(bid) { | ||
|
@@ -123,9 +230,9 @@ function isBidRequestValid(bid) { | |
// - the server, at this point, also doesn't need the consent string to handle gdpr compliance. So passing | ||
// value whether set or not, for the sake of future dev. | ||
function buildRequests(bidRequests, bidderRequest) { | ||
const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent) | ||
const gdprConsent = Object.assign({ consentString: undefined, gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); | ||
|
||
adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(uniques); | ||
adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); | ||
|
||
return bidRequests.map((req) => { | ||
return _createServerRequest(req, gdprConsent); | ||
|
@@ -160,7 +267,7 @@ const spec = { | |
buildRequests, | ||
interpretResponse, | ||
getUserSyncs | ||
} | ||
}; | ||
|
||
registerBidder(spec); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you not use
_transformSizes
method here to construct the format sizes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sizes
constant already has transformed sizes. So I just addext: {}
to each of them.