From 145761b0cd90ccb1003c59b3c106e696479125d5 Mon Sep 17 00:00:00 2001 From: Greg Leonard <45019882+greg-el@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:43:57 +0000 Subject: [PATCH 1/3] Add option to disable `performanceNavigationTiming` plugin (#1375) --- ...gation-timing-config_2024-11-11-14-14.json | 10 +++ .../javascript-tracker/src/configuration.ts | 1 + trackers/javascript-tracker/src/features.ts | 11 +--- .../test/unit/plugin_features.test.ts | 61 +++++++++++++++++++ 4 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 common/changes/@snowplow/javascript-tracker/performance-navigation-timing-config_2024-11-11-14-14.json create mode 100644 trackers/javascript-tracker/test/unit/plugin_features.test.ts diff --git a/common/changes/@snowplow/javascript-tracker/performance-navigation-timing-config_2024-11-11-14-14.json b/common/changes/@snowplow/javascript-tracker/performance-navigation-timing-config_2024-11-11-14-14.json new file mode 100644 index 000000000..c2e234556 --- /dev/null +++ b/common/changes/@snowplow/javascript-tracker/performance-navigation-timing-config_2024-11-11-14-14.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/javascript-tracker", + "comment": "Add `performanceNavigationTiming` option to JS contexts config", + "type": "none" + } + ], + "packageName": "@snowplow/javascript-tracker" +} \ No newline at end of file diff --git a/trackers/javascript-tracker/src/configuration.ts b/trackers/javascript-tracker/src/configuration.ts index 6a9648516..b1fde26a3 100644 --- a/trackers/javascript-tracker/src/configuration.ts +++ b/trackers/javascript-tracker/src/configuration.ts @@ -39,5 +39,6 @@ export interface JavaScriptTrackerConfiguration extends TrackerConfiguration { geolocation: boolean; clientHints: boolean | { includeHighEntropy: boolean }; webVitals: boolean | { loadWebVitalsScript?: boolean; webVitalsSource?: string }; + performanceNavigationTiming: boolean; }; } diff --git a/trackers/javascript-tracker/src/features.ts b/trackers/javascript-tracker/src/features.ts index 34965637a..a667a772e 100644 --- a/trackers/javascript-tracker/src/features.ts +++ b/trackers/javascript-tracker/src/features.ts @@ -30,13 +30,8 @@ import * as WebVitals from '@snowplow/browser-plugin-web-vitals'; * @param configuration - The tracker configuration object */ export function Plugins(configuration: JavaScriptTrackerConfiguration) { - const { - performanceTiming, - gaCookies, - geolocation, - clientHints, - webVitals - } = configuration?.contexts ?? {}; + const { performanceTiming, gaCookies, geolocation, clientHints, webVitals, performanceNavigationTiming } = + configuration?.contexts ?? {}; const activatedPlugins: Array<[BrowserPlugin, {} | Record]> = []; if (plugins.performanceTiming && performanceTiming) { @@ -148,7 +143,7 @@ export function Plugins(configuration: JavaScriptTrackerConfiguration) { activatedPlugins.push([EventSpecificationsPlugin(), apiMethods]); } - if (plugins.performanceNavigationTiming) { + if (plugins.performanceNavigationTiming && performanceNavigationTiming) { const { PerformanceNavigationTimingPlugin, ...apiMethods } = PerformanceNavigationTiming; activatedPlugins.push([PerformanceNavigationTimingPlugin(), apiMethods]); } diff --git a/trackers/javascript-tracker/test/unit/plugin_features.test.ts b/trackers/javascript-tracker/test/unit/plugin_features.test.ts new file mode 100644 index 000000000..ce75881b9 --- /dev/null +++ b/trackers/javascript-tracker/test/unit/plugin_features.test.ts @@ -0,0 +1,61 @@ +import { SelfDescribingJson } from '@snowplow/tracker-core'; +import { Plugins } from '../../src/features'; + +describe('Performance Navigation Timing', () => { + let windowSpy: any; + + const otherContexts = { + webPage: false, + session: false, + performanceTiming: false, + gaCookies: false, + geolocation: false, + clientHints: false, + webVitals: false, + }; + + const hasPerformanceNavigationTimingContext = (plugins: ReturnType): boolean => { + const pluginContexts = plugins.map((plugin) => plugin[0]?.contexts?.()); + const hasPerformanceContext = pluginContexts.some((contexts?: SelfDescribingJson[]) => + contexts?.some( + (context: { schema?: string }) => context.schema === 'iglu:org.w3/PerformanceNavigationTiming/jsonschema/1-0-0' + ) + ); + return hasPerformanceContext; + }; + + beforeEach(() => { + windowSpy = jest.spyOn(global, 'window', 'get'); + + // The PerformanceNavigationTiming context will only be added if the plugin can: + // - Access the `performance` object on the window + // - See that a value is returned from `getEntriesByType` + windowSpy.mockImplementation(() => ({ + performance: { + getEntriesByType: () => [{}], + }, + })); + }); + + it('Is enabled if contexts.performanceNavigationTiming is true', () => { + const plugins = Plugins({ + contexts: { + performanceNavigationTiming: true, + ...otherContexts, + }, + }); + + expect(hasPerformanceNavigationTimingContext(plugins)).toBe(true); + }); + + it('Is disabled if contexts.performanceNavigationTiming is false', () => { + const plugins = Plugins({ + contexts: { + performanceNavigationTiming: false, + ...otherContexts, + }, + }); + + expect(hasPerformanceNavigationTimingContext(plugins)).toBe(false); + }); +}); From e6e853a084a78366b941af70835c3ccde42e2486 Mon Sep 17 00:00:00 2001 From: Matus Tomlein Date: Mon, 11 Nov 2024 16:19:26 +0100 Subject: [PATCH 2/3] Fix customPostPath configuration being ignored (close #1376) PR #1377 --- .../issue-fix_post_path_2024-11-11-14-42.json | 10 ++++++++++ libraries/tracker-core/src/emitter/index.ts | 2 ++ .../tracker-core/test/emitter/index.test.ts | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 common/changes/@snowplow/tracker-core/issue-fix_post_path_2024-11-11-14-42.json diff --git a/common/changes/@snowplow/tracker-core/issue-fix_post_path_2024-11-11-14-42.json b/common/changes/@snowplow/tracker-core/issue-fix_post_path_2024-11-11-14-42.json new file mode 100644 index 000000000..d998d58f4 --- /dev/null +++ b/common/changes/@snowplow/tracker-core/issue-fix_post_path_2024-11-11-14-42.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/tracker-core", + "comment": "Fix customPostPath configuration being ignored (close #1376)", + "type": "none" + } + ], + "packageName": "@snowplow/tracker-core" +} \ No newline at end of file diff --git a/libraries/tracker-core/src/emitter/index.ts b/libraries/tracker-core/src/emitter/index.ts index ca142b7cf..0b7bfc783 100644 --- a/libraries/tracker-core/src/emitter/index.ts +++ b/libraries/tracker-core/src/emitter/index.ts @@ -198,6 +198,7 @@ interface RequestResult { export function newEmitter({ endpoint, eventMethod = 'post', + postPath, protocol, port, maxPostBytes = 40000, @@ -320,6 +321,7 @@ export function newEmitter({ maxPostBytes, useStm, credentials, + postPath, }); } diff --git a/libraries/tracker-core/test/emitter/index.test.ts b/libraries/tracker-core/test/emitter/index.test.ts index 6e01b131a..22c10ee23 100644 --- a/libraries/tracker-core/test/emitter/index.test.ts +++ b/libraries/tracker-core/test/emitter/index.test.ts @@ -333,3 +333,21 @@ test('adds a timeout to the request', async (t) => { t.is(requests.length, 1); t.is(await eventStore.count(), 1); }); + +test('uses custom POST path configured in the emitter', async (t) => { + const requests: Request[] = []; + const mockFetch = createMockFetch(200, requests); + const eventStore = newInMemoryEventStore({}); + const emitter: Emitter = newEmitter({ + endpoint: 'https://example.com', + customFetch: mockFetch, + postPath: '/custom', + eventStore, + }); + + await emitter.input({ e: 'pv' }); + await emitter.flush(); + + t.is(requests.length, 1); + t.is(requests[0].url, 'https://example.com/custom'); +}); From 7e6b787548d4c6ff95e2127a64f41e81d3cd5980 Mon Sep 17 00:00:00 2001 From: Matus Tomlein Date: Mon, 11 Nov 2024 16:22:40 +0100 Subject: [PATCH 3/3] Fix ignored label property in the startHtml5MediaTracking call (#1378) --- ...label_in_media_tracking_2024-11-11-15-16.json | 10 ++++++++++ .../browser-plugin-media-tracking/src/player.ts | 7 +++++-- .../tests/test.test.ts | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 common/changes/@snowplow/browser-plugin-media-tracking/issue-fix_ignored_label_in_media_tracking_2024-11-11-15-16.json diff --git a/common/changes/@snowplow/browser-plugin-media-tracking/issue-fix_ignored_label_in_media_tracking_2024-11-11-15-16.json b/common/changes/@snowplow/browser-plugin-media-tracking/issue-fix_ignored_label_in_media_tracking_2024-11-11-15-16.json new file mode 100644 index 000000000..b0131e443 --- /dev/null +++ b/common/changes/@snowplow/browser-plugin-media-tracking/issue-fix_ignored_label_in_media_tracking_2024-11-11-15-16.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@snowplow/browser-plugin-media-tracking", + "comment": "Fix ignored label property in the startHtml5MediaTracking call", + "type": "none" + } + ], + "packageName": "@snowplow/browser-plugin-media-tracking" +} \ No newline at end of file diff --git a/plugins/browser-plugin-media-tracking/src/player.ts b/plugins/browser-plugin-media-tracking/src/player.ts index da1dfe0f9..e40b6abba 100644 --- a/plugins/browser-plugin-media-tracking/src/player.ts +++ b/plugins/browser-plugin-media-tracking/src/player.ts @@ -59,12 +59,15 @@ function htmlContext(el: HTMLMediaElement): (() => SelfDescribingJson)[] { } export function setUpListeners(config: ElementConfig) { - const { id, video } = config; + const { id, video, label } = config; startMediaTracking({ ...config, id, - player: updatePlayer(video), + player: { + label, + ...updatePlayer(video) + }, context: (config.context ?? []).concat(htmlContext(video)), }); diff --git a/plugins/browser-plugin-media-tracking/tests/test.test.ts b/plugins/browser-plugin-media-tracking/tests/test.test.ts index a1b7e2898..12d254a75 100644 --- a/plugins/browser-plugin-media-tracking/tests/test.test.ts +++ b/plugins/browser-plugin-media-tracking/tests/test.test.ts @@ -312,4 +312,20 @@ describe('MediaTrackingPlugin', () => { expect(eventQueue.length).toBe(0); }); + + it("adds label to tracked event", async () => { + const video = document.createElement('video'); + video.id = id; + document.body.appendChild(video); + + startHtml5MediaTracking({ id: 'id', label: 'foo', video, captureEvents: [MediaEventType.Play] }); + + video.play(); + + let playerContext = eventQueue[0].context.find( + (c) => c.schema === 'iglu:com.snowplowanalytics.snowplow/media_player/jsonschema/2-0-0' + )?.data; + + expect(playerContext?.label).toEqual('foo'); + }); });