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

Mgid RTD Module : add new RTD module #9120

Merged
merged 10 commits into from
Oct 31, 2022
143 changes: 143 additions & 0 deletions integrationExamples/gpt/mgidRtdProvider_example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<!DOCTYPE html>
<html>
<head>
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script>
window.googletag = window.googletag || { cmd: [] };
googletag.cmd.push(function () {
googletag.defineSlot('/46380388/herbeauty_prebid', [[320, 100], [950, 90], [1024, 768], [120, 600], [300, 75], [970, 66], [300, 50], [300, 31], [320, 480], [750, 200], 'fluid', [250, 250], [250, 360], [120, 90], [1, 1], [292, 30], [300, 100], [768, 1024], [88, 31], [200, 200], [300, 600], [300, 1050], [960, 90], [125, 125], [180, 150], [970, 250], [168, 28], [980, 120], [120, 20], [120, 240], [480, 320], [468, 60], [120, 30], [120, 60], [750, 300], [930, 180], [728, 90], [168, 42], [980, 90], [320, 50], [750, 100], [200, 446], [336, 280], [300, 250], [580, 400], [970, 90], [160, 600]], 'div-gpt-ad-1660208650016-0').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
<link rel="icon" type="image/png" href="/favicon.png">
<script src="../../build/dev/prebid.js" async></script>
<script>
var sizes = [
[300, 250]
];
var PREBID_TIMEOUT = 1000;
var FAILSAFE_TIMEOUT = 3000;
var adUnits = [{
code: '/46380388/herbeauty_prebid',
mediaTypes: {
banner: {
sizes: [[320, 100], [950, 90], [1024, 768], [120, 600], [300, 75], [970, 66], [300, 50], [300, 31], [320, 480], [750, 200], [250, 250], [250, 360], [120, 90], [1, 1], [292, 30], [300, 100], [768, 1024], [88, 31], [200, 200], [300, 600], [300, 1050], [960, 90], [125, 125], [180, 150], [970, 250], [168, 28], [980, 120], [120, 20], [120, 240], [480, 320], [468, 60], [120, 30], [120, 60], [750, 300], [930, 180], [728, 90], [168, 42], [980, 90], [320, 50], [750, 100], [200, 446], [336, 280], [300, 250], [580, 400], [970, 90], [160, 600]]
}
},
bids: [{
bidder: 'mgid',
params: {
accountId: '219'
}
}]
}];
// ======== DO NOT EDIT BELOW THIS LINE =========== //
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
pbjs.que.push(function () {
pbjs.setConfig({ priceGranularity: 'high' })
pbjs.setConfig({
debug: true,
realTimeData: {
auctionDelay: 1000,
dataProviders: [{
name: 'mgid',
waitForIt: true,
params: {
clientSiteId: 1
}
}]
},
/*consentManagement: {
gdpr: {
cmpApi: 'iab',
timeout: 8000,
defaultGdprScope: true
}
}*/
// static data for consent management is only for test purpose - with this data we didn't get ads at the auction
/*consentManagement: {
usp: {
cmpApi: 'static',
consentData: {
getUSPData: {
uspString: '1YNY',
}
}
},
gdpr: {
cmpApi: 'static',
consentData: {
getTCData: {
tcString: 'COwK6gaOwK6gaFmAAAENAPCAAAAAAAAAAAAAAAAAAAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
gdprApplies: true,
purpose: {
consents: {
1: true,
2: true,
},
},
vendor: {
consents: {
358: true,
},
}
}
}
}
}*/
});
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: initAdserver,
timeout: PREBID_TIMEOUT,
ortb2: {
site: {
content: {
language: 'en',
}
}
}
});
});

function initAdserver() {
if (pbjs.initAdserverSet) return;
pbjs.initAdserverSet = true;
googletag.cmd.push(function () {
pbjs.setTargetingForGPTAsync && pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
}

// in case PBJS doesn't load
setTimeout(function () {
initAdserver();
}, FAILSAFE_TIMEOUT);

</script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>

<h2>Basic Prebid.js Example</h2>
<h5>Div-1</h5>

<div id='div-gpt-ad-1660208650016-0' style='min-width: 88px; min-height: 20px;'>
<script>
googletag.cmd.push(function () {
googletag.display('div-gpt-ad-1660208650016-0');
});
</script>
</div>

</body>
</html>
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"iasRtdProvider",
"jwplayerRtdProvider",
"medianetRtdProvider",
"mgidRtdProvider",
"oneKeyRtdProvider",
"optimeraRtdProvider",
"permutiveRtdProvider",
Expand Down
190 changes: 190 additions & 0 deletions modules/mgidRtdProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { submodule } from '../src/hook.js';
import {ajax} from '../src/ajax.js';
import {deepAccess, logError, logInfo, mergeDeep} from '../src/utils.js';
import {getStorageManager} from '../src/storageManager.js';
import {getRefererInfo} from '../src/refererDetection.js';

const MODULE_NAME = 'realTimeData';
const SUBMODULE_NAME = 'mgid';
const MGID_RTD_API_URL = 'https://servicer.mgid.com/sda';
const MGUID_LOCAL_STORAGE_KEY = 'mguid';
const ORTB2_NAME = 'www.mgid.com'

const GVLID = 358;
/** @type {?Object} */
export const storage = getStorageManager({
gvlid: GVLID,
moduleName: SUBMODULE_NAME
});

function init(moduleConfig) {
if (!moduleConfig?.params?.clientSiteId) {
logError('Mgid clientSiteId is not set!');
return false;
}
return true;
}

function getBidRequestData(reqBidsConfigObj, onDone, moduleConfig, userConsent) {
let mguid;
try {
mguid = storage.getDataFromLocalStorage(MGUID_LOCAL_STORAGE_KEY);
} catch (e) {
logInfo(`Can't get mguid from localstorage`);
}

const params = [
{
name: 'gdprApplies',
data: typeof userConsent?.gdpr?.gdprApplies !== 'undefined' ? userConsent?.gdpr?.gdprApplies + '' : undefined,
},
{
name: 'consentData',
data: userConsent?.gdpr?.consentString,
},
{
name: 'uspString',
data: userConsent?.usp,
},
{
name: 'cxurl',
data: encodeURIComponent(getContextUrl()),
},
{
name: 'muid',
data: mguid,
},
{
name: 'clientSiteId',
data: moduleConfig?.params?.clientSiteId,
},
{
name: 'cxlang',
data: deepAccess(reqBidsConfigObj.ortb2Fragments.global, 'site.content.language'),
},
];

const url = MGID_RTD_API_URL + '?' + params.filter((p) => p.data).map((p) => p.name + '=' + p.data).join('&');

let isDone = false;

ajax(url, {
success: (response, req) => {
if (req.status === 200) {
try {
const data = JSON.parse(response);
const ortb2 = reqBidsConfigObj?.ortb2Fragments?.global || {};

mergeDeep(ortb2, getDataForMerge(data));

if (data?.muid) {
try {
mguid = storage.setDataInLocalStorage(MGUID_LOCAL_STORAGE_KEY, data.muid);
} catch (e) {
logInfo(`Can't set mguid to localstorage`);
}
}

onDone();
isDone = true;
} catch (e) {
onDone();
isDone = true;

logError('Unable to parse Mgid RTD data', e);
}
} else {
onDone();
isDone = true;

logError('Mgid RTD wrong response status');
}
},
error: () => {
onDone();
isDone = true;

logError('Unable to get Mgid RTD data');
}
},
null, {
method: 'GET',
withCredentials: false,
});

setTimeout(function () {
if (!isDone) {
onDone();
logInfo('Mgid RTD timeout');
isDone = true;
}
}, moduleConfig.params.timeout || 1000);
}

function getContextUrl() {
const refererInfo = getRefererInfo();

let resultUrl = refererInfo.canonicalUrl || refererInfo.topmostLocation;

const metaElements = document.getElementsByTagName('meta');
for (let i = 0; i < metaElements.length; i++) {
if (metaElements[i].getAttribute('property') === 'og:url') {
resultUrl = metaElements[i].content;
}
}

return resultUrl;
}

function getDataForMerge(responseData) {
let siteData = {
name: ORTB2_NAME
};
let userData = {
name: ORTB2_NAME
};

if (responseData.siteSegments) {
siteData.segment = responseData.siteSegments.map((segmentId) => ({ id: segmentId }));
}
if (responseData.siteSegtax) {
siteData.ext = {
segtax: responseData.siteSegtax
}
}

if (responseData.userSegments) {
userData.segment = responseData.userSegments.map((segmentId) => ({ id: segmentId }));
}
if (responseData.userSegtax) {
userData.ext = {
segtax: responseData.userSegtax
}
}

let result = {};
if (siteData.segment || siteData.ext) {
result.site = {
content: {
data: [siteData],
}
}
}

if (userData.segment || userData.ext) {
result.user = {
data: [userData],
}
}

return result;
}

/** @type {RtdSubmodule} */
export const mgidSubmodule = {
name: SUBMODULE_NAME,
init: init,
getBidRequestData: getBidRequestData,
};

submodule(MODULE_NAME, mgidSubmodule);
51 changes: 51 additions & 0 deletions modules/mgidRtdProvider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Overview

```
Module Name: Mgid RTD Provider
Module Type: RTD Provider
Maintainer: prebid@mgid.com
```

# Description

Mgid RTD module allows you to enrich bid data with contextual and audience signals, based on IAB taxonomies.

## Configuration

This module is configured as part of the `realTimeData.dataProviders` object.

{: .table .table-bordered .table-striped }
| Name | Scope | Description | Example | Type |
|------------|----------|----------------------------------------|---------------|----------|
| `name ` | required | Real time data module name | `'mgid'` | `string` |
| `params` | required | | | `Object` |
| `params.clientSiteId` | required | The client site id provided by Mgid. | `'123456'` | `string` |
| `params.timeout` | optional | Maximum amount of milliseconds allowed for module to finish working | `1000` | `number` |

#### Example

```javascript
pbjs.setConfig({
realTimeData: {
dataProviders: [{
name: 'mgid',
params: {
clientSiteId: '123456'
}
}]
}
});
```

## Integration
To install the module, follow these instructions:

#### Step 1: Prepare the base Prebid file

- Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Mgid Realtime Module* module

- Option 2: From the command line, run `gulp build --modules=mgidRtdProvider,...`

#### Step 2: Set configuration

Enable Mgid Real Time Module using `pbjs.setConfig`. Example is provided in Configuration section.
Loading