Skip to content

Commit

Permalink
Mass Module: add module to support MASS protocol (prebid#6332)
Browse files Browse the repository at this point in the history
* 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
3 people authored and stsepelin committed May 28, 2021
1 parent 03ffaa9 commit 3ce9de8
Show file tree
Hide file tree
Showing 4 changed files with 432 additions and 0 deletions.
110 changes: 110 additions & 0 deletions integrationExamples/mass/index.html
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>
129 changes: 129 additions & 0 deletions modules/mass.js
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;
}
}
63 changes: 63 additions & 0 deletions modules/mass.md
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
}
});
});
```
Loading

0 comments on commit 3ce9de8

Please sign in to comment.