-
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.
Mass Module: add module to support MASS protocol (#6332)
* Initial implementation for the MASS module * Updated namespace and CDN location * Updated the data object passed to MASS bootloader * Fix linting issues * Added unit tests * Added a README for the MASS module. * Allow MASS be disabled via Prebid configuration * Only check deal ID for matching MASS bids * Updated docs * Update how we test for MASS bids * Thighten the test for MASS bids * Fix linting issues * Change deal ID prefix and add option to specify the bootloader location. Updates to docs. * Updated tests with the new META_MASS deal ID prefix * Update comment in modules/mass.js Co-authored-by: Scott Menzer <[email protected]> * Additional information about the module * More specific description of external resource * Identify MASS bids by looking for a 'mass' flag in bid meta or testing deal IDs against a publisher defined pattern * Updated MASS module tests * Bug fixing, added integration example and increased test coverage * Fix integration example and add notice * Updated example page * Updated bootloaderUrl param name to renderUrl and removed its default value. Must be specfied in module config now. * Updated integration example for MASS * Update mass.md Updated disclaimer and synced with docs Co-authored-by: Scott Menzer <[email protected]> Co-authored-by: massadmin <[email protected]>
- Loading branch information
1 parent
cd6f1a8
commit 92c9f67
Showing
4 changed files
with
432 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,110 @@ | ||
<html> | ||
<head> | ||
<script> | ||
window.massConfig = { | ||
inskin: { | ||
default: { | ||
plr_PubfileId: '000000/mass' | ||
} | ||
} | ||
}; | ||
|
||
var PREBID_TIMEOUT = 3300; | ||
|
||
var adUnits = [{ | ||
code: 'div-gpt-ad-1460505748561-0', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250], [300, 600]], | ||
} | ||
}, | ||
bids: [{ | ||
bidder: 'ix', | ||
params: { | ||
siteId: '123456', | ||
size: [300, 250] | ||
} | ||
}] | ||
}]; | ||
|
||
var pbjs = pbjs || {}; | ||
pbjs.que = pbjs.que || []; | ||
</script> | ||
|
||
<script> | ||
pbjs.que.push(function() { | ||
pbjs.setConfig({ | ||
mass: { | ||
enabled: true, | ||
renderUrl: 'https://cdn.massplatform.net/bootloader.js', | ||
dealIdPattern: /^MASS/i | ||
} | ||
}); | ||
}); | ||
</script> | ||
|
||
<script type="text/javascript" src="/build/dev/prebid.js" async></script> | ||
<script> | ||
var googletag = googletag || {}; | ||
googletag.cmd = googletag.cmd || []; | ||
googletag.cmd.push(function() { | ||
googletag.pubads().disableInitialLoad(); | ||
}); | ||
|
||
pbjs.que.push(function() { | ||
pbjs.addAdUnits(adUnits); | ||
pbjs.requestBids({ | ||
bidsBackHandler: sendAdserverRequest | ||
}); | ||
}); | ||
|
||
function sendAdserverRequest() { | ||
if (pbjs.adserverRequestSent) return; | ||
pbjs.adserverRequestSent = true; | ||
googletag.cmd.push(function() { | ||
pbjs.que.push(function() { | ||
pbjs.setTargetingForGPTAsync(); | ||
googletag.pubads().refresh(); | ||
}); | ||
}); | ||
} | ||
|
||
setTimeout(function() { | ||
sendAdserverRequest(); | ||
}, PREBID_TIMEOUT); | ||
</script> | ||
|
||
<script> | ||
(function () { | ||
var gads = document.createElement('script'); | ||
gads.async = true; | ||
gads.type = 'text/javascript'; | ||
var useSSL = 'https:' == document.location.protocol; | ||
gads.src = (useSSL ? 'https:' : 'http:') + | ||
'//securepubads.g.doubleclick.net/tag/js/gpt.js'; | ||
var node = document.getElementsByTagName('script')[0]; | ||
node.parentNode.insertBefore(gads, node); | ||
})(); | ||
</script> | ||
|
||
<script> | ||
googletag.cmd.push(function () { | ||
googletag.defineSlot('/19968336/header-bid-tag-0', [[300, 250], [300, 600]], 'div-gpt-ad-1460505748561-0').addService(googletag.pubads()); | ||
|
||
googletag.pubads().enableSingleRequest(); | ||
googletag.enableServices(); | ||
}); | ||
</script> | ||
</head> | ||
|
||
<body style="margin: 0;"> | ||
<div id="content" style="width: 920px; padding: 20px; height: 2500px; margin: 0 auto; background-color: #222; color: #fff;"> | ||
<p>Note: for this example to work, you need access to a bid simulation tool from your MASS enabled Exchange partner.</p> | ||
<div id="div-gpt-ad-1460505748561-0"> | ||
<script type="text/javascript"> | ||
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1460505748561-0'); }); | ||
</script> | ||
</div> | ||
</div> | ||
</body> | ||
</html> |
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,129 @@ | ||
/** | ||
* This module adds MASS support to Prebid.js. | ||
*/ | ||
|
||
import { config } from '../src/config.js'; | ||
import { getHook } from '../src/hook.js'; | ||
import find from 'core-js-pure/features/array/find.js'; | ||
|
||
export let listenerAdded = false; | ||
export let massEnabled = false; | ||
|
||
const defaultCfg = { | ||
dealIdPattern: /^MASS/i | ||
}; | ||
let cfg; | ||
|
||
const massBids = {}; | ||
|
||
init(); | ||
config.getConfig('mass', config => init(config.mass)); | ||
|
||
/** | ||
* Module init. | ||
*/ | ||
export function init(customCfg) { | ||
cfg = Object.assign({}, defaultCfg, customCfg); | ||
|
||
if (cfg.enabled === false) { | ||
if (massEnabled) { | ||
massEnabled = false; | ||
getHook('addBidResponse').getHooks({hook: addBidResponseHook}).remove(); | ||
} | ||
} else { | ||
if (!massEnabled) { | ||
getHook('addBidResponse').before(addBidResponseHook); | ||
massEnabled = true; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Before hook for 'addBidResponse'. | ||
*/ | ||
export function addBidResponseHook(next, adUnitCode, bid) { | ||
if (!isMassBid(bid) || !cfg.renderUrl) { | ||
return next(adUnitCode, bid); | ||
} | ||
|
||
const bidRequest = find(this.bidderRequest.bids, bidRequest => | ||
bidRequest.bidId === bid.requestId | ||
); | ||
|
||
massBids[bid.requestId] = { | ||
bidRequest, | ||
bid, | ||
adm: bid.ad | ||
}; | ||
|
||
bid.ad = '<script>window.parent.postMessage({massBidId: "' + bid.requestId + '"}, "*");\x3c/script>'; | ||
|
||
addListenerOnce(); | ||
|
||
next(adUnitCode, bid); | ||
} | ||
|
||
/** | ||
* Check if a bid is MASS. | ||
*/ | ||
export function isMassBid(bid) { | ||
// either bid.meta.mass is set or deal ID matches a publisher specified pattern: | ||
if (!((bid.meta && bid.meta.mass) || (cfg.dealIdPattern && cfg.dealIdPattern.test(bid.dealId)))) { | ||
return false; | ||
} | ||
|
||
// there must be a 'mass://' or 'pcreative?' in the ad markup: | ||
return /mass:\/\/|\/pcreative\?/i.test(bid.ad); | ||
} | ||
|
||
/** | ||
* Add listener to detect requests to render MASS ads. | ||
*/ | ||
export function addListenerOnce() { | ||
if (!listenerAdded) { | ||
window.addEventListener('message', e => { | ||
if (e && e.data && e.data.massBidId) { | ||
render(getRenderPayload(e)); | ||
} | ||
}); | ||
|
||
listenerAdded = true; | ||
} | ||
} | ||
|
||
/** | ||
* Prepare payload for render. | ||
*/ | ||
export function getRenderPayload(e) { | ||
const payload = { | ||
type: 'prebid', | ||
e | ||
}; | ||
|
||
Object.assign(payload, massBids[e.data.massBidId]); | ||
delete payload.bid.ad; | ||
|
||
return payload; | ||
} | ||
|
||
/** | ||
* Render a MASS ad. | ||
*/ | ||
export function render(payload) { | ||
const ns = window.mass = window.mass || {}; | ||
|
||
ns.bootloader = ns.bootloader || {queue: []}; | ||
ns.bootloader.queue.push(payload); | ||
|
||
if (!ns.bootloader.loaded) { | ||
const s = document.createElement('script'); | ||
s.type = 'text/javascript'; | ||
s.async = true; | ||
s.src = cfg.renderUrl; | ||
|
||
const x = document.getElementsByTagName('script')[0]; | ||
x.parentNode.insertBefore(s, x); | ||
|
||
ns.bootloader.loaded = 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,63 @@ | ||
## Overview | ||
|
||
``` | ||
Module Name: MASS | ||
Module Type: Other | ||
Maintainer: [email protected] | ||
``` | ||
|
||
This module enables the MASS protocol for Prebid. To use it, you'll need to | ||
work with a MASS enabled provider. | ||
|
||
This module scans incoming bids for the presence of a "mass" flag being set to | ||
true in the bid meta or a publisher specified DealID pattern and uses | ||
external resources to decypher and process the MASS:// URI found within the ad markup. | ||
This modules is designed to work with MASS enabled Exchanges and DSP's. | ||
|
||
This module only loads external JavaScript resources if the publisher ad server has | ||
selected a MASS enabled bid as a winner. | ||
|
||
Find out more [here](https://massplatform.net). | ||
|
||
## Disclosure | ||
|
||
- This module loads external JavaScript to render creatives | ||
|
||
## Generic Mode | ||
- You can specify your our own renderUrl using the module configuration option. When specifying a custom renderer, quality assurance is your responsibility. | ||
|
||
## Integration | ||
|
||
Build the MASS module into the Prebid.js package with: | ||
|
||
``` | ||
gulp build --modules=mass,... | ||
``` | ||
|
||
## Module Configuration | ||
|
||
```js | ||
pbjs.que.push(function() { | ||
pbjs.setConfig({ | ||
mass: { | ||
enabled: true, | ||
renderUrl: 'https://cdn.massplatform.net/bootloader.js', | ||
dealIdPattern: /^MASS/i | ||
} | ||
}); | ||
}); | ||
``` | ||
|
||
## Disable MASS | ||
|
||
The MASS module is enabled by default, but you can disable it using: | ||
|
||
```js | ||
pbjs.que.push(function() { | ||
pbjs.setConfig({ | ||
mass: { | ||
enabled: false | ||
} | ||
}); | ||
}); | ||
``` |
Oops, something went wrong.