diff --git a/README.md b/README.md index 609baf82c08..65dc668164e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Prebid.js is open source software that is offered for free as a convenience. Whi *Note:* Requires Prebid.js v1.38.0+ -Prebid.js depends on Babel and some Babel Plugins in order to run correctly in the browser. Here are some examples for +Prebid.js depends on Babel and some Babel Plugins in order to run correctly in the browser. Here are some examples for configuring webpack to work with Prebid.js. With Babel 7: @@ -37,7 +37,7 @@ module.exports = { mode: 'production', module: { rules: [ - + // this rule can be excluded if you don't require babel-loader for your other application files { test: /\.m?js$/, @@ -46,7 +46,7 @@ module.exports = { loader: 'babel-loader', } }, - + // this separate rule is required to make sure that the Prebid.js files are babel-ified. this rule will // override the regular exclusion from above (for being inside node_modules). { @@ -71,7 +71,7 @@ Or for Babel 6: // you must manually install and specify the presets and plugins yourself options: { plugins: [ - "transform-object-assign", // required (for IE support) and "babel-plugin-transform-object-assign" + "transform-object-assign", // required (for IE support) and "babel-plugin-transform-object-assign" // must be installed as part of your package. require('prebid.js/plugins/pbjsGlobals.js') // required! ], @@ -79,7 +79,7 @@ Or for Babel 6: ["env", { // you can use other presets if you wish. "targets": { // this example is using "babel-presets-env", which must be installed if you "browsers": [ // follow this example. - ... // your browser targets. they should probably match the targets you're using for the rest + ... // your browser targets. they should probably match the targets you're using for the rest // of your application ] } @@ -143,7 +143,7 @@ This will run testing but not linting. A web server will start at `http://localh Development may be a bit slower but if you prefer linting and additional watch files you can also still run just: - $ gulp serve + $ gulp serve ### Build Optimization @@ -162,11 +162,11 @@ Building with just these adapters will result in a smaller bundle which should a - Then run the build: $ gulp build --modules=openxBidAdapter,rubiconBidAdapter,sovrnBidAdapter - + Alternatively, a `.json` file can be specified that contains a list of modules you would like to include. $ gulp build --modules=modules.json - + With `modules.json` containing the following ```json modules.json [ @@ -202,7 +202,7 @@ gulp bundle --tag one --modules=one.json gulp bundle --tag two --modules=two.json ``` -This generates slightly larger files, but has the advantage of being much faster to run (after the initial `gulp build`). It's also the method used by [the Prebid.org download page](https://docs.prebid.org/download.html). +This generates slightly larger files, but has the advantage of being much faster to run (after the initial `gulp build`). It's also the method used by [the Prebid.org download page](https://docs.prebid.org/download.html). @@ -378,7 +378,7 @@ For instructions on writing tests for Prebid.js, see [Testing Prebid.js](https:/ ### Supported Browsers -Prebid.js is supported on IE11 and modern browsers until 5.x. 6.x+ transpiles to target >0.25%; not Opera Mini; not IE11. +Prebid.js is supported on IE11 and modern browsers until 5.x. 6.x+ transpiles to target >0.25%; not Opera Mini; not IE11. ### Governance Review our governance model [here](https://github.com/prebid/Prebid.js/tree/master/governance.md). diff --git a/libraries/liveIntentId/externalIdSystem.js b/libraries/liveIntentId/externalIdSystem.js index 5db94b90a44..9fcb9e6da1b 100644 --- a/libraries/liveIntentId/externalIdSystem.js +++ b/libraries/liveIntentId/externalIdSystem.js @@ -1,7 +1,7 @@ import { logError } from '../../src/utils.js'; import { gdprDataHandler, uspDataHandler, gppDataHandler } from '../../src/adapterManager.js'; import { submodule } from '../../src/hook.js'; -import { DEFAULT_AJAX_TIMEOUT, MODULE_NAME, parseRequestedAttributes, composeIdObject, eids, GVLID, PRIMARY_IDS } from './shared.js' +import { DEFAULT_AJAX_TIMEOUT, MODULE_NAME, parseRequestedAttributes, composeIdObject, eids, GVLID, PRIMARY_IDS, makeSourceEventToSend } from './shared.js' // Reference to the client for the liQHub. let cachedClientRef @@ -97,8 +97,9 @@ function initializeClient(configParams) { resolveSettings }) - if (configParams.emailHash != null) { - window.liQHub.push({ type: 'collect', clientRef, sourceEvent: { hash: configParams.emailHash } }) + let sourceEvent = makeSourceEventToSend(configParams) + if (sourceEvent != null) { + window.liQHub.push({ type: 'collect', clientRef, sourceEvent }) } cachedClientRef = clientRef diff --git a/libraries/liveIntentId/idSystem.js b/libraries/liveIntentId/idSystem.js index 2077df8d8bf..a9b8052c752 100644 --- a/libraries/liveIntentId/idSystem.js +++ b/libraries/liveIntentId/idSystem.js @@ -11,7 +11,7 @@ import { submodule } from '../../src/hook.js'; import { LiveConnect } from 'live-connect-js'; // eslint-disable-line prebid/validate-imports import { getStorageManager } from '../../src/storageManager.js'; import { MODULE_TYPE_UID } from '../../src/activities/modules.js'; -import { DEFAULT_AJAX_TIMEOUT, MODULE_NAME, composeIdObject, eids, GVLID, DEFAULT_DELAY, PRIMARY_IDS, parseRequestedAttributes } from './shared.js' +import { DEFAULT_AJAX_TIMEOUT, MODULE_NAME, composeIdObject, eids, GVLID, DEFAULT_DELAY, PRIMARY_IDS, parseRequestedAttributes, makeSourceEventToSend } from './shared.js' /** * @typedef {import('../modules/userId/index.js').Submodule} Submodule @@ -23,7 +23,7 @@ const EVENTS_TOPIC = 'pre_lips'; export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME}); const calls = { - ajaxGet: (url, onSuccess, onError, timeout) => { + ajaxGet: (url, onSuccess, onError, timeout, headers) => { ajaxBuilder(timeout)( url, { @@ -33,7 +33,8 @@ const calls = { undefined, { method: 'GET', - withCredentials: true + withCredentials: true, + customHeaders: headers } ) }, @@ -92,7 +93,11 @@ function initializeLiveConnect(configParams) { const publisherId = configParams.publisherId || 'any'; const identityResolutionConfig = { publisherId: publisherId, - requestedAttributes: parseRequestedAttributes(configParams.requestedAttributesOverrides) + requestedAttributes: parseRequestedAttributes(configParams.requestedAttributesOverrides), + extraAttributes: { + ipv4: configParams.ipv4, + ipv6: configParams.ipv6 + } }; if (configParams.url) { identityResolutionConfig.url = configParams.url; @@ -136,8 +141,10 @@ function initializeLiveConnect(configParams) { // The second param is the storage object, LS & Cookie manipulation uses PBJS. // 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 }); + + const sourceEvent = makeSourceEventToSend(configParams) + if (sourceEvent != null) { + liveConnect.push(sourceEvent); } return liveConnect; } diff --git a/libraries/liveIntentId/shared.js b/libraries/liveIntentId/shared.js index f7b9f32760f..509f91e44d9 100644 --- a/libraries/liveIntentId/shared.js +++ b/libraries/liveIntentId/shared.js @@ -29,6 +29,31 @@ export function parseRequestedAttributes(overrides) { } } +export function makeSourceEventToSend(configParams) { + const sourceEvent = {} + let nonEmpty = false + if (typeof configParams.emailHash === 'string') { + nonEmpty = true + sourceEvent.emailHash = configParams.emailHash + } + if (typeof configParams.ipv4 === 'string') { + nonEmpty = true + sourceEvent.ipv4 = configParams.ipv4 + } + if (typeof configParams.ipv6 === 'string') { + nonEmpty = true + sourceEvent.ipv6 = configParams.ipv6 + } + if (typeof configParams.userAgent === 'string') { + nonEmpty = true + sourceEvent.userAgent = configParams.userAgent + } + + if (nonEmpty) { + return sourceEvent + } +} + export function composeIdObject(value) { const result = {}; diff --git a/package-lock.json b/package-lock.json index 9a47e65df49..e781dc3d7b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "fun-hooks": "^0.9.9", "gulp-wrap": "^0.15.0", "klona": "^2.0.6", - "live-connect-js": "^6.7.3" + "live-connect-js": "^7.1.0" }, "devDependencies": { "@babel/eslint-parser": "^7.16.5", @@ -18197,23 +18197,23 @@ "dev": true }, "node_modules/live-connect-common": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.1.4.tgz", - "integrity": "sha512-NK5HH0b/6bQX6hZQttlDfqrpDiP+iYtYYGO47LfM9YVwT1OZITgYZUJ0oG4IVynwdpas/VGvXv5hN0UcVK97oQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-4.1.0.tgz", + "integrity": "sha512-sRklgbe13377aR+G0qCBiZPayQw5oZZozkuxKEoyipxscLbVzwe9gtA7CPpbmo6UcOdQxdCE6A7J1tI0wTSmqw==", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/live-connect-js": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.7.3.tgz", - "integrity": "sha512-K2/GGhyhJ7/bFJfjiNw41W5xLRER9Smc49a8A6PImCcgit/sp2UsYz/F+sQwoj8IkJ3PufHvBnIGBbeQ31VsBg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-7.1.0.tgz", + "integrity": "sha512-fFxvQjOsHkCjulWsbirjxb6Y8xuAoWdgYqZvBLoSVKry48IyvVnLfvWgJg66qENjxig+8RH9bvlE16I6hJ7J7Q==", "dependencies": { - "live-connect-common": "^v3.1.4", + "live-connect-common": "^v4.1.0", "tiny-hashes": "1.0.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/livereload-js": { @@ -41721,16 +41721,16 @@ "dev": true }, "live-connect-common": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.1.4.tgz", - "integrity": "sha512-NK5HH0b/6bQX6hZQttlDfqrpDiP+iYtYYGO47LfM9YVwT1OZITgYZUJ0oG4IVynwdpas/VGvXv5hN0UcVK97oQ==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-4.1.0.tgz", + "integrity": "sha512-sRklgbe13377aR+G0qCBiZPayQw5oZZozkuxKEoyipxscLbVzwe9gtA7CPpbmo6UcOdQxdCE6A7J1tI0wTSmqw==" }, "live-connect-js": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.7.3.tgz", - "integrity": "sha512-K2/GGhyhJ7/bFJfjiNw41W5xLRER9Smc49a8A6PImCcgit/sp2UsYz/F+sQwoj8IkJ3PufHvBnIGBbeQ31VsBg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-7.1.0.tgz", + "integrity": "sha512-fFxvQjOsHkCjulWsbirjxb6Y8xuAoWdgYqZvBLoSVKry48IyvVnLfvWgJg66qENjxig+8RH9bvlE16I6hJ7J7Q==", "requires": { - "live-connect-common": "^v3.1.4", + "live-connect-common": "^v4.1.0", "tiny-hashes": "1.0.1" } }, diff --git a/package.json b/package.json index ba453eb6da0..340d33aac1e 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "fun-hooks": "^0.9.9", "gulp-wrap": "^0.15.0", "klona": "^2.0.6", - "live-connect-js": "^6.7.3" + "live-connect-js": "^7.1.0" }, "optionalDependencies": { "fsevents": "^2.3.2" diff --git a/test/spec/modules/liveIntentExternalIdSystem_spec.js b/test/spec/modules/liveIntentExternalIdSystem_spec.js index f87819ec85e..3e49eb5fc4b 100644 --- a/test/spec/modules/liveIntentExternalIdSystem_spec.js +++ b/test/spec/modules/liveIntentExternalIdSystem_spec.js @@ -54,7 +54,7 @@ describe('LiveIntentExternalId', function() { }, { clientRef: {}, - sourceEvent: { hash: '123' }, + sourceEvent: { emailHash: '123' }, type: 'collect' }]) }); @@ -120,7 +120,7 @@ describe('LiveIntentExternalId', function() { expect(window.liQHub[1]).to.eql({ clientRef: {}, - sourceEvent: { hash: '58131bc547fb87af94cebdaf3102321f' }, + sourceEvent: { emailHash: '58131bc547fb87af94cebdaf3102321f' }, type: 'collect' }) @@ -179,7 +179,7 @@ describe('LiveIntentExternalId', function() { }, { clientRef: {}, - sourceEvent: { hash: '123' }, + sourceEvent: { emailHash: '123' }, type: 'collect' }]) }); @@ -205,7 +205,36 @@ describe('LiveIntentExternalId', function() { }, { clientRef: {}, - sourceEvent: { hash: '123' }, + sourceEvent: { emailHash: '123' }, + type: 'collect' + }]) + }); + + it('should include the identifier data if it is present in config', function() { + const configParams = { + params: { + ...defaultConfigParams.params, + distributorId: 'did-1111', + emailHash: '123', + ipv4: 'foov4', + ipv6: 'foov6', + userAgent: 'bar' + } + } + liveIntentExternalIdSubmodule.decode({}, configParams); + expect(window.liQHub).to.eql([{ + clientDetails: { name: 'prebid', version: '$prebid.version$' }, + clientRef: {}, + collectSettings: { timeout: DEFAULT_AJAX_TIMEOUT }, + consent: {}, + integration: { distributorId: 'did-1111', publisherId: defaultConfigParams.params.publisherId, type: 'custom' }, + partnerCookies: new Set(), + resolveSettings: { identityPartner: 'did-1111', timeout: DEFAULT_AJAX_TIMEOUT }, + type: 'register_client' + }, + { + clientRef: {}, + sourceEvent: { emailHash: '123', ipv4: 'foov4', ipv6: 'foov6', userAgent: 'bar' }, type: 'collect' }]) }); diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index ea289186144..50f51bd3dc8 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -369,6 +369,21 @@ describe('LiveIntentId', function() { expect(callBackSpy.calledOnce).to.be.true; }); + it('should include ip4,ip6,userAgent if it\'s present', function(done) { + liveIntentIdSubmodule.getId({ params: { + ...defaultConfigParams, + ipv4: 'foov4', + ipv6: 'foov6', + userAgent: 'boo' + }}); + setTimeout(() => { + let request = rpRequests()[0]; + expect(request.url).to.match(/^https:\/\/rp\.liadm\.com\/j?.*pip=.*&pip6=.*$/) + expect(request.requestHeaders['X-LI-Provided-User-Agent']).to.be.eq('boo') + done(); + }, 300); + }); + it('should send an error when the cookie jar throws an unexpected error', function() { getCookieStub.throws('CookieError', 'A message'); liveIntentIdSubmodule.getId({ params: defaultConfigParams });