posthog-js 1.76.0 → 1.77.1

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 (129) hide show
  1. package/dist/array.full.js +2 -2
  2. package/dist/array.full.js.map +1 -1
  3. package/dist/array.js +2 -2
  4. package/dist/array.js.map +1 -1
  5. package/dist/es.js +2 -2
  6. package/dist/es.js.map +1 -1
  7. package/dist/module.d.ts +38 -6
  8. package/dist/module.js +2 -2
  9. package/dist/module.js.map +1 -1
  10. package/lib/package.json +8 -6
  11. package/lib/src/autocapture-utils.d.ts +15 -0
  12. package/lib/src/autocapture-utils.js +303 -0
  13. package/lib/src/autocapture-utils.js.map +1 -0
  14. package/lib/src/autocapture.d.ts +27 -0
  15. package/lib/src/autocapture.js +290 -0
  16. package/lib/src/autocapture.js.map +1 -0
  17. package/lib/src/base-request-queue.d.ts +12 -0
  18. package/lib/src/base-request-queue.js +33 -0
  19. package/lib/src/base-request-queue.js.map +1 -0
  20. package/lib/src/compression.d.ts +3 -0
  21. package/lib/src/compression.js +35 -0
  22. package/lib/src/compression.js.map +1 -0
  23. package/lib/src/config.d.ts +5 -0
  24. package/lib/src/config.js +9 -0
  25. package/lib/src/config.js.map +1 -0
  26. package/lib/src/constants.d.ts +19 -0
  27. package/lib/src/constants.js +41 -0
  28. package/lib/src/constants.js.map +1 -0
  29. package/lib/src/decide.d.ts +8 -0
  30. package/lib/src/decide.js +118 -0
  31. package/lib/src/decide.js.map +1 -0
  32. package/lib/src/extensions/cloud.d.ts +1 -0
  33. package/lib/src/extensions/cloud.js +2 -0
  34. package/lib/src/extensions/cloud.js.map +1 -0
  35. package/lib/src/extensions/exceptions/error-conversion.d.ts +26 -0
  36. package/lib/src/extensions/exceptions/error-conversion.js +204 -0
  37. package/lib/src/extensions/exceptions/error-conversion.js.map +1 -0
  38. package/lib/src/extensions/exceptions/exception-autocapture.d.ts +24 -0
  39. package/lib/src/extensions/exceptions/exception-autocapture.js +164 -0
  40. package/lib/src/extensions/exceptions/exception-autocapture.js.map +1 -0
  41. package/lib/src/extensions/exceptions/stack-trace.d.ts +31 -0
  42. package/lib/src/extensions/exceptions/stack-trace.js +259 -0
  43. package/lib/src/extensions/exceptions/stack-trace.js.map +1 -0
  44. package/lib/src/extensions/exceptions/type-checking.d.ts +10 -0
  45. package/lib/src/extensions/exceptions/type-checking.js +43 -0
  46. package/lib/src/extensions/exceptions/type-checking.js.map +1 -0
  47. package/lib/src/extensions/rageclick.d.ts +10 -0
  48. package/lib/src/extensions/rageclick.js +33 -0
  49. package/lib/src/extensions/rageclick.js.map +1 -0
  50. package/lib/src/extensions/segment-integration.d.ts +44 -0
  51. package/lib/src/extensions/segment-integration.js +34 -0
  52. package/lib/src/extensions/segment-integration.js.map +1 -0
  53. package/lib/src/extensions/sentry-integration.d.ts +30 -0
  54. package/lib/src/extensions/sentry-integration.js +63 -0
  55. package/lib/src/extensions/sentry-integration.js.map +1 -0
  56. package/lib/src/extensions/sessionrecording-utils.d.ts +67 -0
  57. package/lib/src/extensions/sessionrecording-utils.js +192 -0
  58. package/lib/src/extensions/sessionrecording-utils.js.map +1 -0
  59. package/lib/src/extensions/sessionrecording.d.ts +45 -0
  60. package/lib/src/extensions/sessionrecording.js +430 -0
  61. package/lib/src/extensions/sessionrecording.js.map +1 -0
  62. package/lib/src/extensions/toolbar.d.ts +18 -0
  63. package/lib/src/extensions/toolbar.js +151 -0
  64. package/lib/src/extensions/toolbar.js.map +1 -0
  65. package/lib/src/extensions/web-performance.d.ts +20 -0
  66. package/lib/src/extensions/web-performance.js +245 -0
  67. package/lib/src/extensions/web-performance.js.map +1 -0
  68. package/lib/src/gdpr-utils.d.ts +80 -0
  69. package/lib/src/gdpr-utils.js +236 -0
  70. package/lib/src/gdpr-utils.js.map +1 -0
  71. package/lib/src/loader-globals-full.d.ts +1 -0
  72. package/lib/src/loader-globals-full.js +5 -0
  73. package/lib/src/loader-globals-full.js.map +1 -0
  74. package/lib/src/loader-globals.d.ts +1 -0
  75. package/lib/src/loader-globals.js +3 -0
  76. package/lib/src/loader-globals.js.map +1 -0
  77. package/lib/src/loader-module.d.ts +4 -0
  78. package/lib/src/loader-module.js +6 -0
  79. package/lib/src/loader-module.js.map +1 -0
  80. package/lib/src/loader-recorder-v2.d.ts +2 -0
  81. package/lib/src/loader-recorder-v2.js +15 -0
  82. package/lib/src/loader-recorder-v2.js.map +1 -0
  83. package/lib/src/loader-recorder.d.ts +2 -0
  84. package/lib/src/loader-recorder.js +15 -0
  85. package/lib/src/loader-recorder.js.map +1 -0
  86. package/lib/src/page-view.d.ts +38 -0
  87. package/lib/src/page-view.js +127 -0
  88. package/lib/src/page-view.js.map +1 -0
  89. package/lib/src/posthog-core.d.ts +701 -0
  90. package/lib/src/posthog-core.js +1916 -0
  91. package/lib/src/posthog-core.js.map +1 -0
  92. package/lib/src/posthog-featureflags.d.ts +70 -0
  93. package/lib/src/posthog-featureflags.js +438 -0
  94. package/lib/src/posthog-featureflags.js.map +1 -0
  95. package/lib/src/posthog-persistence.d.ts +57 -0
  96. package/lib/src/posthog-persistence.js +256 -0
  97. package/lib/src/posthog-persistence.js.map +1 -0
  98. package/lib/src/posthog-surveys.d.ts +57 -0
  99. package/lib/src/posthog-surveys.js +76 -0
  100. package/lib/src/posthog-surveys.js.map +1 -0
  101. package/lib/src/rate-limiter.d.ts +5 -0
  102. package/lib/src/rate-limiter.js +66 -0
  103. package/lib/src/rate-limiter.js.map +1 -0
  104. package/lib/src/request-queue.d.ts +10 -0
  105. package/lib/src/request-queue.js +146 -0
  106. package/lib/src/request-queue.js.map +1 -0
  107. package/lib/src/retry-queue.d.ts +28 -0
  108. package/lib/src/retry-queue.js +198 -0
  109. package/lib/src/retry-queue.js.map +1 -0
  110. package/lib/src/send-request.d.ts +6 -0
  111. package/lib/src/send-request.js +125 -0
  112. package/lib/src/send-request.js.map +1 -0
  113. package/lib/src/sessionid.d.ts +28 -0
  114. package/lib/src/sessionid.js +205 -0
  115. package/lib/src/sessionid.js.map +1 -0
  116. package/lib/src/storage.d.ts +7 -0
  117. package/lib/src/storage.js +291 -0
  118. package/lib/src/storage.js.map +1 -0
  119. package/lib/src/types.d.ts +294 -0
  120. package/lib/src/types.js +6 -0
  121. package/lib/src/types.js.map +1 -0
  122. package/lib/src/utils.d.ts +89 -0
  123. package/lib/src/utils.js +868 -0
  124. package/lib/src/utils.js.map +1 -0
  125. package/lib/src/uuidv7.d.ts +42 -0
  126. package/lib/src/uuidv7.js +228 -0
  127. package/lib/src/uuidv7.js.map +1 -0
  128. package/package.json +8 -6
  129. package/CHANGELOG.md +0 -1145
@@ -0,0 +1,151 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
23
+ import { _getHashParam, _register_event, loadScript, logger } from '../utils';
24
+ import { POSTHOG_MANAGED_HOSTS } from './cloud';
25
+ var Toolbar = /** @class */ (function () {
26
+ function Toolbar(instance) {
27
+ this.instance = instance;
28
+ }
29
+ Toolbar.prototype.afterDecideResponse = function (response) {
30
+ var toolbarParams = response['toolbarParams'] ||
31
+ response['editorParams'] ||
32
+ (response['toolbarVersion'] ? { toolbarVersion: response['toolbarVersion'] } : {});
33
+ if (response['isAuthenticated'] &&
34
+ toolbarParams['toolbarVersion'] &&
35
+ toolbarParams['toolbarVersion'].indexOf('toolbar') === 0) {
36
+ this.loadToolbar(__assign({}, toolbarParams));
37
+ }
38
+ };
39
+ /**
40
+ * To load the toolbar, we need an access token and other state. That state comes from one of three places:
41
+ * 1. In the URL hash params
42
+ * 2. From session storage under the key `toolbarParams` if the toolbar was initialized on a previous page
43
+ */
44
+ Toolbar.prototype.maybeLoadToolbar = function (location, localStorage, history) {
45
+ if (location === void 0) { location = window.location; }
46
+ if (localStorage === void 0) { localStorage = undefined; }
47
+ if (history === void 0) { history = window.history; }
48
+ try {
49
+ // Before running the code we check if we can access localStorage, if not we opt-out
50
+ if (!localStorage) {
51
+ try {
52
+ window.localStorage.setItem('test', 'test');
53
+ window.localStorage.removeItem('test');
54
+ }
55
+ catch (error) {
56
+ return false;
57
+ }
58
+ // If localStorage was undefined, and localStorage is supported we set the default value
59
+ localStorage = window.localStorage;
60
+ }
61
+ var stateHash = _getHashParam(location.hash, '__posthog') || _getHashParam(location.hash, 'state');
62
+ var state = stateHash ? JSON.parse(decodeURIComponent(stateHash)) : null;
63
+ var parseFromUrl = state && state['action'] === 'ph_authorize';
64
+ var toolbarParams = void 0;
65
+ if (parseFromUrl) {
66
+ // happens if they are initializing the toolbar using an old snippet
67
+ toolbarParams = state;
68
+ toolbarParams.source = 'url';
69
+ if (toolbarParams && Object.keys(toolbarParams).length > 0) {
70
+ if (state['desiredHash']) {
71
+ // hash that was in the url before the redirect
72
+ location.hash = state['desiredHash'];
73
+ }
74
+ else if (history) {
75
+ history.replaceState('', document.title, location.pathname + location.search); // completely remove hash
76
+ }
77
+ else {
78
+ location.hash = ''; // clear hash (but leaves # unfortunately)
79
+ }
80
+ }
81
+ }
82
+ else {
83
+ // get credentials from localStorage from a previous initialzation
84
+ toolbarParams = JSON.parse(localStorage.getItem('_postHogToolbarParams') || '{}');
85
+ toolbarParams.source = 'localstorage';
86
+ // delete "add-action" or other intent from toolbarParams, otherwise we'll have the same intent
87
+ // every time we open the page (e.g. you just visiting your own site an hour later)
88
+ delete toolbarParams.userIntent;
89
+ }
90
+ if (toolbarParams['token'] && this.instance.get_config('token') === toolbarParams['token']) {
91
+ this.loadToolbar(toolbarParams);
92
+ return true;
93
+ }
94
+ else {
95
+ return false;
96
+ }
97
+ }
98
+ catch (e) {
99
+ return false;
100
+ }
101
+ };
102
+ Toolbar.prototype.loadToolbar = function (params) {
103
+ var _this = this;
104
+ if (window['_postHogToolbarLoaded']) {
105
+ return false;
106
+ }
107
+ // only load the toolbar once, even if there are multiple instances of PostHogLib
108
+ ;
109
+ window['_postHogToolbarLoaded'] = true;
110
+ // By design array.js, recorder.js, and toolbar.js are served from Django with no or limited caching, not from our CDN
111
+ // Django respects the query params for caching, returning a 304 if appropriate
112
+ var host = this.instance.get_config('api_host');
113
+ var timestampToNearestThirtySeconds = Math.floor(Date.now() / 30000) * 30000;
114
+ var toolbarUrl = "".concat(host).concat(host.endsWith('/') ? '' : '/', "static/toolbar.js?_ts=").concat(timestampToNearestThirtySeconds);
115
+ var disableToolbarMetrics = !POSTHOG_MANAGED_HOSTS.includes(this.instance.get_config('api_host')) &&
116
+ this.instance.get_config('advanced_disable_toolbar_metrics');
117
+ var toolbarParams = __assign(__assign(__assign({ token: this.instance.get_config('token') }, params), { apiURL: host }), (disableToolbarMetrics ? { instrument: false } : {}));
118
+ var _discard = toolbarParams.source, paramsToPersist = __rest(toolbarParams, ["source"]); // eslint-disable-line
119
+ window.localStorage.setItem('_postHogToolbarParams', JSON.stringify(paramsToPersist));
120
+ loadScript(toolbarUrl, function (err) {
121
+ if (err) {
122
+ logger.error('Failed to load toolbar', err);
123
+ return;
124
+ }
125
+ ;
126
+ (window['ph_load_toolbar'] || window['ph_load_editor'])(toolbarParams, _this.instance);
127
+ });
128
+ // Turbolinks doesn't fire an onload event but does replace the entire body, including the toolbar.
129
+ // Thus, we ensure the toolbar is only loaded inside the body, and then reloaded on turbolinks:load.
130
+ _register_event(window, 'turbolinks:load', function () {
131
+ ;
132
+ window['_postHogToolbarLoaded'] = false;
133
+ _this.loadToolbar(toolbarParams);
134
+ });
135
+ return true;
136
+ };
137
+ /** @deprecated Use "loadToolbar" instead. */
138
+ Toolbar.prototype._loadEditor = function (params) {
139
+ return this.loadToolbar(params);
140
+ };
141
+ /** @deprecated Use "maybeLoadToolbar" instead. */
142
+ Toolbar.prototype.maybeLoadEditor = function (location, localStorage, history) {
143
+ if (location === void 0) { location = window.location; }
144
+ if (localStorage === void 0) { localStorage = undefined; }
145
+ if (history === void 0) { history = window.history; }
146
+ return this.maybeLoadToolbar(location, localStorage, history);
147
+ };
148
+ return Toolbar;
149
+ }());
150
+ export { Toolbar };
151
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../../src/extensions/toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { _getHashParam, _register_event, loadScript, logger } from '../utils'\nimport { PostHog } from '../posthog-core'\nimport { DecideResponse, ToolbarParams } from '../types'\nimport { POSTHOG_MANAGED_HOSTS } from './cloud'\n\nexport class Toolbar {\n instance: PostHog\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n afterDecideResponse(response: DecideResponse) {\n const toolbarParams: ToolbarParams =\n response['toolbarParams'] ||\n response['editorParams'] ||\n (response['toolbarVersion'] ? { toolbarVersion: response['toolbarVersion'] } : {})\n if (\n response['isAuthenticated'] &&\n toolbarParams['toolbarVersion'] &&\n toolbarParams['toolbarVersion'].indexOf('toolbar') === 0\n ) {\n this.loadToolbar({\n ...toolbarParams,\n })\n }\n }\n\n /**\n * To load the toolbar, we need an access token and other state. That state comes from one of three places:\n * 1. In the URL hash params\n * 2. From session storage under the key `toolbarParams` if the toolbar was initialized on a previous page\n */\n maybeLoadToolbar(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n try {\n // Before running the code we check if we can access localStorage, if not we opt-out\n if (!localStorage) {\n try {\n window.localStorage.setItem('test', 'test')\n window.localStorage.removeItem('test')\n } catch (error) {\n return false\n }\n\n // If localStorage was undefined, and localStorage is supported we set the default value\n localStorage = window.localStorage\n }\n\n const stateHash = _getHashParam(location.hash, '__posthog') || _getHashParam(location.hash, 'state')\n const state = stateHash ? JSON.parse(decodeURIComponent(stateHash)) : null\n const parseFromUrl = state && state['action'] === 'ph_authorize'\n let toolbarParams: ToolbarParams\n\n if (parseFromUrl) {\n // happens if they are initializing the toolbar using an old snippet\n toolbarParams = state\n toolbarParams.source = 'url'\n\n if (toolbarParams && Object.keys(toolbarParams).length > 0) {\n if (state['desiredHash']) {\n // hash that was in the url before the redirect\n location.hash = state['desiredHash']\n } else if (history) {\n history.replaceState('', document.title, location.pathname + location.search) // completely remove hash\n } else {\n location.hash = '' // clear hash (but leaves # unfortunately)\n }\n }\n } else {\n // get credentials from localStorage from a previous initialzation\n toolbarParams = JSON.parse(localStorage.getItem('_postHogToolbarParams') || '{}')\n toolbarParams.source = 'localstorage'\n\n // delete \"add-action\" or other intent from toolbarParams, otherwise we'll have the same intent\n // every time we open the page (e.g. you just visiting your own site an hour later)\n delete toolbarParams.userIntent\n }\n\n if (toolbarParams['token'] && this.instance.get_config('token') === toolbarParams['token']) {\n this.loadToolbar(toolbarParams)\n return true\n } else {\n return false\n }\n } catch (e) {\n return false\n }\n }\n\n loadToolbar(params?: ToolbarParams): boolean {\n if ((window as any)['_postHogToolbarLoaded']) {\n return false\n }\n // only load the toolbar once, even if there are multiple instances of PostHogLib\n ;(window as any)['_postHogToolbarLoaded'] = true\n\n // By design array.js, recorder.js, and toolbar.js are served from Django with no or limited caching, not from our CDN\n // Django respects the query params for caching, returning a 304 if appropriate\n const host = this.instance.get_config('api_host')\n const timestampToNearestThirtySeconds = Math.floor(Date.now() / 30000) * 30000\n const toolbarUrl = `${host}${\n host.endsWith('/') ? '' : '/'\n }static/toolbar.js?_ts=${timestampToNearestThirtySeconds}`\n const disableToolbarMetrics =\n !POSTHOG_MANAGED_HOSTS.includes(this.instance.get_config('api_host')) &&\n this.instance.get_config('advanced_disable_toolbar_metrics')\n\n const toolbarParams = {\n token: this.instance.get_config('token'),\n ...params,\n apiURL: host, // defaults to api_host from the instance config if nothing else set\n ...(disableToolbarMetrics ? { instrument: false } : {}),\n }\n\n const { source: _discard, ...paramsToPersist } = toolbarParams // eslint-disable-line\n window.localStorage.setItem('_postHogToolbarParams', JSON.stringify(paramsToPersist))\n\n loadScript(toolbarUrl, (err) => {\n if (err) {\n logger.error('Failed to load toolbar', err)\n return\n }\n ;((window as any)['ph_load_toolbar'] || (window as any)['ph_load_editor'])(toolbarParams, this.instance)\n })\n // Turbolinks doesn't fire an onload event but does replace the entire body, including the toolbar.\n // Thus, we ensure the toolbar is only loaded inside the body, and then reloaded on turbolinks:load.\n _register_event(window, 'turbolinks:load', () => {\n ;(window as any)['_postHogToolbarLoaded'] = false\n this.loadToolbar(toolbarParams)\n })\n return true\n }\n\n /** @deprecated Use \"loadToolbar\" instead. */\n _loadEditor(params: ToolbarParams): boolean {\n return this.loadToolbar(params)\n }\n\n /** @deprecated Use \"maybeLoadToolbar\" instead. */\n maybeLoadEditor(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n return this.maybeLoadToolbar(location, localStorage, history)\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { PostHog } from '../posthog-core';
2
+ import { DecideResponse } from '../types';
3
+ export declare class WebPerformanceObserver {
4
+ instance: PostHog;
5
+ remoteEnabled: boolean | undefined;
6
+ observer: PerformanceObserver | undefined;
7
+ _forceAllowLocalhost: boolean;
8
+ constructor(instance: PostHog);
9
+ startObservingIfEnabled(): void;
10
+ startObserving(): void;
11
+ stopObserving(): void;
12
+ isObserving(): boolean;
13
+ isEnabled(): boolean;
14
+ afterDecideResponse(response: DecideResponse): void;
15
+ _capturePerformanceEvent(event: PerformanceEntry): void;
16
+ /**
17
+ * :TRICKY: Make sure we batch these requests, and don't truncate the strings.
18
+ */
19
+ private capturePerformanceEvent;
20
+ }
@@ -0,0 +1,245 @@
1
+ var __values = (this && this.__values) || function(o) {
2
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
3
+ if (m) return m.call(o);
4
+ if (o && typeof o.length === "number") return {
5
+ next: function () {
6
+ if (o && i >= o.length) o = void 0;
7
+ return { value: o && o[i++], done: !o };
8
+ }
9
+ };
10
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
11
+ };
12
+ import { isLocalhost, logger } from '../utils';
13
+ var PERFORMANCE_EVENTS_MAPPING = {
14
+ // BASE_PERFORMANCE_EVENT_COLUMNS
15
+ entryType: 0,
16
+ timeOrigin: 1,
17
+ name: 2,
18
+ // RESOURCE_EVENT_COLUMNS
19
+ startTime: 3,
20
+ redirectStart: 4,
21
+ redirectEnd: 5,
22
+ workerStart: 6,
23
+ fetchStart: 7,
24
+ domainLookupStart: 8,
25
+ domainLookupEnd: 9,
26
+ connectStart: 10,
27
+ secureConnectionStart: 11,
28
+ connectEnd: 12,
29
+ requestStart: 13,
30
+ responseStart: 14,
31
+ responseEnd: 15,
32
+ decodedBodySize: 16,
33
+ encodedBodySize: 17,
34
+ initiatorType: 18,
35
+ nextHopProtocol: 19,
36
+ renderBlockingStatus: 20,
37
+ responseStatus: 21,
38
+ transferSize: 22,
39
+ // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS
40
+ element: 23,
41
+ renderTime: 24,
42
+ loadTime: 25,
43
+ size: 26,
44
+ id: 27,
45
+ url: 28,
46
+ // NAVIGATION_EVENT_COLUMNS
47
+ domComplete: 29,
48
+ domContentLoadedEvent: 30,
49
+ domInteractive: 31,
50
+ loadEventEnd: 32,
51
+ loadEventStart: 33,
52
+ redirectCount: 34,
53
+ navigationType: 35,
54
+ unloadEventEnd: 36,
55
+ unloadEventStart: 37,
56
+ // Added after v1
57
+ duration: 39,
58
+ timestamp: 40,
59
+ // NOTE: CURRENTLY UNSUPPORTED
60
+ // EVENT_TIMING_EVENT_COLUMNS
61
+ // processingStart: null,
62
+ // processingEnd: null,
63
+ // MARK_AND_MEASURE_EVENT_COLUMNS
64
+ // detail: null,
65
+ };
66
+ var ENTRY_TYPES_TO_OBSERVE = [
67
+ // 'event', // This is too noisy as it covers all browser events
68
+ 'first-input',
69
+ // 'mark', // Mark is used too liberally. We would need to filter for specific marks
70
+ // 'measure', // Measure is used too liberally. We would need to filter for specific measures
71
+ 'navigation',
72
+ 'paint',
73
+ 'resource',
74
+ ];
75
+ var PERFORMANCE_INGESTION_ENDPOINT = '/e/';
76
+ // Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱
77
+ var POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT];
78
+ var WebPerformanceObserver = /** @class */ (function () {
79
+ function WebPerformanceObserver(instance) {
80
+ // Util to help developers working on this feature manually override
81
+ this._forceAllowLocalhost = false;
82
+ this.instance = instance;
83
+ }
84
+ WebPerformanceObserver.prototype.startObservingIfEnabled = function () {
85
+ if (this.isEnabled()) {
86
+ this.startObserving();
87
+ }
88
+ else {
89
+ this.stopObserving();
90
+ }
91
+ };
92
+ WebPerformanceObserver.prototype.startObserving = function () {
93
+ var _this = this;
94
+ var _a;
95
+ if (this.observer) {
96
+ return;
97
+ }
98
+ if (((_a = window === null || window === void 0 ? void 0 : window.PerformanceObserver) === null || _a === void 0 ? void 0 : _a.supportedEntryTypes) === undefined) {
99
+ logger.log('PostHog Performance observer not started because PerformanceObserver is not supported by this browser.');
100
+ return;
101
+ }
102
+ if (isLocalhost() && !this._forceAllowLocalhost) {
103
+ logger.log('PostHog Peformance observer not started because we are on localhost.');
104
+ return;
105
+ }
106
+ try {
107
+ // compat checked above with early return
108
+ // eslint-disable-next-line compat/compat
109
+ this.observer = new PerformanceObserver(function (list) {
110
+ list.getEntries().forEach(function (entry) {
111
+ _this._capturePerformanceEvent(entry);
112
+ });
113
+ });
114
+ // compat checked above with early return
115
+ // eslint-disable-next-line compat/compat
116
+ var entryTypes = PerformanceObserver.supportedEntryTypes.filter(function (x) { return ENTRY_TYPES_TO_OBSERVE.includes(x); });
117
+ entryTypes.forEach(function (entryType) {
118
+ var _a;
119
+ (_a = _this.observer) === null || _a === void 0 ? void 0 : _a.observe({ type: entryType, buffered: true });
120
+ });
121
+ }
122
+ catch (e) {
123
+ console.error('PostHog failed to start performance observer', e);
124
+ this.stopObserving();
125
+ }
126
+ };
127
+ WebPerformanceObserver.prototype.stopObserving = function () {
128
+ if (this.observer) {
129
+ this.observer.disconnect();
130
+ this.observer = undefined;
131
+ }
132
+ };
133
+ WebPerformanceObserver.prototype.isObserving = function () {
134
+ return !!this.observer;
135
+ };
136
+ WebPerformanceObserver.prototype.isEnabled = function () {
137
+ var _a, _b;
138
+ return (_b = (_a = this.instance.get_config('capture_performance')) !== null && _a !== void 0 ? _a : this.remoteEnabled) !== null && _b !== void 0 ? _b : false;
139
+ };
140
+ WebPerformanceObserver.prototype.afterDecideResponse = function (response) {
141
+ this.remoteEnabled = response.capturePerformance || false;
142
+ if (this.isEnabled()) {
143
+ this.startObserving();
144
+ }
145
+ };
146
+ WebPerformanceObserver.prototype._capturePerformanceEvent = function (event) {
147
+ // NOTE: We don't want to capture our own request events.
148
+ var e_1, _a, _b;
149
+ if (event.name.indexOf(this.instance.get_config('api_host')) === 0) {
150
+ var path_1 = event.name.replace(this.instance.get_config('api_host'), '');
151
+ if (POSTHOG_PATHS_TO_IGNORE.find(function (x) { return path_1.indexOf(x) === 0; })) {
152
+ return;
153
+ }
154
+ }
155
+ // NOTE: This is minimal atm but will include more options when we move to the
156
+ // built-in rrweb network recorder
157
+ var networkRequest = {
158
+ url: event.name,
159
+ };
160
+ var userSessionRecordingOptions = this.instance.get_config('session_recording');
161
+ if (userSessionRecordingOptions.maskNetworkRequestFn) {
162
+ networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest);
163
+ }
164
+ if (!networkRequest) {
165
+ return;
166
+ }
167
+ var eventJson = event.toJSON();
168
+ eventJson.name = networkRequest.url;
169
+ var properties = {};
170
+ // kudos to sentry javascript sdk for excellent background on why to use Date.now() here
171
+ // https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70
172
+ // can't start observer if performance.now() is not available
173
+ // eslint-disable-next-line compat/compat
174
+ var timeOrigin = Math.floor(Date.now() - performance.now());
175
+ properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin;
176
+ // clickhouse can't ingest timestamps that are floats
177
+ // (in this case representing fractions of a millisecond we don't care about anyway)
178
+ properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime);
179
+ for (var key in PERFORMANCE_EVENTS_MAPPING) {
180
+ if (eventJson[key] !== undefined) {
181
+ properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key];
182
+ }
183
+ }
184
+ this.capturePerformanceEvent(properties);
185
+ if (exposesServerTiming(event)) {
186
+ try {
187
+ for (var _c = __values(event.serverTiming || []), _d = _c.next(); !_d.done; _d = _c.next()) {
188
+ var timing = _d.value;
189
+ this.capturePerformanceEvent((_b = {},
190
+ _b[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin,
191
+ _b[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime),
192
+ _b[PERFORMANCE_EVENTS_MAPPING['name']] = timing.name,
193
+ _b[PERFORMANCE_EVENTS_MAPPING['duration']] = timing.duration,
194
+ // the spec has a closed list of possible types
195
+ // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType
196
+ // but, we need to know this was a server timing so that we know to
197
+ // match it to the appropriate navigation or resource timing
198
+ // that matching will have to be on timestamp and $current_url
199
+ _b[PERFORMANCE_EVENTS_MAPPING['entryType']] = 'serverTiming',
200
+ _b));
201
+ }
202
+ }
203
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
204
+ finally {
205
+ try {
206
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
207
+ }
208
+ finally { if (e_1) throw e_1.error; }
209
+ }
210
+ }
211
+ };
212
+ /**
213
+ * :TRICKY: Make sure we batch these requests, and don't truncate the strings.
214
+ */
215
+ WebPerformanceObserver.prototype.capturePerformanceEvent = function (properties) {
216
+ var _a;
217
+ var timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']];
218
+ (_a = this.instance.sessionRecording) === null || _a === void 0 ? void 0 : _a.onRRwebEmit({
219
+ type: 6,
220
+ data: {
221
+ plugin: 'posthog/network@1',
222
+ payload: properties,
223
+ },
224
+ timestamp: timestamp,
225
+ });
226
+ // this.instance.capture('$performance_event', properties, {
227
+ // transport: 'XHR',
228
+ // method: 'POST',
229
+ // endpoint: PERFORMANCE_INGESTION_ENDPOINT,
230
+ // _noTruncate: true,
231
+ // _batchKey: 'performanceEvent',
232
+ // })
233
+ };
234
+ return WebPerformanceObserver;
235
+ }());
236
+ export { WebPerformanceObserver };
237
+ /**
238
+ * Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming
239
+ * NB PerformanceNavigationTiming extends PerformanceResourceTiming
240
+ * Here we don't care which interface it implements as both expose `serverTimings`
241
+ */
242
+ var exposesServerTiming = function (event) {
243
+ return event.entryType === 'navigation' || event.entryType === 'resource';
244
+ };
245
+ //# sourceMappingURL=web-performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-performance.js","sourceRoot":"","sources":["../../../src/extensions/web-performance.ts"],"names":[],"mappings":"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","sourcesContent":["import { isLocalhost, logger } from '../utils'\nimport { PostHog } from '../posthog-core'\nimport { DecideResponse, NetworkRequest } from '../types'\n\nconst PERFORMANCE_EVENTS_MAPPING: { [key: string]: number } = {\n // BASE_PERFORMANCE_EVENT_COLUMNS\n entryType: 0,\n timeOrigin: 1,\n name: 2,\n\n // RESOURCE_EVENT_COLUMNS\n startTime: 3,\n redirectStart: 4,\n redirectEnd: 5,\n workerStart: 6,\n fetchStart: 7,\n domainLookupStart: 8,\n domainLookupEnd: 9,\n connectStart: 10,\n secureConnectionStart: 11,\n connectEnd: 12,\n requestStart: 13,\n responseStart: 14,\n responseEnd: 15,\n decodedBodySize: 16,\n encodedBodySize: 17,\n initiatorType: 18,\n nextHopProtocol: 19,\n renderBlockingStatus: 20,\n responseStatus: 21,\n transferSize: 22,\n\n // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS\n element: 23,\n renderTime: 24,\n loadTime: 25,\n size: 26,\n id: 27,\n url: 28,\n\n // NAVIGATION_EVENT_COLUMNS\n domComplete: 29,\n domContentLoadedEvent: 30,\n domInteractive: 31,\n loadEventEnd: 32,\n loadEventStart: 33,\n redirectCount: 34,\n navigationType: 35,\n unloadEventEnd: 36,\n unloadEventStart: 37,\n\n // Added after v1\n duration: 39,\n timestamp: 40,\n\n // NOTE: CURRENTLY UNSUPPORTED\n // EVENT_TIMING_EVENT_COLUMNS\n // processingStart: null,\n // processingEnd: null,\n\n // MARK_AND_MEASURE_EVENT_COLUMNS\n // detail: null,\n}\n\nconst ENTRY_TYPES_TO_OBSERVE = [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n]\n\nconst PERFORMANCE_INGESTION_ENDPOINT = '/e/'\n// Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT]\n\nexport class WebPerformanceObserver {\n instance: PostHog\n remoteEnabled: boolean | undefined\n observer: PerformanceObserver | undefined\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhost = false\n\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n startObservingIfEnabled() {\n if (this.isEnabled()) {\n this.startObserving()\n } else {\n this.stopObserving()\n }\n }\n\n startObserving() {\n if (this.observer) {\n return\n }\n\n if (window?.PerformanceObserver?.supportedEntryTypes === undefined) {\n logger.log(\n 'PostHog Performance observer not started because PerformanceObserver is not supported by this browser.'\n )\n return\n }\n\n if (isLocalhost() && !this._forceAllowLocalhost) {\n logger.log('PostHog Peformance observer not started because we are on localhost.')\n return\n }\n\n try {\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n this.observer = new PerformanceObserver((list) => {\n list.getEntries().forEach((entry) => {\n this._capturePerformanceEvent(entry)\n })\n })\n\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n const entryTypes = PerformanceObserver.supportedEntryTypes.filter((x) => ENTRY_TYPES_TO_OBSERVE.includes(x))\n\n entryTypes.forEach((entryType) => {\n this.observer?.observe({ type: entryType, buffered: true })\n })\n } catch (e) {\n console.error('PostHog failed to start performance observer', e)\n this.stopObserving()\n }\n }\n\n stopObserving() {\n if (this.observer) {\n this.observer.disconnect()\n this.observer = undefined\n }\n }\n\n isObserving() {\n return !!this.observer\n }\n\n isEnabled() {\n return this.instance.get_config('capture_performance') ?? this.remoteEnabled ?? false\n }\n\n afterDecideResponse(response: DecideResponse) {\n this.remoteEnabled = response.capturePerformance || false\n if (this.isEnabled()) {\n this.startObserving()\n }\n }\n\n _capturePerformanceEvent(event: PerformanceEntry) {\n // NOTE: We don't want to capture our own request events.\n\n if (event.name.indexOf(this.instance.get_config('api_host')) === 0) {\n const path = event.name.replace(this.instance.get_config('api_host'), '')\n\n if (POSTHOG_PATHS_TO_IGNORE.find((x) => path.indexOf(x) === 0)) {\n return\n }\n }\n\n // NOTE: This is minimal atm but will include more options when we move to the\n // built-in rrweb network recorder\n let networkRequest: NetworkRequest | null | undefined = {\n url: event.name,\n }\n\n const userSessionRecordingOptions = this.instance.get_config('session_recording')\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n }\n\n if (!networkRequest) {\n return\n }\n\n const eventJson = event.toJSON()\n eventJson.name = networkRequest.url\n const properties: { [key: number]: any } = {}\n // kudos to sentry javascript sdk for excellent background on why to use Date.now() here\n // https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70\n // can't start observer if performance.now() is not available\n // eslint-disable-next-line compat/compat\n const timeOrigin = Math.floor(Date.now() - performance.now())\n properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin\n // clickhouse can't ingest timestamps that are floats\n // (in this case representing fractions of a millisecond we don't care about anyway)\n properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime)\n for (const key in PERFORMANCE_EVENTS_MAPPING) {\n if (eventJson[key] !== undefined) {\n properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key]\n }\n }\n\n this.capturePerformanceEvent(properties)\n\n if (exposesServerTiming(event)) {\n for (const timing of event.serverTiming || []) {\n this.capturePerformanceEvent({\n [PERFORMANCE_EVENTS_MAPPING['timeOrigin']]: timeOrigin,\n [PERFORMANCE_EVENTS_MAPPING['timestamp']]: Math.floor(timeOrigin + event.startTime),\n [PERFORMANCE_EVENTS_MAPPING['name']]: timing.name,\n [PERFORMANCE_EVENTS_MAPPING['duration']]: timing.duration,\n // the spec has a closed list of possible types\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType\n // but, we need to know this was a server timing so that we know to\n // match it to the appropriate navigation or resource timing\n // that matching will have to be on timestamp and $current_url\n [PERFORMANCE_EVENTS_MAPPING['entryType']]: 'serverTiming',\n })\n }\n }\n }\n\n /**\n * :TRICKY: Make sure we batch these requests, and don't truncate the strings.\n */\n private capturePerformanceEvent(properties: { [key: number]: any }) {\n const timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']]\n\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6, // EventType.Plugin,\n data: {\n plugin: 'posthog/network@1',\n payload: properties,\n },\n timestamp,\n })\n\n // this.instance.capture('$performance_event', properties, {\n // transport: 'XHR',\n // method: 'POST',\n // endpoint: PERFORMANCE_INGESTION_ENDPOINT,\n // _noTruncate: true,\n // _batchKey: 'performanceEvent',\n // })\n }\n}\n\n/**\n * Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming\n * NB PerformanceNavigationTiming extends PerformanceResourceTiming\n * Here we don't care which interface it implements as both expose `serverTimings`\n */\nconst exposesServerTiming = (event: PerformanceEntry): event is PerformanceResourceTiming =>\n event.entryType === 'navigation' || event.entryType === 'resource'\n"]}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * GDPR utils
3
+ *
4
+ * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection
5
+ * and privacy for all individuals within the European Union. It addresses the export of personal
6
+ * data outside the EU. The GDPR aims primarily to give control back to citizens and residents
7
+ * over their personal data and to simplify the regulatory environment for international business
8
+ * by unifying the regulation within the EU.
9
+ *
10
+ * This set of utilities is intended to enable opt in/out functionality in the PostHog JS SDK.
11
+ * These functions are used internally by the SDK and are not intended to be publicly exposed.
12
+ */
13
+ import { GDPROptions } from './types';
14
+ import { PostHog } from './posthog-core';
15
+ /**
16
+ * Opt the user in to data capturing and cookies/localstorage for the given token
17
+ * @param {string} token - PostHog project capturing token
18
+ * @param {Object} [options]
19
+ * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action
20
+ * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action
21
+ * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action
22
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
23
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
24
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires
25
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not
26
+ * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not
27
+ */
28
+ export declare function optIn(token: string, options: GDPROptions): void;
29
+ /**
30
+ * Opt the user out of data capturing and cookies/localstorage for the given token
31
+ * @param {string} token - PostHog project capturing token
32
+ * @param {Object} [options]
33
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
34
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
35
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-out cookie expires
36
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-out cookie is set as cross-subdomain or not
37
+ * @param {boolean} [options.secureCookie] - whether the opt-out cookie is set as secure or not
38
+ */
39
+ export declare function optOut(token: string, options: GDPROptions): void;
40
+ /**
41
+ * Check whether the user has opted in to data capturing and cookies/localstorage for the given token
42
+ * @param {string} token - PostHog project capturing token
43
+ * @param {Object} [options]
44
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
45
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
46
+ * @returns {boolean} whether the user has opted in to the given opt type
47
+ */
48
+ export declare function hasOptedIn(token: string, options: GDPROptions): boolean;
49
+ /**
50
+ * Check whether the user has opted out of data capturing and cookies/localstorage for the given token
51
+ * @param {string} token - PostHog project capturing token
52
+ * @param {Object} [options]
53
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
54
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
55
+ * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account
56
+ * @returns {boolean} whether the user has opted out of the given opt type
57
+ */
58
+ export declare function hasOptedOut(token: string, options: Partial<GDPROptions>): boolean;
59
+ /**
60
+ * Clear the user's opt in/out status of data capturing and cookies/localstorage for the given token
61
+ * @param {string} token - PostHog project capturing token
62
+ * @param {Object} [options]
63
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
64
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
65
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires
66
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not
67
+ * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not
68
+ */
69
+ export declare function clearOptInOut(token: string, options: GDPROptions): void;
70
+ export declare function userOptedOut(posthog: PostHog, silenceErrors: boolean | undefined): boolean;
71
+ /**
72
+ * Wrap a method with a check for whether the user is opted out of data capturing and cookies/localstorage for the given token
73
+ * If the user has opted out, return early instead of executing the method.
74
+ * If a callback argument was provided, execute it passing the 0 error code.
75
+ * @param {PostHog} posthog - the posthog instance
76
+ * @param {function} method - wrapped method to be executed if the user has not opted out
77
+ * @param silenceErrors
78
+ * @returns {*} the result of executing method OR undefined if the user has opted out
79
+ */
80
+ export declare function addOptOutCheck<M extends (...args: any[]) => any = (...args: any[]) => any>(posthog: PostHog, method: M, silenceErrors?: boolean): M;