diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index e8a98721e0c..8fe09ab74e6 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -3,18 +3,53 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; const BIDDER_CODE = 'medianet'; -const BID_URL = 'https://prebid.media.net/rtb/prebid'; +const BID_URL = '//prebid.media.net/rtb/prebid'; $$PREBID_GLOBAL$$.medianetGlobals = {}; function siteDetails(site) { site = site || {}; - - return { + let siteData = { domain: site.domain || utils.getTopWindowLocation().host, page: site.page || utils.getTopWindowUrl(), ref: site.ref || utils.getTopWindowReferrer() - } + }; + + return Object.assign(siteData, getPageMeta()); +} + +function getPageMeta() { + let canonicalUrl = getUrlFromSelector('link[rel="canonical"]', 'href'); + let ogUrl = getUrlFromSelector('meta[property="og:url"]', 'content'); + let twitterUrl = getUrlFromSelector('meta[name="twitter:url"]', 'content'); + + return Object.assign({}, + canonicalUrl && { 'canonical_url': canonicalUrl }, + ogUrl && { 'og_url': ogUrl }, + twitterUrl && { 'twitter_url': twitterUrl } + ); +} + +function getUrlFromSelector(selector, attribute) { + let attr = getAttributeFromSelector(selector, attribute); + return attr && getAbsoluteUrl(attr); +} + +function getAttributeFromSelector(selector, attribute) { + try { + let doc = utils.getWindowTop().document; + let element = doc.querySelector(selector); + if (element !== null && element[attribute]) { + return element[attribute]; + } + } catch (e) {} +} + +function getAbsoluteUrl(url) { + let aTag = utils.getWindowTop().document.createElement('a'); + aTag.href = url; + + return aTag.href; } function filterUrlsByType(urls, type) { @@ -65,13 +100,13 @@ function slotParams(bidRequest) { return params; } -function generatePayload(bidRequests) { +function generatePayload(bidRequests, timeout) { return { site: siteDetails(bidRequests[0].params.site), ext: configuredParams(bidRequests[0].params), id: bidRequests[0].auctionId, imp: bidRequests.map(request => slotParams(request)), - tmax: config.getConfig('bidderTimeout') + tmax: timeout } } @@ -120,8 +155,9 @@ export const spec = { * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(bidRequests) { - let payload = generatePayload(bidRequests); + buildRequests: function(bidRequests, auctionData) { + let timeout = auctionData.timeout || config.getConfig('bidderTimeout'); + let payload = generatePayload(bidRequests, timeout); return { method: 'POST', diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 36868e7f993..520ec34fc7d 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -69,6 +69,9 @@ let VALID_BID_REQUEST = [{ 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' }], + VALID_AUCTIONDATA = { + 'timeout': config.getConfig('bidderTimeout'), + }, VALID_PAYLOAD_INVALID_BIDFLOOR = { 'site': { 'page': 'http://media.net/prebidtest', @@ -166,6 +169,18 @@ let VALID_BID_REQUEST = [{ }], 'tmax': config.getConfig('bidderTimeout') }, + VALID_PAYLOAD_PAGE_META = (() => { + let PAGE_META; + try { + PAGE_META = JSON.parse(JSON.stringify(VALID_PAYLOAD)); + } catch (e) {} + PAGE_META.site = Object.assign(PAGE_META.site, { + 'canonical_url': 'http://localhost:9999/canonical-test', + 'twitter_url': 'http://localhost:9999/twitter-test', + 'og_url': 'http://localhost:9999/fb-test' + }); + return PAGE_META; + })(), VALID_PARAMS = { bidder: 'medianet', params: { @@ -343,19 +358,37 @@ describe('Media.net bid adapter', () => { describe('buildRequests', () => { it('should build valid payload on bid', () => { - let requestObj = spec.buildRequests(VALID_BID_REQUEST); + let requestObj = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); }); it('should accept size as a one dimensional array', () => { - let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY); + let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); }); it('should ignore bidfloor if not a valid number', () => { - let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR); + let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); + describe('build requests: when page meta-data is available', () => { + it('should pass canonical, twitter and fb paramters if available', () => { + let sandbox = sinon.sandbox.create(); + let documentStub = sandbox.stub(window.top.document, 'querySelector'); + documentStub.withArgs('link[rel="canonical"]').returns({ + href: 'http://localhost:9999/canonical-test' + }); + documentStub.withArgs('meta[property="og:url"]').returns({ + content: 'http://localhost:9999/fb-test' + }); + documentStub.withArgs('meta[name="twitter:url"]').returns({ + content: 'http://localhost:9999/twitter-test' + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_PAGE_META); + sandbox.restore(); + }); + }); }); describe('getUserSyncs', () => {