Skip to content

Commit

Permalink
Integral Ad Science RTD module: initial release (#6816)
Browse files Browse the repository at this point in the history
* PREP-192 Update Prebid.js PET adapter to operate as a real time data model

* PREP-192 add iasRtdProvider to submodules.json

* PREP-192 sort iasRtdProvider alphabetically

* PREP-192 change getBidRequestData method logic add test cases

* PREP-192 add test cases

* PREP-192 refactor method

* add brandsafety response validation
  • Loading branch information
raguilar-ias authored Jun 8, 2021
1 parent 038a58e commit 86e86d7
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 0 deletions.
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"dgkeywordRtdProvider",
"geoedgeRtdProvider",
"haloRtdProvider",
"iasRtdProvider",
"jwplayerRtdProvider",
"optimeraRtdProvider",
"permutiveRtdProvider",
Expand Down
124 changes: 124 additions & 0 deletions modules/iasRtdProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { submodule } from '../src/hook.js';
import { getGlobal } from '../src/prebidGlobal.js';
import * as utils from '../src/utils.js';
import { ajaxBuilder } from '../src/ajax.js';

/** @type {string} */
const MODULE_NAME = 'realTimeData';
const SUBMODULE_NAME = 'ias';

/**
* Module init
* @param {Object} provider
* @param {Object} userConsent
* @return {boolean}
*/
export function init(config, userConsent) {
return true;
}

function stringifySlotSizes(sizes) {
let result = '';
if (utils.isArray(sizes)) {
result = sizes.reduce((acc, size) => {
acc.push(size.join('.'));
return acc;
}, []);
result = '[' + result.join(',') + ']';
}
return result;
}

function stringifySlot(bidRequest) {
const id = bidRequest.code;
const ss = stringifySlotSizes(bidRequest.sizes);
const p = bidRequest.bids[0].params.adUnitPath;
const slot = { id, ss, p };
const keyValues = utils.getKeys(slot).map(function (key) {
return [key, slot[key]].join(':');
});
return '{' + keyValues.join(',') + '}';
}

function stringifyWindowSize() {
return [window.innerWidth || -1, window.innerHeight || -1].join('.');
}

function stringifyScreenSize() {
return [(window.screen && window.screen.width) || -1, (window.screen && window.screen.height) || -1].join('.');
}

function getPageLevelKeywords(response) {
let result = {};
if (response.brandSafety) {
shallowMerge(result, response.brandSafety);
}
result.fr = response.fr;
result.custom = response.custom;
return result;
}

function shallowMerge(dest, src) {
utils.getKeys(src).reduce((dest, srcKey) => {
dest[srcKey] = src[srcKey];
return dest;
}, dest);
}

function getBidRequestData(reqBidsConfigObj, callback, config) {
const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits;

let isFinish = false;

const IAS_HOST = 'https://pixel.adsafeprotected.com/services/pub';
const { pubId } = config.params;
const anId = pubId;
let queries = [];
queries.push(['anId', anId]);

queries = queries.concat(adUnits.reduce(function (acc, request) {
acc.push(['slot', stringifySlot(request)]);
return acc;
}, []));

queries.push(['wr', stringifyWindowSize()]);
queries.push(['sr', stringifyScreenSize()]);
queries.push(['url', encodeURIComponent(window.location.href)]);

const queryString = encodeURI(queries.map(qs => qs.join('=')).join('&'));

const ajax = ajaxBuilder();

ajax(`${IAS_HOST}?${queryString}`, {
success: function (response, request) {
if (!isFinish) {
if (request.status === 200) {
const iasResponse = JSON.parse(response);
adUnits.forEach(adUnit => {
adUnit.bids.forEach(bid => {
const rtd = bid.rtd || {};
const iasRtd = {};
iasRtd[SUBMODULE_NAME] = Object.assign({}, rtd[SUBMODULE_NAME], getPageLevelKeywords(iasResponse));
bid.rtd = Object.assign({}, rtd, iasRtd);
});
});
}
isFinish = true;
}
callback();
},
error: function () {
utils.logError('failed to retrieve targeting information');
callback();
}
});
}

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

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

Module Name: Integral Ad Science(IAS) Rtd Provider
Module Type: Rtd Provider
Maintainer: [email protected]

# Description

RTD provider for Integral Ad Science(IAS) Contact [email protected] for information.
74 changes: 74 additions & 0 deletions test/spec/modules/iasRtdProvider_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { iasSubModule } from 'modules/iasRtdProvider.js';
import { expect } from 'chai';

describe('iasRtdProvider is a RTD provider that', function () {
it('has the correct module name', function () {
expect(iasSubModule.name).to.equal('ias');
});
describe('has a method `init` that', function () {
it('exists', function () {
expect(iasSubModule.init).to.be.a('function');
});
it('returns true', function () {
expect(iasSubModule.init()).to.equal(true);
});
});
describe('has a method `getBidRequestData` that', function () {
const callback = sinon.spy();
const config = {
name: 'ias',
waitForIt: true,
params: {
pubId: 1234
}
};
it('exists', function () {
expect(iasSubModule.getBidRequestData).to.be.a('function');
});
it('verify config params', function () {
expect(config.name).to.not.be.undefined;
expect(config.name).to.equal('ias');
expect(config.params.pubId).to.not.be.undefined;
expect(config.params).to.have.property('pubId');
});
it('invoke method', function () {
iasSubModule.getBidRequestData({ adUnits: adUnits }, callback, config);
expect(adUnits).to.length(2);
expect(callback.calledOnce).to.be.false;
});
});
});

const adUnits = [
{
code: 'one-div-id',
mediaTypes: {
banner: {
sizes: [[970, 250], [728, 90], [1000, 90]]
}
},
sizes: [[970, 250], [728, 90], [1000, 90]],
bids: [
{
bidder: 'ias',
params: {
pubId: '1234',
adUnitPath: '/a/b/c'
}
}]
},
{
code: 'two-div-id',
mediaTypes: {
banner: { sizes: [[300, 250], [300, 600]] }
},
sizes: [[300, 250], [300, 600]],
bids: [
{
bidder: 'ias',
params: {
pubId: '1234',
adUnitPath: '/d/e/f'
}
}]
}];

0 comments on commit 86e86d7

Please sign in to comment.