From b0c1c202d7ebb9f887d085c2fd8392ea65aba825 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Fri, 30 Jun 2023 15:38:09 +0200 Subject: [PATCH 01/12] add gdpr verification for user-centric modules --- modules/weboramaRtdProvider.js | 58 +++++++++- modules/weboramaRtdProvider.md | 11 +- test/spec/modules/weboramaRtdProvider_spec.js | 109 ++++++++++++++++++ 3 files changed, 171 insertions(+), 7 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 6ba502d2c8b..4e413aed410 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -110,7 +110,8 @@ import { isPlainObject, logWarn, mergeDeep, - tryAppendQueryString + tryAppendQueryString, + deepAccess } from '../src/utils.js'; import { submodule @@ -192,9 +193,11 @@ class WeboramaRtdProvider { * @method * @param {Object} moduleConfig * @param {?ModuleParams} moduleConfig.params + * @param {Object} userConsent + * @param {?Object} userConsent.gdpr * @return {boolean} true if module was initialized with success */ - init(moduleConfig) { + init(moduleConfig, userConsent) { /** @type {Object} */ const globalDefaults = { setPrebidTargeting: true, @@ -212,8 +215,14 @@ class WeboramaRtdProvider { this.#components.WeboUserData.data = null; this.#components.SfbxLiteData.data = null; - this.#components.WeboCtx.initialized = this.#initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, 'token'); - this.#components.WeboUserData.initialized = this.#initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION); + const weboCtxRequiredFields = ['token']; + + this.#components.WeboCtx.initialized = this.#initSubSection(moduleParams, WEBO_CTX_CONF_SECTION, { + requiredFields: weboCtxRequiredFields, + }); + this.#components.WeboUserData.initialized = this.#initSubSection(moduleParams, WEBO_USER_DATA_CONF_SECTION, { + userConsent: userConsent || {}, + }); this.#components.SfbxLiteData.initialized = this.#initSubSection(moduleParams, SFBX_LITE_DATA_CONF_SECTION); return Object.values(this.#components).some((c) => c.initialized); @@ -299,10 +308,12 @@ class WeboramaRtdProvider { * @private * @param {ModuleParams} moduleParams * @param {string} subSection subsection name to initialize - * @param {string[]} requiredFields + * @param {?Object} extra + * @param {string[]} extra.requiredFields + * @param {?Object} extra.userConsent * @return {boolean} true if module subsection was initialized with success */ - #initSubSection(moduleParams, subSection, ...requiredFields) { + #initSubSection(moduleParams, subSection, extra) { /** @type {CommonConf} */ const weboSectionConf = moduleParams[subSection] || { enabled: false }; @@ -315,11 +326,18 @@ class WeboramaRtdProvider { try { this.#normalizeConf(moduleParams, weboSectionConf); + extra = extra || {}; + const requiredFields = extra?.requiredFields || []; + requiredFields.forEach(field => { if (!(field in weboSectionConf)) { throw `missing required field '${field}''`; } }); + + if (isPlainObject(extra?.userConsent?.gdpr) && !this.#checkTCFv2(extra.userConsent.gdpr)) { + throw 'gdpr consent not ok'; + } } catch (e) { logError(`unable to initialize: error on ${subSection} configuration:`, e); return false; @@ -330,6 +348,34 @@ class WeboramaRtdProvider { return true; } + /** check gdpr consent data + * @method + * @private + * @param {Object} gdpr + * @param {?boolean} gdpr.gdprApplies + * @param {?Object} gdpr.vendorData + * @param {?Object} gdpr.vendorData.purpose + * @param {?Object.} gdpr.vendorData.purpose.consents + * @param {?Object.} gdr.vendorData.specialFeatureOptins + * @param {?Object} gdpr.vendorData.vendor + * @param {?Object.} gdpr.vendorData.vendor.consents + * @return {bool} + */ + // eslint-disable-next-line no-dupe-class-members + #checkTCFv2(gdpr) { + if (gdpr?.gdprApplies !== true) { + return true; + } + + if (deepAccess(gdpr, 'vendorData.vendor.consents') && deepAccess(gdpr, 'vendorData.purpose.consents')) { + return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id + gdpr.vendorData.purpose.consents[1] === true && // info storage access + gdpr.vendorData.purpose.consents[3] === true && // create personalized ads + gdpr.vendorData.purpose.consents[4] === true;// select personalized ads + } + + return true; + } /** normalize submodule configuration * @method * @private diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md index 0c6e3339787..7df73340c6d 100644 --- a/modules/weboramaRtdProvider.md +++ b/modules/weboramaRtdProvider.md @@ -16,7 +16,7 @@ Weborama provides a Real-Time Data Submodule for `Prebid.js`, allowing to easy i * LiTE by SFBX® (Local inApp Trust Engine) provides “Zero Party Data” given by users, stored and calculated only on the user’s device. Through a unique cohorting system, it enables better monetization in a consent/consentless and identity-less mode. -Contact prebid-support@weborama.com for more information. +Contact [prebid-support@weborama.com] for more information. ### Publisher Usage @@ -134,6 +134,15 @@ On this section we will explain the `params.weboUserDataConf` subconfiguration: | localStorageProfileKey| String | can be used to customize the local storage key | Optional | | enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present| +##### User Consent + +The WAM User-Centric configuration will check for user consent if gdpr applies. It will check for consent: + +* Vendor ID 284 (Weborama) +* Purpose IDs: 1, 3 and 4 + +If the user consent does not match such conditions, this module will not load, means we will not check for any data in local storage and the default profile will be ignored. + #### Sfbx LiTE Site-Centric Configuration To be possible use the integration between Weborama and Sfbx LiTE you should also contact SFBX® to setup this product. diff --git a/test/spec/modules/weboramaRtdProvider_spec.js b/test/spec/modules/weboramaRtdProvider_spec.js index 7de8474d7c9..625c300c172 100644 --- a/test/spec/modules/weboramaRtdProvider_spec.js +++ b/test/spec/modules/weboramaRtdProvider_spec.js @@ -48,6 +48,115 @@ describe('weboramaRtdProvider', function() { }; expect(weboramaSubmodule.init(moduleConfig)).to.equal(true); }); + + it('instantiate with empty sfbxLiteData should return true', function() { + const moduleConfig = { + params: { + sfbxLiteDataConf: {}, + } + }; + expect(weboramaSubmodule.init(moduleConfig)).to.equal(true); + }); + + describe('webo user data should check gdpr consent', function() { + it('should initialize if gdpr does not applies', function() { + const moduleConfig = { + params: { + weboUserDataConf: {} + } + }; + const userConsent = { + gdpr: { + gdprApplies: false, + }, + } + expect(weboramaSubmodule.init(moduleConfig, userConsent)).to.equal(true); + }); + it('should initialize if gdpr applies and consent is ok', function() { + const moduleConfig = { + params: { + weboUserDataConf: {} + } + }; + const userConsent = { + gdpr: { + gdprApplies: true, + vendorData: { + purpose: { + consents: { + 1: true, + 3: true, + 4: true, + }, + }, + specialFeatureOptins: {}, + vendor: { + consents: { + 284: true, + }, + } + }, + }, + } + expect(weboramaSubmodule.init(moduleConfig, userConsent)).to.equal(true); + }); + it('should NOT initialize if gdpr applies and consent is nok: miss consent vendor id', function() { + const moduleConfig = { + params: { + weboUserDataConf: {} + } + }; + const userConsent = { + gdpr: { + gdprApplies: true, + vendorData: { + purpose: { + consents: { + 1: true, + 3: true, + 4: true, + }, + }, + specialFeatureOptins: {}, + vendor: { + consents: { + 284: false, + }, + } + }, + }, + } + expect(weboramaSubmodule.init(moduleConfig, userConsent)).to.equal(false); + }); + it('should NOT initialize if gdpr applies and consent is nok: miss one purpose id', function() { + const moduleConfig = { + params: { + weboUserDataConf: {} + } + }; + const userConsent = { + gdpr: { + gdprApplies: true, + vendorData: { + purpose: { + consents: { + 1: false, + 3: true, + 4: true, + }, + }, + specialFeatureOptins: {}, + vendor: { + consents: { + 284: true, + }, + } + }, + }, + } + expect(weboramaSubmodule.init(moduleConfig, userConsent)).to.equal(false); + }); + }); }); describe('Handle Set Targeting and Bid Request', function() { From 912b31020603ef358adcbbbd16a2caa1da70a87d Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Fri, 30 Jun 2023 17:14:53 +0200 Subject: [PATCH 02/12] fix log messages --- modules/weboramaRtdProvider.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 4e413aed410..0c3b7632523 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -331,7 +331,7 @@ class WeboramaRtdProvider { requiredFields.forEach(field => { if (!(field in weboSectionConf)) { - throw `missing required field '${field}''`; + throw `missing required field '${field}'`; } }); @@ -339,11 +339,11 @@ class WeboramaRtdProvider { throw 'gdpr consent not ok'; } } catch (e) { - logError(`unable to initialize: error on ${subSection} configuration:`, e); + logError(`unable to initialize: error on '${subSection}' configuration:`, e); return false; } - logMessage(`weborama ${subSection} initialized with success`); + logMessage(`weborama '${subSection}' initialized with success`); return true; } From 2037ae612ab8864888ed2c9edb4795da55342330 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Sun, 2 Jul 2023 09:52:25 +0200 Subject: [PATCH 03/12] refactor logger --- modules/weboramaRtdProvider.js | 43 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 0c3b7632523..591fe532803 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -102,8 +102,6 @@ import { deepSetValue, isEmpty, isFn, - logError, - logMessage, isArray, isStr, isBoolean, @@ -111,7 +109,8 @@ import { logWarn, mergeDeep, tryAppendQueryString, - deepAccess + deepAccess, + prefixLog } from '../src/utils.js'; import { submodule @@ -154,6 +153,8 @@ const SFBX_LITE_DATA_SOURCE_LABEL = 'lite'; /** @type {number} */ const GVLID = 284; +const logger = prefixLog('[WeboramaRTD]'); + export const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: SUBMODULE_NAME @@ -252,7 +253,7 @@ class WeboramaRtdProvider { const weboCtxConf = moduleParams.weboCtxConf || {}; this.#fetchContextualProfile(weboCtxConf, (data) => { - logMessage('fetchContextualProfile on getBidRequestData is done'); + logger.logMessage('fetchContextualProfile on getBidRequestData is done'); this.#setWeboContextualProfile(data); }, () => { @@ -276,17 +277,17 @@ class WeboramaRtdProvider { const profileHandlers = this.#buildProfileHandlers(moduleParams); if (isEmpty(profileHandlers)) { - logMessage('no data to set targeting'); + logger.logMessage('no data to set targeting'); return {}; } try { return adUnitsCodes.reduce((data, adUnitCode) => { data[adUnitCode] = profileHandlers.reduce((targeting, ph) => { - // logMessage(`check if should set targeting for adunit '${adUnitCode}'`); + // logger.logMessage(`check if should set targeting for adunit '${adUnitCode}'`); const [data, metadata] = this.#copyDataAndMetadata(ph); if (ph.setTargeting(adUnitCode, data, metadata)) { - // logMessage(`set targeting for adunit '${adUnitCode}', source '${metadata.source}'`); + // logger.logMessage(`set targeting for adunit '${adUnitCode}', source '${metadata.source}'`); mergeDeep(targeting, data); } @@ -297,7 +298,7 @@ class WeboramaRtdProvider { return data; }, {}); } catch (e) { - logError(`unable to format weborama rtd targeting data:`, e); + logger.logError(`unable to format weborama rtd targeting data:`, e); return {}; } @@ -339,11 +340,11 @@ class WeboramaRtdProvider { throw 'gdpr consent not ok'; } } catch (e) { - logError(`unable to initialize: error on '${subSection}' configuration:`, e); + logger.logError(`unable to initialize: error on '${subSection}' configuration:`, e); return false; } - logMessage(`weborama '${subSection}' initialized with success`); + logger.logMessage(`weborama '${subSection}' initialized with success`); return true; } @@ -487,7 +488,7 @@ class WeboramaRtdProvider { const profileHandlers = this.#buildProfileHandlers(moduleParams); if (isEmpty(profileHandlers)) { - logMessage('no data to send to bidders'); + logger.logMessage('no data to send to bidders'); return; } @@ -497,11 +498,11 @@ class WeboramaRtdProvider { adUnits.forEach( adUnit => adUnit.bids?.forEach( bid => profileHandlers.forEach(ph => { - // logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`); + // logger.logMessage(`check if bidder '${bid.bidder}' and adunit '${adUnit.code} are share ${ph.metadata.source} data`); const [data, metadata] = this.#copyDataAndMetadata(ph); if (ph.sendToBidders(bid, adUnit.code, data, metadata)) { - // logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`); + // logger.logMessage(`handling bidder '${bid.bidder}' with ${ph.metadata.source} data`); this.#handleBid(reqBidsConfigObj, bid, data, ph.metadata); } @@ -509,7 +510,7 @@ class WeboramaRtdProvider { ) ); } catch (e) { - logError('unable to send data to bidders:', e); + logger.logError('unable to send data to bidders:', e); } profileHandlers.forEach(ph => { @@ -517,7 +518,7 @@ class WeboramaRtdProvider { const [data, metadata] = this.#copyDataAndMetadata(ph); ph.onData(data, metadata); } catch (e) { - logError(`error while execute onData callback with ${ph.metadata.source}-based data:`, e); + logger.logError(`error while execute onData callback with ${ph.metadata.source}-based data:`, e); } }); } @@ -558,7 +559,7 @@ class WeboramaRtdProvider { try { assetID = weboCtxConf.assetID(); } catch (e) { - logError('unexpected error while fetching asset id from callback', e); + logger.logError('unexpected error while fetching asset id from callback', e); onDone(); @@ -567,7 +568,7 @@ class WeboramaRtdProvider { } if (!assetID) { - logError('missing asset id'); + logger.logError('missing asset id'); onDone(); @@ -594,7 +595,7 @@ class WeboramaRtdProvider { }; const error = (e, req) => { - logError(`unable to get weborama data`, e, req); + logger.logError(`unable to get weborama data`, e, req); onDone(); }; @@ -652,7 +653,7 @@ class WeboramaRtdProvider { if (profileHandler) { ph.push(profileHandler); } else { - logMessage(`skip ${source} profile: no data`); + logger.logMessage(`skip ${source} profile: no data`); } return ph; @@ -783,13 +784,13 @@ class WeboramaRtdProvider { // eslint-disable-next-line no-dupe-class-members #handleBidViaORTB2(reqBidsConfigObj, bidder, profile, metadata) { if (isBoolean(metadata.user)) { - logMessage(`bidder '${bidder}' is not directly supported, trying set data via bidder ortb2 fpd`); + logger.logMessage(`bidder '${bidder}' is not directly supported, trying set data via bidder ortb2 fpd`); const section = metadata.user ? 'user' : 'site'; const path = `${section}.ext.data`; this.#setBidderOrtb2(reqBidsConfigObj.ortb2Fragments?.bidder, bidder, path, profile) } else { - logMessage(`SKIP unsupported bidder '${bidder}', data from '${metadata.source}' is not defined as user or site-centric`); + logger.logMessage(`SKIP unsupported bidder '${bidder}', data from '${metadata.source}' is not defined as user or site-centric`); } } /** From 41d2dd6edc6569dfb43ecdd1d0bf026368cc7329 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Sun, 2 Jul 2023 09:59:11 +0200 Subject: [PATCH 04/12] small refactors in code and import order --- modules/weboramaRtdProvider.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 591fe532803..e7e532118a7 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -98,19 +98,19 @@ import { getGlobal } from '../src/prebidGlobal.js'; import { + deepAccess, deepClone, deepSetValue, - isEmpty, - isFn, isArray, - isStr, isBoolean, + isEmpty, + isFn, isPlainObject, + isStr, logWarn, mergeDeep, - tryAppendQueryString, - deepAccess, - prefixLog + prefixLog, + tryAppendQueryString } from '../src/utils.js'; import { submodule @@ -121,8 +121,10 @@ import { import { getStorageManager } from '../src/storageManager.js'; +import { + MODULE_TYPE_RTD +} from '../src/activities/modules.js'; import adapterManager from '../src/adapterManager.js'; -import {MODULE_TYPE_RTD} from '../src/activities/modules.js'; /** @type {string} */ const MODULE_NAME = 'realTimeData'; @@ -730,17 +732,25 @@ class WeboramaRtdProvider { #handleBid(reqBidsConfigObj, bid, profile, metadata) { this.#handleBidViaORTB2(reqBidsConfigObj, bid.bidder, profile, metadata); - /** @type {Object.} */ - const bidderAliasRegistry = adapterManager.aliasRegistry || {}; - /** @type {string} */ - const bidder = bidderAliasRegistry[bid.bidder] || bid.bidder; + const bidder = this.#getAdapterNameForAlias(bid.bidder); if (bidder == 'appnexus') { this.#handleAppnexusBid(reqBidsConfigObj, bid, profile); } } + /** return adapter name based on alias, if any + * @method + * @private + * @param {string} aliasName + * @returns {string} + */ + // eslint-disable-next-line no-dupe-class-members + #getAdapterNameForAlias(aliasName) { + return adapterManager.aliasRegistry[aliasName] || aliasName; + } + /** function that handles bid request data * @method * @private From bc7d34d4af29c66572a452ebe17d9936028661e0 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Tue, 4 Jul 2023 12:24:29 +0200 Subject: [PATCH 05/12] add new purpose ids and special feature 1 --- modules/weboramaRtdProvider.js | 11 +++++++++-- modules/weboramaRtdProvider.md | 3 ++- test/spec/modules/weboramaRtdProvider_spec.js | 7 ++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index e7e532118a7..1af9e71ba15 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -370,11 +370,18 @@ class WeboramaRtdProvider { return true; } - if (deepAccess(gdpr, 'vendorData.vendor.consents') && deepAccess(gdpr, 'vendorData.purpose.consents')) { + if (deepAccess(gdpr, 'vendorData.vendor.consents') && + deepAccess(gdpr, 'vendorData.purpose.consents') && + deepAccess(gdpr, 'vendorData.specialFeatureOptins')) { return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id gdpr.vendorData.purpose.consents[1] === true && // info storage access gdpr.vendorData.purpose.consents[3] === true && // create personalized ads - gdpr.vendorData.purpose.consents[4] === true;// select personalized ads + gdpr.vendorData.purpose.consents[4] === true && // select personalized ads + gdpr.vendorData.purpose.consents[5] === true && // create personalized content + gdpr.vendorData.purpose.consents[6] === true && // select personalized content + // understand audiences through statistics or combination of data from different sources + gdpr.vendorData.purpose.consents[9] === true && + gdpr.vendorData.specialFeatureOptins[1] === true; // use precise geolocation data } return true; diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md index 7df73340c6d..170663f788b 100644 --- a/modules/weboramaRtdProvider.md +++ b/modules/weboramaRtdProvider.md @@ -139,7 +139,8 @@ On this section we will explain the `params.weboUserDataConf` subconfiguration: The WAM User-Centric configuration will check for user consent if gdpr applies. It will check for consent: * Vendor ID 284 (Weborama) -* Purpose IDs: 1, 3 and 4 +* Purpose IDs: 1, 3, 4, 5, 6 and 9 +* Special Feature 1 (use precise geolocation data) If the user consent does not match such conditions, this module will not load, means we will not check for any data in local storage and the default profile will be ignored. diff --git a/test/spec/modules/weboramaRtdProvider_spec.js b/test/spec/modules/weboramaRtdProvider_spec.js index 625c300c172..d562d9ffd13 100644 --- a/test/spec/modules/weboramaRtdProvider_spec.js +++ b/test/spec/modules/weboramaRtdProvider_spec.js @@ -87,9 +87,14 @@ describe('weboramaRtdProvider', function() { 1: true, 3: true, 4: true, + 5: true, + 6: true, + 9: true, }, }, - specialFeatureOptins: {}, + specialFeatureOptins: { + 1: true, + }, vendor: { consents: { 284: true, From bcbdadd9f460f0818eda1536794e432233b561cd Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Thu, 21 Dec 2023 15:27:19 +0100 Subject: [PATCH 06/12] remove special feature one, keep purposes 1, 3, 4, 5 and 7 --- modules/weboramaRtdProvider.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 15fd53db3bb..fa4aeab975b 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -361,7 +361,6 @@ class WeboramaRtdProvider { * @param {?Object} gdpr.vendorData * @param {?Object} gdpr.vendorData.purpose * @param {?Object.} gdpr.vendorData.purpose.consents - * @param {?Object.} gdr.vendorData.specialFeatureOptins * @param {?Object} gdpr.vendorData.vendor * @param {?Object.} gdpr.vendorData.vendor.consents * @return {bool} @@ -373,17 +372,13 @@ class WeboramaRtdProvider { } if (deepAccess(gdpr, 'vendorData.vendor.consents') && - deepAccess(gdpr, 'vendorData.purpose.consents') && - deepAccess(gdpr, 'vendorData.specialFeatureOptins')) { + deepAccess(gdpr, 'vendorData.purpose.consents')) { return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id gdpr.vendorData.purpose.consents[1] === true && // info storage access gdpr.vendorData.purpose.consents[3] === true && // create personalized ads gdpr.vendorData.purpose.consents[4] === true && // select personalized ads gdpr.vendorData.purpose.consents[5] === true && // create personalized content - gdpr.vendorData.purpose.consents[6] === true && // select personalized content - // understand audiences through statistics or combination of data from different sources - gdpr.vendorData.purpose.consents[9] === true && - gdpr.vendorData.specialFeatureOptins[1] === true; // use precise geolocation data + gdpr.vendorData.purpose.consents[6] === true; // select personalized content } return true; From c5ddc5ca27f9db2ab74a39879e852974add7abc8 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Thu, 21 Dec 2023 15:27:19 +0100 Subject: [PATCH 07/12] remove special feature one, keep purposes 1, 3, 4, 5 and 7 --- modules/weboramaRtdProvider.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 15fd53db3bb..fa4aeab975b 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -361,7 +361,6 @@ class WeboramaRtdProvider { * @param {?Object} gdpr.vendorData * @param {?Object} gdpr.vendorData.purpose * @param {?Object.} gdpr.vendorData.purpose.consents - * @param {?Object.} gdr.vendorData.specialFeatureOptins * @param {?Object} gdpr.vendorData.vendor * @param {?Object.} gdpr.vendorData.vendor.consents * @return {bool} @@ -373,17 +372,13 @@ class WeboramaRtdProvider { } if (deepAccess(gdpr, 'vendorData.vendor.consents') && - deepAccess(gdpr, 'vendorData.purpose.consents') && - deepAccess(gdpr, 'vendorData.specialFeatureOptins')) { + deepAccess(gdpr, 'vendorData.purpose.consents')) { return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id gdpr.vendorData.purpose.consents[1] === true && // info storage access gdpr.vendorData.purpose.consents[3] === true && // create personalized ads gdpr.vendorData.purpose.consents[4] === true && // select personalized ads gdpr.vendorData.purpose.consents[5] === true && // create personalized content - gdpr.vendorData.purpose.consents[6] === true && // select personalized content - // understand audiences through statistics or combination of data from different sources - gdpr.vendorData.purpose.consents[9] === true && - gdpr.vendorData.specialFeatureOptins[1] === true; // use precise geolocation data + gdpr.vendorData.purpose.consents[6] === true; // select personalized content } return true; From 6f3cc87558a48cbd1b3ee4ed0f6a12719d818c1e Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Thu, 21 Dec 2023 15:27:19 +0100 Subject: [PATCH 08/12] remove special feature one, keep purposes 1, 3, 4, 5 and 6 --- modules/weboramaRtdProvider.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 15fd53db3bb..fa4aeab975b 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -361,7 +361,6 @@ class WeboramaRtdProvider { * @param {?Object} gdpr.vendorData * @param {?Object} gdpr.vendorData.purpose * @param {?Object.} gdpr.vendorData.purpose.consents - * @param {?Object.} gdr.vendorData.specialFeatureOptins * @param {?Object} gdpr.vendorData.vendor * @param {?Object.} gdpr.vendorData.vendor.consents * @return {bool} @@ -373,17 +372,13 @@ class WeboramaRtdProvider { } if (deepAccess(gdpr, 'vendorData.vendor.consents') && - deepAccess(gdpr, 'vendorData.purpose.consents') && - deepAccess(gdpr, 'vendorData.specialFeatureOptins')) { + deepAccess(gdpr, 'vendorData.purpose.consents')) { return gdpr.vendorData.vendor.consents[GVLID] === true && // check weborama vendor id gdpr.vendorData.purpose.consents[1] === true && // info storage access gdpr.vendorData.purpose.consents[3] === true && // create personalized ads gdpr.vendorData.purpose.consents[4] === true && // select personalized ads gdpr.vendorData.purpose.consents[5] === true && // create personalized content - gdpr.vendorData.purpose.consents[6] === true && // select personalized content - // understand audiences through statistics or combination of data from different sources - gdpr.vendorData.purpose.consents[9] === true && - gdpr.vendorData.specialFeatureOptins[1] === true; // use precise geolocation data + gdpr.vendorData.purpose.consents[6] === true; // select personalized content } return true; From 4429bb5d181f1cfb758bfef10e11db5de901e7cd Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Tue, 6 Feb 2024 16:53:36 +0100 Subject: [PATCH 09/12] fix lint warning jsdoc/no-undefined-types --- modules/weboramaRtdProvider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/weboramaRtdProvider.js b/modules/weboramaRtdProvider.js index 074c3bf4125..82feec252eb 100644 --- a/modules/weboramaRtdProvider.js +++ b/modules/weboramaRtdProvider.js @@ -374,7 +374,7 @@ class WeboramaRtdProvider { * @param {?Object.} gdpr.vendorData.purpose.consents * @param {?Object} gdpr.vendorData.vendor * @param {?Object.} gdpr.vendorData.vendor.consents - * @return {bool} + * @return {boolean} */ // eslint-disable-next-line no-dupe-class-members #checkTCFv2(gdpr) { From ccc0dfad74dfd94eaca12f0f239e27a74f69881c Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Tue, 6 Feb 2024 16:55:12 +0100 Subject: [PATCH 10/12] fix typos --- modules/weboramaRtdProvider.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md index 170663f788b..80fcc83c1e1 100644 --- a/modules/weboramaRtdProvider.md +++ b/modules/weboramaRtdProvider.md @@ -117,9 +117,9 @@ On this section we will explain the `params.weboCtxConf` subconfiguration: | enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present| | baseURLProfileAPI | String| if present, update the domain of the contextual api| Optional. Default is `ctx.weborama.com` | -#### WAM User-Centric Configuration +#### User-Centric Configuration -To be possible use the integration with Weborama Audience Manager (WAM) you must be a client with an account id and you lust include the `wamfactory` script in your pages with `wam2gam` feature activated. +To be possible use the integration with Weborama Audience Manager (WAM) you must be a client with an account id and you must include the `wamfactory` script in your pages with `wam2gam` feature activated. Please contact weborama if you don't have it. On this section we will explain the `params.weboUserDataConf` subconfiguration: From 939f0d5f6331e2962c0b412d96e5d6e70ce7f469 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Thu, 29 Feb 2024 15:22:11 +0100 Subject: [PATCH 11/12] update doc --- modules/weboramaRtdProvider.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md index 80fcc83c1e1..0682b50b9fb 100644 --- a/modules/weboramaRtdProvider.md +++ b/modules/weboramaRtdProvider.md @@ -139,8 +139,7 @@ On this section we will explain the `params.weboUserDataConf` subconfiguration: The WAM User-Centric configuration will check for user consent if gdpr applies. It will check for consent: * Vendor ID 284 (Weborama) -* Purpose IDs: 1, 3, 4, 5, 6 and 9 -* Special Feature 1 (use precise geolocation data) +* Purpose IDs: 1, 3, 4, 5 and 6 If the user consent does not match such conditions, this module will not load, means we will not check for any data in local storage and the default profile will be ignored. From ea00e1ebfe0fb392accdbb89cb11b48d3b2d601b Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Thu, 29 Feb 2024 15:34:49 +0100 Subject: [PATCH 12/12] fix link in doc --- modules/weboramaRtdProvider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/weboramaRtdProvider.md b/modules/weboramaRtdProvider.md index 0682b50b9fb..a8fc692ba74 100644 --- a/modules/weboramaRtdProvider.md +++ b/modules/weboramaRtdProvider.md @@ -79,7 +79,7 @@ pbjs.setConfig({ Each module can perform two actions: -* set targeting on [GPT](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) / [AST](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForAst.html]) via `prebid.js` +* set targeting on [GPT](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) / [AST](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForAst.html) via `prebid.js` * send data to other `prebid.js` bidder modules (check the complete list at the end of this page)