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

CM-1091 Extend LiveIntent's User Id Module To Return sharedId #37

Closed
wants to merge 19 commits into from
Closed
18 changes: 18 additions & 0 deletions libraries/pubcidEids/pubcidEids.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const PUBCID_EIDS = {
'pubcid': {
source: 'pubcid.org',
atype: 1,
getValue: function(data) {
if (data.id) {
return data.id;
} else {
return data;
}
},
getUidExt: function(data) {
if (data.ext) {
return data.ext;
}
}
}
};
98 changes: 61 additions & 37 deletions modules/liveIntentIdSystem.js
Original file line number Diff line number Diff line change
@@ -8,23 +8,24 @@ import { triggerPixel, logError } from '../src/utils.js';
import { ajaxBuilder } from '../src/ajax.js';
import { submodule } from '../src/hook.js';
import { LiveConnect } from 'live-connect-js'; // eslint-disable-line prebid/validate-imports
import { gdprDataHandler, uspDataHandler, gppDataHandler } from '../src/adapterManager.js';
import {getStorageManager} from '../src/storageManager.js';
import {MODULE_TYPE_UID} from '../src/activities/modules.js';
import {UID2_EIDS} from '../libraries/uid2Eids/uid2Eids.js';
import { gdprDataHandler, uspDataHandler, gppDataHandler, coppaDataHandler } from '../src/adapterManager.js';
import { getStorageManager } from '../src/storageManager.js';
import { MODULE_TYPE_UID } from '../src/activities/modules.js';
import { UID2_EIDS } from '../libraries/uid2Eids/uid2Eids.js';
import { PUBCID_EIDS } from '../libraries/pubcidEids/pubcidEids.js';

/**
* @typedef {import('../modules/userId/index.js').Submodule} Submodule
* @typedef {import('../modules/userId/index.js').SubmoduleConfig} SubmoduleConfig
* @typedef {import('../modules/userId/index.js').IdResponse} IdResponse
*/

const DEFAULT_AJAX_TIMEOUT = 5000
const EVENTS_TOPIC = 'pre_lips'
const DEFAULT_AJAX_TIMEOUT = 5000;
const EVENTS_TOPIC = 'pre_lips';
const MODULE_NAME = 'liveIntentId';
const LI_PROVIDER_DOMAIN = 'liveintent.com';
export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
const defaultRequestedAttributes = {'nonId': true}
const defaultRequestedAttributes = {'nonId': true};
const calls = {
ajaxGet: (url, onSuccess, onError, timeout) => {
ajaxBuilder(timeout)(
@@ -51,10 +52,10 @@ let liveConnect = null;
*/
export function reset() {
if (window && window.liQ_instances) {
window.liQ_instances.forEach(i => i.eventBus.off(EVENTS_TOPIC, setEventFiredFlag))
window.liQ_instances.forEach(i => i.eventBus.off(EVENTS_TOPIC, setEventFiredFlag));
window.liQ_instances = [];
}
liveIntentIdSubmodule.setModuleMode(null)
liveIntentIdSubmodule.setModuleMode(null);
eventFired = false;
liveConnect = null;
}
@@ -68,7 +69,7 @@ export function setEventFiredFlag() {

function parseLiveIntentCollectorConfig(collectConfig) {
const config = {};
collectConfig = collectConfig || {}
collectConfig = collectConfig || {};
collectConfig.appId && (config.appId = collectConfig.appId);
collectConfig.fpiStorageStrategy && (config.storageStrategy = collectConfig.fpiStorageStrategy);
collectConfig.fpiExpirationDays && (config.expirationDays = collectConfig.fpiExpirationDays);
@@ -84,30 +85,39 @@ function parseLiveIntentCollectorConfig(collectConfig) {
* @returns {Array}
*/
function parseRequestedAttributes(overrides) {
function renameAttribute(attribute) {
if (attribute === 'sharedId') {
return 'idCookie';
} else {
return attribute;
};
}
function createParameterArray(config) {
return Object.entries(config).flatMap(([k, v]) => (typeof v === 'boolean' && v) ? [k] : []);
return Object.entries(config).flatMap(([k, v]) => (typeof v === 'boolean' && v) ? [renameAttribute(k)] : []);
}
if (typeof overrides === 'object') {
return createParameterArray({...defaultRequestedAttributes, ...overrides})
return createParameterArray({...defaultRequestedAttributes, ...overrides});
} else {
return createParameterArray(defaultRequestedAttributes);
}
}

function initializeLiveConnect(configParams) {
configParams = configParams || {};
if (liveConnect) {
return liveConnect;
}

configParams = configParams || {};
const sharedIdConfig = configParams.sharedId || {};

const publisherId = configParams.publisherId || 'any';
const identityResolutionConfig = {
publisherId: publisherId,
requestedAttributes: parseRequestedAttributes(configParams.requestedAttributesOverrides)
};
if (configParams.url) {
identityResolutionConfig.url = configParams.url
}
identityResolutionConfig.url = configParams.url;
};

identityResolutionConfig.ajaxTimeout = configParams.ajaxTimeout || DEFAULT_AJAX_TIMEOUT;

@@ -117,19 +127,24 @@ function initializeLiveConnect(configParams) {
liveConnectConfig.distributorId = configParams.distributorId;
identityResolutionConfig.source = configParams.distributorId;
} else {
identityResolutionConfig.source = configParams.partner || 'prebid'
identityResolutionConfig.source = configParams.partner || 'prebid';
}

liveConnectConfig.wrapperName = 'prebid';
liveConnectConfig.trackerVersion = '$prebid.version$';
liveConnectConfig.identityResolutionConfig = identityResolutionConfig;
liveConnectConfig.identifiersToResolve = configParams.identifiersToResolve || [];
liveConnectConfig.fireEventDelay = configParams.fireEventDelay;

liveConnectConfig.idCookie = {};
liveConnectConfig.idCookie.name = sharedIdConfig.name;
liveConnectConfig.idCookie.strategy = sharedIdConfig.strategy == 'html5' ? 'localStorage' : sharedIdConfig.strategy;

const usPrivacyString = uspDataHandler.getConsentData();
if (usPrivacyString) {
liveConnectConfig.usPrivacyString = usPrivacyString;
}
const gdprConsent = gdprDataHandler.getConsentData()
const gdprConsent = gdprDataHandler.getConsentData();
if (gdprConsent) {
liveConnectConfig.gdprApplies = gdprConsent.gdprApplies;
liveConnectConfig.gdprConsent = gdprConsent.consentString;
@@ -143,21 +158,21 @@ function initializeLiveConnect(configParams) {
// The third param is the ajax and pixel object, the ajax and pixel use PBJS
liveConnect = liveIntentIdSubmodule.getInitializer()(liveConnectConfig, storage, calls);
if (configParams.emailHash) {
liveConnect.push({ hash: configParams.emailHash })
liveConnect.push({ hash: configParams.emailHash });
}
return liveConnect;
}

function tryFireEvent() {
if (!eventFired && liveConnect) {
const eventDelay = liveConnect.config.fireEventDelay || 500
const eventDelay = liveConnect.config.fireEventDelay || 500;
setTimeout(() => {
const instances = window.liQ_instances
instances.forEach(i => i.eventBus.once(EVENTS_TOPIC, setEventFiredFlag))
const instances = window.liQ_instances;
instances.forEach(i => i.eventBus.once(EVENTS_TOPIC, setEventFiredFlag));
if (!eventFired && liveConnect) {
liveConnect.fire();
}
}, eventDelay)
}, eventDelay);
}
}

@@ -171,10 +186,10 @@ export const liveIntentIdSubmodule = {
name: MODULE_NAME,

setModuleMode(mode) {
this.moduleMode = mode
this.moduleMode = mode;
},
getInitializer() {
return (liveConnectConfig, storage, calls) => LiveConnect(liveConnectConfig, storage, calls, this.moduleMode)
return (liveConnectConfig, storage, calls) => LiveConnect(liveConnectConfig, storage, calls, this.moduleMode);
},

/**
@@ -192,49 +207,57 @@ export const liveIntentIdSubmodule = {
const result = {};

// old versions stored lipbid in unifiedId. Ensure that we can still read the data.
const lipbid = value.nonId || value.unifiedId
const lipbid = value.nonId || value.unifiedId;
if (lipbid) {
value.lipbid = lipbid
delete value.unifiedId
result.lipb = value
const lipb = { ...value, lipbid };
delete lipb.unifiedId;
result.lipb = lipb;
}

// Lift usage of uid2 by exposing uid2 if we were asked to resolve it.
// As adapters are applied in lexicographical order, we will always
// be overwritten by the 'proper' uid2 module if it is present.
if (value.uid2) {
result.uid2 = { 'id': value.uid2, ext: { provider: LI_PROVIDER_DOMAIN } }
result.uid2 = { 'id': value.uid2, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.bidswitch) {
result.bidswitch = { 'id': value.bidswitch, ext: { provider: LI_PROVIDER_DOMAIN } }
result.bidswitch = { 'id': value.bidswitch, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.medianet) {
result.medianet = { 'id': value.medianet, ext: { provider: LI_PROVIDER_DOMAIN } }
result.medianet = { 'id': value.medianet, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.magnite) {
result.magnite = { 'id': value.magnite, ext: { provider: LI_PROVIDER_DOMAIN } }
result.magnite = { 'id': value.magnite, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.index) {
result.index = { 'id': value.index, ext: { provider: LI_PROVIDER_DOMAIN } }
result.index = { 'id': value.index, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.openx) {
result.openx = { 'id': value.openx, ext: { provider: LI_PROVIDER_DOMAIN } }
result.openx = { 'id': value.openx, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.pubmatic) {
result.pubmatic = { 'id': value.pubmatic, ext: { provider: LI_PROVIDER_DOMAIN } }
result.pubmatic = { 'id': value.pubmatic, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.sovrn) {
result.sovrn = { 'id': value.sovrn, ext: { provider: LI_PROVIDER_DOMAIN } }
result.sovrn = { 'id': value.sovrn, ext: { provider: LI_PROVIDER_DOMAIN } };
}

if (value.idCookie) {
if (!coppaDataHandler.getCoppa()) {
result.lipb = { ...result.lipb, pubcid: value.idCookie };
result.pubcid = { 'id': value.idCookie, ext: { provider: LI_PROVIDER_DOMAIN } };
}
delete result.lipb.idCookie;
}

return result
return result;
}

if (!liveConnect) {
@@ -274,6 +297,7 @@ export const liveIntentIdSubmodule = {
},
eids: {
...UID2_EIDS,
...PUBCID_EIDS,
'lipb': {
getValue: function(data) {
return data.lipbid;
6 changes: 2 additions & 4 deletions modules/sharedIdSystem.js
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import {getStorageManager} from '../src/storageManager.js';
import {VENDORLESS_GVLID} from '../src/consentHandler.js';
import {MODULE_TYPE_UID} from '../src/activities/modules.js';
import {domainOverrideToRootDomain} from '../libraries/domainOverrideToRootDomain/index.js';
import {PUBCID_EIDS} from '../libraries/pubcidEids/pubcidEids.js';

/**
* @typedef {import('../modules/userId/index.js').Submodule} Submodule
@@ -183,10 +184,7 @@ export const sharedIdSystemSubmodule = {

domainOverride: domainOverrideToRootDomain(storage, 'sharedId'),
eids: {
'pubcid': {
source: 'pubcid.org',
atype: 1
},
...PUBCID_EIDS
}
};

17 changes: 14 additions & 3 deletions modules/userId/eids.md
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ userIdAsEids = [
segments: ['s1', 's2']
}
},

{
source: 'bidswitch.net',
uids: [{
@@ -117,7 +117,7 @@ userIdAsEids = [
}
}]
},

{
source: 'liveintent.indexexchange.com',
uids: [{
@@ -160,7 +160,7 @@ userIdAsEids = [
provider: 'liveintent.com'
}
}]
},
},

{
source: 'media.net',
@@ -184,6 +184,17 @@ userIdAsEids = [
}]
},

{
source: 'pubcid.org',
uids: [{
id: 'some-random-id-value',
atype: 1,
ext: {
provider: 'liveintent.com'
}
}]
},

{
source: 'merkleinc.com',
uids: [{
32 changes: 16 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Oops, something went wrong.