From 884e7fc3d358c95b934e6de828c4fed84fef501f Mon Sep 17 00:00:00 2001 From: Paris Holley Date: Mon, 20 Jul 2020 04:08:55 -0400 Subject: [PATCH] mantis privacy support, removed unsupported media types (#5494) * mantis privacy support, removed unsupported media types * code coverage * lint fix --- modules/mantisBidAdapter.js | 97 +++++++++++----------- test/spec/modules/mantisBidAdapter_spec.js | 92 ++++++++++++++++++++ 2 files changed, 140 insertions(+), 49 deletions(-) diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js index 19e70a3e68b..960fbe27c73 100644 --- a/modules/mantisBidAdapter.js +++ b/modules/mantisBidAdapter.js @@ -16,15 +16,7 @@ function pixel(url, parent) { img.style.cssText = 'display:none !important;'; (parent || document.body).appendChild(img); } -function isDesktop(ignoreTouch) { - var supportsTouch = !ignoreTouch && ('ontouchstart' in window || navigator.msMaxTouchPoints); - if (inIframe()) { - return !supportsTouch; - } - var width = window.innerWidth || window.document.documentElement.clientWidth || window.document.body.clientWidth; - return !supportsTouch && (!width || width >= (window.mantis_breakpoint || 768)); -} -function onVisible(element, doOnVisible, time, pct) { +export function onVisible(win, element, doOnVisible, time, pct) { var started = null; var notified = false; var onNotVisible = null; @@ -78,15 +70,15 @@ function onVisible(element, doOnVisible, time, pct) { }); }; if (isAmp()) { - listener = window.context.observeIntersection(function (changes) { + listener = win.context.observeIntersection(function (changes) { changes.forEach(function (change) { doCheck(change.rootBounds.width, change.rootBounds.height, change.boundingClientRect); }); }); } interval = setInterval(function () { - var winHeight = (window.innerHeight || document.documentElement.clientHeight); - var winWidth = (window.innerWidth || document.documentElement.clientWidth); + var winHeight = (win.innerHeight || document.documentElement.clientHeight); + var winWidth = (win.innerWidth || document.documentElement.clientWidth); doCheck(winWidth, winHeight, element.getBoundingClientRect()); }, 100); } @@ -136,9 +128,6 @@ function isArray(value) { } function jsonToQuery(data, chain, form) { - if (!data) { - return null; - } var parts = form || []; for (var key in data) { var queryKey = key; @@ -152,8 +141,6 @@ function jsonToQuery(data, chain, form) { var aval = val[index]; if (isObject(aval)) { jsonToQuery(aval, akey, parts); - } else if (isSendable(aval)) { - parts.push(akey + '=' + encodeURIComponent(aval)); } } } else if (isObject(val) && val != data) { @@ -173,9 +160,7 @@ function buildMantisUrl(path, data, domain) { secure: isSecure(), version: 9 }; - if (!inIframe() || isAmp()) { - params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; - } + if (window.mantis_uuid) { params.uuid = window.mantis_uuid; } else if (storage.hasLocalStorage()) { @@ -206,20 +191,20 @@ function buildMantisUrl(path, data, domain) { params.referrer = window.context.referrer; } } - Object.keys(data || {}).forEach(function (key) { + Object.keys(data).forEach(function (key) { params[key] = data[key]; }); var query = jsonToQuery(params); return (window.mantis_domain === undefined ? domain || 'https://mantodea.mantisadnetwork.com' : window.mantis_domain) + path + '?' + query; } -const spec = { +export const spec = { code: 'mantis', - supportedMediaTypes: ['banner', 'video', 'native'], + supportedMediaTypes: ['banner'], isBidRequestValid: function (bid) { return !!(bid.params.property && (bid.params.code || bid.params.zoneId || bid.params.zone)); }, - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { var property = null; validBidRequests.some(function (bid) { if (bid.params.property) { @@ -229,6 +214,7 @@ const spec = { }); const query = { measurable: true, + usp: bidderRequest && bidderRequest.uspConsent, bids: validBidRequests.map(function (bid) { return { bidId: bid.bidId, @@ -240,6 +226,12 @@ const spec = { }), property: property }; + + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + // we purposefully do not track data for users in the EU + query.consent = false; + } + return { method: 'GET', url: buildMantisUrl('/prebid/display', query) + '&foo', @@ -262,47 +254,54 @@ const spec = { }; }); }, - getUserSyncs: function (syncOptions) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: buildMantisUrl('/prebid/iframe') + url: buildMantisUrl('/prebid/iframe', {gdpr: gdprConsent, uspConsent: uspConsent}) }]; } if (syncOptions.pixelEnabled) { return [{ type: 'image', - url: buildMantisUrl('/prebid/pixel') + url: buildMantisUrl('/prebid/pixel', {gdpr: gdprConsent, uspConsent: uspConsent}) }]; } } }; + +export function sfPostMessage ($sf, width, height, callback) { + var viewed = false; + // eslint-disable-next-line no-undef + $sf.ext.register(width, height, function () { + // eslint-disable-next-line no-undef + if ($sf.ext.inViewPercentage() < 50 || viewed) { + return; + } + viewed = true; + callback(); + }); +}; + +export function iframePostMessage (win, name, callback) { + var frames = document.getElementsByTagName('iframe'); + for (var i = 0; i < frames.length; i++) { + var frame = frames[i]; + if (frame.name == name) { + onVisible(win, frame, function (stop) { + callback(); + stop(); + }, 1000, 0.50); + } + } +} + onMessage('iframe', function (data) { if (window.$sf) { - var viewed = false; - // eslint-disable-next-line no-undef - $sf.ext.register(data.width, data.height, function () { - // eslint-disable-next-line no-undef - if ($sf.ext.inViewPercentage() < 50 || viewed) { - return; - } - viewed = true; - pixel(data.pixel); - }); + sfPostMessage(window.$sf, data.width, data.height, () => pixel(data.pixel)); } else { - var frames = document.getElementsByTagName('iframe'); - for (var i = 0; i < frames.length; i++) { - var frame = frames[i]; - if (frame.name == data.frame) { - onVisible(frame, function (stop) { - pixel(data.pixel); - stop(); - }, 1000, 0.50); - } - } + iframePostMessage(window, data.frame, () => pixel(data.pixel)); } }); -export { spec }; - registerBidder(spec); diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js index 1dad60f5d98..d9ab3c69a24 100644 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -1,9 +1,21 @@ import {expect} from 'chai'; import {spec} from 'modules/mantisBidAdapter.js'; import {newBidder} from 'src/adapters/bidderFactory.js'; +import {sfPostMessage, iframePostMessage} from 'modules/mantisBidAdapter'; describe('MantisAdapter', function () { const adapter = newBidder(spec); + let sandbox; + let clock; + + beforeEach(function() { + sandbox = sinon.sandbox.create(); + clock = sandbox.useFakeTimers(); + }); + + afterEach(function() { + sandbox.restore(); + }); describe('isBidRequestValid', function () { let bid = { @@ -31,6 +43,68 @@ describe('MantisAdapter', function () { }); }); + describe('viewability', function() { + it('iframe (viewed)', () => { + let viewed = false; + + sandbox.stub(document, 'getElementsByTagName').withArgs('iframe').returns([ + { + name: 'mantis', + getBoundingClientRect: () => ({ + top: 10, + bottom: 260, + left: 10, + right: 190, + width: 300, + height: 250 + }) + } + ]); + + iframePostMessage({innerHeight: 500, innerWidth: 500}, 'mantis', () => viewed = true); + + sandbox.clock.runAll(); + + expect(viewed).to.equal(true); + }); + + it('safeframe (viewed)', () => { + let viewed = false; + + sfPostMessage({ + ext: { + register: (width, height, callback) => { + expect(width).to.equal(100); + expect(height).to.equal(200); + + callback(); + }, + inViewPercentage: () => 60 + } + }, 100, 200, () => viewed = true); + + expect(viewed).to.equal(true); + }); + + it('safeframe (unviewed)', () => { + let viewed = false; + + sfPostMessage({ + ext: { + register: (width, height, callback) => { + expect(width).to.equal(100); + expect(height).to.equal(200); + + callback(); + }, + inViewPercentage: () => 30 + } + }, 100, 200, () => viewed = true); + + expect(viewed).to.equal(false); + }); + }); + describe('buildRequests', function () { let bidRequests = [ { @@ -47,6 +121,24 @@ describe('MantisAdapter', function () { } ]; + it('gdpr consent not required', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {gdprApplies: false}}); + + expect(request.url).not.to.include('consent=false'); + }); + + it('gdpr consent required', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {gdprApplies: true}}); + + expect(request.url).to.include('consent=false'); + }); + + it('usp consent', function () { + const request = spec.buildRequests(bidRequests, {uspConsent: 'foobar'}); + + expect(request.url).to.include('usp=foobar'); + }); + it('domain override', function () { window.mantis_domain = 'https://foo'; const request = spec.buildRequests(bidRequests);