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

Submodule system using hooks #3924

Merged
merged 21 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b2a8f1
prebid-core only contains src and a few node_modules
snapwich Jun 18, 2019
d036244
add back removed neverBundle to webpack build
snapwich Jun 18, 2019
3cd6523
add module and submodule hooks
snapwich Jun 19, 2019
76cba02
allow vargs for submodules for flexibility
snapwich Jun 20, 2019
47d576e
fix jsdoc type syntax
Jun 20, 2019
f158c76
Merge remote-tracking branch 'remote/master' into prebid-core-bundle-fix
Jun 24, 2019
9c0620e
updated id5 userid submodule for submodule bundle size duplication fix
Jun 24, 2019
6b9e976
add id5 userid submodule to .submodules
Jun 25, 2019
38b5727
fix opt out logic
Jun 25, 2019
b42a235
spelling fix to comment
Jun 25, 2019
207fea7
update to automatically include 'pubcommon' and 'unifiedid' (uncommen…
Jun 25, 2019
129abaf
Merge branch 'master' into prebid-core-bundle-fix
Jun 27, 2019
8398037
additional update to automatically include 'pubcommon' and 'unifiedid'
Jun 25, 2019
1bb74d8
additional update to automatically include 'pubcommon' and 'unifiedid'
Jun 25, 2019
f522add
Merge remote-tracking branch 'remote/prebid-core-bundle-fix' into pre…
Jun 27, 2019
45b2770
Merge branch 'master' of https://github.com/prebid/Prebid.js into pre…
Jun 27, 2019
b1e5401
merged differences from master
Jun 27, 2019
73d6f5b
adpod changes to support submodules
Jun 27, 2019
4aa8550
Merge branch 'prebid-core-bundle-fix' of github.com:prebid/Prebid.js …
Jun 27, 2019
058d448
fix --modules argument with .json to work correctly with submodules
snapwich Jun 27, 2019
5d3e818
fix to remove included and duplicated submodules
Jun 28, 2019
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
15 changes: 14 additions & 1 deletion gulpHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ const MANIFEST = 'package.json';
const through = require('through2');
const _ = require('lodash');
const gutil = require('gulp-util');
const submodules = require('./modules/.submodules.json');

const MODULE_PATH = './modules';
const BUILD_PATH = './build/dist';
const DEV_PATH = './build/dev';
const ANALYTICS_PATH = '../analytics';


// get only subdirectories that contain package.json with 'main' property
function isModuleDirectory(filePath) {
try {
Expand Down Expand Up @@ -39,7 +41,9 @@ module.exports = {
.replace(/\/>/g, '\\/>');
},
getArgModules() {
var modules = (argv.modules || '').split(',').filter(module => !!module);
var modules = (argv.modules || '')
.split(',')
.filter(module => !!module);

try {
if (modules.length === 1 && path.extname(modules[0]).toLowerCase() === '.json') {
Expand All @@ -56,6 +60,15 @@ module.exports = {
});
}

Object.keys(submodules).forEach(parentModule => {
if (
!modules.includes(parentModule) &&
modules.some(module => submodules[parentModule].includes(module))
) {
modules.unshift(parentModule);
}
});

return modules;
},
getModules: _.memoize(function(externalModules) {
Expand Down
9 changes: 9 additions & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"userId": [
"digiTrustIdSystem",
"id5IdSystem"
],
"adpod": [
"freeWheelAdserverVideo"
]
}
31 changes: 27 additions & 4 deletions modules/adpod.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@ import * as utils from '../src/utils';
import { addBidToAuction, doCallbacksIfTimedout, AUCTION_IN_PROGRESS, callPrebidCache } from '../src/auction';
import { checkAdUnitSetup } from '../src/prebid';
import { checkVideoBidSetup } from '../src/video';
import { setupBeforeHookFnOnce } from '../src/hook';
import { setupBeforeHookFnOnce, module } from '../src/hook';
import { store } from '../src/videoCache';
import { config } from '../src/config';
import { ADPOD } from '../src/mediaTypes';
import Set from 'core-js/library/fn/set';
import find from 'core-js/library/fn/array/find';

const from = require('core-js/library/fn/array/from');

export const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur';
export const TARGETING_KEY_CACHE_ID = 'hb_cache_id'
const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur';
const TARGETING_KEY_CACHE_ID = 'hb_cache_id';

let queueTimeDelay = 50;
let queueSizeLimit = 5;
Expand Down Expand Up @@ -385,12 +386,13 @@ config.getConfig('adpod', config => adpodSetConfig(config.adpod));
/**
* This function initializes the adpod module's hooks. This is called by the corresponding adserver video module.
*/
export function initAdpodHooks() {
function initAdpodHooks() {
setupBeforeHookFnOnce(callPrebidCache, callPrebidCacheHook);
setupBeforeHookFnOnce(checkAdUnitSetup, checkAdUnitSetupHook);
setupBeforeHookFnOnce(checkVideoBidSetup, checkVideoBidSetupHook);
}

initAdpodHooks()
/**
*
* @param {Array[Object]} bids list of 'winning' bids that need to be cached
Expand Down Expand Up @@ -428,3 +430,24 @@ export function sortByPricePerSecond(a, b) {
}
return 0;
}

const sharedMethods = {
TARGETING_KEY_PB_CAT_DUR: TARGETING_KEY_PB_CAT_DUR,
TARGETING_KEY_CACHE_ID: TARGETING_KEY_CACHE_ID,
'sortByPricePerSecond': sortByPricePerSecond,
'callPrebidCacheAfterAuction': callPrebidCacheAfterAuction
}
Object.freeze(sharedMethods);

module('adpod', function shareAdpodUtilities(...args) {
if (!utils.isPlainObject(args[0])) {
utils.logError('Adpod module needs plain object to share methods with submodule');
return;
}
function addMethods(object, func) {
for (let name in func) {
object[name] = func[name];
}
}
addMethods(args[0], sharedMethods);
});
4 changes: 2 additions & 2 deletions modules/digiTrustIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// import { config } from 'src/config';
import * as utils from '../src/utils'
import { ajax } from '../src/ajax';
import { attachIdSystem } from '../modules/userId';
import { submodule } from '../src/hook';
// import { getGlobal } from 'src/prebidGlobal';

/**
Expand Down Expand Up @@ -336,4 +336,4 @@ export const digiTrustIdSubmodule = {
_testInit: surfaceTestHook
};

attachIdSystem(digiTrustIdSubmodule);
submodule('userId', digiTrustIdSubmodule);
23 changes: 12 additions & 11 deletions modules/freeWheelAdserverVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { auctionManager } from '../src/auctionManager';
import { groupBy, deepAccess, logError, compareOn } from '../src/utils';
import { config } from '../src/config';
import { ADPOD } from '../src/mediaTypes';
import { initAdpodHooks, TARGETING_KEY_PB_CAT_DUR, TARGETING_KEY_CACHE_ID, callPrebidCacheAfterAuction, sortByPricePerSecond } from './adpod';
import { getHook } from '../src/hook';
import { getHook, submodule } from '../src/hook';

export function notifyTranslationModule(fn) {
fn.call(this, 'freewheel');
Expand Down Expand Up @@ -37,7 +36,7 @@ export function getTargeting({codes, callback} = {}) {

let bids = getBidsForAdpod(bidsReceived, adPodAdUnits);
bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids;
bids.sort(sortByPricePerSecond);
bids.sort(adpodUtils.sortByPricePerSecond);

let targeting = {};
if (deferCachingEnabled === false) {
Expand All @@ -50,13 +49,13 @@ export function getTargeting({codes, callback} = {}) {
.forEach((bid, index, arr) => {
if (bid.video.durationBucket <= adPodDurationSeconds) {
adPodTargeting.push({
[TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR]
[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]
});
adPodDurationSeconds -= bid.video.durationBucket;
}
if (index === arr.length - 1 && adPodTargeting.length > 0) {
adPodTargeting.push({
[TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID]
[adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID]
});
}
});
Expand All @@ -79,7 +78,7 @@ export function getTargeting({codes, callback} = {}) {
});
});

callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) {
adpodUtils.callPrebidCacheAfterAuction(bidsToCache, function(error, bidsSuccessfullyCached) {
if (error) {
callback(error, null);
} else {
Expand All @@ -89,12 +88,12 @@ export function getTargeting({codes, callback} = {}) {

groupedBids[adUnitCode].forEach((bid, index, arr) => {
adPodTargeting.push({
[TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR]
[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]
});

if (index === arr.length - 1 && adPodTargeting.length > 0) {
adPodTargeting.push({
[TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID]
[adpodUtils.TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_CACHE_ID]
});
}
});
Expand Down Expand Up @@ -126,8 +125,8 @@ function getAdPodAdUnits(codes) {
*/
function getExclusiveBids(bidsReceived) {
let bids = bidsReceived
.map((bid) => Object.assign({}, bid, {[TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR]}));
bids = groupBy(bids, TARGETING_KEY_PB_CAT_DUR);
.map((bid) => Object.assign({}, bid, {[adpodUtils.TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[adpodUtils.TARGETING_KEY_PB_CAT_DUR]}));
bids = groupBy(bids, adpodUtils.TARGETING_KEY_PB_CAT_DUR);
let filteredBids = [];
Object.keys(bids).forEach((targetingKey) => {
bids[targetingKey].sort(compareOn('responseTimestamp'));
Expand All @@ -148,7 +147,9 @@ function getBidsForAdpod(bidsReceived, adPodAdUnits) {
.filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) != -1 && (bid.video && bid.video.context === ADPOD))
}

initAdpodHooks();
registerVideoSupport('freewheel', {
getTargeting: getTargeting
});

export const adpodUtils = {};
submodule('adpod', adpodUtils);
10 changes: 5 additions & 5 deletions modules/id5IdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* @requires module:modules/userId
*/

import * as utils from '../src/utils.js'
import {ajax} from '../src/ajax.js';
import {isGDPRApplicable, attachIdSystem} from './userId.js';
import * as utils from '../src/utils'
import {ajax} from '../src/ajax';
import {submodule} from '../src/hook';

/** @type {Submodule} */
export const id5IdSubmodule = {
Expand Down Expand Up @@ -37,7 +37,7 @@ export const id5IdSubmodule = {
utils.logError(`User ID - ID5 submodule requires partner to be defined as a number`);
return;
}
const hasGdpr = isGDPRApplicable(consentData) ? 1 : 0;
const hasGdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0;
const gdprConsentString = hasGdpr ? consentData.consentString : '';
const url = `https://id5-sync.com/g/v1/${configParams.partner}.json?gdpr=${hasGdpr}&gdpr_consent=${gdprConsentString}`;

Expand All @@ -57,4 +57,4 @@ export const id5IdSubmodule = {
}
};

attachIdSystem(id5IdSubmodule);
submodule('userId', id5IdSubmodule);
36 changes: 15 additions & 21 deletions modules/userId.js → modules/userId/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
* @name Submodule#getId
* @param {SubmoduleParams} configParams
* @param {ConsentData} consentData
* @return {(Object|function} id data or a callback, the callback is called on the auction end event
* @return {(Object|function)} id data or a callback, the callback is called on the auction end event
*/

/**
* @function
* @summary decode a stored value for passing to bid requests
* @name Submodule#decode
* @param {Object|string} value
* @return {(Object|undefined}
* @return {(Object|undefined)}
*/

/**
Expand Down Expand Up @@ -68,14 +68,15 @@
*/

import find from 'core-js/library/fn/array/find';
import {config} from '../src/config.js';
import events from '../src/events.js';
import * as utils from '../src/utils.js';
import {getGlobal} from '../src/prebidGlobal.js';
import {gdprDataHandler} from '../src/adapterManager.js';
import {config} from '../../src/config';
import events from '../../src/events';
import * as utils from '../../src/utils';
import {getGlobal} from '../../src/prebidGlobal';
import {gdprDataHandler} from '../../src/adapterManager';
import CONSTANTS from '../../src/constants.json';
import {module} from '../../src/hook';
import {unifiedIdSubmodule} from './unifiedIdSystem.js';
import {pubCommonIdSubmodule} from './pubCommonIdSystem.js';
import CONSTANTS from '../src/constants.json';

const MODULE_NAME = 'User ID';
const COOKIE = 'cookie';
Expand Down Expand Up @@ -158,22 +159,13 @@ function getStoredValue(storage) {
return storedValue;
}

/**
* test if consent module is present, and if GDPR applies
* @param {ConsentData} consentData
* @returns {boolean}
*/
export function isGDPRApplicable(consentData) {
return consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies;
}

/**
* test if consent module is present, applies, and is valid for local storage or cookies (purpose 1)
* @param {ConsentData} consentData
* @returns {boolean}
*/
export function hasGDPRConsent(consentData) {
if (isGDPRApplicable(consentData)) {
function hasGDPRConsent(consentData) {
if (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) {
if (!consentData.consentString) {
return false;
}
Expand Down Expand Up @@ -331,7 +323,7 @@ function getValidSubmoduleConfigs(configRegistry, submoduleRegistry, activeStora
if (!config || utils.isEmptyStr(config.name)) {
return carry;
}
// alidate storage config contains 'type' and 'name' properties with non-empty string values
// Validate storage config contains 'type' and 'name' properties with non-empty string values
// 'type' must be a value currently enabled in the browser
if (config.storage &&
!utils.isEmptyStr(config.storage.type) &&
Expand Down Expand Up @@ -409,7 +401,7 @@ export function init(config) {
return;
}
// _pubcid_optout is checked for compatiblility with pubCommonId
if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') && localStorage.getItem('_pubcid_optout'))) {
if (validStorageTypes.indexOf(LOCAL_STORAGE) !== -1 && (localStorage.getItem('_pbjs_id_optout') || localStorage.getItem('_pubcid_optout'))) {
utils.logInfo(`${MODULE_NAME} - opt-out localStorage found, exit module`);
return;
}
Expand All @@ -431,3 +423,5 @@ init(config);
// add submodules after init has been called
attachIdSystem(pubCommonIdSubmodule);
attachIdSystem(unifiedIdSubmodule);

module('userId', attachIdSystem);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @requires module:modules/userId
*/

import * as utils from '../src/utils.js'
import * as utils from '../../src/utils';

/** @type {Submodule} */
export const pubCommonIdSubmodule = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* @requires module:modules/userId
*/

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

/** @type {Submodule} */
export const unifiedIdSubmodule = {
Expand Down
24 changes: 2 additions & 22 deletions modules/userId.md → modules/userId/userId.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
Example showing `cookie` storage for user id data for both submodules
```
pbjs.setConfig({
usersync: {
userSync: {
userIds: [{
name: "unifiedId",
params: {
partner: "prebid",
url: "http://match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json"
url: "//match.adsrvr.org/track/rid?ttd_pid=prebid&fmt=json"
},
storage: {
type: "cookie",
Expand All @@ -28,26 +28,6 @@ pbjs.setConfig({
});
```

Example showing `cookie` storage for user id data for id5 submodule
```
pbjs.setConfig({
usersync: {
userIds: [{
name: "id5Id",
params: {
partner: 173 // @TODO: Set your real ID5 partner ID here for production, please ask for one contact@id5.io
},
storage: {
type: "cookie",
name: "id5id",
expires: 90
}
}],
syncDelay: 5000
}
});
```

Example showing `localStorage` for user id data for both submodules
```
pbjs.setConfig({
Expand Down
Loading