@amplitude/plugin-page-url-enrichment-browser 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/lib/cjs/index.d.ts +3 -0
  4. package/lib/cjs/index.d.ts.map +1 -0
  5. package/lib/cjs/index.js +11 -0
  6. package/lib/cjs/index.js.map +1 -0
  7. package/lib/cjs/page-url-enrichment.d.ts +11 -0
  8. package/lib/cjs/page-url-enrichment.d.ts.map +1 -0
  9. package/lib/cjs/page-url-enrichment.js +195 -0
  10. package/lib/cjs/page-url-enrichment.js.map +1 -0
  11. package/lib/cjs/typings/page-url-enrichment.d.ts +6 -0
  12. package/lib/cjs/typings/page-url-enrichment.d.ts.map +1 -0
  13. package/lib/cjs/typings/page-url-enrichment.js +3 -0
  14. package/lib/cjs/typings/page-url-enrichment.js.map +1 -0
  15. package/lib/esm/index.d.ts +3 -0
  16. package/lib/esm/index.d.ts.map +1 -0
  17. package/lib/esm/index.js +3 -0
  18. package/lib/esm/index.js.map +1 -0
  19. package/lib/esm/page-url-enrichment.d.ts +11 -0
  20. package/lib/esm/page-url-enrichment.d.ts.map +1 -0
  21. package/lib/esm/page-url-enrichment.js +190 -0
  22. package/lib/esm/page-url-enrichment.js.map +1 -0
  23. package/lib/esm/typings/page-url-enrichment.d.ts +6 -0
  24. package/lib/esm/typings/page-url-enrichment.d.ts.map +1 -0
  25. package/lib/esm/typings/page-url-enrichment.js +2 -0
  26. package/lib/esm/typings/page-url-enrichment.js.map +1 -0
  27. package/lib/scripts/amplitude-min.umd.js +1 -0
  28. package/lib/scripts/amplitude-min.umd.js.gz +0 -0
  29. package/lib/scripts/index.d.ts +3 -0
  30. package/lib/scripts/index.d.ts.map +1 -0
  31. package/lib/scripts/page-url-enrichment.d.ts +11 -0
  32. package/lib/scripts/page-url-enrichment.d.ts.map +1 -0
  33. package/lib/scripts/typings/page-url-enrichment.d.ts +6 -0
  34. package/lib/scripts/typings/page-url-enrichment.d.ts.map +1 -0
  35. package/package.json +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Amplitude Analytics
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ <p align="center">
2
+ <a href="https://amplitude.com" target="_blank" align="center">
3
+ <img src="https://static.amplitude.com/lightning/46c85bfd91905de8047f1ee65c7c93d6fa9ee6ea/static/media/amplitude-logo-with-text.4fb9e463.svg" width="280">
4
+ </a>
5
+ <br />
6
+ </p>
7
+
8
+ # @amplitude/plugin-page-url-enrichment-browser
9
+
10
+ Official Browser SDK plugin for page url enrichment
11
+
12
+ ## Installation
13
+
14
+ This package is published on NPM registry and is available to be installed using npm and yarn.
15
+
16
+ ```sh
17
+ # npm
18
+ npm install @amplitude/plugin-page-url-enrichment-browser
19
+
20
+ # yarn
21
+ yarn add @amplitude/plugin-page-url-enrichment-browser
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ This plugin works on top of Amplitude Browser SDK and adds page url enrichment properties to all events. To use this plugin, you need to install `@amplitude/analytics-browser` version `v2.0.0` or later.
27
+
28
+ ### 1. Import Amplitude packages
29
+
30
+ * `@amplitude/plugin-page-url-enrichment-browser`
31
+
32
+ ```typescript
33
+ import { pageUrlEnrichmentPlugin } from '@amplitude/plugin-page-url-enrichment-browser';
34
+ ```
35
+
36
+ ### 2. Instantiate page url enrichment plugin
37
+
38
+ The plugin accepts an optional parameter of type `Object` to configure the plugin based on your use case.
39
+
40
+ ```typescript
41
+ const pageUrlEnrichment = pageUrlEnrichmentPlugin();
42
+ ```
43
+
44
+ #### Options
45
+
46
+
47
+ ### 3. Install plugin to Amplitude SDK
48
+
49
+ ```typescript
50
+ amplitude.add(pageUrlEnrichment);
51
+ ```
52
+
53
+ ### 4. Initialize Amplitude SDK
54
+
55
+ ```typescript
56
+ amplitude.init('API_KEY');
57
+ ```
58
+
59
+ ## Resulting Page URL properties
60
+
61
+ This plugin adds Page URL properties to all events based on your configuration
62
+
63
+ #### Event type
64
+ * No event type added
65
+
66
+ #### Event properties
67
+
68
+ | Property | Description |
69
+ | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
70
+ | `'[Amplitude] Page Domain'` | The website's hostname or `location.hostname` |
71
+ | `'[Amplitude] Page Location'` | The website's full url or `location.href` |
72
+ | `'[Amplitude] Page Path'` | The website's pathname or `location.pathname` |
73
+ | `'[Amplitude] Page Title'` | The website's title or `document.title` |
74
+ | `'[Amplitude] Page URL'` | The website's url excluding query parameters |
75
+ | `'[Amplitude] Previous Page Location'` | The URL of the previous page the user visited; document.referrer if coming from an external domain; and using the sessionStorage which tracks the last url otherwise |
76
+ | `'Amplitude] Previous Page Type'` | A classification of the previous page (e.g., 'Internal', 'External', 'Direct'), typically derived from a custom function that analyzes the previous page's URL |
@@ -0,0 +1,3 @@
1
+ export { pageUrlEnrichmentPlugin, CURRENT_PAGE_STORAGE_KEY, PREVIOUS_PAGE_STORAGE_KEY, URL_INFO_STORAGE_KEY, } from './page-url-enrichment';
2
+ export { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.plugin = exports.URL_INFO_STORAGE_KEY = exports.PREVIOUS_PAGE_STORAGE_KEY = exports.CURRENT_PAGE_STORAGE_KEY = exports.pageUrlEnrichmentPlugin = void 0;
4
+ var page_url_enrichment_1 = require("./page-url-enrichment");
5
+ Object.defineProperty(exports, "pageUrlEnrichmentPlugin", { enumerable: true, get: function () { return page_url_enrichment_1.pageUrlEnrichmentPlugin; } });
6
+ Object.defineProperty(exports, "CURRENT_PAGE_STORAGE_KEY", { enumerable: true, get: function () { return page_url_enrichment_1.CURRENT_PAGE_STORAGE_KEY; } });
7
+ Object.defineProperty(exports, "PREVIOUS_PAGE_STORAGE_KEY", { enumerable: true, get: function () { return page_url_enrichment_1.PREVIOUS_PAGE_STORAGE_KEY; } });
8
+ Object.defineProperty(exports, "URL_INFO_STORAGE_KEY", { enumerable: true, get: function () { return page_url_enrichment_1.URL_INFO_STORAGE_KEY; } });
9
+ var page_url_enrichment_2 = require("./page-url-enrichment");
10
+ Object.defineProperty(exports, "plugin", { enumerable: true, get: function () { return page_url_enrichment_2.pageUrlEnrichmentPlugin; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAK+B;AAJ7B,8HAAA,uBAAuB,OAAA;AACvB,+HAAA,wBAAwB,OAAA;AACxB,gIAAA,yBAAyB,OAAA;AACzB,2HAAA,oBAAoB,OAAA;AAEtB,6DAA0E;AAAjE,6GAAA,uBAAuB,OAAU","sourcesContent":["export {\n pageUrlEnrichmentPlugin,\n CURRENT_PAGE_STORAGE_KEY,\n PREVIOUS_PAGE_STORAGE_KEY,\n URL_INFO_STORAGE_KEY,\n} from './page-url-enrichment';\nexport { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';\n"]}
@@ -0,0 +1,11 @@
1
+ import type { EnrichmentPlugin } from '@amplitude/analytics-types';
2
+ export declare const CURRENT_PAGE_STORAGE_KEY = "AMP_CURRENT_PAGE";
3
+ export declare const PREVIOUS_PAGE_STORAGE_KEY = "AMP_PREVIOUS_PAGE";
4
+ export declare const URL_INFO_STORAGE_KEY = "AMP_URL_INFO";
5
+ export type URLInfo = {
6
+ [CURRENT_PAGE_STORAGE_KEY]?: string;
7
+ [PREVIOUS_PAGE_STORAGE_KEY]?: string;
8
+ };
9
+ export declare const isPageUrlEnrichmentEnabled: (option: unknown) => boolean;
10
+ export declare const pageUrlEnrichmentPlugin: () => EnrichmentPlugin;
11
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../src/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,gBAAgB,EAAiB,MAAM,4BAA4B,CAAC;AAGhH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAC3D,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,wBAAwB,CAAC,CAAC,EAAE,MAAM,CAAC;IACpC,CAAC,yBAAyB,CAAC,CAAC,EAAE,MAAM,CAAC;CACtC,CAAC;AAQF,eAAO,MAAM,0BAA0B,WAAY,OAAO,KAAG,OAQ5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,QAAO,gBAuK1C,CAAC"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pageUrlEnrichmentPlugin = exports.isPageUrlEnrichmentEnabled = exports.URL_INFO_STORAGE_KEY = exports.PREVIOUS_PAGE_STORAGE_KEY = exports.CURRENT_PAGE_STORAGE_KEY = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var analytics_core_1 = require("@amplitude/analytics-core");
6
+ exports.CURRENT_PAGE_STORAGE_KEY = 'AMP_CURRENT_PAGE';
7
+ exports.PREVIOUS_PAGE_STORAGE_KEY = 'AMP_PREVIOUS_PAGE';
8
+ exports.URL_INFO_STORAGE_KEY = 'AMP_URL_INFO';
9
+ var PreviousPageType;
10
+ (function (PreviousPageType) {
11
+ PreviousPageType["Direct"] = "direct";
12
+ PreviousPageType["Internal"] = "internal";
13
+ PreviousPageType["External"] = "external";
14
+ })(PreviousPageType || (PreviousPageType = {}));
15
+ var isPageUrlEnrichmentEnabled = function (option) {
16
+ if (typeof option === 'boolean') {
17
+ return option;
18
+ }
19
+ if (typeof option === 'object' && option !== null && 'pageUrlEnrichment' in option) {
20
+ return Boolean(option.pageUrlEnrichment);
21
+ }
22
+ return false;
23
+ };
24
+ exports.isPageUrlEnrichmentEnabled = isPageUrlEnrichmentEnabled;
25
+ var pageUrlEnrichmentPlugin = function () {
26
+ var globalScope = (0, analytics_core_1.getGlobalScope)();
27
+ var sessionStorage = undefined;
28
+ var isStorageEnabled = false;
29
+ var loggerProvider = undefined;
30
+ var isProxied = false;
31
+ var isTracking = false;
32
+ var getDecodeURI = function (locationStr) {
33
+ var decodedLocationStr = locationStr;
34
+ try {
35
+ decodedLocationStr = decodeURI(locationStr);
36
+ }
37
+ catch (e) {
38
+ /* istanbul ignore next */
39
+ loggerProvider === null || loggerProvider === void 0 ? void 0 : loggerProvider.error('Malformed URI sequence: ', e);
40
+ }
41
+ return decodedLocationStr;
42
+ };
43
+ var getHostname = function (url) {
44
+ var hostname;
45
+ try {
46
+ var decodedUrl = getDecodeURI(url);
47
+ hostname = new URL(decodedUrl).hostname;
48
+ }
49
+ catch (e) {
50
+ /* istanbul ignore next */
51
+ loggerProvider === null || loggerProvider === void 0 ? void 0 : loggerProvider.error('Could not parse URL: ', e);
52
+ }
53
+ return hostname;
54
+ };
55
+ var getPrevPageType = function (previousPage) {
56
+ var currentDomain = (typeof location !== 'undefined' && location.hostname) || '';
57
+ var previousPageDomain = previousPage ? getHostname(previousPage) : undefined;
58
+ switch (previousPageDomain) {
59
+ case undefined:
60
+ return PreviousPageType.Direct;
61
+ case currentDomain:
62
+ return PreviousPageType.Internal;
63
+ default:
64
+ return PreviousPageType.External;
65
+ }
66
+ };
67
+ var saveURLInfo = function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
68
+ var URLInfo, previousURL, currentURL;
69
+ var _a;
70
+ return tslib_1.__generator(this, function (_b) {
71
+ switch (_b.label) {
72
+ case 0:
73
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 3];
74
+ return [4 /*yield*/, sessionStorage.get(exports.URL_INFO_STORAGE_KEY)];
75
+ case 1:
76
+ URLInfo = _b.sent();
77
+ previousURL = (URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[exports.CURRENT_PAGE_STORAGE_KEY]) || '';
78
+ currentURL = getDecodeURI((typeof location !== 'undefined' && location.href) || '');
79
+ return [4 /*yield*/, sessionStorage.set(exports.URL_INFO_STORAGE_KEY, (_a = {},
80
+ _a[exports.CURRENT_PAGE_STORAGE_KEY] = currentURL,
81
+ _a[exports.PREVIOUS_PAGE_STORAGE_KEY] = previousURL,
82
+ _a))];
83
+ case 2:
84
+ _b.sent();
85
+ _b.label = 3;
86
+ case 3: return [2 /*return*/];
87
+ }
88
+ });
89
+ }); };
90
+ var saveUrlInfoWrapper = function () {
91
+ void saveURLInfo();
92
+ };
93
+ var plugin = {
94
+ name: '@amplitude/plugin-page-url-enrichment-browser',
95
+ type: 'enrichment',
96
+ setup: function (config, _) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
97
+ return tslib_1.__generator(this, function (_a) {
98
+ switch (_a.label) {
99
+ case 0:
100
+ loggerProvider = config.loggerProvider;
101
+ loggerProvider.log('Installing @amplitude/plugin-page-url-enrichment-browser');
102
+ isTracking = true;
103
+ if (!globalScope) return [3 /*break*/, 2];
104
+ sessionStorage = new analytics_core_1.BrowserStorage(globalScope.sessionStorage);
105
+ return [4 /*yield*/, sessionStorage.isEnabled()];
106
+ case 1:
107
+ isStorageEnabled = _a.sent();
108
+ globalScope.addEventListener('popstate', saveUrlInfoWrapper);
109
+ if (!isProxied) {
110
+ /* istanbul ignore next */
111
+ // There is no global browser listener for changes to history, so we have
112
+ // to modify pushState and replaceState directly.
113
+ // https://stackoverflow.com/a/64927639
114
+ // eslint-disable-next-line @typescript-eslint/unbound-method
115
+ globalScope.history.pushState = new Proxy(globalScope.history.pushState, {
116
+ apply: function (target, thisArg, _a) {
117
+ var _b = tslib_1.__read(_a, 3), state = _b[0], unused = _b[1], url = _b[2];
118
+ target.apply(thisArg, [state, unused, url]);
119
+ if (isTracking) {
120
+ saveUrlInfoWrapper();
121
+ }
122
+ },
123
+ });
124
+ // eslint-disable-next-line @typescript-eslint/unbound-method
125
+ globalScope.history.replaceState = new Proxy(globalScope.history.replaceState, {
126
+ apply: function (target, thisArg, _a) {
127
+ var _b = tslib_1.__read(_a, 3), state = _b[0], unused = _b[1], url = _b[2];
128
+ target.apply(thisArg, [state, unused, url]);
129
+ if (isTracking) {
130
+ saveUrlInfoWrapper();
131
+ }
132
+ },
133
+ });
134
+ isProxied = true;
135
+ }
136
+ _a.label = 2;
137
+ case 2: return [2 /*return*/];
138
+ }
139
+ });
140
+ }); },
141
+ execute: function (event) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
142
+ var locationHREF, previousPage, URLInfo;
143
+ var _a;
144
+ return tslib_1.__generator(this, function (_b) {
145
+ switch (_b.label) {
146
+ case 0:
147
+ locationHREF = getDecodeURI((typeof location !== 'undefined' && location.href) || '');
148
+ previousPage = '';
149
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 4];
150
+ return [4 /*yield*/, sessionStorage.get(exports.URL_INFO_STORAGE_KEY)];
151
+ case 1:
152
+ URLInfo = _b.sent();
153
+ previousPage = (URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[exports.PREVIOUS_PAGE_STORAGE_KEY]) || document.referrer || '';
154
+ if (!!(URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[exports.CURRENT_PAGE_STORAGE_KEY])) return [3 /*break*/, 3];
155
+ return [4 /*yield*/, sessionStorage.set(exports.URL_INFO_STORAGE_KEY, tslib_1.__assign(tslib_1.__assign({}, (URLInfo || {})), (_a = {}, _a[exports.CURRENT_PAGE_STORAGE_KEY] = locationHREF, _a[exports.PREVIOUS_PAGE_STORAGE_KEY] = previousPage, _a)))];
156
+ case 2:
157
+ _b.sent();
158
+ _b.label = 3;
159
+ case 3:
160
+ event.event_properties = tslib_1.__assign(tslib_1.__assign({}, (event.event_properties || {})), { '[Amplitude] Page Domain': addIfNotExist(event, '[Amplitude] Page Domain', (typeof location !== 'undefined' && location.hostname) || ''), '[Amplitude] Page Location': addIfNotExist(event, '[Amplitude] Page Location', locationHREF), '[Amplitude] Page Path': addIfNotExist(event, '[Amplitude] Page Path', (typeof location !== 'undefined' && getDecodeURI(location.pathname)) || ''), '[Amplitude] Page Title': addIfNotExist(event, '[Amplitude] Page Title', (typeof document !== 'undefined' && document.title) || ''), '[Amplitude] Page URL': addIfNotExist(event, '[Amplitude] Page URL', locationHREF.split('?')[0]), '[Amplitude] Previous Page Location': previousPage, '[Amplitude] Previous Page Type': getPrevPageType(previousPage) });
161
+ _b.label = 4;
162
+ case 4: return [2 /*return*/, event];
163
+ }
164
+ });
165
+ }); },
166
+ teardown: function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
167
+ return tslib_1.__generator(this, function (_a) {
168
+ switch (_a.label) {
169
+ case 0:
170
+ if (!globalScope) return [3 /*break*/, 2];
171
+ globalScope.removeEventListener('popstate', saveUrlInfoWrapper);
172
+ isTracking = false;
173
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 2];
174
+ return [4 /*yield*/, sessionStorage.set(exports.URL_INFO_STORAGE_KEY, {})];
175
+ case 1:
176
+ _a.sent();
177
+ _a.label = 2;
178
+ case 2: return [2 /*return*/];
179
+ }
180
+ });
181
+ }); },
182
+ };
183
+ return plugin;
184
+ };
185
+ exports.pageUrlEnrichmentPlugin = pageUrlEnrichmentPlugin;
186
+ function addIfNotExist(event, key, value) {
187
+ if (!event.event_properties) {
188
+ event.event_properties = {};
189
+ }
190
+ if (event.event_properties[key] === undefined) {
191
+ return value;
192
+ }
193
+ return event.event_properties[key];
194
+ }
195
+ //# sourceMappingURL=page-url-enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.js","sourceRoot":"","sources":["../../src/page-url-enrichment.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrowserClient, BrowserConfig, EnrichmentPlugin, Event, Logger } from '@amplitude/analytics-types';\nimport { getGlobalScope, BrowserStorage } from '@amplitude/analytics-core';\n\nexport const CURRENT_PAGE_STORAGE_KEY = 'AMP_CURRENT_PAGE';\nexport const PREVIOUS_PAGE_STORAGE_KEY = 'AMP_PREVIOUS_PAGE';\n\nexport const URL_INFO_STORAGE_KEY = 'AMP_URL_INFO';\n\nexport type URLInfo = {\n [CURRENT_PAGE_STORAGE_KEY]?: string;\n [PREVIOUS_PAGE_STORAGE_KEY]?: string;\n};\n\nenum PreviousPageType {\n Direct = 'direct', // for no prev page or referrer\n Internal = 'internal', // for same domain - this excludes subdomains\n External = 'external', // for different domains\n}\n\nexport const isPageUrlEnrichmentEnabled = (option: unknown): boolean => {\n if (typeof option === 'boolean') {\n return option;\n }\n if (typeof option === 'object' && option !== null && 'pageUrlEnrichment' in option) {\n return Boolean((option as { pageUrlEnrichment?: boolean }).pageUrlEnrichment);\n }\n return false;\n};\n\nexport const pageUrlEnrichmentPlugin = (): EnrichmentPlugin => {\n const globalScope = getGlobalScope();\n let sessionStorage: BrowserStorage<URLInfo> | undefined = undefined;\n let isStorageEnabled = false;\n let loggerProvider: Logger | undefined = undefined;\n\n let isProxied = false;\n let isTracking = false;\n\n const getDecodeURI = (locationStr: string): string => {\n let decodedLocationStr = locationStr;\n try {\n decodedLocationStr = decodeURI(locationStr);\n } catch (e) {\n /* istanbul ignore next */\n loggerProvider?.error('Malformed URI sequence: ', e);\n }\n\n return decodedLocationStr;\n };\n\n const getHostname = (url: string): string | undefined => {\n let hostname: string | undefined;\n\n try {\n const decodedUrl = getDecodeURI(url);\n hostname = new URL(decodedUrl).hostname;\n } catch (e) {\n /* istanbul ignore next */\n loggerProvider?.error('Could not parse URL: ', e);\n }\n\n return hostname;\n };\n\n const getPrevPageType = (previousPage: string) => {\n const currentDomain = (typeof location !== 'undefined' && location.hostname) || '';\n const previousPageDomain = previousPage ? getHostname(previousPage) : undefined;\n\n switch (previousPageDomain) {\n case undefined:\n return PreviousPageType.Direct;\n case currentDomain:\n return PreviousPageType.Internal;\n default:\n return PreviousPageType.External;\n }\n };\n\n const saveURLInfo = async () => {\n if (sessionStorage && isStorageEnabled) {\n const URLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY);\n const previousURL = URLInfo?.[CURRENT_PAGE_STORAGE_KEY] || '';\n const currentURL = getDecodeURI((typeof location !== 'undefined' && location.href) || '');\n\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {\n [CURRENT_PAGE_STORAGE_KEY]: currentURL,\n [PREVIOUS_PAGE_STORAGE_KEY]: previousURL,\n });\n }\n };\n\n const saveUrlInfoWrapper = () => {\n void saveURLInfo();\n };\n\n const plugin: EnrichmentPlugin = {\n name: '@amplitude/plugin-page-url-enrichment-browser',\n type: 'enrichment',\n\n setup: async (config: BrowserConfig, _: BrowserClient) => {\n loggerProvider = config.loggerProvider;\n loggerProvider.log('Installing @amplitude/plugin-page-url-enrichment-browser');\n\n isTracking = true;\n\n if (globalScope) {\n sessionStorage = new BrowserStorage<URLInfo>(globalScope.sessionStorage);\n isStorageEnabled = await sessionStorage.isEnabled();\n\n globalScope.addEventListener('popstate', saveUrlInfoWrapper);\n\n if (!isProxied) {\n /* istanbul ignore next */\n // There is no global browser listener for changes to history, so we have\n // to modify pushState and replaceState directly.\n // https://stackoverflow.com/a/64927639\n // eslint-disable-next-line @typescript-eslint/unbound-method\n globalScope.history.pushState = new Proxy(globalScope.history.pushState, {\n apply: (target, thisArg, [state, unused, url]) => {\n target.apply(thisArg, [state, unused, url]);\n if (isTracking) {\n saveUrlInfoWrapper();\n }\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n globalScope.history.replaceState = new Proxy(globalScope.history.replaceState, {\n apply: (target, thisArg, [state, unused, url]) => {\n target.apply(thisArg, [state, unused, url]);\n if (isTracking) {\n saveUrlInfoWrapper();\n }\n },\n });\n\n isProxied = true;\n }\n }\n },\n execute: async (event: Event) => {\n const locationHREF = getDecodeURI((typeof location !== 'undefined' && location.href) || '');\n\n let previousPage = '';\n if (sessionStorage && isStorageEnabled) {\n const URLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY);\n previousPage = URLInfo?.[PREVIOUS_PAGE_STORAGE_KEY] || document.referrer || '';\n\n if (!URLInfo?.[CURRENT_PAGE_STORAGE_KEY]) {\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {\n ...(URLInfo || {}),\n [CURRENT_PAGE_STORAGE_KEY]: locationHREF,\n [PREVIOUS_PAGE_STORAGE_KEY]: previousPage,\n });\n }\n\n event.event_properties = {\n ...(event.event_properties || {}),\n '[Amplitude] Page Domain': addIfNotExist(\n event,\n '[Amplitude] Page Domain',\n (typeof location !== 'undefined' && location.hostname) || '',\n ),\n '[Amplitude] Page Location': addIfNotExist(event, '[Amplitude] Page Location', locationHREF),\n '[Amplitude] Page Path': addIfNotExist(\n event,\n '[Amplitude] Page Path',\n (typeof location !== 'undefined' && getDecodeURI(location.pathname)) || '',\n ),\n '[Amplitude] Page Title': addIfNotExist(\n event,\n '[Amplitude] Page Title',\n (typeof document !== 'undefined' && document.title) || '',\n ),\n '[Amplitude] Page URL': addIfNotExist(event, '[Amplitude] Page URL', locationHREF.split('?')[0]),\n '[Amplitude] Previous Page Location': previousPage,\n '[Amplitude] Previous Page Type': getPrevPageType(previousPage),\n };\n }\n\n return event;\n },\n teardown: async () => {\n if (globalScope) {\n globalScope.removeEventListener('popstate', saveUrlInfoWrapper);\n\n isTracking = false;\n\n if (sessionStorage && isStorageEnabled) {\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {});\n }\n }\n },\n };\n\n return plugin;\n};\n\nfunction addIfNotExist(event: Event, key: string, value: string): string {\n if (!event.event_properties) {\n event.event_properties = {};\n }\n\n if ((event.event_properties as { [key: string]: any })[key] === undefined) {\n return value;\n }\n\n return (event.event_properties as { [key: string]: any })[key] as string;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { EnrichmentPlugin, PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
2
+ export type { PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
3
+ export interface CreatePageUrlEnrichmentBrowserPlugin {
4
+ (options?: Options): EnrichmentPlugin;
5
+ }
6
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../../src/typings/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEvG,YAAY,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,oCAAoC;IACnD,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACvC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=page-url-enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.js","sourceRoot":"","sources":["../../../src/typings/page-url-enrichment.ts"],"names":[],"mappings":"","sourcesContent":["import type { EnrichmentPlugin, PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';\n\nexport type { PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';\n\nexport interface CreatePageUrlEnrichmentBrowserPlugin {\n (options?: Options): EnrichmentPlugin;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export { pageUrlEnrichmentPlugin, CURRENT_PAGE_STORAGE_KEY, PREVIOUS_PAGE_STORAGE_KEY, URL_INFO_STORAGE_KEY, } from './page-url-enrichment';
2
+ export { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { pageUrlEnrichmentPlugin, CURRENT_PAGE_STORAGE_KEY, PREVIOUS_PAGE_STORAGE_KEY, URL_INFO_STORAGE_KEY, } from './page-url-enrichment';
2
+ export { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["export {\n pageUrlEnrichmentPlugin,\n CURRENT_PAGE_STORAGE_KEY,\n PREVIOUS_PAGE_STORAGE_KEY,\n URL_INFO_STORAGE_KEY,\n} from './page-url-enrichment';\nexport { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';\n"]}
@@ -0,0 +1,11 @@
1
+ import type { EnrichmentPlugin } from '@amplitude/analytics-types';
2
+ export declare const CURRENT_PAGE_STORAGE_KEY = "AMP_CURRENT_PAGE";
3
+ export declare const PREVIOUS_PAGE_STORAGE_KEY = "AMP_PREVIOUS_PAGE";
4
+ export declare const URL_INFO_STORAGE_KEY = "AMP_URL_INFO";
5
+ export type URLInfo = {
6
+ [CURRENT_PAGE_STORAGE_KEY]?: string;
7
+ [PREVIOUS_PAGE_STORAGE_KEY]?: string;
8
+ };
9
+ export declare const isPageUrlEnrichmentEnabled: (option: unknown) => boolean;
10
+ export declare const pageUrlEnrichmentPlugin: () => EnrichmentPlugin;
11
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../src/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,gBAAgB,EAAiB,MAAM,4BAA4B,CAAC;AAGhH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAC3D,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,wBAAwB,CAAC,CAAC,EAAE,MAAM,CAAC;IACpC,CAAC,yBAAyB,CAAC,CAAC,EAAE,MAAM,CAAC;CACtC,CAAC;AAQF,eAAO,MAAM,0BAA0B,WAAY,OAAO,KAAG,OAQ5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,QAAO,gBAuK1C,CAAC"}
@@ -0,0 +1,190 @@
1
+ import { __assign, __awaiter, __generator, __read } from "tslib";
2
+ import { getGlobalScope, BrowserStorage } from '@amplitude/analytics-core';
3
+ export var CURRENT_PAGE_STORAGE_KEY = 'AMP_CURRENT_PAGE';
4
+ export var PREVIOUS_PAGE_STORAGE_KEY = 'AMP_PREVIOUS_PAGE';
5
+ export var URL_INFO_STORAGE_KEY = 'AMP_URL_INFO';
6
+ var PreviousPageType;
7
+ (function (PreviousPageType) {
8
+ PreviousPageType["Direct"] = "direct";
9
+ PreviousPageType["Internal"] = "internal";
10
+ PreviousPageType["External"] = "external";
11
+ })(PreviousPageType || (PreviousPageType = {}));
12
+ export var isPageUrlEnrichmentEnabled = function (option) {
13
+ if (typeof option === 'boolean') {
14
+ return option;
15
+ }
16
+ if (typeof option === 'object' && option !== null && 'pageUrlEnrichment' in option) {
17
+ return Boolean(option.pageUrlEnrichment);
18
+ }
19
+ return false;
20
+ };
21
+ export var pageUrlEnrichmentPlugin = function () {
22
+ var globalScope = getGlobalScope();
23
+ var sessionStorage = undefined;
24
+ var isStorageEnabled = false;
25
+ var loggerProvider = undefined;
26
+ var isProxied = false;
27
+ var isTracking = false;
28
+ var getDecodeURI = function (locationStr) {
29
+ var decodedLocationStr = locationStr;
30
+ try {
31
+ decodedLocationStr = decodeURI(locationStr);
32
+ }
33
+ catch (e) {
34
+ /* istanbul ignore next */
35
+ loggerProvider === null || loggerProvider === void 0 ? void 0 : loggerProvider.error('Malformed URI sequence: ', e);
36
+ }
37
+ return decodedLocationStr;
38
+ };
39
+ var getHostname = function (url) {
40
+ var hostname;
41
+ try {
42
+ var decodedUrl = getDecodeURI(url);
43
+ hostname = new URL(decodedUrl).hostname;
44
+ }
45
+ catch (e) {
46
+ /* istanbul ignore next */
47
+ loggerProvider === null || loggerProvider === void 0 ? void 0 : loggerProvider.error('Could not parse URL: ', e);
48
+ }
49
+ return hostname;
50
+ };
51
+ var getPrevPageType = function (previousPage) {
52
+ var currentDomain = (typeof location !== 'undefined' && location.hostname) || '';
53
+ var previousPageDomain = previousPage ? getHostname(previousPage) : undefined;
54
+ switch (previousPageDomain) {
55
+ case undefined:
56
+ return PreviousPageType.Direct;
57
+ case currentDomain:
58
+ return PreviousPageType.Internal;
59
+ default:
60
+ return PreviousPageType.External;
61
+ }
62
+ };
63
+ var saveURLInfo = function () { return __awaiter(void 0, void 0, void 0, function () {
64
+ var URLInfo, previousURL, currentURL;
65
+ var _a;
66
+ return __generator(this, function (_b) {
67
+ switch (_b.label) {
68
+ case 0:
69
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 3];
70
+ return [4 /*yield*/, sessionStorage.get(URL_INFO_STORAGE_KEY)];
71
+ case 1:
72
+ URLInfo = _b.sent();
73
+ previousURL = (URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[CURRENT_PAGE_STORAGE_KEY]) || '';
74
+ currentURL = getDecodeURI((typeof location !== 'undefined' && location.href) || '');
75
+ return [4 /*yield*/, sessionStorage.set(URL_INFO_STORAGE_KEY, (_a = {},
76
+ _a[CURRENT_PAGE_STORAGE_KEY] = currentURL,
77
+ _a[PREVIOUS_PAGE_STORAGE_KEY] = previousURL,
78
+ _a))];
79
+ case 2:
80
+ _b.sent();
81
+ _b.label = 3;
82
+ case 3: return [2 /*return*/];
83
+ }
84
+ });
85
+ }); };
86
+ var saveUrlInfoWrapper = function () {
87
+ void saveURLInfo();
88
+ };
89
+ var plugin = {
90
+ name: '@amplitude/plugin-page-url-enrichment-browser',
91
+ type: 'enrichment',
92
+ setup: function (config, _) { return __awaiter(void 0, void 0, void 0, function () {
93
+ return __generator(this, function (_a) {
94
+ switch (_a.label) {
95
+ case 0:
96
+ loggerProvider = config.loggerProvider;
97
+ loggerProvider.log('Installing @amplitude/plugin-page-url-enrichment-browser');
98
+ isTracking = true;
99
+ if (!globalScope) return [3 /*break*/, 2];
100
+ sessionStorage = new BrowserStorage(globalScope.sessionStorage);
101
+ return [4 /*yield*/, sessionStorage.isEnabled()];
102
+ case 1:
103
+ isStorageEnabled = _a.sent();
104
+ globalScope.addEventListener('popstate', saveUrlInfoWrapper);
105
+ if (!isProxied) {
106
+ /* istanbul ignore next */
107
+ // There is no global browser listener for changes to history, so we have
108
+ // to modify pushState and replaceState directly.
109
+ // https://stackoverflow.com/a/64927639
110
+ // eslint-disable-next-line @typescript-eslint/unbound-method
111
+ globalScope.history.pushState = new Proxy(globalScope.history.pushState, {
112
+ apply: function (target, thisArg, _a) {
113
+ var _b = __read(_a, 3), state = _b[0], unused = _b[1], url = _b[2];
114
+ target.apply(thisArg, [state, unused, url]);
115
+ if (isTracking) {
116
+ saveUrlInfoWrapper();
117
+ }
118
+ },
119
+ });
120
+ // eslint-disable-next-line @typescript-eslint/unbound-method
121
+ globalScope.history.replaceState = new Proxy(globalScope.history.replaceState, {
122
+ apply: function (target, thisArg, _a) {
123
+ var _b = __read(_a, 3), state = _b[0], unused = _b[1], url = _b[2];
124
+ target.apply(thisArg, [state, unused, url]);
125
+ if (isTracking) {
126
+ saveUrlInfoWrapper();
127
+ }
128
+ },
129
+ });
130
+ isProxied = true;
131
+ }
132
+ _a.label = 2;
133
+ case 2: return [2 /*return*/];
134
+ }
135
+ });
136
+ }); },
137
+ execute: function (event) { return __awaiter(void 0, void 0, void 0, function () {
138
+ var locationHREF, previousPage, URLInfo;
139
+ var _a;
140
+ return __generator(this, function (_b) {
141
+ switch (_b.label) {
142
+ case 0:
143
+ locationHREF = getDecodeURI((typeof location !== 'undefined' && location.href) || '');
144
+ previousPage = '';
145
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 4];
146
+ return [4 /*yield*/, sessionStorage.get(URL_INFO_STORAGE_KEY)];
147
+ case 1:
148
+ URLInfo = _b.sent();
149
+ previousPage = (URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[PREVIOUS_PAGE_STORAGE_KEY]) || document.referrer || '';
150
+ if (!!(URLInfo === null || URLInfo === void 0 ? void 0 : URLInfo[CURRENT_PAGE_STORAGE_KEY])) return [3 /*break*/, 3];
151
+ return [4 /*yield*/, sessionStorage.set(URL_INFO_STORAGE_KEY, __assign(__assign({}, (URLInfo || {})), (_a = {}, _a[CURRENT_PAGE_STORAGE_KEY] = locationHREF, _a[PREVIOUS_PAGE_STORAGE_KEY] = previousPage, _a)))];
152
+ case 2:
153
+ _b.sent();
154
+ _b.label = 3;
155
+ case 3:
156
+ event.event_properties = __assign(__assign({}, (event.event_properties || {})), { '[Amplitude] Page Domain': addIfNotExist(event, '[Amplitude] Page Domain', (typeof location !== 'undefined' && location.hostname) || ''), '[Amplitude] Page Location': addIfNotExist(event, '[Amplitude] Page Location', locationHREF), '[Amplitude] Page Path': addIfNotExist(event, '[Amplitude] Page Path', (typeof location !== 'undefined' && getDecodeURI(location.pathname)) || ''), '[Amplitude] Page Title': addIfNotExist(event, '[Amplitude] Page Title', (typeof document !== 'undefined' && document.title) || ''), '[Amplitude] Page URL': addIfNotExist(event, '[Amplitude] Page URL', locationHREF.split('?')[0]), '[Amplitude] Previous Page Location': previousPage, '[Amplitude] Previous Page Type': getPrevPageType(previousPage) });
157
+ _b.label = 4;
158
+ case 4: return [2 /*return*/, event];
159
+ }
160
+ });
161
+ }); },
162
+ teardown: function () { return __awaiter(void 0, void 0, void 0, function () {
163
+ return __generator(this, function (_a) {
164
+ switch (_a.label) {
165
+ case 0:
166
+ if (!globalScope) return [3 /*break*/, 2];
167
+ globalScope.removeEventListener('popstate', saveUrlInfoWrapper);
168
+ isTracking = false;
169
+ if (!(sessionStorage && isStorageEnabled)) return [3 /*break*/, 2];
170
+ return [4 /*yield*/, sessionStorage.set(URL_INFO_STORAGE_KEY, {})];
171
+ case 1:
172
+ _a.sent();
173
+ _a.label = 2;
174
+ case 2: return [2 /*return*/];
175
+ }
176
+ });
177
+ }); },
178
+ };
179
+ return plugin;
180
+ };
181
+ function addIfNotExist(event, key, value) {
182
+ if (!event.event_properties) {
183
+ event.event_properties = {};
184
+ }
185
+ if (event.event_properties[key] === undefined) {
186
+ return value;
187
+ }
188
+ return event.event_properties[key];
189
+ }
190
+ //# sourceMappingURL=page-url-enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.js","sourceRoot":"","sources":["../../src/page-url-enrichment.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrowserClient, BrowserConfig, EnrichmentPlugin, Event, Logger } from '@amplitude/analytics-types';\nimport { getGlobalScope, BrowserStorage } from '@amplitude/analytics-core';\n\nexport const CURRENT_PAGE_STORAGE_KEY = 'AMP_CURRENT_PAGE';\nexport const PREVIOUS_PAGE_STORAGE_KEY = 'AMP_PREVIOUS_PAGE';\n\nexport const URL_INFO_STORAGE_KEY = 'AMP_URL_INFO';\n\nexport type URLInfo = {\n [CURRENT_PAGE_STORAGE_KEY]?: string;\n [PREVIOUS_PAGE_STORAGE_KEY]?: string;\n};\n\nenum PreviousPageType {\n Direct = 'direct', // for no prev page or referrer\n Internal = 'internal', // for same domain - this excludes subdomains\n External = 'external', // for different domains\n}\n\nexport const isPageUrlEnrichmentEnabled = (option: unknown): boolean => {\n if (typeof option === 'boolean') {\n return option;\n }\n if (typeof option === 'object' && option !== null && 'pageUrlEnrichment' in option) {\n return Boolean((option as { pageUrlEnrichment?: boolean }).pageUrlEnrichment);\n }\n return false;\n};\n\nexport const pageUrlEnrichmentPlugin = (): EnrichmentPlugin => {\n const globalScope = getGlobalScope();\n let sessionStorage: BrowserStorage<URLInfo> | undefined = undefined;\n let isStorageEnabled = false;\n let loggerProvider: Logger | undefined = undefined;\n\n let isProxied = false;\n let isTracking = false;\n\n const getDecodeURI = (locationStr: string): string => {\n let decodedLocationStr = locationStr;\n try {\n decodedLocationStr = decodeURI(locationStr);\n } catch (e) {\n /* istanbul ignore next */\n loggerProvider?.error('Malformed URI sequence: ', e);\n }\n\n return decodedLocationStr;\n };\n\n const getHostname = (url: string): string | undefined => {\n let hostname: string | undefined;\n\n try {\n const decodedUrl = getDecodeURI(url);\n hostname = new URL(decodedUrl).hostname;\n } catch (e) {\n /* istanbul ignore next */\n loggerProvider?.error('Could not parse URL: ', e);\n }\n\n return hostname;\n };\n\n const getPrevPageType = (previousPage: string) => {\n const currentDomain = (typeof location !== 'undefined' && location.hostname) || '';\n const previousPageDomain = previousPage ? getHostname(previousPage) : undefined;\n\n switch (previousPageDomain) {\n case undefined:\n return PreviousPageType.Direct;\n case currentDomain:\n return PreviousPageType.Internal;\n default:\n return PreviousPageType.External;\n }\n };\n\n const saveURLInfo = async () => {\n if (sessionStorage && isStorageEnabled) {\n const URLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY);\n const previousURL = URLInfo?.[CURRENT_PAGE_STORAGE_KEY] || '';\n const currentURL = getDecodeURI((typeof location !== 'undefined' && location.href) || '');\n\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {\n [CURRENT_PAGE_STORAGE_KEY]: currentURL,\n [PREVIOUS_PAGE_STORAGE_KEY]: previousURL,\n });\n }\n };\n\n const saveUrlInfoWrapper = () => {\n void saveURLInfo();\n };\n\n const plugin: EnrichmentPlugin = {\n name: '@amplitude/plugin-page-url-enrichment-browser',\n type: 'enrichment',\n\n setup: async (config: BrowserConfig, _: BrowserClient) => {\n loggerProvider = config.loggerProvider;\n loggerProvider.log('Installing @amplitude/plugin-page-url-enrichment-browser');\n\n isTracking = true;\n\n if (globalScope) {\n sessionStorage = new BrowserStorage<URLInfo>(globalScope.sessionStorage);\n isStorageEnabled = await sessionStorage.isEnabled();\n\n globalScope.addEventListener('popstate', saveUrlInfoWrapper);\n\n if (!isProxied) {\n /* istanbul ignore next */\n // There is no global browser listener for changes to history, so we have\n // to modify pushState and replaceState directly.\n // https://stackoverflow.com/a/64927639\n // eslint-disable-next-line @typescript-eslint/unbound-method\n globalScope.history.pushState = new Proxy(globalScope.history.pushState, {\n apply: (target, thisArg, [state, unused, url]) => {\n target.apply(thisArg, [state, unused, url]);\n if (isTracking) {\n saveUrlInfoWrapper();\n }\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n globalScope.history.replaceState = new Proxy(globalScope.history.replaceState, {\n apply: (target, thisArg, [state, unused, url]) => {\n target.apply(thisArg, [state, unused, url]);\n if (isTracking) {\n saveUrlInfoWrapper();\n }\n },\n });\n\n isProxied = true;\n }\n }\n },\n execute: async (event: Event) => {\n const locationHREF = getDecodeURI((typeof location !== 'undefined' && location.href) || '');\n\n let previousPage = '';\n if (sessionStorage && isStorageEnabled) {\n const URLInfo = await sessionStorage.get(URL_INFO_STORAGE_KEY);\n previousPage = URLInfo?.[PREVIOUS_PAGE_STORAGE_KEY] || document.referrer || '';\n\n if (!URLInfo?.[CURRENT_PAGE_STORAGE_KEY]) {\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {\n ...(URLInfo || {}),\n [CURRENT_PAGE_STORAGE_KEY]: locationHREF,\n [PREVIOUS_PAGE_STORAGE_KEY]: previousPage,\n });\n }\n\n event.event_properties = {\n ...(event.event_properties || {}),\n '[Amplitude] Page Domain': addIfNotExist(\n event,\n '[Amplitude] Page Domain',\n (typeof location !== 'undefined' && location.hostname) || '',\n ),\n '[Amplitude] Page Location': addIfNotExist(event, '[Amplitude] Page Location', locationHREF),\n '[Amplitude] Page Path': addIfNotExist(\n event,\n '[Amplitude] Page Path',\n (typeof location !== 'undefined' && getDecodeURI(location.pathname)) || '',\n ),\n '[Amplitude] Page Title': addIfNotExist(\n event,\n '[Amplitude] Page Title',\n (typeof document !== 'undefined' && document.title) || '',\n ),\n '[Amplitude] Page URL': addIfNotExist(event, '[Amplitude] Page URL', locationHREF.split('?')[0]),\n '[Amplitude] Previous Page Location': previousPage,\n '[Amplitude] Previous Page Type': getPrevPageType(previousPage),\n };\n }\n\n return event;\n },\n teardown: async () => {\n if (globalScope) {\n globalScope.removeEventListener('popstate', saveUrlInfoWrapper);\n\n isTracking = false;\n\n if (sessionStorage && isStorageEnabled) {\n await sessionStorage.set(URL_INFO_STORAGE_KEY, {});\n }\n }\n },\n };\n\n return plugin;\n};\n\nfunction addIfNotExist(event: Event, key: string, value: string): string {\n if (!event.event_properties) {\n event.event_properties = {};\n }\n\n if ((event.event_properties as { [key: string]: any })[key] === undefined) {\n return value;\n }\n\n return (event.event_properties as { [key: string]: any })[key] as string;\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { EnrichmentPlugin, PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
2
+ export type { PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
3
+ export interface CreatePageUrlEnrichmentBrowserPlugin {
4
+ (options?: Options): EnrichmentPlugin;
5
+ }
6
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../../src/typings/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEvG,YAAY,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,oCAAoC;IACnD,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACvC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=page-url-enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.js","sourceRoot":"","sources":["../../../src/typings/page-url-enrichment.ts"],"names":[],"mappings":"","sourcesContent":["import type { EnrichmentPlugin, PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';\n\nexport type { PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';\n\nexport interface CreatePageUrlEnrichmentBrowserPlugin {\n (options?: Options): EnrichmentPlugin;\n}\n"]}
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).amplitude={})}(this,(function(e){"use strict";var t=function(){return t=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},t.apply(this,arguments)};function n(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{l(r.next(e))}catch(e){i(e)}}function u(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}l((r=r.apply(e,t||[])).next())}))}function r(e,t){var n,r,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(n)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(n=1,r&&(o=2&u[0]?r.return:u[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,u[1])).done)return o;switch(r=0,o&&(u=[2&u[0],o.value]),u[0]){case 0:case 1:o=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,r=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!o||u[1]>o[0]&&u[1]<o[3])){i.label=u[1];break}if(6===u[0]&&i.label<o[1]){i.label=o[1],o=u;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(u);break}o[2]&&i.ops.pop(),i.trys.pop();continue}u=t.call(e,i)}catch(e){u=[6,e],r=0}finally{n=o=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}function o(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}"function"==typeof SuppressedError&&SuppressedError;var i,a=function(){function e(e){this.storage=e}return e.prototype.isEnabled=function(){return n(this,void 0,void 0,(function(){var t,n,o;return r(this,(function(r){switch(r.label){case 0:if(!this.storage)return[2,!1];t=String(Date.now()),n=new e(this.storage),o="AMP_TEST",r.label=1;case 1:return r.trys.push([1,4,5,7]),[4,n.set(o,t)];case 2:return r.sent(),[4,n.get(o)];case 3:return[2,r.sent()===t];case 4:return r.sent(),[2,!1];case 5:return[4,n.remove(o)];case 6:return r.sent(),[7];case 7:return[2]}}))}))},e.prototype.get=function(e){return n(this,void 0,void 0,(function(){var t;return r(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,this.getRaw(e)];case 1:return(t=n.sent())?[2,JSON.parse(t)]:[2,void 0];case 2:return n.sent(),console.error("[Amplitude] Error: Could not get value from storage"),[2,void 0];case 3:return[2]}}))}))},e.prototype.getRaw=function(e){var t;return n(this,void 0,void 0,(function(){return r(this,(function(n){return[2,(null===(t=this.storage)||void 0===t?void 0:t.getItem(e))||void 0]}))}))},e.prototype.set=function(e,t){var o;return n(this,void 0,void 0,(function(){return r(this,(function(n){try{null===(o=this.storage)||void 0===o||o.setItem(e,JSON.stringify(t))}catch(e){}return[2]}))}))},e.prototype.remove=function(e){var t;return n(this,void 0,void 0,(function(){return r(this,(function(n){try{null===(t=this.storage)||void 0===t||t.removeItem(e)}catch(e){}return[2]}))}))},e.prototype.reset=function(){var e;return n(this,void 0,void 0,(function(){return r(this,(function(t){try{null===(e=this.storage)||void 0===e||e.clear()}catch(e){}return[2]}))}))},e}(),u="AMP_CURRENT_PAGE",l="AMP_PREVIOUS_PAGE",s="AMP_URL_INFO";!function(e){e.Direct="direct",e.Internal="internal",e.External="external"}(i||(i={}));var c=function(){var e,c=(e="ampIntegrationContext","undefined"!=typeof globalThis&&void 0!==globalThis[e]?globalThis[e]:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:void 0),p=void 0,d=!1,v=void 0,h=!1,y=!1,g=function(e){var t=e;try{t=decodeURI(e)}catch(e){null==v||v.error("Malformed URI sequence: ",e)}return t},b=function(e){var t="undefined"!=typeof location&&location.hostname||"";switch(e?function(e){var t;try{var n=g(e);t=new URL(n).hostname}catch(e){null==v||v.error("Could not parse URL: ",e)}return t}(e):void 0){case void 0:return i.Direct;case t:return i.Internal;default:return i.External}},m=function(){n(void 0,void 0,void 0,(function(){var e,t,n,o;return r(this,(function(r){switch(r.label){case 0:return p&&d?[4,p.get(s)]:[3,3];case 1:return e=r.sent(),t=(null==e?void 0:e[u])||"",n=g("undefined"!=typeof location&&location.href||""),[4,p.set(s,(o={},o[u]=n,o[l]=t,o))];case 2:r.sent(),r.label=3;case 3:return[2]}}))}))};return{name:"@amplitude/plugin-page-url-enrichment-browser",type:"enrichment",setup:function(e,t){return n(void 0,void 0,void 0,(function(){return r(this,(function(t){switch(t.label){case 0:return(v=e.loggerProvider).log("Installing @amplitude/plugin-page-url-enrichment-browser"),y=!0,c?[4,(p=new a(c.sessionStorage)).isEnabled()]:[3,2];case 1:d=t.sent(),c.addEventListener("popstate",m),h||(c.history.pushState=new Proxy(c.history.pushState,{apply:function(e,t,n){var r=o(n,3),i=r[0],a=r[1],u=r[2];e.apply(t,[i,a,u]),y&&m()}}),c.history.replaceState=new Proxy(c.history.replaceState,{apply:function(e,t,n){var r=o(n,3),i=r[0],a=r[1],u=r[2];e.apply(t,[i,a,u]),y&&m()}}),h=!0),t.label=2;case 2:return[2]}}))}))},execute:function(e){return n(void 0,void 0,void 0,(function(){var n,o,i,a;return r(this,(function(r){switch(r.label){case 0:return n=g("undefined"!=typeof location&&location.href||""),o="",p&&d?[4,p.get(s)]:[3,4];case 1:return i=r.sent(),o=(null==i?void 0:i[l])||document.referrer||"",(null==i?void 0:i[u])?[3,3]:[4,p.set(s,t(t({},i||{}),(a={},a[u]=n,a[l]=o,a)))];case 2:r.sent(),r.label=3;case 3:e.event_properties=t(t({},e.event_properties||{}),{"[Amplitude] Page Domain":f(e,"[Amplitude] Page Domain","undefined"!=typeof location&&location.hostname||""),"[Amplitude] Page Location":f(e,"[Amplitude] Page Location",n),"[Amplitude] Page Path":f(e,"[Amplitude] Page Path","undefined"!=typeof location&&g(location.pathname)||""),"[Amplitude] Page Title":f(e,"[Amplitude] Page Title","undefined"!=typeof document&&document.title||""),"[Amplitude] Page URL":f(e,"[Amplitude] Page URL",n.split("?")[0]),"[Amplitude] Previous Page Location":o,"[Amplitude] Previous Page Type":b(o)}),r.label=4;case 4:return[2,e]}}))}))},teardown:function(){return n(void 0,void 0,void 0,(function(){return r(this,(function(e){switch(e.label){case 0:return c?(c.removeEventListener("popstate",m),y=!1,p&&d?[4,p.set(s,{})]:[3,2]):[3,2];case 1:e.sent(),e.label=2;case 2:return[2]}}))}))}}};function f(e,t,n){return e.event_properties||(e.event_properties={}),void 0===e.event_properties[t]?n:e.event_properties[t]}e.CURRENT_PAGE_STORAGE_KEY=u,e.PREVIOUS_PAGE_STORAGE_KEY=l,e.URL_INFO_STORAGE_KEY=s,e.pageUrlEnrichmentPlugin=c,e.plugin=c,Object.defineProperty(e,"__esModule",{value:!0})}));
@@ -0,0 +1,3 @@
1
+ export { pageUrlEnrichmentPlugin, CURRENT_PAGE_STORAGE_KEY, PREVIOUS_PAGE_STORAGE_KEY, URL_INFO_STORAGE_KEY, } from './page-url-enrichment';
2
+ export { pageUrlEnrichmentPlugin as plugin } from './page-url-enrichment';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { EnrichmentPlugin } from '@amplitude/analytics-types';
2
+ export declare const CURRENT_PAGE_STORAGE_KEY = "AMP_CURRENT_PAGE";
3
+ export declare const PREVIOUS_PAGE_STORAGE_KEY = "AMP_PREVIOUS_PAGE";
4
+ export declare const URL_INFO_STORAGE_KEY = "AMP_URL_INFO";
5
+ export type URLInfo = {
6
+ [CURRENT_PAGE_STORAGE_KEY]?: string;
7
+ [PREVIOUS_PAGE_STORAGE_KEY]?: string;
8
+ };
9
+ export declare const isPageUrlEnrichmentEnabled: (option: unknown) => boolean;
10
+ export declare const pageUrlEnrichmentPlugin: () => EnrichmentPlugin;
11
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../src/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,gBAAgB,EAAiB,MAAM,4BAA4B,CAAC;AAGhH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAC3D,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,wBAAwB,CAAC,CAAC,EAAE,MAAM,CAAC;IACpC,CAAC,yBAAyB,CAAC,CAAC,EAAE,MAAM,CAAC;CACtC,CAAC;AAQF,eAAO,MAAM,0BAA0B,WAAY,OAAO,KAAG,OAQ5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,QAAO,gBAuK1C,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { EnrichmentPlugin, PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
2
+ export type { PageUrlEnrichmentOptions as Options } from '@amplitude/analytics-core';
3
+ export interface CreatePageUrlEnrichmentBrowserPlugin {
4
+ (options?: Options): EnrichmentPlugin;
5
+ }
6
+ //# sourceMappingURL=page-url-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-url-enrichment.d.ts","sourceRoot":"","sources":["../../../src/typings/page-url-enrichment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEvG,YAAY,EAAE,wBAAwB,IAAI,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,oCAAoC;IACnD,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACvC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@amplitude/plugin-page-url-enrichment-browser",
3
+ "version": "0.2.0",
4
+ "description": "",
5
+ "author": "Amplitude Inc",
6
+ "homepage": "https://github.com/amplitude/Amplitude-TypeScript",
7
+ "license": "MIT",
8
+ "main": "lib/cjs/index.js",
9
+ "module": "lib/esm/index.js",
10
+ "types": "lib/esm/index.d.ts",
11
+ "sideEffects": false,
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "tag": "latest"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/amplitude/Amplitude-TypeScript.git"
19
+ },
20
+ "scripts": {
21
+ "build": "yarn bundle && yarn build:es5 && yarn build:esm",
22
+ "bundle": "rollup --config rollup.config.js",
23
+ "build:es5": "tsc -p ./tsconfig.es5.json",
24
+ "build:esm": "tsc -p ./tsconfig.esm.json",
25
+ "watch": "tsc -p ./tsconfig.esm.json --watch",
26
+ "clean": "rimraf node_modules lib coverage",
27
+ "fix": "yarn fix:eslint & yarn fix:prettier",
28
+ "fix:eslint": "eslint '{src,test}/**/*.ts' --fix",
29
+ "fix:prettier": "prettier --write \"{src,test}/**/*.ts\"",
30
+ "lint": "yarn lint:eslint & yarn lint:prettier",
31
+ "lint:eslint": "eslint '{src,test}/**/*.ts'",
32
+ "lint:prettier": "prettier --check \"{src,test}/**/*.ts\"",
33
+ "test": "jest",
34
+ "typecheck": "tsc -p ./tsconfig.json"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/amplitude/Amplitude-TypeScript/issues"
38
+ },
39
+ "dependencies": {
40
+ "@amplitude/analytics-client-common": "^2.3.32",
41
+ "@amplitude/analytics-core": "^2.20.0",
42
+ "@amplitude/analytics-types": "^2.9.2",
43
+ "tslib": "^2.4.1"
44
+ },
45
+ "devDependencies": {
46
+ "@rollup/plugin-commonjs": "^23.0.4",
47
+ "@rollup/plugin-node-resolve": "^15.0.1",
48
+ "@rollup/plugin-typescript": "^10.0.1",
49
+ "rollup": "^2.79.1",
50
+ "rollup-plugin-execute": "^1.1.1",
51
+ "rollup-plugin-gzip": "^3.1.0",
52
+ "rollup-plugin-terser": "^7.0.2"
53
+ },
54
+ "files": [
55
+ "lib"
56
+ ],
57
+ "gitHead": "cb2be608bc3d8a45da74afe8ebe6ef0132c1db06"
58
+ }