Skip to content
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

Mass Module: add module to support MASS protocol #6332

Merged
merged 25 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
def532d
Initial implementation for the MASS module
cciocov Dec 11, 2020
7544628
Updated namespace and CDN location
cciocov Dec 23, 2020
d57c9ae
Updated the data object passed to MASS bootloader
cciocov Dec 23, 2020
255216d
Fix linting issues
cciocov Jan 9, 2021
4d03e3e
Added unit tests
cciocov Jan 9, 2021
23f2d54
Added a README for the MASS module.
cciocov Jan 11, 2021
b419408
Allow MASS be disabled via Prebid configuration
cciocov Jan 21, 2021
76181e0
Only check deal ID for matching MASS bids
cciocov Feb 16, 2021
cbd8d06
Updated docs
cciocov Feb 18, 2021
8cd13f2
Update how we test for MASS bids
cciocov Feb 19, 2021
821baa9
Thighten the test for MASS bids
cciocov Feb 19, 2021
ccaf65f
Fix linting issues
cciocov Feb 20, 2021
03e7246
Change deal ID prefix and add option to specify the bootloader locati…
cciocov Feb 25, 2021
daeac99
Updated tests with the new META_MASS deal ID prefix
cciocov Feb 25, 2021
1b6ecdd
Update comment in modules/mass.js
cciocov Mar 2, 2021
645379b
Additional information about the module
massadmin Mar 3, 2021
01207e9
More specific description of external resource
massadmin Mar 3, 2021
72e202d
Identify MASS bids by looking for a 'mass' flag in bid meta or testin…
cciocov Mar 5, 2021
89b44d0
Updated MASS module tests
cciocov Mar 5, 2021
5115b4e
Bug fixing, added integration example and increased test coverage
cciocov Mar 13, 2021
05ba36b
Fix integration example and add notice
cciocov Mar 16, 2021
10b9fb0
Updated example page
cciocov Mar 17, 2021
2d7add2
Updated bootloaderUrl param name to renderUrl and removed its default…
cciocov Mar 18, 2021
2aad196
Updated integration example for MASS
cciocov Mar 18, 2021
7a0177f
Update mass.md
massadmin Mar 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]
}
}]
FilipStamenkovic marked this conversation as resolved.
Show resolved Hide resolved
}];

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
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you set even the defaults you have here on endpoint and deal pattern so that it serves as an example of how to change them

});
});
</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