diff --git a/packages/analytics-browser-test/test/helpers.ts b/packages/analytics-browser-test/test/helpers.ts index 6c807ddaf..bee955029 100644 --- a/packages/analytics-browser-test/test/helpers.ts +++ b/packages/analytics-browser-test/test/helpers.ts @@ -64,8 +64,17 @@ const generateAttributionUserProps = (campaignURL: string, referrerString?: stri return user_properties; }; -export const generateEvent = (event_id: number, event_type: string): BaseEvent => { - return { +export const generateEvent = ( + event_id: number, + event_type: string, + options?: { + withPageURLEnrichmentProperties?: { + url?: string; + previousPageUrl?: string; + }; + }, +): BaseEvent => { + const event = { device_id: uuid, event_id: event_id, event_type: event_type, @@ -81,6 +90,15 @@ export const generateEvent = (event_id: number, event_type: string): BaseEvent = user_agent: userAgent, user_id: 'user1@amplitude.com', }; + + if (options?.withPageURLEnrichmentProperties) { + return addPageUrlEnrichmentProperties( + event, + options.withPageURLEnrichmentProperties.url || '', + options.withPageURLEnrichmentProperties.previousPageUrl || '', + ); + } + return event; }; export const generateAttributionEvent = (event_id: number, campaignURL: string, referrer?: string) => { @@ -89,16 +107,62 @@ export const generateAttributionEvent = (event_id: number, campaignURL: string, return attributionEvent; }; -export const generateSessionStartEvent = (event_id: number) => { - return generateEvent(event_id, 'session_start'); +export const generateSessionStartEvent = ( + event_id: number, + options: { + withPageURLEnrichmentProperties: { + url?: string; + previousPageUrl?: string; + }; + }, +) => { + const sessionStartEvent = generateEvent(event_id, 'session_start'); + + if (options.withPageURLEnrichmentProperties) { + return addPageUrlEnrichmentProperties( + sessionStartEvent, + options.withPageURLEnrichmentProperties.url || '', + options.withPageURLEnrichmentProperties.previousPageUrl || '', + ); + } + return sessionStartEvent; }; -export const generateSessionEndEvent = (event_id: number) => { - return generateEvent(event_id, 'session_end'); +export const generateSessionEndEvent = ( + event_id: number, + options?: { + withPageURLEnrichmentProperties: { + url?: string; + previousPageUrl?: string; + }; + }, +) => { + const sessionEndEvent = generateEvent(event_id, 'session_end'); + + if (options?.withPageURLEnrichmentProperties) { + return addPageUrlEnrichmentProperties( + sessionEndEvent, + options?.withPageURLEnrichmentProperties.url || '', + options?.withPageURLEnrichmentProperties.previousPageUrl || '', + ); + } + return sessionEndEvent; }; -const generatePageViewEventProps = (pageCounter: number, urlString: string, referrerString?: string) => { +const generatePageViewEventProps = ( + pageCounter: number, + urlString: string, + referrerString?: string, + options?: { + withPageURLEnrichmentProperties?: { + previousPageUrl?: string; + }; + }, +) => { const referrer = getReferrerObject(referrerString); + const previousUrl = options?.withPageURLEnrichmentProperties?.previousPageUrl + ? new URL(options?.withPageURLEnrichmentProperties.previousPageUrl) + : { href: '' }; const url = new URL(urlString); const campaign = parseQueryString(urlString); @@ -110,14 +174,29 @@ const generatePageViewEventProps = (pageCounter: number, urlString: string, refe '[Amplitude] Page Path': url.pathname, '[Amplitude] Page Title': '', '[Amplitude] Page URL': url.href.split('?')[0], + ...(options?.withPageURLEnrichmentProperties + ? addPageUrlEnrichmentPreviousPageProperties(url.href, previousUrl.href || '') + : {}), ...campaign, ...referrer, }; }; -export const generatePageViewEvent = (event_id: number, pageCounter: number, url: string, referrer?: string) => { +export const generatePageViewEvent = ( + event_id: number, + pageCounter: number, + url: string, + referrer?: string, + options?: { + withPageURLEnrichmentProperties?: { + previousPageUrl?: string; + }; + }, +) => { const generatePageViewEvent = generateEvent(event_id, '[Amplitude] Page Viewed'); - generatePageViewEvent.event_properties = generatePageViewEventProps(pageCounter, url, referrer); + generatePageViewEvent.event_properties = generatePageViewEventProps(pageCounter, url, referrer, { + withPageURLEnrichmentProperties: options?.withPageURLEnrichmentProperties, + }); return generatePageViewEvent; }; @@ -138,3 +217,38 @@ export const navigateTo = (urlString: string, referrer?: string) => { writable: true, }); }; + +export const addPageUrlEnrichmentProperties = (event: BaseEvent, urlString: string, previousPageUrl?: string) => { + const url = new URL(urlString); + const previousUrl = previousPageUrl ? new URL(previousPageUrl) : { href: '' }; + + event.event_properties = { + ...event.event_properties, + '[Amplitude] Page Domain': url.hostname, + '[Amplitude] Page Location': url.href, + '[Amplitude] Page Path': url.pathname, + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': url.href.split('?')[0], + ...addPageUrlEnrichmentPreviousPageProperties(url.href, previousUrl.href), + }; + return event; +}; + +export const addPageUrlEnrichmentPreviousPageProperties = (current: string, previous: string) => { + // note that the five duplicate properties with the page viewed are skipped here + return { + '[Amplitude] Previous Page Location': previous, + '[Amplitude] Previous Page Type': getPreviousPageType(current, previous), + }; +}; + +export const getPreviousPageType = (current: string, previous: string) => { + if (!previous) { + return 'direct'; + } + + const currentUrl = new URL(current); + const previousUrl = new URL(previous); + + return previousUrl.hostname === currentUrl.hostname ? 'internal' : 'external'; +}; diff --git a/packages/analytics-browser-test/test/index.test.ts b/packages/analytics-browser-test/test/index.test.ts index 4924b7efc..a9411d801 100644 --- a/packages/analytics-browser-test/test/index.test.ts +++ b/packages/analytics-browser-test/test/index.test.ts @@ -56,6 +56,9 @@ describe('integration', () => { document.cookie = `amp_${apiKey.substring(0, 6)}=null; expires=1 Jan 1970 00:00:00 GMT`; document.cookie = `AMP_${apiKey.substring(0, 10)}=null; expires=1 Jan 1970 00:00:00 GMT`; document.cookie = `AMP_MKTG_${apiKey.substring(0, 10)}=null; expires=1 Jan 1970 00:00:00 GMT`; + + // clear url info in session storage + window.sessionStorage.setItem('AMP_URL_INFO', '{}'); }); describe('defer initialization', () => { @@ -109,6 +112,15 @@ describe('integration', () => { device_id: deviceId, // NOTE: Device ID was set before init event_id: 0, event_type: 'Event Before Init', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -185,6 +197,8 @@ describe('integration', () => { '[Amplitude] Page Title': '', '[Amplitude] Page URL': '', '[Amplitude] Page Counter': 1, + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, user_agent: userAgent, user_properties: { @@ -245,6 +259,15 @@ describe('integration', () => { insert_id: uuid, event_type: 'Event Before Init', event_id: 1, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, library: library, user_agent: userAgent, }, @@ -279,6 +302,13 @@ describe('integration', () => { event_id: 0, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -308,6 +338,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -339,6 +378,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -376,6 +424,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, ingestion_metadata: { @@ -420,6 +477,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, groups: { @@ -465,6 +531,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 1', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -482,6 +557,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 2', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 1, library: library, user_agent: userAgent, @@ -516,6 +600,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 1', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -533,6 +626,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 2', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 1, library: library, user_agent: userAgent, @@ -576,6 +678,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 1', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -593,6 +704,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 2', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 1, library: library, user_agent: userAgent, @@ -625,6 +745,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 1', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -642,6 +771,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event 2', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 1, library: library, user_agent: userAgent, @@ -674,6 +812,15 @@ describe('integration', () => { insert_id: uuid, partner_id: undefined, event_type: 'test event', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_id: 0, library: library, user_agent: userAgent, @@ -916,6 +1063,15 @@ describe('integration', () => { device_id: previousSessionDeviceId, event_id: 100, event_type: 'session_end', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -992,6 +1148,15 @@ describe('integration', () => { device_id: uuid, event_id: 102, event_type: 'session_start', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1007,6 +1172,15 @@ describe('integration', () => { { device_id: uuid, event_id: 103, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Event in first session', insert_id: uuid, ip: '$remote', @@ -1024,6 +1198,15 @@ describe('integration', () => { device_id: uuid, event_id: 104, event_type: 'session_end', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1040,6 +1223,15 @@ describe('integration', () => { device_id: uuid, event_id: 105, event_type: 'session_start', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1055,6 +1247,15 @@ describe('integration', () => { { device_id: uuid, event_id: 106, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Event in next session', insert_id: uuid, ip: '$remote', @@ -1200,6 +1401,15 @@ describe('integration', () => { device_id: uuid, event_id: 1, event_type: 'session_start', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1215,6 +1425,15 @@ describe('integration', () => { { device_id: uuid, event_id: 2, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Event in first session', insert_id: uuid, ip: '$remote', @@ -1232,6 +1451,15 @@ describe('integration', () => { device_id: uuid, event_id: 3, event_type: 'session_end', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1248,6 +1476,15 @@ describe('integration', () => { device_id: uuid, event_id: 4, event_type: 'session_start', + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1263,6 +1500,15 @@ describe('integration', () => { { device_id: uuid, event_id: 5, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Event in next session', insert_id: uuid, ip: '$remote', @@ -1326,6 +1572,15 @@ describe('integration', () => { { device_id: uuid, event_id: 100, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'First event in first session', insert_id: uuid, ip: '$remote', @@ -1342,6 +1597,15 @@ describe('integration', () => { { device_id: uuid, event_id: 101, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Second event in first session', insert_id: uuid, ip: '$remote', @@ -1358,6 +1622,15 @@ describe('integration', () => { { device_id: uuid, event_id: 102, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, event_type: 'Third event in first session', insert_id: uuid, ip: '$remote', @@ -1405,6 +1678,13 @@ describe('integration', () => { event_id: 100, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -1439,6 +1719,13 @@ describe('integration', () => { event_id: 100, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -1472,6 +1759,13 @@ describe('integration', () => { event_id: 100, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -1518,6 +1812,8 @@ describe('integration', () => { '[Amplitude] Page Title': '', '[Amplitude] Page URL': '', '[Amplitude] Page Counter': 1, + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, event_type: '[Amplitude] Page Viewed', insert_id: uuid, @@ -1646,6 +1942,8 @@ describe('integration', () => { '[Amplitude] Page Title': '', '[Amplitude] Page URL': 'https://www.example.com/about', '[Amplitude] Page Counter': 1, + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, event_type: '[Amplitude] Page Viewed', insert_id: uuid, @@ -1664,6 +1962,15 @@ describe('integration', () => { device_id: uuid, event_id: 1, event_type: 'Event in first session', + event_properties: { + '[Amplitude] Page Domain': 'www.example.com', + '[Amplitude] Page Location': 'https://www.example.com/about', + '[Amplitude] Page Path': '/about', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': 'https://www.example.com/about', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, insert_id: uuid, ip: '$remote', language: 'en-US', @@ -1685,6 +1992,8 @@ describe('integration', () => { '[Amplitude] Page Path': '/contact', '[Amplitude] Page Title': '', '[Amplitude] Page URL': 'https://www.example.com/contact', + '[Amplitude] Previous Page Location': 'https://www.example.com/about', + '[Amplitude] Previous Page Type': 'internal', '[Amplitude] Page Counter': 2, }, event_type: '[Amplitude] Page Viewed', @@ -1710,6 +2019,8 @@ describe('integration', () => { '[Amplitude] Page Title': '', '[Amplitude] Page URL': 'https://www.example.com/more', '[Amplitude] Page Counter': 1, + '[Amplitude] Previous Page Location': 'https://www.example.com/contact', + '[Amplitude] Previous Page Type': 'internal', }, event_type: '[Amplitude] Page Viewed', insert_id: uuid, @@ -1766,6 +2077,8 @@ describe('integration', () => { '[Amplitude] Page Title': '', '[Amplitude] Page URL': '', '[Amplitude] Page Counter': 1, + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, event_type: '[Amplitude] Page Viewed', insert_id: uuid, @@ -1834,6 +2147,13 @@ describe('integration', () => { event_id: 100, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -1869,6 +2189,13 @@ describe('integration', () => { event_id: 100, event_properties: { mode: 'test', + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', }, library: library, user_agent: userAgent, @@ -1903,6 +2230,15 @@ describe('integration', () => { partner_id: undefined, event_type: 'test event', event_id: 0, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, library: library, user_agent: userAgent, }); @@ -1943,6 +2279,15 @@ describe('integration', () => { partner_id: undefined, event_type: 'test event', event_id: 0, + event_properties: { + '[Amplitude] Page Domain': '', + '[Amplitude] Page Location': '', + '[Amplitude] Page Path': '', + '[Amplitude] Page Title': '', + '[Amplitude] Page URL': '', + '[Amplitude] Previous Page Location': '', + '[Amplitude] Previous Page Type': 'direct', + }, library: library, user_agent: userAgent, }); @@ -1950,9 +2295,9 @@ describe('integration', () => { expect(response.message).toBe(SUCCESS_MESSAGE); scope.done(); - expect(logger.debug).toHaveBeenCalledTimes(14); + expect(logger.debug).toHaveBeenCalledTimes(15); /* eslint-disable */ - const debugContext = JSON.parse(logger.debug.mock.calls[13]); + const debugContext = JSON.parse(logger.debug.mock.calls[14]); expect(debugContext.type).toBeDefined(); expect(debugContext.name).toEqual('track'); expect(debugContext.args).toBeDefined(); @@ -1978,9 +2323,9 @@ describe('integration', () => { }).promise; client.setOptOut(true); - expect(logger.debug).toHaveBeenCalledTimes(8); + expect(logger.debug).toHaveBeenCalledTimes(9); /* eslint-disable */ - const debugContext = JSON.parse(logger.debug.mock.calls[7]); + const debugContext = JSON.parse(logger.debug.mock.calls[8]); expect(debugContext.type).toBeDefined(); expect(debugContext.name).toEqual('setOptOut'); expect(debugContext.args).toBeDefined(); diff --git a/packages/analytics-browser-test/test/web-attribution.test.ts b/packages/analytics-browser-test/test/web-attribution.test.ts index cf7d73546..492f3f296 100644 --- a/packages/analytics-browser-test/test/web-attribution.test.ts +++ b/packages/analytics-browser-test/test/web-attribution.test.ts @@ -74,8 +74,12 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url, referrer), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url, referrer), + generateSessionStartEvent(++eventId, { + withPageURLEnrichmentProperties: { url, previousPageUrl: referrer }, + }), + generatePageViewEvent(++eventId, 1, url, referrer, { + withPageURLEnrichmentProperties: { previousPageUrl: referrer }, + }), ], options: { min_id_length: undefined, @@ -113,8 +117,10 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), ], options: { min_id_length: undefined, @@ -157,7 +163,14 @@ describe('Web attribution', () => { expect(payload).toEqual({ api_key: apiKey, client_upload_time: event_upload_time, - events: [generateSessionStartEvent(++eventId), generatePageViewEvent(++eventId, 1, url, referrer)], + events: [ + generateSessionStartEvent(++eventId, { + withPageURLEnrichmentProperties: { url, previousPageUrl: referrer }, + }), + generatePageViewEvent(++eventId, 1, url, referrer, { + withPageURLEnrichmentProperties: { previousPageUrl: referrer }, + }), + ], options: { min_id_length: undefined, }, @@ -205,6 +218,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 200)); + // refresh during the session. const directUrl = 'https://www.example.com/home'; navigateTo(directUrl); @@ -225,9 +240,13 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), - generatePageViewEvent(++eventId, 2, directUrl), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), + generatePageViewEvent(++eventId, 2, directUrl, undefined, { + withPageURLEnrichmentProperties: {}, // no referrer because the previous page prop relies on document.referrer for non-SPA sites + }), ], options: { min_id_length: undefined, @@ -265,6 +284,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 200)); + // mock refresh during the session with updated campaign change. const newCampaignURL = 'https://www.example.com/?utm_source=second_utm_source&utm_content=test_utm_content'; navigateTo(newCampaignURL); @@ -285,10 +306,14 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), generateAttributionEvent(++eventId, newCampaignURL), - generatePageViewEvent(++eventId, 2, newCampaignURL), + generatePageViewEvent(++eventId, 2, newCampaignURL, undefined, { + withPageURLEnrichmentProperties: {}, // no referrer because the previous page prop relies on document.referrer for non-SPA sites + }), ], options: { min_id_length: undefined, @@ -331,6 +356,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 100)); + // refresh during the session. const directUrl = 'https://www.example.com/?utm_content=test_utm_content'; navigateTo(directUrl); @@ -357,12 +384,16 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), - generateSessionEndEvent(++eventId), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), + generateSessionEndEvent(++eventId, { withPageURLEnrichmentProperties: { url: directUrl } }), // no referrer because the previous page prop relies on document.referrer for non-SPA sites generateAttributionEvent(++eventId, directUrl), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, directUrl), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url: directUrl } }), // no referrer because the previous page prop relies on document.referrer for non-SPA sites + generatePageViewEvent(++eventId, 1, directUrl, undefined, { + withPageURLEnrichmentProperties: {}, + }), // no referrer because the previous page prop relies on document.referrer for non-SPA sites ], options: { min_id_length: undefined, @@ -422,11 +453,15 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), - generateSessionEndEvent(++eventId), - generateSessionStartEvent(++eventId), - generateEvent(++eventId, 'test event after session timeout'), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), + generateSessionEndEvent(++eventId, { withPageURLEnrichmentProperties: { url: newCampaignURL } }), // no previous page url prop since there is no pushstate event or referrer + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url: newCampaignURL } }), // no previous page url prop since there is no pushstate event or referrer + generateEvent(++eventId, 'test event after session timeout', { + withPageURLEnrichmentProperties: { url: newCampaignURL }, // no previous page url prop since there is no pushstate event or referrer + }), ], options: { min_id_length: undefined, @@ -479,11 +514,22 @@ describe('Web attribution', () => { api_key: apiKey, client_upload_time: event_upload_time, events: [ - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url, referrer), - generateSessionEndEvent(++eventId), - generateSessionStartEvent(++eventId), - generateEvent(++eventId, 'test event after session timeout'), + generateSessionStartEvent(++eventId, { + withPageURLEnrichmentProperties: { url, previousPageUrl: referrer }, + }), + generatePageViewEvent(++eventId, 1, url, referrer, { + withPageURLEnrichmentProperties: { previousPageUrl: referrer }, + }), + generateSessionEndEvent(++eventId, { + withPageURLEnrichmentProperties: { url: newCampaignURL, previousPageUrl: referrer }, // referrer stays the same as it has not been changed or removed + }), + generateSessionStartEvent(++eventId, { + withPageURLEnrichmentProperties: { url: newCampaignURL, previousPageUrl: referrer }, // referrer stays the same as it has not been changed or removed + }), + + generateEvent(++eventId, 'test event after session timeout', { + withPageURLEnrichmentProperties: { url: newCampaignURL, previousPageUrl: referrer }, // referrer stays the same as it has not been changed or removed + }), ], options: { min_id_length: undefined, @@ -526,6 +572,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 100)); + // update the url and fire the first event during the same session without refreshing the page const newCampaignURL = 'https://www.example.com?utm_source=second_utm_source&utm_content=test_utm_content'; navigateTo(newCampaignURL); @@ -539,9 +587,13 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), - generateEvent(++eventId, 'test event in the same session'), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: { previousPageUrl: '' }, // no previous page url prop since there is no pushstate event or referrer + }), + generateEvent(++eventId, 'test event in the same session', { + withPageURLEnrichmentProperties: { url: newCampaignURL, previousPageUrl: '' }, // no previous page url prop since there is no pushstate event or referrer + }), ], options: { min_id_length: undefined, @@ -578,6 +630,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 100)); + // refresh during the session. const directUrl = 'https://www.example.com/?utm_content=test_utm_content'; navigateTo(directUrl); @@ -591,9 +645,13 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url), - generateEvent(++eventId, 'test event in same session'), + generateSessionStartEvent(++eventId, { withPageURLEnrichmentProperties: { url } }), + generatePageViewEvent(++eventId, 1, url, undefined, { + withPageURLEnrichmentProperties: {}, + }), + generateEvent(++eventId, 'test event in same session', { + withPageURLEnrichmentProperties: { url: directUrl, previousPageUrl: '' }, // no previous page url prop since there is no pushstate event or referrer + }), ], options: { min_id_length: undefined, @@ -608,6 +666,7 @@ describe('Web attribution', () => { test('should not drop campaign without reinitializing the SDK after unsetting the referrer', async () => { const url = 'https://www.example.com?utm_source=test_utm_source'; const initReferrer = 'https://www.test.com/'; + navigateTo(url, initReferrer); expect(document.referrer).toEqual(initReferrer); @@ -626,6 +685,8 @@ describe('Web attribution', () => { flushIntervalMillis: 3000, }).promise; + await new Promise((resolve) => setTimeout(resolve, 100)); + // Unset the referrer after first hit Object.defineProperty(document, 'referrer', { value: '', configurable: true }); expect(document.referrer).toEqual(''); @@ -643,9 +704,15 @@ describe('Web attribution', () => { client_upload_time: event_upload_time, events: [ generateAttributionEvent(++eventId, url, initReferrer), - generateSessionStartEvent(++eventId), - generatePageViewEvent(++eventId, 1, url, initReferrer), - generatePageViewEvent(++eventId, 2, newURL), + generateSessionStartEvent(++eventId, { + withPageURLEnrichmentProperties: { url, previousPageUrl: initReferrer }, + }), + generatePageViewEvent(++eventId, 1, url, initReferrer, { + withPageURLEnrichmentProperties: { previousPageUrl: initReferrer }, + }), + generatePageViewEvent(++eventId, 2, newURL, undefined, { + withPageURLEnrichmentProperties: { previousPageUrl: url }, + }), ], options: { min_id_length: undefined, @@ -671,5 +738,8 @@ describe('Web attribution', () => { search: '', }; Object.defineProperty(document, 'referrer', { value: '', configurable: true }); + + // clear url info in session storage from page url enrichment plugin + window.sessionStorage.setItem('AMP_URL_INFO', '{}'); }; }); diff --git a/packages/analytics-browser/package.json b/packages/analytics-browser/package.json index c8eea5881..e6cb52641 100644 --- a/packages/analytics-browser/package.json +++ b/packages/analytics-browser/package.json @@ -52,6 +52,7 @@ "@amplitude/plugin-network-capture-browser": "^1.6.10", "@amplitude/plugin-page-view-tracking-browser": "^2.5.4", "@amplitude/plugin-web-vitals-browser": "^0.1.0-beta.32", + "@amplitude/plugin-page-url-enrichment-browser": "^0.4.2", "tslib": "^2.4.1" }, "devDependencies": { diff --git a/packages/analytics-browser/src/browser-client.ts b/packages/analytics-browser/src/browser-client.ts index 1c3615025..203d27dba 100644 --- a/packages/analytics-browser/src/browser-client.ts +++ b/packages/analytics-browser/src/browser-client.ts @@ -44,6 +44,7 @@ import { isWebVitalsEnabled, isFrustrationInteractionsEnabled, getFrustrationInteractionsConfig, + isPageUrlEnrichmentEnabled, } from './default-tracking'; import { convertProxyObjectToRealObject, isInstanceProxy } from './utils/snippet-helper'; import { Context } from './plugins/context'; @@ -61,6 +62,7 @@ import { webVitalsPlugin } from '@amplitude/plugin-web-vitals-browser'; import { WebAttribution } from './attribution/web-attribution'; import { LIBPREFIX } from './lib-prefix'; import { VERSION } from './version'; +import { pageUrlEnrichmentPlugin } from '@amplitude/plugin-page-url-enrichment-browser'; /** * Exported for `@amplitude/unified` or integration with blade plugins. @@ -255,6 +257,11 @@ export class AmplitudeBrowser extends AmplitudeCore implements BrowserClient, An await this.add(webVitalsPlugin()).promise; } + if (isPageUrlEnrichmentEnabled(this.config.autocapture)) { + this.config.loggerProvider.debug('Adding referrer page url plugin'); + await this.add(pageUrlEnrichmentPlugin()).promise; + } + this.initializing = false; // Step 6: Run queued dispatch functions diff --git a/packages/analytics-browser/src/default-tracking.ts b/packages/analytics-browser/src/default-tracking.ts index 58ed7d821..a1689ecaf 100644 --- a/packages/analytics-browser/src/default-tracking.ts +++ b/packages/analytics-browser/src/default-tracking.ts @@ -16,7 +16,7 @@ import { */ type AutocaptureOptionsDefaultAvailable = Pick< AutocaptureOptions, - 'pageViews' | 'sessions' | 'fileDownloads' | 'formInteractions' | 'attribution' + 'pageViews' | 'sessions' | 'fileDownloads' | 'formInteractions' | 'attribution' | 'pageUrlEnrichment' >; /** @@ -53,6 +53,9 @@ export const isPageViewTrackingEnabled = (autocapture: AutocaptureOptions | bool export const isSessionTrackingEnabled = (autocapture: AutocaptureOptions | boolean | undefined) => isTrackingEnabled(autocapture, 'sessions'); +export const isPageUrlEnrichmentEnabled = (autocapture: AutocaptureOptions | boolean | undefined) => + isTrackingEnabled(autocapture, 'pageUrlEnrichment'); + /** * Returns true if * 1. if autocapture.networkTracking === true diff --git a/packages/analytics-browser/test/browser-client.test.ts b/packages/analytics-browser/test/browser-client.test.ts index 7138273ac..54f5727a7 100644 --- a/packages/analytics-browser/test/browser-client.test.ts +++ b/packages/analytics-browser/test/browser-client.test.ts @@ -26,6 +26,7 @@ import * as formInteractionTracking from '../src/plugins/form-interaction-tracki import * as networkConnectivityChecker from '../src/plugins/network-connectivity-checker'; import * as SnippetHelper from '../src/utils/snippet-helper'; import * as joinedConfig from '../src/config/joined-config'; +import * as pageUrlEnrichment from '@amplitude/plugin-page-url-enrichment-browser'; // Mock RemoteConfigClient constructor const mockRemoteConfigClient = { @@ -720,6 +721,34 @@ describe('browser-client', () => { addEventListenerMock.mockRestore(); }); + test('should add page url previous page plugin if pageUrlEnrichment is true', async () => { + const pageUrlEnrichmentPlugin = jest.spyOn(pageUrlEnrichment, 'pageUrlEnrichmentPlugin'); + await client.init(apiKey, userId, { + autocapture: { + pageUrlEnrichment: true, + }, + }).promise; + expect(pageUrlEnrichmentPlugin).toHaveBeenCalledTimes(1); + }); + + test('should NOT add page url previous page plugin if pageUrlEnrichment is false', async () => { + const pageUrlEnrichmentPlugin = jest.spyOn(pageUrlEnrichment, 'pageUrlEnrichmentPlugin'); + await client.init(apiKey, userId, { + autocapture: { + pageUrlEnrichment: false, + }, + }).promise; + expect(pageUrlEnrichmentPlugin).toHaveBeenCalledTimes(0); + }); + + test('should add page url previous page plugin if pageUrlEnrichment is undefined', async () => { + const pageUrlEnrichmentPlugin = jest.spyOn(pageUrlEnrichment, 'pageUrlEnrichmentPlugin'); + await client.init(apiKey, userId, { + autocapture: {}, + }).promise; + expect(pageUrlEnrichmentPlugin).toHaveBeenCalledTimes(1); + }); + test.each([[url], [new URL(`https://www.example.com?deviceId=${testDeviceId}`)]])( 'should set device id from url', async (mockedUrl) => { diff --git a/packages/analytics-browser/test/default-tracking.test.ts b/packages/analytics-browser/test/default-tracking.test.ts index 9b9dda784..6289555f2 100644 --- a/packages/analytics-browser/test/default-tracking.test.ts +++ b/packages/analytics-browser/test/default-tracking.test.ts @@ -1,17 +1,18 @@ import { getAttributionTrackingConfig, - getPageViewTrackingConfig, getElementInteractionsConfig, getFrustrationInteractionsConfig, + getNetworkTrackingConfig, + getPageViewTrackingConfig, isAttributionTrackingEnabled, + isElementInteractionsEnabled, isFileDownloadTrackingEnabled, isFormInteractionTrackingEnabled, + isFrustrationInteractionsEnabled, + isNetworkTrackingEnabled, + isPageUrlEnrichmentEnabled, isPageViewTrackingEnabled, isSessionTrackingEnabled, - isElementInteractionsEnabled, - getNetworkTrackingConfig, - isNetworkTrackingEnabled, - isFrustrationInteractionsEnabled, isWebVitalsEnabled, } from '../src/default-tracking'; @@ -599,3 +600,41 @@ describe('getElementInteractionsConfig', () => { expect(config?.dataAttributePrefix).toBe(testDataAttributePrefix); }); }); + +describe('isPageUrlEnrichmentEnabled', () => { + test('should return true with true parameter', () => { + expect(isPageUrlEnrichmentEnabled(true)).toBe(true); + }); + + test('should return true with undefined parameter', () => { + expect(isPageUrlEnrichmentEnabled(undefined)).toBe(true); + }); + + test('should return false with false parameter', () => { + expect(isPageUrlEnrichmentEnabled(false)).toBe(false); + }); + + test('should return true with object parameter set to true', () => { + expect( + isPageUrlEnrichmentEnabled({ + pageUrlEnrichment: true, + }), + ).toBe(true); + }); + + test('should return false with object parameter set to false', () => { + expect( + isPageUrlEnrichmentEnabled({ + pageUrlEnrichment: false, + }), + ).toBe(false); + }); + + test('should return true with object parameter undefined', () => { + expect( + isPageUrlEnrichmentEnabled({ + pageUrlEnrichment: undefined, + }), + ).toBe(true); + }); +}); diff --git a/packages/analytics-core/src/types/config/browser-config.ts b/packages/analytics-core/src/types/config/browser-config.ts index e455dfad4..30e11ef7b 100644 --- a/packages/analytics-core/src/types/config/browser-config.ts +++ b/packages/analytics-core/src/types/config/browser-config.ts @@ -192,6 +192,12 @@ export interface AutocaptureOptions { * @defaultValue `false` */ webVitals?: boolean; + /** + * Enables/disables page url enrichment. + * @defaultValue `true` + * @experimental This feature is experimental and may not be stable + */ + pageUrlEnrichment?: boolean; } export interface TrackingOptions { diff --git a/packages/plugin-page-url-enrichment-browser/src/page-url-enrichment.ts b/packages/plugin-page-url-enrichment-browser/src/page-url-enrichment.ts index 50eb2bd81..8588621e6 100644 --- a/packages/plugin-page-url-enrichment-browser/src/page-url-enrichment.ts +++ b/packages/plugin-page-url-enrichment-browser/src/page-url-enrichment.ts @@ -14,7 +14,6 @@ import { export const CURRENT_PAGE_STORAGE_KEY = 'AMP_CURRENT_PAGE'; export const PREVIOUS_PAGE_STORAGE_KEY = 'AMP_PREVIOUS_PAGE'; - export const URL_INFO_STORAGE_KEY = 'AMP_URL_INFO'; export type URLInfo = { @@ -155,19 +154,21 @@ export const pageUrlEnrichmentPlugin = (): EnrichmentPlugin => { execute: async (event: Event) => { const locationHREF = getDecodeURI((typeof location !== 'undefined' && location.href) || ''); - let previousPage = ''; if (sessionStorage && isStorageEnabled) { const URLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY); - previousPage = URLInfo?.[PREVIOUS_PAGE_STORAGE_KEY] || document.referrer || ''; - if (!URLInfo?.[CURRENT_PAGE_STORAGE_KEY]) { await sessionStorage.set(URL_INFO_STORAGE_KEY, { - ...(URLInfo || {}), [CURRENT_PAGE_STORAGE_KEY]: locationHREF, - [PREVIOUS_PAGE_STORAGE_KEY]: previousPage, + [PREVIOUS_PAGE_STORAGE_KEY]: document.referrer || '', }); } + const updatedURLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY); + let previousPage = ''; + if (updatedURLInfo) { + previousPage = updatedURLInfo[PREVIOUS_PAGE_STORAGE_KEY] || ''; + } + // no need to proceed to add additional properties if the event is one of the default event types to be excluded if (EXCLUDED_DEFAULT_EVENT_TYPES.has(event.event_type)) { return event; @@ -204,10 +205,10 @@ export const pageUrlEnrichmentPlugin = (): EnrichmentPlugin => { globalScope.removeEventListener('popstate', saveUrlInfoWrapper); isTracking = false; + } - if (sessionStorage && isStorageEnabled) { - await sessionStorage.set(URL_INFO_STORAGE_KEY, {}); - } + if (sessionStorage && isStorageEnabled) { + await sessionStorage.set(URL_INFO_STORAGE_KEY, {}); } }, }; diff --git a/packages/plugin-page-url-enrichment-browser/test/page-url-enrichment.test.ts b/packages/plugin-page-url-enrichment-browser/test/page-url-enrichment.test.ts index 4040f8a9d..7430900f0 100644 --- a/packages/plugin-page-url-enrichment-browser/test/page-url-enrichment.test.ts +++ b/packages/plugin-page-url-enrichment-browser/test/page-url-enrichment.test.ts @@ -120,6 +120,7 @@ describe('pageUrlEnrichmentPlugin', () => { afterEach(async () => { await plugin.teardown?.(); + window.sessionStorage.setItem('AMP_URL_INFO', '{}'); jest.restoreAllMocks(); }); diff --git a/packages/plugin-session-replay-browser/test/integration/browser-sdk-integration.test.ts b/packages/plugin-session-replay-browser/test/integration/browser-sdk-integration.test.ts index 7ffd97941..a122efc0b 100644 --- a/packages/plugin-session-replay-browser/test/integration/browser-sdk-integration.test.ts +++ b/packages/plugin-session-replay-browser/test/integration/browser-sdk-integration.test.ts @@ -89,10 +89,10 @@ describe('SessionReplayPlugin Integration with Browser SDK', () => { const sessionId = startSessionEvent?.session_id as number; expect(startSessionEvent).toEqual( expect.objectContaining({ - event_properties: { + event_properties: expect.objectContaining({ '[Amplitude] Session Replay Debug': JSON.stringify({ appHash: '-109988594' }), '[Amplitude] Session Replay ID': `${deviceId}/${sessionId}`, - }, + }), }), ); }); @@ -113,10 +113,10 @@ describe('SessionReplayPlugin Integration with Browser SDK', () => { const deviceId = startSessionEvent?.device_id as string; expect(startSessionEvent).toEqual( expect.objectContaining({ - event_properties: { + event_properties: expect.objectContaining({ '[Amplitude] Session Replay Debug': JSON.stringify({ appHash: '-109988594' }), '[Amplitude] Session Replay ID': `${deviceId}/${newSessionId}`, - }, + }), }), ); }); @@ -136,10 +136,10 @@ describe('SessionReplayPlugin Integration with Browser SDK', () => { const sessionId = pageViewEvent?.session_id as number; expect(pageViewEvent).toEqual( expect.objectContaining({ - event_properties: { + event_properties: expect.objectContaining({ '[Amplitude] Session Replay Debug': JSON.stringify({ appHash: '-109988594' }), '[Amplitude] Session Replay ID': `${deviceId}/${sessionId}`, - }, + }), }), ); }); diff --git a/test-server/browser-sdk/page-url-previous-page.html b/test-server/browser-sdk/page-url-enrichment.html similarity index 89% rename from test-server/browser-sdk/page-url-previous-page.html rename to test-server/browser-sdk/page-url-enrichment.html index 5a498ce5f..88740d308 100644 --- a/test-server/browser-sdk/page-url-previous-page.html +++ b/test-server/browser-sdk/page-url-enrichment.html @@ -10,7 +10,7 @@