posthog-js 1.36.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.d.ts CHANGED
@@ -135,13 +135,40 @@ interface CaptureResult {
135
135
  timestamp?: Date;
136
136
  }
137
137
  declare type CaptureCallback = (response: any, data: any) => void;
138
+ declare type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label';
139
+ declare type DomAutocaptureEvents = 'click' | 'change' | 'submit';
140
+ /**
141
+ * If an array is passed for an allowlist, autocapture events will only be sent for elements matching
142
+ * at least one of the elements in the array. Multiple allowlists can be used
143
+ */
144
+ interface AutocaptureConfig {
145
+ /**
146
+ * List of URLs to allow autocapture on, can be strings to match
147
+ * or regexes e.g. ['https://example.com', 'test.com/.*']
148
+ */
149
+ url_allowlist?: (string | RegExp)[];
150
+ /**
151
+ * List of DOM events to allow autocapture on e.g. ['click', 'change', 'submit']
152
+ */
153
+ dom_event_allowlist?: DomAutocaptureEvents[];
154
+ /**
155
+ * List of DOM elements to allow autocapture on
156
+ * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']
157
+ */
158
+ element_allowlist?: AutocaptureCompatibleElement[];
159
+ /**
160
+ * List of CSS selectors to allow autocapture on
161
+ * e.g. ['[ph-capture]']
162
+ */
163
+ css_selector_allowlist?: string[];
164
+ }
138
165
  interface PostHogConfig {
139
166
  api_host: string;
140
167
  api_method: string;
141
168
  api_transport: string;
142
169
  ui_host: string | null;
143
170
  token: string;
144
- autocapture: boolean;
171
+ autocapture: boolean | AutocaptureConfig;
145
172
  rageclick: boolean;
146
173
  cross_subdomain_cookie: boolean;
147
174
  persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie';
@@ -908,7 +935,7 @@ declare class PostHog {
908
935
  _jsc: JSC;
909
936
  __captureHooks: ((eventName: string) => void)[];
910
937
  __request_queue: [url: string, data: Record<string, any>, options: XHROptions, callback?: RequestCallback][];
911
- __autocapture_enabled: boolean | undefined;
938
+ __autocapture: boolean | AutocaptureConfig | undefined;
912
939
  decideEndpointWasHit: boolean;
913
940
  SentryIntegration: typeof SentryIntegration;
914
941
  segmentIntegration: () => any;
@@ -1098,6 +1125,10 @@ declare class PostHog {
1098
1125
  * @param {Object} groupPropertiesToSet Optional properties to set for group
1099
1126
  */
1100
1127
  group(groupType: string, groupKey: string, groupPropertiesToSet?: Properties): void;
1128
+ /**
1129
+ * Resets only the group properties of the user currently logged in.
1130
+ */
1131
+ resetGroups(): void;
1101
1132
  /**
1102
1133
  * Clears super properties and generates a new random distinct_id for this instance.
1103
1134
  * Useful for clearing data when a user logs out.
@@ -1163,8 +1194,8 @@ declare class PostHog {
1163
1194
  * // Automatically capture clicks, form submissions and change events
1164
1195
  * autocapture: true
1165
1196
  *
1166
- * // Capture rage clicks (beta) - useful for session recording
1167
- * rageclick: false
1197
+ * // Capture rage clicks
1198
+ * rageclick: true
1168
1199
  *
1169
1200
  * // transport for sending requests ('XHR' or 'sendBeacon')
1170
1201
  * // NB: sendBeacon should only be used for scenarios such as
@@ -1440,4 +1471,4 @@ declare class PostHog {
1440
1471
 
1441
1472
  declare const posthog: PostHog;
1442
1473
 
1443
- export { AutoCaptureCustomProperty, Breaker, CaptureCallback, CaptureOptions, CaptureResult, Compression, CompressionData, DecideResponse, EventHandler, FeatureFlagsCallback, GDPROptions, JSC, OptInOutCapturingOptions, PersistentStore, PostData, PostHog, PostHogConfig, Properties, Property, QueuedRequestData, RequestCallback, RetryQueueElement, SessionRecordingOptions, SnippetArrayItem, ToolbarParams, ToolbarSource, ToolbarUserIntent, ToolbarVersion, XHROptions, XHRParams, posthog as default, isFeatureEnabledOptions, posthog };
1474
+ export { AutoCaptureCustomProperty, AutocaptureCompatibleElement, AutocaptureConfig, Breaker, CaptureCallback, CaptureOptions, CaptureResult, Compression, CompressionData, DecideResponse, DomAutocaptureEvents, EventHandler, FeatureFlagsCallback, GDPROptions, JSC, OptInOutCapturingOptions, PersistentStore, PostData, PostHog, PostHogConfig, Properties, Property, QueuedRequestData, RequestCallback, RetryQueueElement, SessionRecordingOptions, SnippetArrayItem, ToolbarParams, ToolbarSource, ToolbarUserIntent, ToolbarVersion, XHROptions, XHRParams, posthog as default, isFeatureEnabledOptions, posthog };
package/dist/module.js CHANGED
@@ -921,7 +921,7 @@ var LZString = {
921
921
  }
922
922
  };
923
923
 
924
- var version = "1.36.0";
924
+ var version = "1.37.0";
925
925
 
926
926
  // e.g. Config.DEBUG = Config.DEBUG || instance.get_config('debug')
927
927
 
@@ -1203,7 +1203,6 @@ var _strip_empty_properties = function _strip_empty_properties(p) {
1203
1203
 
1204
1204
  return ret;
1205
1205
  };
1206
- var COPY_IN_PROGRESS_ATTRIBUTE = typeof Symbol !== 'undefined' ? Symbol('__deepCircularCopyInProgress__') : '__deepCircularCopyInProgress__';
1207
1206
  /**
1208
1207
  * Deep copies an object.
1209
1208
  * It handles cycles by replacing all references to them with `undefined`
@@ -1211,35 +1210,39 @@ var COPY_IN_PROGRESS_ATTRIBUTE = typeof Symbol !== 'undefined' ? Symbol('__deepC
1211
1210
  *
1212
1211
  * @param value
1213
1212
  * @param customizer
1214
- * @param [key] if provided this is the object key associated with the value to be copied. It allows the customizer function to have context when it runs
1215
1213
  * @returns {{}|undefined|*}
1216
1214
  */
1217
1215
 
1218
- function deepCircularCopy(value, customizer, key) {
1219
- if (value !== Object(value)) return customizer ? customizer(value, key) : value; // primitive value
1216
+ function deepCircularCopy(value, customizer) {
1217
+ var COPY_IN_PROGRESS_SET = new Set();
1220
1218
 
1221
- if (value[COPY_IN_PROGRESS_ATTRIBUTE]) return undefined;
1222
- value[COPY_IN_PROGRESS_ATTRIBUTE] = true;
1223
- var result;
1219
+ function internalDeepCircularCopy(value, key) {
1220
+ if (value !== Object(value)) return customizer ? customizer(value, key) : value; // primitive value
1224
1221
 
1225
- if (_isArray(value)) {
1226
- result = [];
1222
+ if (COPY_IN_PROGRESS_SET.has(value)) return undefined;
1223
+ COPY_IN_PROGRESS_SET.add(value);
1224
+ var result;
1227
1225
 
1228
- _eachArray(value, function (it) {
1229
- result.push(deepCircularCopy(it, customizer));
1230
- });
1231
- } else {
1232
- result = {};
1226
+ if (_isArray(value)) {
1227
+ result = [];
1233
1228
 
1234
- _each(value, function (val, key) {
1235
- if (key !== COPY_IN_PROGRESS_ATTRIBUTE) {
1236
- result[key] = deepCircularCopy(val, customizer, key);
1237
- }
1238
- });
1229
+ _eachArray(value, function (it) {
1230
+ result.push(internalDeepCircularCopy(it));
1231
+ });
1232
+ } else {
1233
+ result = {};
1234
+
1235
+ _each(value, function (val, key) {
1236
+ if (!COPY_IN_PROGRESS_SET.has(val)) {
1237
+ result[key] = internalDeepCircularCopy(val, key);
1238
+ }
1239
+ });
1240
+ }
1241
+
1242
+ return result;
1239
1243
  }
1240
1244
 
1241
- delete value[COPY_IN_PROGRESS_ATTRIBUTE];
1242
- return result;
1245
+ return internalDeepCircularCopy(value);
1243
1246
  }
1244
1247
 
1245
1248
  var LONG_STRINGS_ALLOW_LIST = ['$performance_raw'];
@@ -1865,20 +1868,64 @@ function isTextNode(el) {
1865
1868
  function isDocumentFragment(el) {
1866
1869
  return !!el && el.nodeType === 11; // Node.DOCUMENT_FRAGMENT_NODE - use integer constant for browser portability
1867
1870
  }
1868
- var usefulElements = ['a', 'button', 'form', 'input', 'select', 'textarea', 'label'];
1871
+ var autocaptureCompatibleElements = ['a', 'button', 'form', 'input', 'select', 'textarea', 'label'];
1869
1872
  /*
1870
1873
  * Check whether a DOM event should be "captured" or if it may contain sentitive data
1871
1874
  * using a variety of heuristics.
1872
1875
  * @param {Element} el - element to check
1873
1876
  * @param {Event} event - event to check
1877
+ * @param {Object} autocaptureConfig - autocapture config
1874
1878
  * @returns {boolean} whether the event should be captured
1875
1879
  */
1876
1880
 
1877
1881
  function shouldCaptureDomEvent(el, event) {
1882
+ var autocaptureConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
1883
+
1878
1884
  if (!el || isTag(el, 'html') || !isElementNode(el)) {
1879
1885
  return false;
1880
1886
  }
1881
1887
 
1888
+ if (autocaptureConfig !== null && autocaptureConfig !== void 0 && autocaptureConfig.url_allowlist) {
1889
+ var url = window.location.href;
1890
+ var allowlist = autocaptureConfig.url_allowlist;
1891
+
1892
+ if (allowlist && !allowlist.some(function (regex) {
1893
+ return url.match(regex);
1894
+ })) {
1895
+ return false;
1896
+ }
1897
+ }
1898
+
1899
+ if (autocaptureConfig !== null && autocaptureConfig !== void 0 && autocaptureConfig.dom_event_allowlist) {
1900
+ var _allowlist = autocaptureConfig.dom_event_allowlist;
1901
+
1902
+ if (_allowlist && !_allowlist.some(function (eventType) {
1903
+ return event.type === eventType;
1904
+ })) {
1905
+ return false;
1906
+ }
1907
+ }
1908
+
1909
+ if (autocaptureConfig !== null && autocaptureConfig !== void 0 && autocaptureConfig.element_allowlist) {
1910
+ var _allowlist2 = autocaptureConfig.element_allowlist;
1911
+
1912
+ if (_allowlist2 && !_allowlist2.some(function (elementType) {
1913
+ return el.tagName.toLowerCase() === elementType;
1914
+ })) {
1915
+ return false;
1916
+ }
1917
+ }
1918
+
1919
+ if (autocaptureConfig !== null && autocaptureConfig !== void 0 && autocaptureConfig.css_selector_allowlist) {
1920
+ var _allowlist3 = autocaptureConfig.css_selector_allowlist;
1921
+
1922
+ if (_allowlist3 && !_allowlist3.some(function (selector) {
1923
+ return el.matches(selector);
1924
+ })) {
1925
+ return false;
1926
+ }
1927
+ }
1928
+
1882
1929
  var parentIsUsefulElement = false;
1883
1930
  var targetElementList = [el]; // TODO: remove this var, it's never queried
1884
1931
 
@@ -1896,7 +1943,7 @@ function shouldCaptureDomEvent(el, event) {
1896
1943
  parentNode = curEl.parentNode || false;
1897
1944
  if (!parentNode) break;
1898
1945
 
1899
- if (usefulElements.indexOf(parentNode.tagName.toLowerCase()) > -1) {
1946
+ if (autocaptureCompatibleElements.indexOf(parentNode.tagName.toLowerCase()) > -1) {
1900
1947
  parentIsUsefulElement = true;
1901
1948
  } else {
1902
1949
  var _compStyles = window.getComputedStyle(parentNode);
@@ -1934,7 +1981,7 @@ function shouldCaptureDomEvent(el, event) {
1934
1981
 
1935
1982
  default:
1936
1983
  if (parentIsUsefulElement) return event.type === 'click';
1937
- return event.type === 'click' && (usefulElements.indexOf(tag) > -1 || el.getAttribute('contenteditable') === 'true');
1984
+ return event.type === 'click' && (autocaptureCompatibleElements.indexOf(tag) > -1 || el.getAttribute('contenteditable') === 'true');
1938
1985
  }
1939
1986
  }
1940
1987
  /*
@@ -2138,7 +2185,7 @@ var autocapture = {
2138
2185
  tag_name: tag_name
2139
2186
  };
2140
2187
 
2141
- if (usefulElements.indexOf(tag_name) > -1 && !maskText) {
2188
+ if (autocaptureCompatibleElements.indexOf(tag_name) > -1 && !maskText) {
2142
2189
  props['$el_text'] = getSafeText(elem);
2143
2190
  }
2144
2191
 
@@ -2249,7 +2296,7 @@ var autocapture = {
2249
2296
  (_this$rageclicks = this.rageclicks) === null || _this$rageclicks === void 0 ? void 0 : _this$rageclicks.click(e.clientX, e.clientY, new Date().getTime());
2250
2297
  }
2251
2298
 
2252
- if (target && shouldCaptureDomEvent(target, e)) {
2299
+ if (target && shouldCaptureDomEvent(target, e, this.config)) {
2253
2300
  var targetElementList = [target];
2254
2301
  var curEl = target;
2255
2302
 
@@ -2329,7 +2376,21 @@ var autocapture = {
2329
2376
  },
2330
2377
  _customProperties: [],
2331
2378
  rageclicks: null,
2379
+ config: undefined,
2332
2380
  init: function init(instance) {
2381
+ var _this$config;
2382
+
2383
+ if (typeof instance.__autocapture !== 'boolean') {
2384
+ this.config = instance.__autocapture;
2385
+ } // precompile the regex
2386
+
2387
+
2388
+ if ((_this$config = this.config) !== null && _this$config !== void 0 && _this$config.url_allowlist) {
2389
+ this.config.url_allowlist = this.config.url_allowlist.map(function (url) {
2390
+ return new RegExp(url);
2391
+ });
2392
+ }
2393
+
2333
2394
  this.rageclicks = new RageClick(instance);
2334
2395
  },
2335
2396
  afterDecideResponse: function afterDecideResponse(response, instance) {
@@ -2350,7 +2411,7 @@ var autocapture = {
2350
2411
 
2351
2412
  this._addDomEventHandlers(instance);
2352
2413
  } else {
2353
- instance['__autocapture_enabled'] = false;
2414
+ instance['__autocapture'] = false;
2354
2415
  }
2355
2416
  },
2356
2417
  // this is a mechanism to ramp up CE with no server-side interaction.
@@ -5298,6 +5359,10 @@ function strToU8(str, latin1) {
5298
5359
  return slc(ar, 0, ai);
5299
5360
  }
5300
5361
 
5362
+ /**
5363
+ * If an array is passed for an allowlist, autocapture events will only be sent for elements matching
5364
+ * at least one of the elements in the array. Multiple allowlists can be used
5365
+ */
5301
5366
  exports.Compression = void 0;
5302
5367
 
5303
5368
  (function (Compression) {
@@ -6121,7 +6186,7 @@ var defaultConfig = function defaultConfig() {
6121
6186
  ui_host: null,
6122
6187
  token: '',
6123
6188
  autocapture: true,
6124
- rageclick: false,
6189
+ rageclick: true,
6125
6190
  cross_subdomain_cookie: (document$1 === null || document$1 === void 0 ? void 0 : (_document$location = document$1.location) === null || _document$location === void 0 ? void 0 : (_document$location$ho = _document$location.hostname) === null || _document$location$ho === void 0 ? void 0 : _document$location$ho.indexOf('herokuapp.com')) === -1,
6126
6191
  persistence: 'cookie',
6127
6192
  persistence_name: '',
@@ -6224,17 +6289,18 @@ var create_mplib = function create_mplib(token, config, name) {
6224
6289
  instance.toolbar.maybeLoadToolbar();
6225
6290
  instance.sessionRecording = new SessionRecording(instance);
6226
6291
  instance.sessionRecording.startRecordingIfEnabled();
6227
- instance.__autocapture_enabled = instance.get_config('autocapture');
6292
+ instance.__autocapture = instance.get_config('autocapture');
6228
6293
 
6229
6294
  if (instance.get_config('autocapture')) {
6295
+ instance.__autocapture = instance.get_config('autocapture');
6230
6296
  var num_buckets = 100;
6231
6297
  var num_enabled_buckets = 100;
6232
6298
 
6233
6299
  if (!autocapture.enabledForProject(instance.get_config('token'), num_buckets, num_enabled_buckets)) {
6234
- instance.__autocapture_enabled = false;
6300
+ instance.__autocapture = false;
6235
6301
  logger.log('Not in active bucket: disabling Automatic Event Collection.');
6236
6302
  } else if (!autocapture.isBrowserSupported()) {
6237
- instance.__autocapture_enabled = false;
6303
+ instance.__autocapture = false;
6238
6304
  logger.log('Disabling Automatic Event Collection because this browser is not supported');
6239
6305
  } else {
6240
6306
  autocapture.init(instance);
@@ -6280,7 +6346,7 @@ var PostHog = /*#__PURE__*/function () {
6280
6346
  this.__captureHooks = [];
6281
6347
  this.__request_queue = [];
6282
6348
  this.__loaded = false;
6283
- this.__autocapture_enabled = undefined;
6349
+ this.__autocapture = undefined;
6284
6350
 
6285
6351
  this._jsc = function () {};
6286
6352
 
@@ -7159,6 +7225,19 @@ var PostHog = /*#__PURE__*/function () {
7159
7225
  this.reloadFeatureFlags();
7160
7226
  }
7161
7227
  }
7228
+ /**
7229
+ * Resets only the group properties of the user currently logged in.
7230
+ */
7231
+
7232
+ }, {
7233
+ key: "resetGroups",
7234
+ value: function resetGroups() {
7235
+ this.register({
7236
+ $groups: {}
7237
+ }); // If groups changed, reload feature flags.
7238
+
7239
+ this.reloadFeatureFlags();
7240
+ }
7162
7241
  /**
7163
7242
  * Clears super properties and generates a new random distinct_id for this instance.
7164
7243
  * Useful for clearing data when a user logs out.
@@ -7273,8 +7352,8 @@ var PostHog = /*#__PURE__*/function () {
7273
7352
  * // Automatically capture clicks, form submissions and change events
7274
7353
  * autocapture: true
7275
7354
  *
7276
- * // Capture rage clicks (beta) - useful for session recording
7277
- * rageclick: false
7355
+ * // Capture rage clicks
7356
+ * rageclick: true
7278
7357
  *
7279
7358
  * // transport for sending requests ('XHR' or 'sendBeacon')
7280
7359
  * // NB: sendBeacon should only be used for scenarios such as