@aws-amplify/analytics
Version:
Analytics category of aws-amplify
1 lines • 10.8 kB
Source Map (JSON)
{"version":3,"file":"PageViewTracker.mjs","sources":["../../../src/trackers/PageViewTracker.ts"],"sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { ConsoleLogger } from '@aws-amplify/core';\nimport { isBrowser } from '@aws-amplify/core/internals/utils';\nconst logger = new ConsoleLogger('PageViewTracker');\nconst DEFAULT_EVENT_NAME = 'pageView';\nconst DEFAULT_APP_TYPE = 'singlePage';\nconst DEFAULT_URL_PROVIDER = () => {\n return window.location.origin + window.location.pathname;\n};\nconst PREV_URL_STORAGE_KEY = 'aws-amplify-analytics-prevUrl';\n/**\n * Custom event broadcast by the shared history patch (see below) whenever\n * `history.pushState` / `history.replaceState` is invoked. Every active\n * `PageViewTracker` subscribes to it, so a single global patch can drive any\n * number of concurrent tracker instances.\n */\nconst SPA_NAVIGATION_EVENT = 'amplify-analytics-spa-navigation';\n/**\n * Reference-counted, process-global patch of the History API.\n *\n * `PageViewTracker` instances previously each installed their own revocable\n * proxy on `window.history.pushState` / `replaceState`. That is not safe once\n * more than one instance can exist at a time (e.g. `pageView` auto-track enabled\n * on both Pinpoint and Kinesis): the proxies stacked (each instance captured the\n * previous instance's proxy as its \"original\"), so only the last-installed\n * instance actually received SPA navigations, and disabling providers in the\n * wrong order could leave a revoked proxy installed — throwing on the next\n * `pushState`.\n *\n * Instead the History API is patched exactly once (guarded by a reference\n * count). The patch simply forwards to the native implementation and broadcasts\n * {@link SPA_NAVIGATION_EVENT}; each tracker instance listens for that event.\n * The patch is removed and the native methods restored only when the last\n * instance tears down, so any number of trackers can be enabled / disabled in\n * any order safely.\n */\nlet historyPatchRefCount = 0;\nlet nativePushState;\nlet nativeReplaceState;\nconst installHistoryPatch = () => {\n historyPatchRefCount += 1;\n // The patch is shared across all instances; only install it once.\n if (historyPatchRefCount > 1) {\n return;\n }\n nativePushState = window.history.pushState;\n nativeReplaceState = window.history.replaceState;\n const dispatchNavigation = () => {\n window.dispatchEvent(new Event(SPA_NAVIGATION_EVENT));\n };\n window.history.pushState = function pushState(...args) {\n nativePushState.apply(this, args);\n dispatchNavigation();\n };\n window.history.replaceState = function replaceState(...args) {\n nativeReplaceState.apply(this, args);\n dispatchNavigation();\n };\n};\nconst uninstallHistoryPatch = () => {\n if (historyPatchRefCount === 0) {\n return;\n }\n historyPatchRefCount -= 1;\n // Keep the patch installed while other instances still rely on it.\n if (historyPatchRefCount > 0) {\n return;\n }\n if (nativePushState) {\n window.history.pushState = nativePushState;\n nativePushState = undefined;\n }\n if (nativeReplaceState) {\n window.history.replaceState = nativeReplaceState;\n nativeReplaceState = undefined;\n }\n};\nexport class PageViewTracker {\n constructor(eventRecorder, options, namespace) {\n this.options = {};\n this.trackerActive = true;\n this.eventRecorder = eventRecorder;\n this.spaTrackingActive = false;\n this.storageKey = namespace\n ? `${PREV_URL_STORAGE_KEY}-${namespace}`\n : PREV_URL_STORAGE_KEY;\n this.handleLocationChange = this.handleLocationChange.bind(this);\n this.configure(eventRecorder, options);\n }\n configure(eventRecorder, options) {\n this.eventRecorder = eventRecorder;\n // Clean up any existing listeners\n this.cleanup();\n // Apply defaults\n this.options = {\n appType: options?.appType ?? DEFAULT_APP_TYPE,\n attributes: options?.attributes ?? undefined,\n eventName: options?.eventName ?? DEFAULT_EVENT_NAME,\n urlProvider: options?.urlProvider ?? DEFAULT_URL_PROVIDER,\n };\n // Configure SPA or MPA page view tracking\n if (isBrowser()) {\n if (this.options.appType === 'singlePage') {\n this.setupSPATracking();\n }\n else {\n this.setupMPATracking();\n }\n this.trackerActive = true;\n }\n }\n cleanup() {\n // No-op if document listener is not active\n if (!this.trackerActive) {\n return;\n }\n // Clean up SPA page view listeners\n if (this.spaTrackingActive) {\n window.removeEventListener(SPA_NAVIGATION_EVENT, this.handleLocationChange);\n window.removeEventListener('popstate', this.handleLocationChange);\n uninstallHistoryPatch();\n this.spaTrackingActive = false;\n }\n }\n setupSPATracking() {\n if (!this.spaTrackingActive) {\n // Subscribe to the shared history patch (installed once, ref-counted)\n // plus native `popstate`. Both funnel through `handleLocationChange`.\n installHistoryPatch();\n window.addEventListener(SPA_NAVIGATION_EVENT, this.handleLocationChange);\n window.addEventListener('popstate', this.handleLocationChange);\n sessionStorage.removeItem(this.storageKey);\n this.spaTrackingActive = true;\n }\n }\n setupMPATracking() {\n this.handleLocationChange();\n }\n handleLocationChange() {\n const currentUrl = this.options.urlProvider();\n const eventName = this.options.eventName || DEFAULT_EVENT_NAME;\n if (this.urlHasChanged()) {\n sessionStorage.setItem(this.storageKey, currentUrl);\n // Assemble attribute list\n const attributes = Object.assign({\n url: currentUrl,\n }, this.options.attributes);\n logger.debug('Recording automatically tracked page view event', {\n eventName,\n attributes,\n });\n this.eventRecorder(eventName, attributes);\n }\n }\n urlHasChanged() {\n const prevUrl = sessionStorage.getItem(this.storageKey);\n const currUrl = this.options.urlProvider();\n return currUrl !== prevUrl;\n }\n}\n"],"names":[],"mappings":"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"}