From b65e527b0a65207f5ca72a165dc6823e8410156f Mon Sep 17 00:00:00 2001 From: tech-infra-rudderstack Date: Wed, 1 Jul 2026 08:58:03 +0000 Subject: [PATCH 1/8] feat: wire amplitude v2 autocapture toggles --- .agents/knowledge/entry-points.md | 5 + .agents/knowledge/patterns.md | 5 + .../integrations/Amplitude/browser.test.js | 126 +++++++++++++++--- .../integrations/Amplitude/util.test.js | 59 ++++++++ .../src/integrations/Amplitude/browser.js | 37 +++-- .../src/integrations/Amplitude/constants.js | 18 +++ .../src/integrations/Amplitude/utils.js | 53 ++++++++ 7 files changed, 272 insertions(+), 31 deletions(-) diff --git a/.agents/knowledge/entry-points.md b/.agents/knowledge/entry-points.md index 2d5389772..c9eedd583 100644 --- a/.agents/knowledge/entry-points.md +++ b/.agents/knowledge/entry-points.md @@ -16,3 +16,8 @@ - `packages/analytics-js/src/components/core/Analytics.ts` — v3 lifecycle engine, service composition, and initialization sequence (`packages/analytics-js/src/components/core/Analytics.ts::Analytics`). - `packages/analytics-v1.1/src/core/analytics.js` — legacy line core implementation (class-centric runtime still shipped as `rudder-sdk-js`) (`packages/analytics-v1.1/src/core/analytics.js::Analytics`). - `packages/loading-scripts/src/index.ts` — snippet loader that buffers calls and chooses modern vs legacy runtime script dynamically (`packages/loading-scripts/src/index.ts:1`). + +## SDK-5014 — Amplitude V2 Autocapture Entry Points + +- Amplitude device-mode integration work lives under `packages/analytics-js-integrations/src/integrations/Amplitude/`; for v2 autocapture changes, start with `browser.js` for initialization, `utils.js` for helper getters, and `constants.js` for integration constants. +- Existing Jest coverage for Amplitude Browser SDK v2 initialization payload shape is in `packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js`; helper behavior is covered in `packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js`. diff --git a/.agents/knowledge/patterns.md b/.agents/knowledge/patterns.md index 98a2fa94a..a6c66fa4d 100644 --- a/.agents/knowledge/patterns.md +++ b/.agents/knowledge/patterns.md @@ -17,3 +17,8 @@ - Plugin calls prefer extension-point invocation (`invokeSingle`/`invokeMultiple`) to keep queue and destination behaviors swappable (`packages/analytics-js/src/services/PluginEngine/PluginEngine.ts::PluginEngine.invokeSingle`). - Load-time buffering is a consistent behavior: preload snippet arrays and in-memory queues are drained after initialization to preserve call order (`packages/loading-scripts/src/index.ts:12`, `packages/analytics-js/src/components/core/Analytics.ts::Analytics.processDataInPreloadBuffer`). - Legacy v1.1 still follows class-centric mutable state and explicit polling for integration readiness (`allModulesInitialized` Promise loop), unlike v3 reactive effects (`packages/analytics-v1.1/src/core/analytics.js::Analytics.allModulesInitialized`). + +## SDK-5014 — Amplitude V2 Autocapture Config Boundaries + +- Amplitude Browser SDK v2 autocapture config is assembled in `packages/analytics-js-integrations/src/integrations/Amplitude/browser.js:init()` using helper getters from `packages/analytics-js-integrations/src/integrations/Amplitude/utils.js`. +- The dedicated `autoCapturePageViews` config key maps only to the Amplitude SDK `autocapture.pageViews` option; it intentionally does not affect Rudder `page()` translation gates such as `trackAllPages`, `trackCategorizedPages`, or `trackNamedPages`. diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js index 4716db813..2ba05b07b 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js @@ -66,6 +66,19 @@ const destinationInfo = { destinationId: 'sample-destination-id', }; +const defaultV2Autocapture = { + attribution: true, + pageViews: false, + sessions: false, + formInteractions: false, + fileDownloads: false, + elementInteractions: false, + frustrationInteractions: false, + networkTracking: false, + webVitals: false, + pageUrlEnrichment: false, +}; + describe('Amplitude', () => { beforeAll(() => { // Add a dummy script as it is required by the init script @@ -277,18 +290,7 @@ describe('Amplitude', () => { expect(window.amplitude._q[0].name).toBe('init'); expect(window.amplitude._q[0].args[1]).toBeUndefined(); expect(window.amplitude._q[0].args[2]).toMatchObject({ - autocapture: { - attribution: true, - pageViews: false, - sessions: false, - formInteractions: false, - fileDownloads: false, - elementInteractions: false, - frustrationInteractions: false, - networkTracking: false, - webVitals: false, - pageUrlEnrichment: false, - }, + autocapture: defaultV2Autocapture, serverUrl: 'https://some.proxyserverurl.com', }); expect(window.amplitude._q[0].args[2].attribution).toBeUndefined(); @@ -309,22 +311,71 @@ describe('Amplitude', () => { expect(document.querySelector(`script[src="${AMPLITUDE_V2_SDK_URL}"]`)).toBeTruthy(); expect(window.amplitude._q[0].args[2]).toMatchObject({ autocapture: { + ...defaultV2Autocapture, attribution: false, - pageViews: false, - sessions: false, - formInteractions: false, - fileDownloads: false, - elementInteractions: false, - frustrationInteractions: false, - networkTracking: false, - webVitals: false, - pageUrlEnrichment: false, }, serverUrl: 'https://some.proxyserverurl.com', }); expect(window.amplitude._q[0].args[2].attribution).toBeUndefined(); }); + it.each([ + ['autoCapturePageViews', 'pageViews', true], + ['pageUrlEnrichment', 'pageUrlEnrichment', true], + ['trackSessionEvents', 'sessions', { web: true }], + ['webVitals', 'webVitals', true], + ['fileDownloads', 'fileDownloads', true], + ['frustrationInteractions', 'frustrationInteractions', true], + ['networkTracking', 'networkTracking', true], + ['elementInteractions', 'elementInteractions', true], + ['formInteractions', 'formInteractions', true], + ])( + 'should map %s config to only autocapture.%s for v2', + (configKey, autocaptureKey, configValue) => { + const amplitude = new Amplitude( + { + ...destinationConfig, + sdkVersion: 2, + attribution: false, + [configKey]: configValue, + }, + analyticsInstance, + destinationInfo, + ); + amplitude.init(); + + expect(window.amplitude._q[0].args[2].autocapture).toStrictEqual({ + ...defaultV2Autocapture, + [autocaptureKey]: true, + }); + }, + ); + + it('should keep auto-capture page views independent from user-instrumented page toggles', () => { + const amplitude = new Amplitude( + { + ...destinationConfig, + sdkVersion: 2, + attribution: false, + autoCapturePageViews: true, + trackAllPages: false, + trackCategorizedPages: false, + trackNamedPages: false, + }, + analyticsInstance, + destinationInfo, + ); + amplitude.init(); + + expect(window.amplitude._q[0].args[2].autocapture).toStrictEqual({ + ...defaultV2Autocapture, + pageViews: true, + }); + expect(amplitude.trackAllPages).toBe(false); + expect(amplitude.trackCategorizedPages).toBe(false); + expect(amplitude.trackNamedPages).toBe(false); + }); + it('should set the correct SRI integrity on the injected v1 script', () => { const amplitude = new Amplitude( { ...destinationConfig, sdkVersion: 1 }, @@ -1075,6 +1126,39 @@ describe('Amplitude', () => { expect(spy).toHaveBeenCalledWith('Viewed page NAME', {}); }); + + it('should not translate page calls when only v2 auto-capture page views is enabled', () => { + const config = { + apiKey: 'YOUR_AMPLITUDE_API_KEY', + sdkVersion: 2, + autoCapturePageViews: true, + trackAllPages: false, + trackCategorizedPages: false, + trackNamedPages: false, + }; + + const analytics = { + logLevel: 'debug', + getAnonymousId: () => 'ANONYMOUS_ID', + }; + + const rudderElement = { + message: { + properties: {}, + name: 'NAME', + category: 'CATEGORY', + integrations: {}, + }, + }; + + const amplitude = new Amplitude(config, analytics, destinationInfo); + const spy = jest.spyOn(window.amplitude, 'track'); + spy.mockClear(); + + amplitude.page(rudderElement); + + expect(spy).not.toHaveBeenCalled(); + }); }); describe('group', () => { diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js index ecba4f0ba..e4bf6a201 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js @@ -5,6 +5,15 @@ import { getDestinationOptions, formatUrl, getAmplitudeSdkVersion, + getAutoCapturePageViews, + getPageUrlEnrichment, + getTrackSessionEvents, + getWebVitals, + getFileDownloads, + getFrustrationInteractions, + getNetworkTracking, + getElementInteractions, + getFormInteractions, } from '../../../src/integrations/Amplitude/utils'; describe('getTraitsToSetOnce', () => { @@ -210,3 +219,53 @@ describe('getAmplitudeSdkVersion', () => { expect(getAmplitudeSdkVersion({ sdkVersion: '2' })).toBe(2); }); }); + +describe('Amplitude v2 autocapture config helpers', () => { + const helperCases = [ + { + name: 'getAutoCapturePageViews', + getter: getAutoCapturePageViews, + key: 'autoCapturePageViews', + }, + { name: 'getPageUrlEnrichment', getter: getPageUrlEnrichment, key: 'pageUrlEnrichment' }, + { name: 'getWebVitals', getter: getWebVitals, key: 'webVitals' }, + { name: 'getFileDownloads', getter: getFileDownloads, key: 'fileDownloads' }, + { + name: 'getFrustrationInteractions', + getter: getFrustrationInteractions, + key: 'frustrationInteractions', + }, + { name: 'getNetworkTracking', getter: getNetworkTracking, key: 'networkTracking' }, + { name: 'getElementInteractions', getter: getElementInteractions, key: 'elementInteractions' }, + { name: 'getFormInteractions', getter: getFormInteractions, key: 'formInteractions' }, + ]; + + it.each(helperCases)('$name should default missing config to false', ({ getter }) => { + expect(getter({})).toBe(false); + }); + + it.each(helperCases)('$name should read true and false config values', ({ getter, key }) => { + expect(getter({ [key]: true })).toBe(true); + expect(getter({ [key]: false })).toBe(false); + }); + + it('getTrackSessionEvents should default missing config to false', () => { + expect(getTrackSessionEvents({})).toBe(false); + }); + + it('getTrackSessionEvents should read the web source value shape', () => { + expect(getTrackSessionEvents({ trackSessionEvents: { web: true } })).toBe(true); + expect(getTrackSessionEvents({ trackSessionEvents: { web: false } })).toBe(false); + expect(getTrackSessionEvents({ trackSessionEvents: { web: { enabled: true } } })).toBe(true); + expect(getTrackSessionEvents({ trackSessionEvents: { web: { enabled: false } } })).toBe(false); + }); + + it('getTrackSessionEvents should ignore non-web source values', () => { + expect(getTrackSessionEvents({ trackSessionEvents: { android: true, ios: true } })).toBe(false); + }); + + it('getTrackSessionEvents should support legacy boolean values', () => { + expect(getTrackSessionEvents({ trackSessionEvents: true })).toBe(true); + expect(getTrackSessionEvents({ trackSessionEvents: false })).toBe(false); + }); +}); diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js b/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js index dd3894080..05250ec02 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/browser.js @@ -11,6 +11,15 @@ import { getFieldsToUnset, formatUrl, getAmplitudeSdkVersion, + getAutoCapturePageViews, + getPageUrlEnrichment, + getTrackSessionEvents, + getWebVitals, + getFileDownloads, + getFrustrationInteractions, + getNetworkTracking, + getElementInteractions, + getFormInteractions, } from './utils'; import { getValueOrDefault } from '../../utils/utils'; @@ -44,6 +53,15 @@ class Amplitude { this.groupTypeTrait = config.groupTypeTrait; this.groupValueTrait = config.groupValueTrait; this.sdkVersion = getAmplitudeSdkVersion(config); + this.autoCapturePageViews = getAutoCapturePageViews(config); + this.pageUrlEnrichment = getPageUrlEnrichment(config); + this.trackSessionEvents = getTrackSessionEvents(config); + this.webVitals = getWebVitals(config); + this.fileDownloads = getFileDownloads(config); + this.frustrationInteractions = getFrustrationInteractions(config); + this.networkTracking = getNetworkTracking(config); + this.elementInteractions = getElementInteractions(config); + this.formInteractions = getFormInteractions(config); ({ shouldApplyDeviceModeTransformation: this.shouldApplyDeviceModeTransformation, propagateEventsUntransformedOnError: this.propagateEventsUntransformedOnError, @@ -69,18 +87,17 @@ class Amplitude { this.sdkVersion === AMPLITUDE_SDK_V2 ? { ...commonInitOptions, - // Enable only attribution in v2; all other autocapture toggles stay off. autocapture: { attribution: !this.attribution, - pageViews: false, - sessions: false, - formInteractions: false, - fileDownloads: false, - elementInteractions: false, - frustrationInteractions: false, - networkTracking: false, - webVitals: false, - pageUrlEnrichment: false, + pageViews: this.autoCapturePageViews, + sessions: this.trackSessionEvents, + formInteractions: this.formInteractions, + fileDownloads: this.fileDownloads, + elementInteractions: this.elementInteractions, + frustrationInteractions: this.frustrationInteractions, + networkTracking: this.networkTracking, + webVitals: this.webVitals, + pageUrlEnrichment: this.pageUrlEnrichment, }, } : { diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js b/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js index 36c59c6dc..7e1e70bef 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js @@ -2,6 +2,15 @@ import { AM_NAME as NAME, AM_DISPLAY_NAME as DISPLAY_NAME } from '../../constant const DIR_NAME = 'Amplitude'; const AMPLITUDE_SDK_VERSION_CONFIG_KEY = 'sdkVersion'; +const AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY = 'autoCapturePageViews'; +const AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY = 'pageUrlEnrichment'; +const AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY = 'trackSessionEvents'; +const AMPLITUDE_WEB_VITALS_CONFIG_KEY = 'webVitals'; +const AMPLITUDE_FILE_DOWNLOADS_CONFIG_KEY = 'fileDownloads'; +const AMPLITUDE_FRUSTRATION_INTERACTIONS_CONFIG_KEY = 'frustrationInteractions'; +const AMPLITUDE_NETWORK_TRACKING_CONFIG_KEY = 'networkTracking'; +const AMPLITUDE_ELEMENT_INTERACTIONS_CONFIG_KEY = 'elementInteractions'; +const AMPLITUDE_FORM_INTERACTIONS_CONFIG_KEY = 'formInteractions'; const AMPLITUDE_SDK_V1 = 1; const AMPLITUDE_SDK_V2 = 2; @@ -18,6 +27,15 @@ export { DISPLAY_NAME, DIR_NAME, AMPLITUDE_SDK_VERSION_CONFIG_KEY, + AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY, + AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY, + AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY, + AMPLITUDE_WEB_VITALS_CONFIG_KEY, + AMPLITUDE_FILE_DOWNLOADS_CONFIG_KEY, + AMPLITUDE_FRUSTRATION_INTERACTIONS_CONFIG_KEY, + AMPLITUDE_NETWORK_TRACKING_CONFIG_KEY, + AMPLITUDE_ELEMENT_INTERACTIONS_CONFIG_KEY, + AMPLITUDE_FORM_INTERACTIONS_CONFIG_KEY, AMPLITUDE_SDK_V1, AMPLITUDE_SDK_V2, }; diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js b/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js index cd5d3d69d..9a0ee98c6 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js @@ -4,6 +4,15 @@ import { AMPLITUDE_SDK_V1, AMPLITUDE_SDK_V2, AMPLITUDE_SDK_VERSION_CONFIG_KEY, + AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY, + AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY, + AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY, + AMPLITUDE_WEB_VITALS_CONFIG_KEY, + AMPLITUDE_FILE_DOWNLOADS_CONFIG_KEY, + AMPLITUDE_FRUSTRATION_INTERACTIONS_CONFIG_KEY, + AMPLITUDE_NETWORK_TRACKING_CONFIG_KEY, + AMPLITUDE_ELEMENT_INTERACTIONS_CONFIG_KEY, + AMPLITUDE_FORM_INTERACTIONS_CONFIG_KEY, } from './constants'; const getTraitsToSetOnce = config => { @@ -74,6 +83,41 @@ const getAmplitudeSdkVersion = config => { : AMPLITUDE_SDK_V1; }; +const getBooleanConfigValue = (config, key) => config?.[key] === true; + +const getAutoCapturePageViews = config => + getBooleanConfigValue(config, AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY); + +const getPageUrlEnrichment = config => + getBooleanConfigValue(config, AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY); + +const getTrackSessionEvents = config => { + const trackSessionEvents = config?.[AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY]; + + if (typeof trackSessionEvents === 'boolean') { + return trackSessionEvents; + } + + return trackSessionEvents?.web === true || trackSessionEvents?.web?.enabled === true; +}; + +const getWebVitals = config => getBooleanConfigValue(config, AMPLITUDE_WEB_VITALS_CONFIG_KEY); + +const getFileDownloads = config => + getBooleanConfigValue(config, AMPLITUDE_FILE_DOWNLOADS_CONFIG_KEY); + +const getFrustrationInteractions = config => + getBooleanConfigValue(config, AMPLITUDE_FRUSTRATION_INTERACTIONS_CONFIG_KEY); + +const getNetworkTracking = config => + getBooleanConfigValue(config, AMPLITUDE_NETWORK_TRACKING_CONFIG_KEY); + +const getElementInteractions = config => + getBooleanConfigValue(config, AMPLITUDE_ELEMENT_INTERACTIONS_CONFIG_KEY); + +const getFormInteractions = config => + getBooleanConfigValue(config, AMPLITUDE_FORM_INTERACTIONS_CONFIG_KEY); + export { getTraitsToSetOnce, getTraitsToIncrement, @@ -81,4 +125,13 @@ export { getFieldsToUnset, formatUrl, getAmplitudeSdkVersion, + getAutoCapturePageViews, + getPageUrlEnrichment, + getTrackSessionEvents, + getWebVitals, + getFileDownloads, + getFrustrationInteractions, + getNetworkTracking, + getElementInteractions, + getFormInteractions, }; From 6832730139ae3fad7e245efc34c6cb51f57f1748 Mon Sep 17 00:00:00 2001 From: tech-infra-rudderstack Date: Wed, 1 Jul 2026 09:13:14 +0000 Subject: [PATCH 2/8] fix: bump form-data audit resolution --- package-lock.json | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04fc3f5e8..bd1ae28ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14578,21 +14578,33 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" } }, + "node_modules/form-data/node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -22270,6 +22282,23 @@ } } }, + "node_modules/nx/node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/nx/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", From 1a5ec698cd52d5bd88a7c7490026326cf699dfba Mon Sep 17 00:00:00 2001 From: Satheesh Kannan Date: Wed, 1 Jul 2026 15:30:57 +0530 Subject: [PATCH 3/8] fix: rename amplitude pageViews key --- .../__tests__/integrations/Amplitude/browser.test.js | 6 +++--- .../__tests__/integrations/Amplitude/util.test.js | 2 +- .../src/integrations/Amplitude/constants.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js index 2ba05b07b..204ff7b28 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js @@ -320,7 +320,7 @@ describe('Amplitude', () => { }); it.each([ - ['autoCapturePageViews', 'pageViews', true], + ['pageViews', 'pageViews', true], ['pageUrlEnrichment', 'pageUrlEnrichment', true], ['trackSessionEvents', 'sessions', { web: true }], ['webVitals', 'webVitals', true], @@ -357,7 +357,7 @@ describe('Amplitude', () => { ...destinationConfig, sdkVersion: 2, attribution: false, - autoCapturePageViews: true, + pageViews: true, trackAllPages: false, trackCategorizedPages: false, trackNamedPages: false, @@ -1131,7 +1131,7 @@ describe('Amplitude', () => { const config = { apiKey: 'YOUR_AMPLITUDE_API_KEY', sdkVersion: 2, - autoCapturePageViews: true, + pageViews: true, trackAllPages: false, trackCategorizedPages: false, trackNamedPages: false, diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js index e4bf6a201..1e6a5c630 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js @@ -225,7 +225,7 @@ describe('Amplitude v2 autocapture config helpers', () => { { name: 'getAutoCapturePageViews', getter: getAutoCapturePageViews, - key: 'autoCapturePageViews', + key: 'pageViews', }, { name: 'getPageUrlEnrichment', getter: getPageUrlEnrichment, key: 'pageUrlEnrichment' }, { name: 'getWebVitals', getter: getWebVitals, key: 'webVitals' }, diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js b/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js index 7e1e70bef..b68d2ca0f 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/constants.js @@ -2,7 +2,7 @@ import { AM_NAME as NAME, AM_DISPLAY_NAME as DISPLAY_NAME } from '../../constant const DIR_NAME = 'Amplitude'; const AMPLITUDE_SDK_VERSION_CONFIG_KEY = 'sdkVersion'; -const AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY = 'autoCapturePageViews'; +const AMPLITUDE_AUTO_CAPTURE_PAGE_VIEWS_CONFIG_KEY = 'pageViews'; const AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY = 'pageUrlEnrichment'; const AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY = 'trackSessionEvents'; const AMPLITUDE_WEB_VITALS_CONFIG_KEY = 'webVitals'; From 8eaafd096bc111274e17149d97ac655a1c32f4ad Mon Sep 17 00:00:00 2001 From: Satheesh Kannan Date: Wed, 1 Jul 2026 15:55:30 +0530 Subject: [PATCH 4/8] refactor: simplify trackSessionEvents getter --- .../integrations/Amplitude/browser.test.js | 2 +- .../integrations/Amplitude/util.test.js | 20 +------------------ .../src/integrations/Amplitude/utils.js | 11 ++-------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js index 204ff7b28..3c3c022bc 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js @@ -322,7 +322,7 @@ describe('Amplitude', () => { it.each([ ['pageViews', 'pageViews', true], ['pageUrlEnrichment', 'pageUrlEnrichment', true], - ['trackSessionEvents', 'sessions', { web: true }], + ['trackSessionEvents', 'sessions', true], ['webVitals', 'webVitals', true], ['fileDownloads', 'fileDownloads', true], ['frustrationInteractions', 'frustrationInteractions', true], diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js index 1e6a5c630..3e17112ec 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/util.test.js @@ -238,6 +238,7 @@ describe('Amplitude v2 autocapture config helpers', () => { { name: 'getNetworkTracking', getter: getNetworkTracking, key: 'networkTracking' }, { name: 'getElementInteractions', getter: getElementInteractions, key: 'elementInteractions' }, { name: 'getFormInteractions', getter: getFormInteractions, key: 'formInteractions' }, + { name: 'getTrackSessionEvents', getter: getTrackSessionEvents, key: 'trackSessionEvents' }, ]; it.each(helperCases)('$name should default missing config to false', ({ getter }) => { @@ -249,23 +250,4 @@ describe('Amplitude v2 autocapture config helpers', () => { expect(getter({ [key]: false })).toBe(false); }); - it('getTrackSessionEvents should default missing config to false', () => { - expect(getTrackSessionEvents({})).toBe(false); - }); - - it('getTrackSessionEvents should read the web source value shape', () => { - expect(getTrackSessionEvents({ trackSessionEvents: { web: true } })).toBe(true); - expect(getTrackSessionEvents({ trackSessionEvents: { web: false } })).toBe(false); - expect(getTrackSessionEvents({ trackSessionEvents: { web: { enabled: true } } })).toBe(true); - expect(getTrackSessionEvents({ trackSessionEvents: { web: { enabled: false } } })).toBe(false); - }); - - it('getTrackSessionEvents should ignore non-web source values', () => { - expect(getTrackSessionEvents({ trackSessionEvents: { android: true, ios: true } })).toBe(false); - }); - - it('getTrackSessionEvents should support legacy boolean values', () => { - expect(getTrackSessionEvents({ trackSessionEvents: true })).toBe(true); - expect(getTrackSessionEvents({ trackSessionEvents: false })).toBe(false); - }); }); diff --git a/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js b/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js index 9a0ee98c6..08b97440f 100644 --- a/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js +++ b/packages/analytics-js-integrations/src/integrations/Amplitude/utils.js @@ -91,15 +91,8 @@ const getAutoCapturePageViews = config => const getPageUrlEnrichment = config => getBooleanConfigValue(config, AMPLITUDE_PAGE_URL_ENRICHMENT_CONFIG_KEY); -const getTrackSessionEvents = config => { - const trackSessionEvents = config?.[AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY]; - - if (typeof trackSessionEvents === 'boolean') { - return trackSessionEvents; - } - - return trackSessionEvents?.web === true || trackSessionEvents?.web?.enabled === true; -}; +const getTrackSessionEvents = config => + getBooleanConfigValue(config, AMPLITUDE_TRACK_SESSION_EVENTS_CONFIG_KEY); const getWebVitals = config => getBooleanConfigValue(config, AMPLITUDE_WEB_VITALS_CONFIG_KEY); From f4b63f8af4211a083769bf880a9fcc1051837b13 Mon Sep 17 00:00:00 2001 From: Satheesh Kannan Date: Wed, 1 Jul 2026 15:55:37 +0530 Subject: [PATCH 5/8] docs: fix amplitude pageViews key reference --- .agents/knowledge/patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/knowledge/patterns.md b/.agents/knowledge/patterns.md index a6c66fa4d..026a5b557 100644 --- a/.agents/knowledge/patterns.md +++ b/.agents/knowledge/patterns.md @@ -21,4 +21,4 @@ ## SDK-5014 — Amplitude V2 Autocapture Config Boundaries - Amplitude Browser SDK v2 autocapture config is assembled in `packages/analytics-js-integrations/src/integrations/Amplitude/browser.js:init()` using helper getters from `packages/analytics-js-integrations/src/integrations/Amplitude/utils.js`. -- The dedicated `autoCapturePageViews` config key maps only to the Amplitude SDK `autocapture.pageViews` option; it intentionally does not affect Rudder `page()` translation gates such as `trackAllPages`, `trackCategorizedPages`, or `trackNamedPages`. +- The dedicated `pageViews` config key maps only to the Amplitude SDK `autocapture.pageViews` option; it intentionally does not affect Rudder `page()` translation gates such as `trackAllPages`, `trackCategorizedPages`, or `trackNamedPages`. From 7ac3a7724ac2c4355cc31d6180f79405fb52c20e Mon Sep 17 00:00:00 2001 From: Satheesh Kannan Date: Wed, 8 Jul 2026 19:13:14 +0530 Subject: [PATCH 6/8] chore: address copilot review comments --- .../__tests__/integrations/Amplitude/browser.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js index 3c3c022bc..c1a4193e4 100644 --- a/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js +++ b/packages/analytics-js-integrations/__tests__/integrations/Amplitude/browser.test.js @@ -1152,8 +1152,8 @@ describe('Amplitude', () => { }; const amplitude = new Amplitude(config, analytics, destinationInfo); + window.amplitude = window.amplitude ?? { track: jest.fn() }; const spy = jest.spyOn(window.amplitude, 'track'); - spy.mockClear(); amplitude.page(rudderElement); From f1c199cb9c99d08b57e764b9624ec77ad5008b25 Mon Sep 17 00:00:00 2001 From: tech-infra-rudderstack Date: Thu, 9 Jul 2026 08:39:14 +0000 Subject: [PATCH 7/8] chore: revert unrelated lockfile changes --- package-lock.json | 39 +++++---------------------------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd1ae28ae..04fc3f5e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14578,33 +14578,21 @@ } }, "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, - "node_modules/form-data/node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -22282,23 +22270,6 @@ } } }, - "node_modules/nx/node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/nx/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", From 2574f24f989e8ee0f6091727a746fba0c5bdf8b4 Mon Sep 17 00:00:00 2001 From: tech-infra-rudderstack Date: Thu, 9 Jul 2026 08:51:42 +0000 Subject: [PATCH 8/8] fix: resolve form-data audit finding --- package-lock.json | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04fc3f5e8..668721dcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14578,16 +14578,16 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -15365,9 +15365,9 @@ "license": "ISC" }, "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -22270,6 +22270,23 @@ } } }, + "node_modules/nx/node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/nx/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",