From db3ff52b133ada3a9e089bbb092e8e5f99142a3c Mon Sep 17 00:00:00 2001 From: dmytro-po Date: Tue, 4 Mar 2025 16:08:39 +0200 Subject: [PATCH 01/11] AGT-403: Add adType parameter to payload in report --- modules/intentIqAnalyticsAdapter.js | 3 +++ .../modules/intentIqAnalyticsAdapter_spec.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/modules/intentIqAnalyticsAdapter.js b/modules/intentIqAnalyticsAdapter.js index 3cc0efbdb57..3de34244b6c 100644 --- a/modules/intentIqAnalyticsAdapter.js +++ b/modules/intentIqAnalyticsAdapter.js @@ -235,6 +235,9 @@ function prepareData (data, result) { if (data.auctionId) { result.prebidAuctionId = data.auctionId; } + if (data.mediaType) { + result.adType = data.mediaType; + } if (data.placementId) { result.placementId = data.placementId; } else { diff --git a/test/spec/modules/intentIqAnalyticsAdapter_spec.js b/test/spec/modules/intentIqAnalyticsAdapter_spec.js index 26a70ded14e..51c4af7279f 100644 --- a/test/spec/modules/intentIqAnalyticsAdapter_spec.js +++ b/test/spec/modules/intentIqAnalyticsAdapter_spec.js @@ -134,6 +134,22 @@ describe('IntentIQ tests all', function () { expect(request.url).to.contain('iiqid=f961ffb1-a0e1-4696-a9d2-a21d815bd344'); }); + it('should include adType in payload when present in BID_WON event', function () { + localStorage.setItem(FIRST_PARTY_KEY, defaultData); + getWindowLocationStub = sinon.stub(utils, 'getWindowLocation').returns({ href: 'http://localhost:9876/' }); + const bidWonEvent = { ...wonRequest, mediaType: 'video' }; + + events.emit(EVENTS.BID_WON, bidWonEvent); + + const request = server.requests[0]; + const urlParams = new URL(request.url); + const payloadEncoded = urlParams.searchParams.get('payload'); + const payloadDecoded = JSON.parse(atob(JSON.parse(payloadEncoded)[0])); + + expect(server.requests.length).to.be.above(0); + expect(payloadDecoded).to.have.property('adType', bidWonEvent.mediaType); + }); + it('should send report to report-gdpr address if gdpr is detected', function () { const gppStub = sinon.stub(gppDataHandler, 'getConsentData').returns({ gppString: '{"key1":"value1","key2":"value2"}' }); const uspStub = sinon.stub(uspDataHandler, 'getConsentData').returns('1NYN'); From 90fdc7ae083b3cde4c7f3b06aeb49fe2983470f1 Mon Sep 17 00:00:00 2001 From: dmytro-po Date: Fri, 7 Mar 2025 16:03:14 +0200 Subject: [PATCH 02/11] AGT-403: Test for partner report, adType parameter --- modules/intentIqAnalyticsAdapter.js | 9 +++++--- .../modules/intentIqAnalyticsAdapter_spec.js | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/intentIqAnalyticsAdapter.js b/modules/intentIqAnalyticsAdapter.js index 3de34244b6c..90c9b56c1d8 100644 --- a/modules/intentIqAnalyticsAdapter.js +++ b/modules/intentIqAnalyticsAdapter.js @@ -55,7 +55,8 @@ const PARAMS_NAMES = { prebidVersion: 'pbjsver', partnerId: 'partnerId', firstPartyId: 'pcid', - placementId: 'placementId' + placementId: 'placementId', + adType: 'adType' }; let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({defaultUrl: REPORT_ENDPOINT, analyticsType}), { @@ -214,6 +215,8 @@ function fillEidsData(result) { } function prepareData (data, result) { + const adTypeValue = data.adType || data.mediaType; + if (data.bidderCode) { result.bidderCode = data.bidderCode; } @@ -235,8 +238,8 @@ function prepareData (data, result) { if (data.auctionId) { result.prebidAuctionId = data.auctionId; } - if (data.mediaType) { - result.adType = data.mediaType; + if (adTypeValue) { + result[PARAMS_NAMES.adType] = adTypeValue; } if (data.placementId) { result.placementId = data.placementId; diff --git a/test/spec/modules/intentIqAnalyticsAdapter_spec.js b/test/spec/modules/intentIqAnalyticsAdapter_spec.js index 51c4af7279f..76282ebcd43 100644 --- a/test/spec/modules/intentIqAnalyticsAdapter_spec.js +++ b/test/spec/modules/intentIqAnalyticsAdapter_spec.js @@ -150,6 +150,28 @@ describe('IntentIQ tests all', function () { expect(payloadDecoded).to.have.property('adType', bidWonEvent.mediaType); }); + it('should include adType in payload when present in reportExternalWin event', function () { + getWindowLocationStub = sinon.stub(utils, 'getWindowLocation').returns({ href: 'http://localhost:9876/' }); + const externalWinEvent = { cpm: 1, currency: 'USD', adType: 'banner' }; + const partnerId = USERID_CONFIG[0].params.partner; + USERID_CONFIG[0].params.manualWinReportEnabled = true; + + events.emit(EVENTS.BID_REQUESTED); + + window[`intentIqAnalyticsAdapter_${partnerId}`].reportExternalWin(externalWinEvent); + + expect(server.requests.length).to.be.above(0); + + const request = server.requests[0]; + const urlParams = new URL(request.url); + const payloadEncoded = urlParams.searchParams.get('payload'); + const payloadDecoded = JSON.parse(atob(JSON.parse(payloadEncoded)[0])); + + expect(payloadDecoded).to.have.property('adType', externalWinEvent.adType); + // reset iiqConfig.params.manualWinReportEnabled + USERID_CONFIG[0].params.manualWinReportEnabled = false; + }); + it('should send report to report-gdpr address if gdpr is detected', function () { const gppStub = sinon.stub(gppDataHandler, 'getConsentData').returns({ gppString: '{"key1":"value1","key2":"value2"}' }); const uspStub = sinon.stub(uspDataHandler, 'getConsentData').returns('1NYN'); From d0d0af9ab435d7f04a1aa074168a53afc687ecce Mon Sep 17 00:00:00 2001 From: dmytro-po Date: Fri, 7 Mar 2025 16:40:26 +0200 Subject: [PATCH 03/11] AGT-403: Test refactoring --- .../modules/intentIqAnalyticsAdapter_spec.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/test/spec/modules/intentIqAnalyticsAdapter_spec.js b/test/spec/modules/intentIqAnalyticsAdapter_spec.js index 76282ebcd43..6a4af47948e 100644 --- a/test/spec/modules/intentIqAnalyticsAdapter_spec.js +++ b/test/spec/modules/intentIqAnalyticsAdapter_spec.js @@ -21,12 +21,13 @@ const REPORT_ENDPOINT_GDPR = 'https://reports-gdpr.intentiq.com/report'; const storage = getStorageManager({ moduleType: 'analytics', moduleName: 'iiqAnalytics' }); -const USERID_CONFIG = [ +const getUserConfig = () => [ { 'name': 'intentIqId', 'params': { 'partner': partner, 'unpack': null, + 'manualWinReportEnabled': false }, 'storage': { 'type': 'html5', @@ -79,7 +80,7 @@ describe('IntentIQ tests all', function () { beforeEach(function () { logErrorStub = sinon.stub(utils, 'logError'); - sinon.stub(config, 'getConfig').withArgs('userSync.userIds').returns(USERID_CONFIG); + sinon.stub(config, 'getConfig').withArgs('userSync.userIds').returns(getUserConfig()); sinon.stub(events, 'getEvents').returns([]); iiqAnalyticsAnalyticsAdapter.enableAnalytics({ provider: 'iiqAnalytics', @@ -153,23 +154,24 @@ describe('IntentIQ tests all', function () { it('should include adType in payload when present in reportExternalWin event', function () { getWindowLocationStub = sinon.stub(utils, 'getWindowLocation').returns({ href: 'http://localhost:9876/' }); const externalWinEvent = { cpm: 1, currency: 'USD', adType: 'banner' }; - const partnerId = USERID_CONFIG[0].params.partner; - USERID_CONFIG[0].params.manualWinReportEnabled = true; + const [userConfig] = getUserConfig(); + userConfig.params.manualWinReportEnabled = true; + config.getConfig.restore(); + sinon.stub(config, 'getConfig').withArgs('userSync.userIds').returns([userConfig]); + + const partnerId = userConfig.params.partner; events.emit(EVENTS.BID_REQUESTED); window[`intentIqAnalyticsAdapter_${partnerId}`].reportExternalWin(externalWinEvent); - expect(server.requests.length).to.be.above(0); - const request = server.requests[0]; const urlParams = new URL(request.url); const payloadEncoded = urlParams.searchParams.get('payload'); const payloadDecoded = JSON.parse(atob(JSON.parse(payloadEncoded)[0])); + expect(server.requests.length).to.be.above(0); expect(payloadDecoded).to.have.property('adType', externalWinEvent.adType); - // reset iiqConfig.params.manualWinReportEnabled - USERID_CONFIG[0].params.manualWinReportEnabled = false; }); it('should send report to report-gdpr address if gdpr is detected', function () { @@ -313,7 +315,7 @@ describe('IntentIQ tests all', function () { }); it('should not send request if the browser is in blacklist (chrome)', function () { - const USERID_CONFIG_BROWSER = [...USERID_CONFIG]; + const USERID_CONFIG_BROWSER = [...getUserConfig()]; USERID_CONFIG_BROWSER[0].params.browserBlackList = 'ChrOmE'; config.getConfig.restore(); @@ -327,7 +329,7 @@ describe('IntentIQ tests all', function () { }); it('should send request if the browser is not in blacklist (safari)', function () { - const USERID_CONFIG_BROWSER = [...USERID_CONFIG]; + const USERID_CONFIG_BROWSER = [...getUserConfig()]; USERID_CONFIG_BROWSER[0].params.browserBlackList = 'chrome,firefox'; config.getConfig.restore(); From f1f5a0a9e56d9ba5d1216483bccdd4b79ea92282 Mon Sep 17 00:00:00 2001 From: dmytro-po Date: Fri, 7 Mar 2025 16:49:50 +0200 Subject: [PATCH 04/11] AGT-403: Documentation updated --- modules/intentIqAnalyticsAdapter.md | 4 +++- modules/intentIqIdSystem.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/intentIqAnalyticsAdapter.md b/modules/intentIqAnalyticsAdapter.md index 2a3eece0576..2f601658a3d 100644 --- a/modules/intentIqAnalyticsAdapter.md +++ b/modules/intentIqAnalyticsAdapter.md @@ -60,7 +60,8 @@ currency: 'USD', // Currency for the CPM value. originalCpm: 1.5, // Original CPM value. originalCurrency: 'USD', // Original currency. status: 'rendered', // Auction status, e.g., 'rendered'. -placementId: 'div-1' // ID of the ad placement. +placementId: 'div-1', // ID of the ad placement. +adType: 'banner' // Specifies the type of ad served } ``` @@ -76,6 +77,7 @@ placementId: 'div-1' // ID of the ad placement. | originalCurrency | String | Currency of the original auction | USD | No | | status | String | Status of the impression. Leave empty or undefined if Prebid is not the bidding platform | rendered | No | | placementId | String | Unique identifier of the ad unit on the webpage that showed this ad | div-1 | No | +| adType | String | Specifies the type of ad served. Possible values: “banner“, “video“, “native“, “audio“. | banner | No | To report the auction win, call the function as follows: diff --git a/modules/intentIqIdSystem.md b/modules/intentIqIdSystem.md index 44e4032e23d..d3eb1c8a2d8 100644 --- a/modules/intentIqIdSystem.md +++ b/modules/intentIqIdSystem.md @@ -38,7 +38,7 @@ Please find below list of paramters that could be used in configuring Intent IQ | params.partner | Required | Number | This is the partner ID value obtained from registering with IntentIQ. | `1177538` | | params.pcid | Optional | String | This is the partner cookie ID, it is a dynamic value attached to the request. | `"g3hC52b"` | | params.pai | Optional | String | This is the partner customer ID / advertiser ID, it is a dynamic value attached to the request. | `"advertiser1"` | -| params.callback | Required | Function | This is a callback which is trigered with data and AB group | `(data, group) => console.log({ data, group })` | +| params.callback | Optional | Function | This is a callback which is trigered with data and AB group | `(data, group) => console.log({ data, group })` | | params.timeoutInMillis | Optional | Number | This is the timeout in milliseconds, which defines the maximum duration before the callback is triggered. The default value is 500. | `450` | | params.browserBlackList | Optional |  String | This is the name of a browser that can be added to a blacklist. | `"chrome"` | | params.manualWinReportEnabled | Optional | Boolean | This variable determines whether the bidWon event is triggered automatically. If set to false, the event will occur automatically, and manual reporting with reportExternalWin will be disabled. If set to true, the event will not occur automatically, allowing manual reporting through reportExternalWin. The default value is false. | `true`| From b913180c17e748d2433a20c7bc9bef2f32ffecc9 Mon Sep 17 00:00:00 2001 From: dmytro-po Date: Mon, 17 Mar 2025 13:36:06 +0200 Subject: [PATCH 05/11] IntentIq Analytics Module: adUnitCode or placemetId to report (#9) * AGT-446: adUnitCode or placemetId to report * AGT-446: Description of changes, example * AGT-446: Fix documentation * AGT-446: Changes after review --- modules/intentIqAnalyticsAdapter.js | 55 +++++++++----- modules/intentIqIdSystem.md | 6 +- .../modules/intentIqAnalyticsAdapter_spec.js | 76 ++++++++++++++++++- 3 files changed, 116 insertions(+), 21 deletions(-) diff --git a/modules/intentIqAnalyticsAdapter.js b/modules/intentIqAnalyticsAdapter.js index 90c9b56c1d8..8554b383e8b 100644 --- a/modules/intentIqAnalyticsAdapter.js +++ b/modules/intentIqAnalyticsAdapter.js @@ -241,30 +241,49 @@ function prepareData (data, result) { if (adTypeValue) { result[PARAMS_NAMES.adType] = adTypeValue; } - if (data.placementId) { - result.placementId = data.placementId; - } else { - // Simplified placementId determination - let placeIdFound = false; - if (data.params && Array.isArray(data.params)) { - for (let i = 0; i < data.params.length; i++) { - const param = data.params[i]; - if (param.placementId) { - result.placementId = param.placementId; - placeIdFound = true; - break; - } - } - } - if (!placeIdFound && data.adUnitCode) { - result.placementId = data.adUnitCode; - } + const iiqConfig = getIntentIqConfig(); + const adUnitConfig = iiqConfig.params?.adUnitConfig; + + switch (adUnitConfig) { + case 1: + // adUnitCode or placementId + result.placementId = data.adUnitCode || extractPlacementId(data) || ''; + break; + case 2: + // placementId or adUnitCode + result.placementId = extractPlacementId(data) || data.adUnitCode || ''; + break; + case 3: + // Only adUnitCode + result.placementId = data.adUnitCode || ''; + break; + case 4: + // Only placementId + result.placementId = extractPlacementId(data) || ''; + break; + default: + // Default (like in case #1) + result.placementId = data.adUnitCode || extractPlacementId(data) || ''; } result.biddingPlatformId = 1; result.partnerAuctionId = 'BW'; } +function extractPlacementId(data) { + if (data.placementId) { + return data.placementId; + } + if (data.params && Array.isArray(data.params)) { + for (let i = 0; i < data.params.length; i++) { + if (data.params[i].placementId) { + return data.params[i].placementId; + } + } + } + return null; +} + function getDefaultDataObject() { return { 'inbbl': false, diff --git a/modules/intentIqIdSystem.md b/modules/intentIqIdSystem.md index d3eb1c8a2d8..39bbb47256f 100644 --- a/modules/intentIqIdSystem.md +++ b/modules/intentIqIdSystem.md @@ -41,10 +41,11 @@ Please find below list of paramters that could be used in configuring Intent IQ | params.callback | Optional | Function | This is a callback which is trigered with data and AB group | `(data, group) => console.log({ data, group })` | | params.timeoutInMillis | Optional | Number | This is the timeout in milliseconds, which defines the maximum duration before the callback is triggered. The default value is 500. | `450` | | params.browserBlackList | Optional |  String | This is the name of a browser that can be added to a blacklist. | `"chrome"` | -| params.manualWinReportEnabled | Optional | Boolean | This variable determines whether the bidWon event is triggered automatically. If set to false, the event will occur automatically, and manual reporting with reportExternalWin will be disabled. If set to true, the event will not occur automatically, allowing manual reporting through reportExternalWin. The default value is false. | `true`| +| params.manualWinReportEnabled | Optional | Boolean | This variable determines whether the bidWon event is triggered automatically. If set to false, the event will occur automatically, and manual reporting with reportExternalWin will be disabled. If set to true, the event will not occur automatically, allowing manual reporting through reportExternalWin. The default value is false. | `true` | | params.domainName | Optional | String | Specifies the domain of the page in which the IntentIQ object is currently running and serving the impression. This domain will be used later in the revenue reporting breakdown by domain. For example, cnn.com. It identifies the primary source of requests to the IntentIQ servers, even within nested web pages. | `"currentDomain.com"` | -| params.gamObjectReference | Optional | Object | This is a reference to the Google Ad Manager (GAM) object, which will be used to set targeting. If this parameter is not provided, the group reporting will not be configured. | `googletag` | +| params.gamObjectReference | Optional | Object | This is a reference to the Google Ad Manager (GAM) object, which will be used to set targeting. If this parameter is not provided, the group reporting will not be configured. | `googletag` | | params.gamParameterName | Optional | String | The name of the targeting parameter that will be used to pass the group. If not specified, the default value is `intent_iq_group`. | `"intent_iq_group"` | +| params.adUnitConfig | Optional | Number | Determines how the placementId parameter is extracted in the report (default is 1). Possible values: 1 – adUnitCode first, 2 – placementId first, 3 – only adUnitCode, 4 – only placementId | `1` | ### Configuration example @@ -60,6 +61,7 @@ pbjs.setConfig({ callback: (data, group) => window.pbjs.requestBids(), manualWinReportEnabled: true, domainName: "currentDomain.com", + adUnitConfig: 1 // Extracting placementId strategy (adUnitCode or placementId order of priorities) }, storage: { type: "html5", diff --git a/test/spec/modules/intentIqAnalyticsAdapter_spec.js b/test/spec/modules/intentIqAnalyticsAdapter_spec.js index 6a4af47948e..7697ed571e1 100644 --- a/test/spec/modules/intentIqAnalyticsAdapter_spec.js +++ b/test/spec/modules/intentIqAnalyticsAdapter_spec.js @@ -59,7 +59,6 @@ let wonRequest = { 'responseTimestamp': 1669644710345, 'requestTimestamp': 1669644710109, 'bidder': 'testbidder', - 'adUnitCode': 'addUnitCode', 'timeToRespond': 236, 'pbLg': '5.00', 'pbMg': '5.00', @@ -407,4 +406,79 @@ describe('IntentIQ tests all', function () { } }); }); + + const adUnitConfigTests = [ + { + adUnitConfig: 1, + description: 'should extract adUnitCode first (adUnitConfig = 1)', + event: { adUnitCode: 'adUnitCode-123', placementId: 'placementId-456' }, + expectedPlacementId: 'adUnitCode-123' + }, + { + adUnitConfig: 1, + description: 'should extract placementId if there is no adUnitCode (adUnitConfig = 1)', + event: { placementId: 'placementId-456' }, + expectedPlacementId: 'placementId-456' + }, + { + adUnitConfig: 2, + description: 'should extract placementId first (adUnitConfig = 2)', + event: { adUnitCode: 'adUnitCode-123', placementId: 'placementId-456' }, + expectedPlacementId: 'placementId-456' + }, + { + adUnitConfig: 2, + description: 'should extract adUnitCode if there is no placementId (adUnitConfig = 2)', + event: { adUnitCode: 'adUnitCode-123', }, + expectedPlacementId: 'adUnitCode-123' + }, + { + adUnitConfig: 3, + description: 'should extract only adUnitCode (adUnitConfig = 3)', + event: { adUnitCode: 'adUnitCode-123', placementId: 'placementId-456' }, + expectedPlacementId: 'adUnitCode-123' + }, + { + adUnitConfig: 4, + description: 'should extract only placementId (adUnitConfig = 4)', + event: { adUnitCode: 'adUnitCode-123', placementId: 'placementId-456' }, + expectedPlacementId: 'placementId-456' + }, + { + adUnitConfig: 1, + description: 'should return empty placementId if neither adUnitCode or placementId exist', + event: {}, + expectedPlacementId: '' + }, + { + adUnitConfig: 1, + description: 'should extract placementId from params array if no top-level adUnitCode or placementId exist (adUnitConfig = 1)', + event: { + params: [{ someKey: 'value' }, { placementId: 'nested-placementId' }] + }, + expectedPlacementId: 'nested-placementId' + } + ]; + + adUnitConfigTests.forEach(({ adUnitConfig, description, event, expectedPlacementId }) => { + it(description, function () { + const [userConfig] = getUserConfig(); + userConfig.params.adUnitConfig = adUnitConfig; + + config.getConfig.restore(); + sinon.stub(config, 'getConfig').withArgs('userSync.userIds').returns([userConfig]); + + const testEvent = { ...wonRequest, ...event }; + events.emit(EVENTS.BID_WON, testEvent); + + const request = server.requests[0]; + const urlParams = new URL(request.url); + const encodedPayload = urlParams.searchParams.get('payload'); + const decodedPayload = JSON.parse(atob(JSON.parse(encodedPayload)[0])); + + expect(server.requests.length).to.be.above(0); + expect(encodedPayload).to.exist; + expect(decodedPayload).to.have.property('placementId', expectedPlacementId); + }); + }); }); From 70274acb0d9e1e604f4b0098daadb4ac7fafe45c Mon Sep 17 00:00:00 2001 From: dLepetynskyiIntentiq Date: Tue, 18 Mar 2025 09:25:52 +0200 Subject: [PATCH 06/11] Agt 409 full url in prebid modules (#8) * add sync * update full url * set url param * fix comment * fix issue fix sync mode * update url * update full url * add test --- .../intentIqConstants/intentIqConstants.js | 20 +++- libraries/intentIqUtils/getRefferer.js | 15 ++- libraries/intentIqUtils/getSyncKey.js | 1 + modules/intentIqAnalyticsAdapter.js | 4 +- modules/intentIqIdSystem.js | 110 ++++++++++++++---- test/spec/modules/intentIqIdSystem_spec.js | 87 +++++++++++++- 6 files changed, 207 insertions(+), 30 deletions(-) create mode 100644 libraries/intentIqUtils/getSyncKey.js diff --git a/libraries/intentIqConstants/intentIqConstants.js b/libraries/intentIqConstants/intentIqConstants.js index 6dc16969d6c..a0f48caf97c 100644 --- a/libraries/intentIqConstants/intentIqConstants.js +++ b/libraries/intentIqConstants/intentIqConstants.js @@ -1,4 +1,5 @@ export const FIRST_PARTY_KEY = '_iiq_fdata'; + export const SUPPORTED_TYPES = ['html5', 'cookie'] export const WITH_IIQ = 'A'; @@ -8,4 +9,21 @@ export const BLACK_LIST = 'L'; export const CLIENT_HINTS_KEY = '_iiq_ch'; export const EMPTY = 'EMPTY'; export const GVLID = '1323'; -export const VERSION = 0.27; +export const VERSION = 0.28; + +export const VR_ENDPOINT = 'https://api.intentiq.com'; +export const GDPR_ENDPOINT = 'https://api-gdpr.intentiq.com'; +export const INVALID_ID = 'INVALID_ID'; + +export const SYNC_ENDPOINT = 'https://sync.intentiq.com' +export const GDPR_SYNC_ENDPOINT = 'https://sync-gdpr.intentiq.com' +export const SCREEN_PARAMS = { + 0: 'windowInnerHeight', + 1: 'windowInnerWidth', + 2: 'devicePixelRatio', + 3: 'windowScreenHeight', + 4: 'windowScreenWidth', + 5: 'language' +}; + +export const SYNC_REFRESH_MILL = 3600000; diff --git a/libraries/intentIqUtils/getRefferer.js b/libraries/intentIqUtils/getRefferer.js index 39fde70ac24..20c6a6a5b47 100644 --- a/libraries/intentIqUtils/getRefferer.js +++ b/libraries/intentIqUtils/getRefferer.js @@ -6,11 +6,16 @@ import { getWindowTop, logError, getWindowLocation, getWindowSelf } from '../../ */ export function getReferrer() { try { - if (getWindowSelf() === getWindowTop()) { - return encodeURIComponent(getWindowLocation().href); - } else { - return encodeURIComponent(getWindowTop().location.href); + const url = getWindowSelf() === getWindowTop() + ? getWindowLocation().href + : getWindowTop().location.href; + + if (url.length >= 50) { + const { origin } = new URL(url); + return origin; } + + return url; } catch (error) { logError(`Error accessing location: ${error}`); return ''; @@ -26,7 +31,7 @@ export function getReferrer() { * @return {string} The modified URL with appended `vrref` or `fui` parameters. */ export function appendVrrefAndFui(url, domainName) { - const fullUrl = getReferrer(); + const fullUrl = encodeURIComponent(getReferrer()); if (fullUrl) { return (url += '&vrref=' + getRelevantRefferer(domainName, fullUrl)); } diff --git a/libraries/intentIqUtils/getSyncKey.js b/libraries/intentIqUtils/getSyncKey.js new file mode 100644 index 00000000000..723a60e0059 --- /dev/null +++ b/libraries/intentIqUtils/getSyncKey.js @@ -0,0 +1 @@ +export const SYNC_KEY = (partner) => '_iiq_sync' + '_' + partner diff --git a/modules/intentIqAnalyticsAdapter.js b/modules/intentIqAnalyticsAdapter.js index 8554b383e8b..2adc664d9e1 100644 --- a/modules/intentIqAnalyticsAdapter.js +++ b/modules/intentIqAnalyticsAdapter.js @@ -130,7 +130,7 @@ function initReadLsIds() { iiqAnalyticsAnalyticsAdapter.initOptions.terminationCause = pData.terminationCause iiqAnalyticsAnalyticsAdapter.initOptions.dataInLs = pData.data; iiqAnalyticsAnalyticsAdapter.initOptions.eidl = pData.eidl || -1; - iiqAnalyticsAnalyticsAdapter.initOptions.ct = pData.ct || null; + iiqAnalyticsAnalyticsAdapter.initOptions.clientType = pData.clientType || null; iiqAnalyticsAnalyticsAdapter.initOptions.siteId = pData.siteId || null; iiqAnalyticsAnalyticsAdapter.initOptions.wsrvcll = pData.wsrvcll || false; iiqAnalyticsAnalyticsAdapter.initOptions.rrtt = pData.rrtt || null; @@ -189,7 +189,7 @@ export function preparePayload(data) { result[PARAMS_NAMES.referrer] = getReferrer(); result[PARAMS_NAMES.terminationCause] = iiqAnalyticsAnalyticsAdapter.initOptions.terminationCause; result[PARAMS_NAMES.abTestGroup] = iiqAnalyticsAnalyticsAdapter.initOptions.currentGroup; - result[PARAMS_NAMES.clientType] = iiqAnalyticsAnalyticsAdapter.initOptions.ct; + result[PARAMS_NAMES.clientType] = iiqAnalyticsAnalyticsAdapter.initOptions.clientType; result[PARAMS_NAMES.siteId] = iiqAnalyticsAnalyticsAdapter.initOptions.siteId; result[PARAMS_NAMES.wasServerCalled] = iiqAnalyticsAnalyticsAdapter.initOptions.wsrvcll; result[PARAMS_NAMES.requestRtt] = iiqAnalyticsAnalyticsAdapter.initOptions.rrtt; diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index 548af86d772..0e949c80676 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -22,8 +22,9 @@ import { CLIENT_HINTS_KEY, EMPTY, GVLID, - VERSION, + VERSION, INVALID_ID, GDPR_ENDPOINT, VR_ENDPOINT, SYNC_ENDPOINT, SCREEN_PARAMS, GDPR_SYNC_ENDPOINT, SYNC_REFRESH_MILL } from '../libraries/intentIqConstants/intentIqConstants.js'; +import {SYNC_KEY} from '../libraries/intentIqUtils/getSyncKey.js'; /** * @typedef {import('../modules/userId/index.js').Submodule} Submodule @@ -44,9 +45,7 @@ const encoderCH = { wow64: 7, fullVersionList: 8 }; -const INVALID_ID = 'INVALID_ID'; -const ENDPOINT = 'https://api.intentiq.com'; -const GDPR_ENDPOINT = 'https://api-gdpr.intentiq.com'; + export let firstPartyData; /** @@ -82,6 +81,78 @@ export function decryptData(encryptedText) { return bytes.toString(Utf8); } +function collectDeviceInfo() { + return { + windowInnerHeight: window.innerHeight, + windowInnerWidth: window.innerWidth, + devicePixelRatio: window.devicePixelRatio, + windowScreenHeight: window.screen.height, + windowScreenWidth: window.screen.width, + language: navigator.language + } +} + +function addUniquenessToUrl(url) { + url += '&tsrnd=' + Math.floor(Math.random() * 1000) + '_' + new Date().getTime(); + return url; +} + +function appendDeviceInfoToUrl(url, deviceInfo) { + const screenParamsString = Object.entries(SCREEN_PARAMS) + .map(([index, param]) => { + const value = (deviceInfo)[param]; + return `${index}:${value}`; + }) + .join(','); + + url += `&cz=${encodeURIComponent(screenParamsString)}`; + url += `&dw=${deviceInfo.windowScreenWidth}&dh=${deviceInfo.windowScreenHeight}&dpr=${deviceInfo.devicePixelRatio}&lan=${deviceInfo.language}`; + return url; +} + +function appendFirstPartyData (url, firstPartyData, partnerData) { + url += firstPartyData.pid ? '&pid=' + encodeURIComponent(firstPartyData.pid) : ''; + url += firstPartyData.pcid ? '&iiqidtype=2&iiqpcid=' + encodeURIComponent(firstPartyData.pcid) : ''; + url += firstPartyData.pcidDate ? '&iiqpciddate=' + encodeURIComponent(firstPartyData.pcidDate) : ''; + return url +} + +function appendCMPData (url, cmpData) { + url += cmpData.uspString ? '&us_privacy=' + encodeURIComponent(cmpData.uspString) : ''; + url += cmpData.gppString ? '&gpp=' + encodeURIComponent(cmpData.gppString) : ''; + url += cmpData.gdprApplies + ? '&gdpr_consent=' + encodeURIComponent(cmpData.gdprString) + '&gdpr=1' + : '&gdpr=0'; + return url +} + +export function createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData) { + const deviceInfo = collectDeviceInfo() + + let url = cmpData.gdprString ? GDPR_SYNC_ENDPOINT : SYNC_ENDPOINT; + url += '/profiles_engine/ProfilesEngineServlet?at=20&mi=10&secure=1' + url += '&dpi=' + configParams.partner; + url = appendFirstPartyData(url, firstPartyData, partnerData); + url = addUniquenessToUrl(url); + url += partnerData?.clientType ? '&idtype=' + partnerData.clientType : ''; + if (deviceInfo) url = appendDeviceInfoToUrl(url, deviceInfo) + url += VERSION ? '&jsver=' + VERSION : ''; + if (clientHints) url += '&uh=' + encodeURIComponent(clientHints); + url = appendVrrefAndFui(url, configParams.domainName); + url = appendCMPData(url, cmpData) + return url; +} + +function sendSyncRequest(allowedStorage, url, partner) { + const lastSyncDate = Number(readData(SYNC_KEY(partner) || '', allowedStorage)) || false; + const lastSyncElapsedTime = Date.now() - lastSyncDate + if (!lastSyncDate || lastSyncElapsedTime > SYNC_REFRESH_MILL) { + storeData(SYNC_KEY(partner), Date.now() + '', allowedStorage); + ajax(url, () => { + }, undefined, {method: 'GET', withCredentials: true}); + } +} + /** * Parse json if possible, else return null * @param data @@ -161,6 +232,7 @@ export const intentIqIdSubmodule = { decode(value) { return value && value != '' && INVALID_ID != value ? {'intentIqId': value} : undefined; }, + /** * performs action to obtain id and return a value in the callback's response argument * @function @@ -211,13 +283,6 @@ export const intentIqIdSubmodule = { const currentBrowserLowerCase = detectBrowser(); const browserBlackList = typeof configParams.browserBlackList === 'string' ? configParams.browserBlackList.toLowerCase() : ''; - // Check if current browser is in blacklist - if (browserBlackList?.includes(currentBrowserLowerCase)) { - logError('User ID - intentIqId submodule: browser is in blacklist!'); - if (configParams.callback) configParams.callback('', BLACK_LIST); - return; - } - if (!firstPartyData?.pcid) { const firstPartyId = generateGUID(); firstPartyData = { @@ -303,20 +368,23 @@ export const intentIqIdSubmodule = { return { id: runtimeEids.eids }; } + // Check if current browser is in blacklist + if (browserBlackList?.includes(currentBrowserLowerCase)) { + logError('User ID - intentIqId submodule: browser is in blacklist!'); + if (configParams.callback) configParams.callback('', BLACK_LIST); + const url = createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData) + sendSyncRequest(allowedStorage, url, configParams.partner) + return + } + // use protocol relative urls for http or https - let url = `${gdprDetected ? GDPR_ENDPOINT : ENDPOINT}/profiles_engine/ProfilesEngineServlet?at=39&mi=10&dpi=${configParams.partner}&pt=17&dpn=1`; + let url = `${gdprDetected ? GDPR_ENDPOINT : VR_ENDPOINT}/profiles_engine/ProfilesEngineServlet?at=39&mi=10&dpi=${configParams.partner}&pt=17&dpn=1`; url += configParams.pcid ? '&pcid=' + encodeURIComponent(configParams.pcid) : ''; url += configParams.pai ? '&pai=' + encodeURIComponent(configParams.pai) : ''; - url += firstPartyData.pcid ? '&iiqidtype=2&iiqpcid=' + encodeURIComponent(firstPartyData.pcid) : ''; - url += firstPartyData.pid ? '&pid=' + encodeURIComponent(firstPartyData.pid) : ''; + url = appendFirstPartyData(url, firstPartyData, partnerData); url += (partnerData.cttl) ? '&cttl=' + encodeURIComponent(partnerData.cttl) : ''; url += (partnerData.rrtt) ? '&rrtt=' + encodeURIComponent(partnerData.rrtt) : ''; - url += firstPartyData.pcidDate ? '&iiqpciddate=' + encodeURIComponent(firstPartyData.pcidDate) : ''; - url += cmpData.uspString ? '&us_privacy=' + encodeURIComponent(cmpData.uspString) : ''; - url += cmpData.gppString ? '&gpp=' + encodeURIComponent(cmpData.gppString) : ''; - url += cmpData.gdprApplies - ? '&gdpr_consent=' + encodeURIComponent(cmpData.gdprString) + '&gdpr=1' - : '&gdpr=0'; + url = appendCMPData(url, cmpData) url += clientHints ? '&uh=' + encodeURIComponent(clientHints) : ''; url += VERSION ? '&jsver=' + VERSION : ''; url += firstPartyData?.group ? '&testGroup=' + encodeURIComponent(firstPartyData.group) : ''; @@ -403,7 +471,7 @@ export const intentIqIdSubmodule = { } if ('ct' in respJson) { - partnerData.ct = respJson.ct; + partnerData.clientType = respJson.ct; } if ('sid' in respJson) { diff --git a/test/spec/modules/intentIqIdSystem_spec.js b/test/spec/modules/intentIqIdSystem_spec.js index d4220710c1f..b2837f6e467 100644 --- a/test/spec/modules/intentIqIdSystem_spec.js +++ b/test/spec/modules/intentIqIdSystem_spec.js @@ -1,7 +1,13 @@ import { expect } from 'chai'; import * as utils from 'src/utils.js'; import { server } from 'test/mocks/xhr.js'; -import { intentIqIdSubmodule, decryptData, handleClientHints, firstPartyData as moduleFPD } from '../../../modules/intentIqIdSystem'; +import { + intentIqIdSubmodule, + decryptData, + handleClientHints, + firstPartyData as moduleFPD, + isCMPStringTheSame, createPixelUrl +} from '../../../modules/intentIqIdSystem'; import {storage, readData} from '../../../libraries/intentIqUtils/storageUtils.js'; import { gppDataHandler, uspDataHandler, gdprDataHandler } from '../../../src/consentHandler'; import { clearAllCookies } from '../../helpers/cookies'; @@ -589,6 +595,85 @@ describe('IntentIQ tests', function () { expect(savedClientHints).to.equal(expectedClientHints); }); + it('should return true if CMP strings are the same', function () { + const fpData = { gdprString: '123', gppString: '456', uspString: '789' }; + const cmpData = { gdprString: '123', gppString: '456', uspString: '789' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.true; + }); + + it('should return false if gdprString is different', function () { + const fpData = { gdprString: '123', gppString: '456', uspString: '789' }; + const cmpData = { gdprString: '321', gppString: '456', uspString: '789' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should return false if gppString is different', function () { + const fpData = { gdprString: '123', gppString: '456', uspString: '789' }; + const cmpData = { gdprString: '123', gppString: '654', uspString: '789' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should return false if uspString is different', function () { + const fpData = { gdprString: '123', gppString: '456', uspString: '789' }; + const cmpData = { gdprString: '123', gppString: '456', uspString: '987' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should return false if one of the properties is missing in fpData', function () { + const fpData = { gdprString: '123', gppString: '456' }; + const cmpData = { gdprString: '123', gppString: '456', uspString: '789' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should return false if one of the properties is missing in cmpData', function () { + const fpData = { gdprString: '123', gppString: '456', uspString: '789' }; + const cmpData = { gdprString: '123', gppString: '456' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should return true if both objects are empty', function () { + const fpData = {}; + const cmpData = {}; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.true; + }); + + it('should return false if one object is empty and another is not', function () { + const fpData = {}; + const cmpData = { gdprString: '123', gppString: '456', uspString: '789' }; + + expect(isCMPStringTheSame(fpData, cmpData)).to.be.false; + }); + + it('should add clientHints to the URL if provided', function () { + const firstPartyData = {}; + const clientHints = 'exampleClientHints'; + const configParams = { partner: 'testPartner', domainName: 'example.com' }; + const partnerData = {}; + const cmpData = {}; + + const url = createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData); + + expect(url).to.include(`&uh=${encodeURIComponent(clientHints)}`); + }); + + it('should not add clientHints to the URL if not provided', function () { + const firstPartyData = {}; + const configParams = { partner: 'testPartner', domainName: 'example.com' }; + const partnerData = {}; + const cmpData = {}; + + const url = createPixelUrl(firstPartyData, undefined, configParams, partnerData, cmpData); + + expect(url).to.not.include('&uh='); + }); + it('should run callback from params', async () => { let wasCallbackCalled = false const callbackConfigParams = { params: { partner: partner, From 17251b55f14a2b720953615d6c9c35b2d069bc65 Mon Sep 17 00:00:00 2001 From: dLepetynskyiIntentiq Date: Tue, 18 Mar 2025 14:21:49 +0200 Subject: [PATCH 07/11] move browser_blacklist (#10) --- modules/intentIqIdSystem.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index 0e949c80676..d458f4542d9 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -362,21 +362,21 @@ export const intentIqIdSubmodule = { firePartnerCallback() } - if (!shouldCallServer) { - if (isGroupB) runtimeEids = { eids: [] }; - firePartnerCallback(); - return { id: runtimeEids.eids }; - } - // Check if current browser is in blacklist if (browserBlackList?.includes(currentBrowserLowerCase)) { - logError('User ID - intentIqId submodule: browser is in blacklist!'); + logError('User ID - intentIqId submodule: browser is in blacklist! Data will be not provided.'); if (configParams.callback) configParams.callback('', BLACK_LIST); const url = createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData) sendSyncRequest(allowedStorage, url, configParams.partner) return } + if (!shouldCallServer) { + if (isGroupB) runtimeEids = { eids: [] }; + firePartnerCallback(); + return { id: runtimeEids.eids }; + } + // use protocol relative urls for http or https let url = `${gdprDetected ? GDPR_ENDPOINT : VR_ENDPOINT}/profiles_engine/ProfilesEngineServlet?at=39&mi=10&dpi=${configParams.partner}&pt=17&dpn=1`; url += configParams.pcid ? '&pcid=' + encodeURIComponent(configParams.pcid) : ''; From 5944451e347c8457a4ca9769bde9d5aebca25aac Mon Sep 17 00:00:00 2001 From: dLepetynskyiIntentiq Date: Wed, 19 Mar 2025 11:51:56 +0200 Subject: [PATCH 08/11] add is optedOut (#11) --- modules/intentIqIdSystem.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index d458f4542d9..a23de562c58 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -143,13 +143,22 @@ export function createPixelUrl(firstPartyData, clientHints, configParams, partne return url; } -function sendSyncRequest(allowedStorage, url, partner) { +function sendSyncRequest(allowedStorage, url, partner, firstPartyData) { const lastSyncDate = Number(readData(SYNC_KEY(partner) || '', allowedStorage)) || false; const lastSyncElapsedTime = Date.now() - lastSyncDate - if (!lastSyncDate || lastSyncElapsedTime > SYNC_REFRESH_MILL) { - storeData(SYNC_KEY(partner), Date.now() + '', allowedStorage); - ajax(url, () => { - }, undefined, {method: 'GET', withCredentials: true}); + + if (firstPartyData.isOptedOut) { + const needToDoSync = (Date.now() - (firstPartyData?.date || firstPartyData?.sCal || Date.now())) > SYNC_REFRESH_MILL + if (needToDoSync) { + ajax(url, () => { + }, undefined, {method: 'GET', withCredentials: true}); + } + } else { + if (!lastSyncDate || lastSyncElapsedTime > SYNC_REFRESH_MILL) { + storeData(SYNC_KEY(partner), Date.now() + '', allowedStorage); + ajax(url, () => { + }, undefined, {method: 'GET', withCredentials: true}); + } } } @@ -367,7 +376,7 @@ export const intentIqIdSubmodule = { logError('User ID - intentIqId submodule: browser is in blacklist! Data will be not provided.'); if (configParams.callback) configParams.callback('', BLACK_LIST); const url = createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData) - sendSyncRequest(allowedStorage, url, configParams.partner) + sendSyncRequest(allowedStorage, url, configParams.partner, firstPartyData) return } From af9b59e44317f73bd63a69420a5f730ce7bc56c0 Mon Sep 17 00:00:00 2001 From: dLepetynskyiIntentiq Date: Wed, 19 Mar 2025 14:13:40 +0200 Subject: [PATCH 09/11] update date in FPD after sync (#12) --- modules/intentIqIdSystem.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index a23de562c58..26dc2280128 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -152,13 +152,15 @@ function sendSyncRequest(allowedStorage, url, partner, firstPartyData) { if (needToDoSync) { ajax(url, () => { }, undefined, {method: 'GET', withCredentials: true}); + if (firstPartyData?.date) { + firstPartyData.date = Date.now() + storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData), allowedStorage, firstPartyData); + } } - } else { - if (!lastSyncDate || lastSyncElapsedTime > SYNC_REFRESH_MILL) { - storeData(SYNC_KEY(partner), Date.now() + '', allowedStorage); - ajax(url, () => { - }, undefined, {method: 'GET', withCredentials: true}); - } + } else if (!lastSyncDate || lastSyncElapsedTime > SYNC_REFRESH_MILL) { + storeData(SYNC_KEY(partner), Date.now() + '', allowedStorage); + ajax(url, () => { + }, undefined, {method: 'GET', withCredentials: true}); } } From e22894e9ca6bef3bf553822e1f326fbf05b44144 Mon Sep 17 00:00:00 2001 From: DimaIntentIQ <139111483+DimaIntentIQ@users.noreply.github.com> Date: Wed, 19 Mar 2025 17:21:45 +0200 Subject: [PATCH 10/11] update sync logic for new user (#13) --- modules/intentIqIdSystem.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index 26dc2280128..f4a1b316adc 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -143,13 +143,13 @@ export function createPixelUrl(firstPartyData, clientHints, configParams, partne return url; } -function sendSyncRequest(allowedStorage, url, partner, firstPartyData) { +function sendSyncRequest(allowedStorage, url, partner, firstPartyData, newUser) { const lastSyncDate = Number(readData(SYNC_KEY(partner) || '', allowedStorage)) || false; const lastSyncElapsedTime = Date.now() - lastSyncDate if (firstPartyData.isOptedOut) { const needToDoSync = (Date.now() - (firstPartyData?.date || firstPartyData?.sCal || Date.now())) > SYNC_REFRESH_MILL - if (needToDoSync) { + if (newUser || needToDoSync) { ajax(url, () => { }, undefined, {method: 'GET', withCredentials: true}); if (firstPartyData?.date) { @@ -293,6 +293,7 @@ export const intentIqIdSubmodule = { const currentBrowserLowerCase = detectBrowser(); const browserBlackList = typeof configParams.browserBlackList === 'string' ? configParams.browserBlackList.toLowerCase() : ''; + let newUser = false; if (!firstPartyData?.pcid) { const firstPartyId = generateGUID(); @@ -306,6 +307,7 @@ export const intentIqIdSubmodule = { gdprString: EMPTY, date: Date.now() }; + newUser = true; storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData), allowedStorage, firstPartyData); } else if (!firstPartyData.pcidDate) { firstPartyData.pcidDate = Date.now(); @@ -360,7 +362,6 @@ export const intentIqIdSubmodule = { firstPartyData.uspString = cmpData.uspString; firstPartyData.gppString = cmpData.gppString; firstPartyData.gdprString = cmpData.gdprString; - firstPartyData.date = Date.now(); shouldCallServer = true; storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData), allowedStorage, firstPartyData); storeData(FIRST_PARTY_DATA_KEY, JSON.stringify(partnerData), allowedStorage, firstPartyData); @@ -378,7 +379,7 @@ export const intentIqIdSubmodule = { logError('User ID - intentIqId submodule: browser is in blacklist! Data will be not provided.'); if (configParams.callback) configParams.callback('', BLACK_LIST); const url = createPixelUrl(firstPartyData, clientHints, configParams, partnerData, cmpData) - sendSyncRequest(allowedStorage, url, configParams.partner, firstPartyData) + sendSyncRequest(allowedStorage, url, configParams.partner, firstPartyData, newUser) return } From 3f45a848b725b8f05e0d4b8925e836e0a470f488 Mon Sep 17 00:00:00 2001 From: DimaIntentIQ Date: Wed, 19 Mar 2025 18:17:48 +0200 Subject: [PATCH 11/11] fix unit tests --- test/spec/modules/intentIqAnalyticsAdapter_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/intentIqAnalyticsAdapter_spec.js b/test/spec/modules/intentIqAnalyticsAdapter_spec.js index 7697ed571e1..eccff1165cd 100644 --- a/test/spec/modules/intentIqAnalyticsAdapter_spec.js +++ b/test/spec/modules/intentIqAnalyticsAdapter_spec.js @@ -289,7 +289,7 @@ describe('IntentIQ tests all', function () { getWindowLocationStub = sinon.stub(utils, 'getWindowLocation').returns({ href: 'http://localhost:9876/' }); const referrer = getReferrer(); - expect(referrer).to.equal(encodeURIComponent('http://localhost:9876/')); + expect(referrer).to.equal('http://localhost:9876/'); }); it('should return window.top.location.href when window.self !== window.top and access is successful', function () { @@ -299,7 +299,7 @@ describe('IntentIQ tests all', function () { const referrer = getReferrer(); - expect(referrer).to.equal(encodeURIComponent('http://example.com/')); + expect(referrer).to.equal('http://example.com/'); }); it('should return an empty string and log an error when accessing window.top.location.href throws an error', function () {