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

Weborama Real-time Data Module: add new RTD module #7437

Merged
merged 18 commits into from
Sep 22, 2021
126 changes: 126 additions & 0 deletions integrationExamples/gpt/weboramaRtdProvider_example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>

<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script src="../../build/dev/prebid.js" async></script>

<script>
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

pbjs.que.push(function() {
pbjs.setConfig({
debug: true,
realTimeData: {
auctionDelay: 1000,
dataProviders: [
{
name: "weborama",
waitForIt: true,
params: {
weboCtxConf: {
setTargeting: true,
token: "to-be-defined",
targetURL: "https://prebid.org/",
defaultProfile: {
webo_ctx: ['moon']
}
}
}
}
]
}
});
});
</script>
<script>
var div_1_sizes = [
[300, 300]
];

var PREBID_TIMEOUT = 3000;
var FAILSAFE_TIMEOUT = 5000;

var adUnits = [
{
code: '/1056029/webo-ctx-prebid',
mediaTypes: {
banner: {
sizes: div_1_sizes
}
},
bids: [{
bidder: 'appnexus',
params: {
placementId: 1
}
}]
}
];

// ======== 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.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: initAdserver,
timeout: PREBID_TIMEOUT
});
});

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


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

googletag.cmd.push(function() {
googletag.defineSlot('/1056029/webo-ctx-prebid', div_1_sizes, 'div-gpt-ad-1620653642627-0').addService(googletag.pubads());
googletag.pubads().disableInitialLoad();
googletag.enableServices();
});

</script>

<article>
<p>
test webo ctx using prebid.js
</p>
</article>
<h2>Basic Prebid.js Example</h2>
<h5>Div-1</h5>
<div id='div-gpt-ad-1620653642627-0' style='width: 300px; height: 300px;'>
<script type='text/javascript'>
googletag.cmd.push(function() {
googletag.display('div-gpt-ad-1620653642627-0');
});
</script>
</div>
<button onclick="googletag.cmd.push(function() { googletag.pubads().refresh(); });">
Show/Refresh Ad
</button>
</body>
</html>
174 changes: 174 additions & 0 deletions modules/weboramaRtdProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* This module adds Weborama provider to the real time data module
* The {@link module:modules/realTimeData} module is required
* The module will fetch contextual data (page-centric) from Weborama server
* @module modules/weboramaRtdProvider
* @requires module:modules/realTimeData
*/

/**
* @typedef {Object} ModuleParams
* @property {WeboCtxConf} weboCtxConf
*/

/**
* @typedef {Object} WeboCtxConf
* @property {string} token required token to be used on bigsea contextual API requests
* @property {?string} targetURL specify the target url instead use the referer
* @property {?boolean} setTargeting if true will set the GAM targeting
* @property {?object} defaultProfile to be used if the profile is not found
*/

import * as utils from '../src/utils.js';
import {submodule} from '../src/hook.js';
import {ajax} from '../src/ajax.js';
import {config} from '../src/config.js';

/** @type {string} */
const MODULE_NAME = 'realTimeData';
/** @type {string} */
const SUBMODULE_NAME = 'weborama';
/** @type {string} */
const WEBO_CTX = 'webo_ctx';
/** @type {string} */
const WEBO_DS = 'webo_ds';

/** @type {null|Object} */
let _bigseaContextualProfile = null;

/** function that provides ad server targeting data to RTD-core
* @param {Array} adUnitsCodes
* @param {Object} moduleConfig
* @returns {Object} target data
*/
function getTargetingData(adUnitsCodes, moduleConfig) {
moduleConfig = moduleConfig || {};
const moduleParams = moduleConfig.params || {};
const weboCtxConf = moduleParams.weboCtxConf || {};
const defaultContextualProfiles = weboCtxConf.defaultProfile || {}
const profile = _bigseaContextualProfile || defaultContextualProfiles;

if (weboCtxConf.setOrtb2) {
const ortb2 = config.getConfig('ortb2') || {};
if (profile[WEBO_CTX]) {
utils.deepSetValue(ortb2, 'site.ext.data.webo_ctx', profile[WEBO_CTX]);
}
if (profile[WEBO_DS]) {
utils.deepSetValue(ortb2, 'site.ext.data.webo_ds', profile[WEBO_DS]);
}
config.setConfig({ortb2: ortb2});
}

if (weboCtxConf.setTargeting === false) {
return {};
}

try {
const formattedProfile = profile;
const r = adUnitsCodes.reduce((rp, adUnitCode) => {
if (adUnitCode) {
rp[adUnitCode] = formattedProfile;
}
return rp;
}, {});
return r;
} catch (e) {
utils.logError('unable to format weborama rtd targeting data', e);
return {};
}
}

/** set bigsea contextual profile on module state
* if the profile is empty, will store the default profile
* @param {null|Object} data
* @returns {void}
*/
export function setBigseaContextualProfile(data) {
if (data && Object.keys(data).length > 0) {
_bigseaContextualProfile = data;
}
}

/** onSuccess callback type
* @callback successCallback
* @param {null|Object} data
* @returns {void}
*/

/** onDone callback type
* @callback doneCallback
* @returns {void}
*/

/** Fetch Bigsea Contextual Profile
* @param {WeboCtxConf} weboCtxConf
* @param {successCallback} onSuccess callback
* @param {doneCallback} onDone callback
* @returns {void}
*/
function fetchContextualProfile(weboCtxConf, onSuccess, onDone) {
const targetURL = weboCtxConf.targetURL || document.URL;
const token = weboCtxConf.token;

let queryString = '';
queryString = utils.tryAppendQueryString(queryString, 'token', token);
queryString = utils.tryAppendQueryString(queryString, 'url', targetURL);

const url = 'https://ctx.weborama.com/api/profile?' + queryString;

ajax(url, {
success: function (response, req) {
if (req.status === 200) {
try {
const data = JSON.parse(response);
onSuccess(data);
onDone();
} catch (e) {
onDone();
utils.logError('unable to parse weborama data', e);
}
} else if (req.status === 204) {
onDone();
}
},
error: function () {
onDone();
utils.logError('unable to get weborama data');
}
},
null,
{
method: 'GET',
withCredentials: false,
});
}

/** Initialize module
* @param {object} moduleConfig
* @return {boolean} true if module was initialized with success
*/
function init(moduleConfig) {
_bigseaContextualProfile = null;

moduleConfig = moduleConfig || {};
const moduleParams = moduleConfig.params || {};
const weboCtxConf = moduleParams.weboCtxConf || {};

if (weboCtxConf.token) {
fetchContextualProfile(weboCtxConf, setBigseaContextualProfile,
() => utils.logMessage('fetchContextualProfile on init is done'));
} else {
utils.logError('missing param "token" for weborama rtd module initialization');
return false;
}

return true;
}

export const weboramaSubmodule = {
name: SUBMODULE_NAME,
init: init,
getTargetingData: getTargetingData,
};

submodule(MODULE_NAME, weboramaSubmodule);
70 changes: 70 additions & 0 deletions modules/weboramaRtdProvider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Weborama Real-Time Data Submodule

```
Module Name: Weborama Rtd Provider
Module Type: Rtd Provider
Maintainer: prebid-support@weborama.com
```

# Description

Weborama provides a Semantic AI Contextual API that classifies in Real-time a web page seen by a web user within generic and custom topics. It enables publishers to better monetize their inventory and unlock it to programmatic.

ORTB2 compliant and FPD support for Prebid versions < 4.29

Contact prebid-support@weborama.com for information.

### Publisher Usage

Compile the Weborama RTD module into your Prebid build:

`gulp build --modules=rtdModule,weboramaRtdProvider`

Add the Weborama RTD provider to your Prebid config.

```javascript
pbjs.setConfig(
...
realTimeData: {
auctionDelay: 1000,
dataProviders: [
{
name: "weborama",
waitForIt: true,
params: {
weboCtxConf: {
setTargeting: true,
token: "<<token provided by weborama>>",
targetURL: "..." // default is document.URL
}
}
}
]
}
...
}
```

### Parameter Descriptions for the Weborama Configuration Section

| Name |Type | Description | Notes |
| :------------ | :------------ | :------------ |:------------ |
| name | String | Real time data module name | Mandatory. Always 'Weborama' |
| waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true |
| params | Object | | Optional |
| params.weboCtxConf | Object | Weborama Contextual Configuration | Optional |
| params.weboCtxConf.token | String | Security Token provided by Weborama, unique per client | Mandatory |
| params.weboCtxConf.targetURL | String | Url to be profiled in the contextual api | Optional. Defaults to `document.URL` |
| params.weboCtxConf.defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` |
| params.weboCtxConf.setTargeting|Boolean|If true, will use the contextual profile to set the gam targeting of all adunits managed by prebid.js| Optional. Default is *true*.|
| params.weboCtxConf.setOrtb2|Boolean|If true, will use the contextual profile to set the ortb2 configuration on `site.ext.data`| Optional. Default is *false*.|

### Testing

To view an example of available segments returned by Weborama's backends:

`gulp serve --modules=rtdModule,weboramaRtdProvider,appnexusBidAdapter`

and then point your browser at:

`http://localhost:9999/integrationExamples/gpt/weboramaRtdProvider_example.html`
Loading