{"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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"}