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,236 @@
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 { _each, _includes, _isNumber, _isString, window } from './utils';
14
+ import { cookieStore, localStore, localPlusCookieStore } from './storage';
15
+ /**
16
+ * A function used to capture a PostHog event (e.g. PostHogLib.capture)
17
+ * @callback captureFunction
18
+ * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.
19
+ * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.
20
+ * @param {Function} [callback] If provided, the callback function will be called after capturing the event.
21
+ */
22
+ /** Public **/
23
+ var GDPR_DEFAULT_PERSISTENCE_PREFIX = '__ph_opt_in_out_';
24
+ /**
25
+ * Opt the user in to data capturing and cookies/localstorage for the given token
26
+ * @param {string} token - PostHog project capturing token
27
+ * @param {Object} [options]
28
+ * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action
29
+ * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action
30
+ * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action
31
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
32
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
33
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires
34
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not
35
+ * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not
36
+ */
37
+ export function optIn(token, options) {
38
+ _optInOut(true, token, options);
39
+ }
40
+ /**
41
+ * Opt the user out of 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
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-out cookie expires
47
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-out cookie is set as cross-subdomain or not
48
+ * @param {boolean} [options.secureCookie] - whether the opt-out cookie is set as secure or not
49
+ */
50
+ export function optOut(token, options) {
51
+ _optInOut(false, token, options);
52
+ }
53
+ /**
54
+ * Check whether the user has opted in to data capturing and cookies/localstorage for the given token
55
+ * @param {string} token - PostHog project capturing token
56
+ * @param {Object} [options]
57
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
58
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
59
+ * @returns {boolean} whether the user has opted in to the given opt type
60
+ */
61
+ export function hasOptedIn(token, options) {
62
+ return _getStorageValue(token, options) === '1';
63
+ }
64
+ /**
65
+ * Check whether the user has opted out of data capturing and cookies/localstorage for the given token
66
+ * @param {string} token - PostHog project capturing token
67
+ * @param {Object} [options]
68
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
69
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
70
+ * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account
71
+ * @returns {boolean} whether the user has opted out of the given opt type
72
+ */
73
+ export function hasOptedOut(token, options) {
74
+ if (_hasDoNotTrackFlagOn(options)) {
75
+ return true;
76
+ }
77
+ return _getStorageValue(token, options) === '0';
78
+ }
79
+ /**
80
+ * Clear the user's opt in/out status of data capturing and cookies/localstorage for the given token
81
+ * @param {string} token - PostHog project capturing token
82
+ * @param {Object} [options]
83
+ * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage
84
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
85
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires
86
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not
87
+ * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not
88
+ */
89
+ export function clearOptInOut(token, options) {
90
+ options = options || {};
91
+ _getStorage(options).remove(_getStorageKey(token, options), !!options.crossSubdomainCookie);
92
+ }
93
+ /** Private **/
94
+ /**
95
+ * Get storage util
96
+ * @param {Object} [options]
97
+ * @param {string} [options.persistenceType]
98
+ * @returns {object} either cookieStore or localStore
99
+ */
100
+ function _getStorage(options) {
101
+ options = options || {};
102
+ if (options.persistenceType === 'localStorage') {
103
+ return localStore;
104
+ }
105
+ if (options.persistenceType === 'localStorage+cookie') {
106
+ return localPlusCookieStore;
107
+ }
108
+ return cookieStore;
109
+ }
110
+ /**
111
+ * Get the name of the cookie that is used for the given opt type (capturing, cookie, etc.)
112
+ * @param {string} token - PostHog project capturing token
113
+ * @param {Object} [options]
114
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
115
+ * @returns {string} the name of the cookie for the given opt type
116
+ */
117
+ function _getStorageKey(token, options) {
118
+ options = options || {};
119
+ return (options.persistencePrefix || GDPR_DEFAULT_PERSISTENCE_PREFIX) + token;
120
+ }
121
+ /**
122
+ * Get the value of the cookie that is used for the given opt type (capturing, cookie, etc.)
123
+ * @param {string} token - PostHog project capturing token
124
+ * @param {Object} [options]
125
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
126
+ * @returns {string} the value of the cookie for the given opt type
127
+ */
128
+ function _getStorageValue(token, options) {
129
+ return _getStorage(options).get(_getStorageKey(token, options));
130
+ }
131
+ /**
132
+ * Check whether the user has set the DNT/doNotTrack setting to true in their browser
133
+ * @param {Object} [options]
134
+ * @param {string} [options.window] - alternate window object to check; used to force various DNT settings in browser tests
135
+ * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account
136
+ * @returns {boolean} whether the DNT setting is true
137
+ */
138
+ function _hasDoNotTrackFlagOn(options) {
139
+ if (options && options.respectDnt) {
140
+ var win = (options && options.window) || window;
141
+ var nav = win['navigator'] || {};
142
+ var hasDntOn_1 = false;
143
+ _each([
144
+ nav['doNotTrack'],
145
+ nav['msDoNotTrack'],
146
+ win['doNotTrack'],
147
+ ], function (dntValue) {
148
+ if (_includes([true, 1, '1', 'yes'], dntValue)) {
149
+ hasDntOn_1 = true;
150
+ }
151
+ });
152
+ return hasDntOn_1;
153
+ }
154
+ return false;
155
+ }
156
+ /**
157
+ * Set cookie/localstorage for the user indicating that they are opted in or out for the given opt type
158
+ * @param {boolean} optValue - whether to opt the user in or out for the given opt type
159
+ * @param {string} token - PostHog project capturing token
160
+ * @param {Object} [options]
161
+ * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action
162
+ * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action
163
+ * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action
164
+ * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name
165
+ * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires
166
+ * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not
167
+ * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not
168
+ */
169
+ function _optInOut(optValue, token, options) {
170
+ if (!_isString(token) || !token.length) {
171
+ console.error('gdpr.' + (optValue ? 'optIn' : 'optOut') + ' called with an invalid token');
172
+ return;
173
+ }
174
+ options = options || {};
175
+ _getStorage(options).set(_getStorageKey(token, options), optValue ? 1 : 0, _isNumber(options.cookieExpiration) ? options.cookieExpiration : null, options.crossSubdomainCookie, options.secureCookie);
176
+ if (options.capture && optValue) {
177
+ // only capture event if opting in (optValue=true)
178
+ options.capture(options.captureEventName || '$opt_in', options.captureProperties || {}, {
179
+ send_instantly: true,
180
+ });
181
+ }
182
+ }
183
+ export function userOptedOut(posthog, silenceErrors) {
184
+ var optedOut = false;
185
+ try {
186
+ var token = posthog.get_config('token');
187
+ var respectDnt = posthog.get_config('respect_dnt');
188
+ var persistenceType = posthog.get_config('opt_out_capturing_persistence_type');
189
+ var persistencePrefix = posthog.get_config('opt_out_capturing_cookie_prefix') || undefined;
190
+ var win = posthog.get_config('window'); // used to override window during browser tests
191
+ if (token) {
192
+ // if there was an issue getting the token, continue method execution as normal
193
+ optedOut = hasOptedOut(token, {
194
+ respectDnt: respectDnt,
195
+ persistenceType: persistenceType,
196
+ persistencePrefix: persistencePrefix,
197
+ window: win,
198
+ });
199
+ }
200
+ }
201
+ catch (err) {
202
+ if (!silenceErrors) {
203
+ console.error('Unexpected error when checking capturing opt-out status: ' + err);
204
+ }
205
+ }
206
+ return optedOut;
207
+ }
208
+ /**
209
+ * Wrap a method with a check for whether the user is opted out of data capturing and cookies/localstorage for the given token
210
+ * If the user has opted out, return early instead of executing the method.
211
+ * If a callback argument was provided, execute it passing the 0 error code.
212
+ * @param {PostHog} posthog - the posthog instance
213
+ * @param {function} method - wrapped method to be executed if the user has not opted out
214
+ * @param silenceErrors
215
+ * @returns {*} the result of executing method OR undefined if the user has opted out
216
+ */
217
+ export function addOptOutCheck(posthog, method, silenceErrors) {
218
+ return function () {
219
+ var args = [];
220
+ for (var _i = 0; _i < arguments.length; _i++) {
221
+ args[_i] = arguments[_i];
222
+ }
223
+ var optedOut = userOptedOut(posthog, silenceErrors);
224
+ if (!optedOut) {
225
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
226
+ // @ts-ignore
227
+ return method.apply(this, args);
228
+ }
229
+ var callback = args[args.length - 1];
230
+ if (typeof callback === 'function') {
231
+ callback(0);
232
+ }
233
+ return;
234
+ };
235
+ }
236
+ //# sourceMappingURL=gdpr-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gdpr-utils.js","sourceRoot":"","sources":["../../src/gdpr-utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GDPR utils\n *\n * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection\n * and privacy for all individuals within the European Union. It addresses the export of personal\n * data outside the EU. The GDPR aims primarily to give control back to citizens and residents\n * over their personal data and to simplify the regulatory environment for international business\n * by unifying the regulation within the EU.\n *\n * This set of utilities is intended to enable opt in/out functionality in the PostHog JS SDK.\n * These functions are used internally by the SDK and are not intended to be publicly exposed.\n */\n\nimport { _each, _includes, _isNumber, _isString, window } from './utils'\nimport { cookieStore, localStore, localPlusCookieStore } from './storage'\nimport { GDPROptions, PersistentStore } from './types'\nimport { PostHog } from './posthog-core'\n\n/**\n * A function used to capture a PostHog event (e.g. PostHogLib.capture)\n * @callback captureFunction\n * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.\n * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.\n * @param {Function} [callback] If provided, the callback function will be called after capturing the event.\n */\n\n/** Public **/\n\nconst GDPR_DEFAULT_PERSISTENCE_PREFIX = '__ph_opt_in_out_'\n\n/**\n * Opt the user in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function optIn(token: string, options: GDPROptions): void {\n _optInOut(true, token, options)\n}\n\n/**\n * Opt the user out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-out cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-out cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-out cookie is set as secure or not\n */\nexport function optOut(token: string, options: GDPROptions): void {\n _optInOut(false, token, options)\n}\n\n/**\n * Check whether the user has opted in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {boolean} whether the user has opted in to the given opt type\n */\nexport function hasOptedIn(token: string, options: GDPROptions): boolean {\n return _getStorageValue(token, options) === '1'\n}\n\n/**\n * Check whether the user has opted out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the user has opted out of the given opt type\n */\nexport function hasOptedOut(token: string, options: Partial<GDPROptions>): boolean {\n if (_hasDoNotTrackFlagOn(options)) {\n return true\n }\n return _getStorageValue(token, options) === '0'\n}\n\n/**\n * Clear the user's opt in/out status of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function clearOptInOut(token: string, options: GDPROptions) {\n options = options || {}\n _getStorage(options).remove(_getStorageKey(token, options), !!options.crossSubdomainCookie)\n}\n\n/** Private **/\n\n/**\n * Get storage util\n * @param {Object} [options]\n * @param {string} [options.persistenceType]\n * @returns {object} either cookieStore or localStore\n */\nfunction _getStorage(options: GDPROptions): PersistentStore {\n options = options || {}\n if (options.persistenceType === 'localStorage') {\n return localStore\n }\n if (options.persistenceType === 'localStorage+cookie') {\n return localPlusCookieStore\n }\n return cookieStore\n}\n\n/**\n * Get the name of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the name of the cookie for the given opt type\n */\nfunction _getStorageKey(token: string, options: GDPROptions) {\n options = options || {}\n return (options.persistencePrefix || GDPR_DEFAULT_PERSISTENCE_PREFIX) + token\n}\n\n/**\n * Get the value of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the value of the cookie for the given opt type\n */\nfunction _getStorageValue(token: string, options: GDPROptions) {\n return _getStorage(options).get(_getStorageKey(token, options))\n}\n\n/**\n * Check whether the user has set the DNT/doNotTrack setting to true in their browser\n * @param {Object} [options]\n * @param {string} [options.window] - alternate window object to check; used to force various DNT settings in browser tests\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the DNT setting is true\n */\nfunction _hasDoNotTrackFlagOn(options: GDPROptions) {\n if (options && options.respectDnt) {\n const win = (options && options.window) || window\n const nav = win['navigator'] || {}\n let hasDntOn = false\n _each(\n [\n nav['doNotTrack'], // standard\n (nav as any)['msDoNotTrack'],\n (win as any)['doNotTrack'],\n ],\n function (dntValue) {\n if (_includes([true, 1, '1', 'yes'], dntValue)) {\n hasDntOn = true\n }\n }\n )\n return hasDntOn\n }\n return false\n}\n\n/**\n * Set cookie/localstorage for the user indicating that they are opted in or out for the given opt type\n * @param {boolean} optValue - whether to opt the user in or out for the given opt type\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nfunction _optInOut(optValue: boolean, token: string, options: GDPROptions) {\n if (!_isString(token) || !token.length) {\n console.error('gdpr.' + (optValue ? 'optIn' : 'optOut') + ' called with an invalid token')\n return\n }\n\n options = options || {}\n\n _getStorage(options).set(\n _getStorageKey(token, options),\n optValue ? 1 : 0,\n _isNumber(options.cookieExpiration) ? options.cookieExpiration : null,\n options.crossSubdomainCookie,\n options.secureCookie\n )\n\n if (options.capture && optValue) {\n // only capture event if opting in (optValue=true)\n options.capture(options.captureEventName || '$opt_in', options.captureProperties || {}, {\n send_instantly: true,\n })\n }\n}\n\nexport function userOptedOut(posthog: PostHog, silenceErrors: boolean | undefined) {\n let optedOut = false\n\n try {\n const token = posthog.get_config('token')\n const respectDnt = posthog.get_config('respect_dnt')\n const persistenceType = posthog.get_config('opt_out_capturing_persistence_type')\n const persistencePrefix = posthog.get_config('opt_out_capturing_cookie_prefix') || undefined\n const win = posthog.get_config('window' as any) as Window | undefined // used to override window during browser tests\n\n if (token) {\n // if there was an issue getting the token, continue method execution as normal\n optedOut = hasOptedOut(token, {\n respectDnt,\n persistenceType,\n persistencePrefix,\n window: win,\n })\n }\n } catch (err) {\n if (!silenceErrors) {\n console.error('Unexpected error when checking capturing opt-out status: ' + err)\n }\n }\n return optedOut\n}\n\n/**\n * Wrap a method with a check for whether the user is opted out of data capturing and cookies/localstorage for the given token\n * If the user has opted out, return early instead of executing the method.\n * If a callback argument was provided, execute it passing the 0 error code.\n * @param {PostHog} posthog - the posthog instance\n * @param {function} method - wrapped method to be executed if the user has not opted out\n * @param silenceErrors\n * @returns {*} the result of executing method OR undefined if the user has opted out\n */\nexport function addOptOutCheck<M extends (...args: any[]) => any = (...args: any[]) => any>(\n posthog: PostHog,\n method: M,\n silenceErrors?: boolean\n): M {\n return function (...args) {\n const optedOut = userOptedOut(posthog, silenceErrors)\n\n if (!optedOut) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return method.apply(this, args)\n }\n\n const callback = args[args.length - 1]\n if (typeof callback === 'function') {\n callback(0)\n }\n\n return\n } as M\n}\n"]}
@@ -0,0 +1 @@
1
+ import './loader-recorder';
@@ -0,0 +1,5 @@
1
+ // Same as loader-globals.ts except includes rrweb scripts.
2
+ import './loader-recorder';
3
+ import { init_from_snippet } from './posthog-core';
4
+ init_from_snippet();
5
+ //# sourceMappingURL=loader-globals-full.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-globals-full.js","sourceRoot":"","sources":["../../src/loader-globals-full.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,OAAO,mBAAmB,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,iBAAiB,EAAE,CAAA","sourcesContent":["// Same as loader-globals.ts except includes rrweb scripts.\n\nimport './loader-recorder'\nimport { init_from_snippet } from './posthog-core'\n\ninit_from_snippet()\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { init_from_snippet } from './posthog-core';
2
+ init_from_snippet();
3
+ //# sourceMappingURL=loader-globals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-globals.js","sourceRoot":"","sources":["../../src/loader-globals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,iBAAiB,EAAE,CAAA","sourcesContent":["import { init_from_snippet } from './posthog-core'\n\ninit_from_snippet()\n"]}
@@ -0,0 +1,4 @@
1
+ export { PostHog } from './posthog-core';
2
+ export * from './types';
3
+ export declare const posthog: import("./posthog-core").PostHog;
4
+ export default posthog;
@@ -0,0 +1,6 @@
1
+ import { init_as_module } from './posthog-core';
2
+ export { PostHog } from './posthog-core';
3
+ export * from './types';
4
+ export var posthog = init_as_module();
5
+ export default posthog;
6
+ //# sourceMappingURL=loader-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-module.js","sourceRoot":"","sources":["../../src/loader-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,cAAc,SAAS,CAAA;AACvB,MAAM,CAAC,IAAM,OAAO,GAAG,cAAc,EAAE,CAAA;AACvC,eAAe,OAAO,CAAA","sourcesContent":["import { init_as_module } from './posthog-core'\nexport { PostHog } from './posthog-core'\nexport * from './types'\nexport const posthog = init_as_module()\nexport default posthog\n"]}
@@ -0,0 +1,2 @@
1
+ import rrwebRecord from 'rrweb/es/rrweb/packages/rrweb/src/record';
2
+ export default rrwebRecord;
@@ -0,0 +1,15 @@
1
+ import { version } from 'rrweb/package.json';
2
+ // Same as loader-globals.ts except includes rrweb2 scripts.
3
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
+ // @ts-ignore
5
+ import rrwebRecord from 'rrweb/es/rrweb/packages/rrweb/src/record';
6
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
7
+ // @ts-ignore
8
+ import { getRecordConsolePlugin } from 'rrweb/es/rrweb/packages/rrweb/src/plugins/console/record';
9
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
10
+ // @ts-ignore
11
+ var win = typeof window !== 'undefined' ? window : {};
12
+ win.rrweb = { record: rrwebRecord, version: 'v2', rrwebVersion: version };
13
+ win.rrwebConsoleRecord = { getRecordConsolePlugin: getRecordConsolePlugin };
14
+ export default rrwebRecord;
15
+ //# sourceMappingURL=loader-recorder-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-recorder-v2.js","sourceRoot":"","sources":["../../src/loader-recorder-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE5C,4DAA4D;AAC5D,6DAA6D;AAC7D,aAAa;AACb,OAAO,WAAW,MAAM,0CAA0C,CAAA;AAClE,6DAA6D;AAC7D,aAAa;AACb,OAAO,EAAE,sBAAsB,EAAE,MAAM,0DAA0D,CAAA;AACjG,6DAA6D;AAC7D,aAAa;AAEb,IAAM,GAAG,GAA+B,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,EAAoB,CAErG;AAAC,GAAW,CAAC,KAAK,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAClF;AAAC,GAAW,CAAC,kBAAkB,GAAG,EAAE,sBAAsB,wBAAA,EAAE,CAAA;AAE7D,eAAe,WAAW,CAAA","sourcesContent":["import { version } from 'rrweb/package.json'\n\n// Same as loader-globals.ts except includes rrweb2 scripts.\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrwebRecord from 'rrweb/es/rrweb/packages/rrweb/src/record'\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport { getRecordConsolePlugin } from 'rrweb/es/rrweb/packages/rrweb/src/plugins/console/record'\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n\nconst win: Window & typeof globalThis = typeof window !== 'undefined' ? window : ({} as typeof window)\n\n;(win as any).rrweb = { record: rrwebRecord, version: 'v2', rrwebVersion: version }\n;(win as any).rrwebConsoleRecord = { getRecordConsolePlugin }\n\nexport default rrwebRecord\n"]}
@@ -0,0 +1,2 @@
1
+ import rrwebRecord from 'rrweb-v1/es/rrweb/packages/rrweb/src/record';
2
+ export default rrwebRecord;
@@ -0,0 +1,15 @@
1
+ import { version } from 'rrweb-v1/package.json';
2
+ // Same as loader-globals.ts except includes rrweb scripts.
3
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
+ // @ts-ignore
5
+ import rrwebRecord from 'rrweb-v1/es/rrweb/packages/rrweb/src/record';
6
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
7
+ // @ts-ignore
8
+ import { getRecordConsolePlugin } from 'rrweb-v1/es/rrweb/packages/rrweb/src/plugins/console/record';
9
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
10
+ // @ts-ignore
11
+ var win = typeof window !== 'undefined' ? window : {};
12
+ win.rrweb = { record: rrwebRecord, version: 'v1', rrwebVersion: version };
13
+ win.rrwebConsoleRecord = { getRecordConsolePlugin: getRecordConsolePlugin };
14
+ export default rrwebRecord;
15
+ //# sourceMappingURL=loader-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-recorder.js","sourceRoot":"","sources":["../../src/loader-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAE/C,2DAA2D;AAC3D,6DAA6D;AAC7D,aAAa;AACb,OAAO,WAAW,MAAM,6CAA6C,CAAA;AACrE,6DAA6D;AAC7D,aAAa;AACb,OAAO,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAA;AACpG,6DAA6D;AAC7D,aAAa;AAEb,IAAM,GAAG,GAA+B,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,EAAoB,CAErG;AAAC,GAAW,CAAC,KAAK,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAClF;AAAC,GAAW,CAAC,kBAAkB,GAAG,EAAE,sBAAsB,wBAAA,EAAE,CAAA;AAE7D,eAAe,WAAW,CAAA","sourcesContent":["import { version } from 'rrweb-v1/package.json'\n\n// Same as loader-globals.ts except includes rrweb scripts.\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrwebRecord from 'rrweb-v1/es/rrweb/packages/rrweb/src/record'\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport { getRecordConsolePlugin } from 'rrweb-v1/es/rrweb/packages/rrweb/src/plugins/console/record'\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n\nconst win: Window & typeof globalThis = typeof window !== 'undefined' ? window : ({} as typeof window)\n\n;(win as any).rrweb = { record: rrwebRecord, version: 'v1', rrwebVersion: version }\n;(win as any).rrwebConsoleRecord = { getRecordConsolePlugin }\n\nexport default rrwebRecord\n"]}
@@ -0,0 +1,38 @@
1
+ interface PageViewData {
2
+ pathname: string;
3
+ maxScrollHeight?: number;
4
+ maxScrollY?: number;
5
+ lastScrollY?: number;
6
+ maxContentHeight?: number;
7
+ maxContentY?: number;
8
+ lastContentY?: number;
9
+ }
10
+ interface ScrollProperties {
11
+ $prev_pageview_last_scroll?: number;
12
+ $prev_pageview_last_scroll_percentage?: number;
13
+ $prev_pageview_max_scroll?: number;
14
+ $prev_pageview_max_scroll_percentage?: number;
15
+ $prev_pageview_last_content?: number;
16
+ $prev_pageview_last_content_percentage?: number;
17
+ $prev_pageview_max_content?: number;
18
+ $prev_pageview_max_content_percentage?: number;
19
+ }
20
+ interface PageViewEventProperties extends ScrollProperties {
21
+ $prev_pageview_pathname?: string;
22
+ }
23
+ export declare class PageViewManager {
24
+ _pageViewData: PageViewData | undefined;
25
+ _hasSeenPageView: boolean;
26
+ _createPageViewData(): PageViewData;
27
+ doPageView(): PageViewEventProperties;
28
+ doPageLeave(): PageViewEventProperties;
29
+ _calculatePrevPageScrollProperties(prevPageViewData: PageViewData | undefined): ScrollProperties;
30
+ _updateScrollData: () => void;
31
+ startMeasuringScrollPosition(): void;
32
+ stopMeasuringScrollPosition(): void;
33
+ _scrollHeight(): number;
34
+ _scrollY(): number;
35
+ _contentHeight(): number;
36
+ _contentY(): number;
37
+ }
38
+ export {};
@@ -0,0 +1,127 @@
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
+ import { window } from './utils';
13
+ var PageViewManager = /** @class */ (function () {
14
+ function PageViewManager() {
15
+ var _this = this;
16
+ this._hasSeenPageView = false;
17
+ this._updateScrollData = function () {
18
+ var _a, _b, _c, _d;
19
+ if (!_this._pageViewData) {
20
+ _this._pageViewData = _this._createPageViewData();
21
+ }
22
+ var pageViewData = _this._pageViewData;
23
+ var scrollY = _this._scrollY();
24
+ var scrollHeight = _this._scrollHeight();
25
+ var contentY = _this._contentY();
26
+ var contentHeight = _this._contentHeight();
27
+ pageViewData.lastScrollY = scrollY;
28
+ pageViewData.maxScrollY = Math.max(scrollY, (_a = pageViewData.maxScrollY) !== null && _a !== void 0 ? _a : 0);
29
+ pageViewData.maxScrollHeight = Math.max(scrollHeight, (_b = pageViewData.maxScrollHeight) !== null && _b !== void 0 ? _b : 0);
30
+ pageViewData.lastContentY = contentY;
31
+ pageViewData.maxContentY = Math.max(contentY, (_c = pageViewData.maxContentY) !== null && _c !== void 0 ? _c : 0);
32
+ pageViewData.maxContentHeight = Math.max(contentHeight, (_d = pageViewData.maxContentHeight) !== null && _d !== void 0 ? _d : 0);
33
+ };
34
+ }
35
+ PageViewManager.prototype._createPageViewData = function () {
36
+ return {
37
+ pathname: window.location.pathname,
38
+ };
39
+ };
40
+ PageViewManager.prototype.doPageView = function () {
41
+ var prevPageViewData;
42
+ // if there were events created before the first PageView, we would have created a
43
+ // pageViewData for them. If this happened, we don't want to create a new pageViewData
44
+ if (!this._hasSeenPageView) {
45
+ this._hasSeenPageView = true;
46
+ prevPageViewData = undefined;
47
+ if (!this._pageViewData) {
48
+ this._pageViewData = this._createPageViewData();
49
+ }
50
+ }
51
+ else {
52
+ prevPageViewData = this._pageViewData;
53
+ this._pageViewData = this._createPageViewData();
54
+ }
55
+ // update the scroll properties for the new page, but wait until the next tick
56
+ // of the event loop
57
+ setTimeout(this._updateScrollData, 0);
58
+ return __assign({ $prev_pageview_pathname: prevPageViewData === null || prevPageViewData === void 0 ? void 0 : prevPageViewData.pathname }, this._calculatePrevPageScrollProperties(prevPageViewData));
59
+ };
60
+ PageViewManager.prototype.doPageLeave = function () {
61
+ var prevPageViewData = this._pageViewData;
62
+ return __assign({ $prev_pageview_pathname: prevPageViewData === null || prevPageViewData === void 0 ? void 0 : prevPageViewData.pathname }, this._calculatePrevPageScrollProperties(prevPageViewData));
63
+ };
64
+ PageViewManager.prototype._calculatePrevPageScrollProperties = function (prevPageViewData) {
65
+ if (!prevPageViewData ||
66
+ prevPageViewData.maxScrollHeight == null ||
67
+ prevPageViewData.lastScrollY == null ||
68
+ prevPageViewData.maxScrollY == null ||
69
+ prevPageViewData.maxContentHeight == null ||
70
+ prevPageViewData.lastContentY == null ||
71
+ prevPageViewData.maxContentY == null) {
72
+ return {};
73
+ }
74
+ var maxScrollHeight = prevPageViewData.maxScrollHeight, lastScrollY = prevPageViewData.lastScrollY, maxScrollY = prevPageViewData.maxScrollY, maxContentHeight = prevPageViewData.maxContentHeight, lastContentY = prevPageViewData.lastContentY, maxContentY = prevPageViewData.maxContentY;
75
+ // Use ceil, so that e.g. scrolling 999.5px of a 1000px page is considered 100% scrolled
76
+ maxScrollHeight = Math.ceil(maxScrollHeight);
77
+ lastScrollY = Math.ceil(lastScrollY);
78
+ maxScrollY = Math.ceil(maxScrollY);
79
+ maxContentHeight = Math.ceil(maxContentHeight);
80
+ lastContentY = Math.ceil(lastContentY);
81
+ maxContentY = Math.ceil(maxContentY);
82
+ // if the maximum scroll height is near 0, then the percentage is 1
83
+ var lastScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(lastScrollY / maxScrollHeight, 0, 1);
84
+ var maxScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(maxScrollY / maxScrollHeight, 0, 1);
85
+ var lastContentPercentage = maxContentHeight <= 1 ? 1 : clamp(lastContentY / maxContentHeight, 0, 1);
86
+ var maxContentPercentage = maxContentHeight <= 1 ? 1 : clamp(maxContentY / maxContentHeight, 0, 1);
87
+ return {
88
+ $prev_pageview_last_scroll: lastScrollY,
89
+ $prev_pageview_last_scroll_percentage: lastScrollPercentage,
90
+ $prev_pageview_max_scroll: maxScrollY,
91
+ $prev_pageview_max_scroll_percentage: maxScrollPercentage,
92
+ $prev_pageview_last_content: lastContentY,
93
+ $prev_pageview_last_content_percentage: lastContentPercentage,
94
+ $prev_pageview_max_content: maxContentY,
95
+ $prev_pageview_max_content_percentage: maxContentPercentage,
96
+ };
97
+ };
98
+ PageViewManager.prototype.startMeasuringScrollPosition = function () {
99
+ window.addEventListener('scroll', this._updateScrollData);
100
+ window.addEventListener('scrollend', this._updateScrollData);
101
+ window.addEventListener('resize', this._updateScrollData);
102
+ };
103
+ PageViewManager.prototype.stopMeasuringScrollPosition = function () {
104
+ window.removeEventListener('scroll', this._updateScrollData);
105
+ window.removeEventListener('scrollend', this._updateScrollData);
106
+ window.removeEventListener('resize', this._updateScrollData);
107
+ };
108
+ PageViewManager.prototype._scrollHeight = function () {
109
+ return Math.max(0, window.document.documentElement.scrollHeight - window.document.documentElement.clientHeight);
110
+ };
111
+ PageViewManager.prototype._scrollY = function () {
112
+ return window.scrollY || window.pageYOffset || window.document.documentElement.scrollTop || 0;
113
+ };
114
+ PageViewManager.prototype._contentHeight = function () {
115
+ return window.document.documentElement.scrollHeight || 0;
116
+ };
117
+ PageViewManager.prototype._contentY = function () {
118
+ var clientHeight = window.document.documentElement.clientHeight || 0;
119
+ return this._scrollY() + clientHeight;
120
+ };
121
+ return PageViewManager;
122
+ }());
123
+ export { PageViewManager };
124
+ function clamp(x, min, max) {
125
+ return Math.max(min, Math.min(x, max));
126
+ }
127
+ //# sourceMappingURL=page-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-view.js","sourceRoot":"","sources":["../../src/page-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { window } from './utils'\n\ninterface PageViewData {\n pathname: string\n // scroll is how far down the page the user has scrolled,\n // content is how far down the page the user can view content\n // (e.g. if the page is 1000 tall, but the user's screen is only 500 tall,\n // and they don't scroll at all, then scroll is 0 and content is 500)\n maxScrollHeight?: number\n maxScrollY?: number\n lastScrollY?: number\n maxContentHeight?: number\n maxContentY?: number\n lastContentY?: number\n}\n\ninterface ScrollProperties {\n $prev_pageview_last_scroll?: number\n $prev_pageview_last_scroll_percentage?: number\n $prev_pageview_max_scroll?: number\n $prev_pageview_max_scroll_percentage?: number\n $prev_pageview_last_content?: number\n $prev_pageview_last_content_percentage?: number\n $prev_pageview_max_content?: number\n $prev_pageview_max_content_percentage?: number\n}\n\ninterface PageViewEventProperties extends ScrollProperties {\n $prev_pageview_pathname?: string\n}\n\nexport class PageViewManager {\n _pageViewData: PageViewData | undefined\n _hasSeenPageView = false\n\n _createPageViewData(): PageViewData {\n return {\n pathname: window.location.pathname,\n }\n }\n\n doPageView(): PageViewEventProperties {\n let prevPageViewData: PageViewData | undefined\n // if there were events created before the first PageView, we would have created a\n // pageViewData for them. If this happened, we don't want to create a new pageViewData\n if (!this._hasSeenPageView) {\n this._hasSeenPageView = true\n prevPageViewData = undefined\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n } else {\n prevPageViewData = this._pageViewData\n this._pageViewData = this._createPageViewData()\n }\n\n // update the scroll properties for the new page, but wait until the next tick\n // of the event loop\n setTimeout(this._updateScrollData, 0)\n\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n doPageLeave(): PageViewEventProperties {\n const prevPageViewData = this._pageViewData\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n _calculatePrevPageScrollProperties(prevPageViewData: PageViewData | undefined): ScrollProperties {\n if (\n !prevPageViewData ||\n prevPageViewData.maxScrollHeight == null ||\n prevPageViewData.lastScrollY == null ||\n prevPageViewData.maxScrollY == null ||\n prevPageViewData.maxContentHeight == null ||\n prevPageViewData.lastContentY == null ||\n prevPageViewData.maxContentY == null\n ) {\n return {}\n }\n\n let { maxScrollHeight, lastScrollY, maxScrollY, maxContentHeight, lastContentY, maxContentY } = prevPageViewData\n\n // Use ceil, so that e.g. scrolling 999.5px of a 1000px page is considered 100% scrolled\n maxScrollHeight = Math.ceil(maxScrollHeight)\n lastScrollY = Math.ceil(lastScrollY)\n maxScrollY = Math.ceil(maxScrollY)\n maxContentHeight = Math.ceil(maxContentHeight)\n lastContentY = Math.ceil(lastContentY)\n maxContentY = Math.ceil(maxContentY)\n\n // if the maximum scroll height is near 0, then the percentage is 1\n const lastScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(lastScrollY / maxScrollHeight, 0, 1)\n const maxScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(maxScrollY / maxScrollHeight, 0, 1)\n const lastContentPercentage = maxContentHeight <= 1 ? 1 : clamp(lastContentY / maxContentHeight, 0, 1)\n const maxContentPercentage = maxContentHeight <= 1 ? 1 : clamp(maxContentY / maxContentHeight, 0, 1)\n\n return {\n $prev_pageview_last_scroll: lastScrollY,\n $prev_pageview_last_scroll_percentage: lastScrollPercentage,\n $prev_pageview_max_scroll: maxScrollY,\n $prev_pageview_max_scroll_percentage: maxScrollPercentage,\n $prev_pageview_last_content: lastContentY,\n $prev_pageview_last_content_percentage: lastContentPercentage,\n $prev_pageview_max_content: maxContentY,\n $prev_pageview_max_content_percentage: maxContentPercentage,\n }\n }\n\n _updateScrollData = () => {\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n const pageViewData = this._pageViewData\n\n const scrollY = this._scrollY()\n const scrollHeight = this._scrollHeight()\n const contentY = this._contentY()\n const contentHeight = this._contentHeight()\n\n pageViewData.lastScrollY = scrollY\n pageViewData.maxScrollY = Math.max(scrollY, pageViewData.maxScrollY ?? 0)\n pageViewData.maxScrollHeight = Math.max(scrollHeight, pageViewData.maxScrollHeight ?? 0)\n\n pageViewData.lastContentY = contentY\n pageViewData.maxContentY = Math.max(contentY, pageViewData.maxContentY ?? 0)\n pageViewData.maxContentHeight = Math.max(contentHeight, pageViewData.maxContentHeight ?? 0)\n }\n\n startMeasuringScrollPosition() {\n window.addEventListener('scroll', this._updateScrollData)\n window.addEventListener('scrollend', this._updateScrollData)\n window.addEventListener('resize', this._updateScrollData)\n }\n\n stopMeasuringScrollPosition() {\n window.removeEventListener('scroll', this._updateScrollData)\n window.removeEventListener('scrollend', this._updateScrollData)\n window.removeEventListener('resize', this._updateScrollData)\n }\n\n _scrollHeight(): number {\n return Math.max(0, window.document.documentElement.scrollHeight - window.document.documentElement.clientHeight)\n }\n\n _scrollY(): number {\n return window.scrollY || window.pageYOffset || window.document.documentElement.scrollTop || 0\n }\n\n _contentHeight(): number {\n return window.document.documentElement.scrollHeight || 0\n }\n\n _contentY(): number {\n const clientHeight = window.document.documentElement.clientHeight || 0\n return this._scrollY() + clientHeight\n }\n}\n\nfunction clamp(x: number, min: number, max: number) {\n return Math.max(min, Math.min(x, max))\n}\n"]}