mixpanel-browser 2.78.0 → 2.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.eslintrc.json +12 -0
  2. package/.github/workflows/integration-tests.yml +1 -0
  3. package/.github/workflows/openfeature-provider-tests.yml +31 -0
  4. package/CHANGELOG.md +14 -1
  5. package/build.sh +2 -2
  6. package/dist/async-modules/{mixpanel-recorder-BjSlYaNJ.min.js → mixpanel-recorder-B61POiHc.min.js} +2 -2
  7. package/dist/async-modules/mixpanel-recorder-B61POiHc.min.js.map +1 -0
  8. package/dist/async-modules/{mixpanel-recorder-zMBXIyeG.js → mixpanel-recorder-C3AW7mPl.js} +63 -35
  9. package/dist/async-modules/{mixpanel-targeting-UHf4eBfC.js → mixpanel-targeting-CBwOQJZw.js} +24 -13
  10. package/dist/async-modules/mixpanel-targeting-kdl-eE-1.min.js +2 -0
  11. package/dist/async-modules/mixpanel-targeting-kdl-eE-1.min.js.map +1 -0
  12. package/dist/mixpanel-core.cjs.d.ts +45 -1
  13. package/dist/mixpanel-core.cjs.js +577 -209
  14. package/dist/mixpanel-recorder.js +63 -35
  15. package/dist/mixpanel-recorder.min.js +1 -1
  16. package/dist/mixpanel-recorder.min.js.map +1 -1
  17. package/dist/mixpanel-targeting.js +24 -13
  18. package/dist/mixpanel-targeting.min.js +1 -1
  19. package/dist/mixpanel-targeting.min.js.map +1 -1
  20. package/dist/mixpanel-with-async-modules.cjs.d.ts +45 -1
  21. package/dist/mixpanel-with-async-modules.cjs.js +579 -211
  22. package/dist/mixpanel-with-async-recorder.cjs.d.ts +45 -1
  23. package/dist/mixpanel-with-async-recorder.cjs.js +579 -211
  24. package/dist/mixpanel-with-recorder.d.ts +45 -1
  25. package/dist/mixpanel-with-recorder.js +508 -136
  26. package/dist/mixpanel-with-recorder.min.d.ts +45 -1
  27. package/dist/mixpanel-with-recorder.min.js +1 -1
  28. package/dist/mixpanel.amd.d.ts +45 -1
  29. package/dist/mixpanel.amd.js +508 -136
  30. package/dist/mixpanel.cjs.d.ts +45 -1
  31. package/dist/mixpanel.cjs.js +508 -136
  32. package/dist/mixpanel.globals.js +579 -211
  33. package/dist/mixpanel.min.js +200 -190
  34. package/dist/mixpanel.module.d.ts +45 -1
  35. package/dist/mixpanel.module.js +508 -136
  36. package/dist/mixpanel.umd.d.ts +45 -1
  37. package/dist/mixpanel.umd.js +508 -136
  38. package/package.json +1 -1
  39. package/packages/openfeature-web-provider/README.md +357 -0
  40. package/packages/openfeature-web-provider/package-lock.json +1636 -0
  41. package/packages/openfeature-web-provider/package.json +51 -0
  42. package/packages/openfeature-web-provider/rollup.config.browser.mjs +26 -0
  43. package/packages/openfeature-web-provider/src/MixpanelProvider.ts +302 -0
  44. package/packages/openfeature-web-provider/src/index.ts +1 -0
  45. package/packages/openfeature-web-provider/src/types.ts +72 -0
  46. package/packages/openfeature-web-provider/test/MixpanelProvider.spec.ts +484 -0
  47. package/packages/openfeature-web-provider/tsconfig.json +15 -0
  48. package/src/autocapture/index.js +17 -12
  49. package/src/config.js +1 -1
  50. package/src/flags/flags-persistence.js +176 -0
  51. package/src/flags/index.js +176 -25
  52. package/src/index.d.ts +45 -1
  53. package/src/mixpanel-core.js +24 -7
  54. package/src/recorder/idb-config.js +16 -0
  55. package/src/recorder/recording-registry.js +7 -2
  56. package/src/recorder/session-recording.js +15 -6
  57. package/src/recorder-manager.js +7 -2
  58. package/src/request-queue.js +1 -2
  59. package/src/shared-lock.js +2 -3
  60. package/src/storage/indexed-db.js +16 -15
  61. package/src/storage/local-storage.js +5 -3
  62. package/src/utils.js +25 -12
  63. package/tsconfig.base.json +9 -0
  64. package/.claude/settings.local.json +0 -16
  65. package/dist/async-modules/mixpanel-recorder-BjSlYaNJ.min.js.map +0 -1
  66. package/dist/async-modules/mixpanel-targeting-BSHal4N9.min.js +0 -2
  67. package/dist/async-modules/mixpanel-targeting-BSHal4N9.min.js.map +0 -1
@@ -27,7 +27,7 @@ define((function () { 'use strict';
27
27
 
28
28
  var Config = {
29
29
  DEBUG: false,
30
- LIB_VERSION: '2.78.0'
30
+ LIB_VERSION: '2.80.0'
31
31
  };
32
32
 
33
33
  // Window global names for async modules
@@ -19125,6 +19125,7 @@ define((function () { 'use strict';
19125
19125
  var console_with_prefix = function(prefix) {
19126
19126
  return {
19127
19127
  log: log_func_with_prefix(console$1.log, prefix),
19128
+ warn: log_func_with_prefix(console$1.warn, prefix),
19128
19129
  error: log_func_with_prefix(console$1.error, prefix),
19129
19130
  critical: log_func_with_prefix(console$1.critical, prefix)
19130
19131
  };
@@ -20071,7 +20072,8 @@ define((function () { 'use strict';
20071
20072
  if (_localStorageSupported !== null && !forceCheck) {
20072
20073
  return _localStorageSupported;
20073
20074
  }
20074
- return _localStorageSupported = _testStorageSupported(storage || win.localStorage);
20075
+
20076
+ return _localStorageSupported = _testStorageSupported(storage);
20075
20077
  };
20076
20078
 
20077
20079
  var _sessionStorageSupported = null;
@@ -20079,7 +20081,8 @@ define((function () { 'use strict';
20079
20081
  if (_sessionStorageSupported !== null && !forceCheck) {
20080
20082
  return _sessionStorageSupported;
20081
20083
  }
20082
- return _sessionStorageSupported = _testStorageSupported(storage || win.sessionStorage);
20084
+
20085
+ return _sessionStorageSupported = _testStorageSupported(storage);
20083
20086
  };
20084
20087
 
20085
20088
  function _storageWrapper(storage, name, is_supported_fn) {
@@ -20129,17 +20132,26 @@ define((function () { 'use strict';
20129
20132
  };
20130
20133
  }
20131
20134
 
20132
- // Safari errors out accessing localStorage/sessionStorage when cookies are disabled,
20133
- // so create dummy storage wrappers that silently fail as a fallback.
20134
- var windowLocalStorage = null, windowSessionStorage = null;
20135
- try {
20136
- windowLocalStorage = win.localStorage;
20137
- windowSessionStorage = win.sessionStorage;
20138
- // eslint-disable-next-line no-empty
20139
- } catch (_err) {}
20135
+ // Safari and other browsers may error out accessing localStorage/sessionStorage
20136
+ // when cookies are disabled, so wrap access in a try-catch.
20137
+ var getLocalStorage = function() {
20138
+ try {
20139
+ return win.localStorage; // eslint-disable-line no-restricted-properties
20140
+ } catch (_err) {
20141
+ return null;
20142
+ }
20143
+ };
20144
+
20145
+ var getSessionStorage = function() {
20146
+ try {
20147
+ return win.sessionStorage; // eslint-disable-line no-restricted-properties
20148
+ } catch (_err) {
20149
+ return null;
20150
+ }
20151
+ };
20140
20152
 
20141
- _.localStorage = _storageWrapper(windowLocalStorage, 'localStorage', localStorageSupported);
20142
- _.sessionStorage = _storageWrapper(windowSessionStorage, 'sessionStorage', sessionStorageSupported);
20153
+ _.localStorage = _storageWrapper(getLocalStorage(), 'localStorage', localStorageSupported);
20154
+ _.sessionStorage = _storageWrapper(getSessionStorage(), 'sessionStorage', sessionStorageSupported);
20143
20155
 
20144
20156
  _.register_event = (function() {
20145
20157
  // written by Dean Edwards, 2005
@@ -20808,29 +20820,26 @@ define((function () { 'use strict';
20808
20820
  _['toArray'] = _.toArray;
20809
20821
  _['NPO'] = NpoPromise;
20810
20822
 
20811
- var MIXPANEL_DB_NAME = 'mixpanelBrowserDb';
20812
-
20813
- var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
20814
- var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
20815
-
20816
- // note: increment the version number when adding new object stores
20817
- var DB_VERSION = 1;
20818
- var OBJECT_STORES = [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME];
20819
-
20820
20823
  /**
20821
20824
  * @type {import('./wrapper').StorageWrapper}
20822
20825
  */
20823
- var IDBStorageWrapper = function (storeName) {
20826
+ var IDBStorageWrapper = function (dbName, storeName, versionData) {
20827
+ this.dbName = dbName;
20828
+ this.storeName = storeName;
20829
+ this.version = versionData.version;
20830
+ this.storeNamesInDb = versionData.storeNames;
20824
20831
  /**
20825
20832
  * @type {Promise<IDBDatabase>|null}
20826
20833
  */
20827
20834
  this.dbPromise = null;
20828
- this.storeName = storeName;
20829
20835
  };
20830
20836
 
20831
20837
  IDBStorageWrapper.prototype._openDb = function () {
20838
+ var dbName = this.dbName;
20839
+ var version = this.version;
20840
+ var storeNamesInDb = this.storeNamesInDb;
20832
20841
  return new PromisePolyfill(function (resolve, reject) {
20833
- var openRequest = win.indexedDB.open(MIXPANEL_DB_NAME, DB_VERSION);
20842
+ var openRequest = win.indexedDB.open(dbName, version);
20834
20843
  openRequest['onerror'] = function () {
20835
20844
  reject(openRequest.error);
20836
20845
  };
@@ -20842,8 +20851,10 @@ define((function () { 'use strict';
20842
20851
  openRequest['onupgradeneeded'] = function (ev) {
20843
20852
  var db = ev.target.result;
20844
20853
 
20845
- OBJECT_STORES.forEach(function (storeName) {
20846
- db.createObjectStore(storeName);
20854
+ storeNamesInDb.forEach(function (storeName) {
20855
+ if (!db.objectStoreNames.contains(storeName)) {
20856
+ db.createObjectStore(storeName);
20857
+ }
20847
20858
  });
20848
20859
  };
20849
20860
  });
@@ -20935,6 +20946,16 @@ define((function () { 'use strict';
20935
20946
  });
20936
20947
  };
20937
20948
 
20949
+ var MIXPANEL_BROWSER_DB_NAME = 'mixpanelBrowserDb';
20950
+ var RECORDING_EVENTS_STORE_NAME = 'mixpanelRecordingEvents';
20951
+ var RECORDING_REGISTRY_STORE_NAME = 'mixpanelRecordingRegistry';
20952
+
20953
+ // Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
20954
+ var RECORDER_VERSION_DATA = {
20955
+ version: 1,
20956
+ storeNames: [RECORDING_EVENTS_STORE_NAME, RECORDING_REGISTRY_STORE_NAME]
20957
+ };
20958
+
20938
20959
  /**
20939
20960
  * GDPR utils
20940
20961
  *
@@ -21235,7 +21256,7 @@ define((function () { 'use strict';
21235
21256
  };
21236
21257
  }
21237
21258
 
21238
- var logger$8 = console_with_prefix('lock');
21259
+ var logger$9 = console_with_prefix('lock');
21239
21260
 
21240
21261
  /**
21241
21262
  * SharedLock: a mutex built on HTML5 localStorage, to ensure that only one browser
@@ -21261,7 +21282,7 @@ define((function () { 'use strict';
21261
21282
  options = options || {};
21262
21283
 
21263
21284
  this.storageKey = key;
21264
- this.storage = options.storage || win.localStorage;
21285
+ this.storage = options.storage || getLocalStorage();
21265
21286
  this.pollIntervalMS = options.pollIntervalMS || 100;
21266
21287
  this.timeoutMS = options.timeoutMS || 2000;
21267
21288
 
@@ -21287,7 +21308,7 @@ define((function () { 'use strict';
21287
21308
 
21288
21309
  var delay = function(cb) {
21289
21310
  if (new Date().getTime() - startTime > timeoutMS) {
21290
- logger$8.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21311
+ logger$9.error('Timeout waiting for mutex on ' + key + '; clearing lock. [' + i + ']');
21291
21312
  storage.removeItem(keyZ);
21292
21313
  storage.removeItem(keyY);
21293
21314
  loop();
@@ -21389,10 +21410,13 @@ define((function () { 'use strict';
21389
21410
  * @type {import('./wrapper').StorageWrapper}
21390
21411
  */
21391
21412
  var LocalStorageWrapper = function (storageOverride) {
21392
- this.storage = storageOverride || win.localStorage;
21413
+ this.storage = storageOverride || getLocalStorage();
21393
21414
  };
21394
21415
 
21395
21416
  LocalStorageWrapper.prototype.init = function () {
21417
+ if (!this.storage) {
21418
+ return PromisePolyfill.reject(new Error('localStorage is not available'));
21419
+ }
21396
21420
  return PromisePolyfill.resolve();
21397
21421
  };
21398
21422
 
@@ -21434,7 +21458,7 @@ define((function () { 'use strict';
21434
21458
  }, this));
21435
21459
  };
21436
21460
 
21437
- var logger$7 = console_with_prefix('batch');
21461
+ var logger$8 = console_with_prefix('batch');
21438
21462
 
21439
21463
  /**
21440
21464
  * RequestQueue: queue for batching API requests with localStorage backup for retries.
@@ -21459,11 +21483,11 @@ define((function () { 'use strict';
21459
21483
  if (this.usePersistence) {
21460
21484
  this.queueStorage = options.queueStorage || new LocalStorageWrapper();
21461
21485
  this.lock = new SharedLock(storageKey, {
21462
- storage: options.sharedLockStorage || win.localStorage,
21486
+ storage: options.sharedLockStorage,
21463
21487
  timeoutMS: options.sharedLockTimeoutMS,
21464
21488
  });
21465
21489
  }
21466
- this.reportError = options.errorReporter || _.bind(logger$7.error, logger$7);
21490
+ this.reportError = options.errorReporter || _.bind(logger$8.error, logger$8);
21467
21491
 
21468
21492
  this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
21469
21493
 
@@ -21796,7 +21820,7 @@ define((function () { 'use strict';
21796
21820
  // maximum interval between request retries after exponential backoff
21797
21821
  var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
21798
21822
 
21799
- var logger$6 = console_with_prefix('batch');
21823
+ var logger$7 = console_with_prefix('batch');
21800
21824
 
21801
21825
  /**
21802
21826
  * RequestBatcher: manages the queueing, flushing, retry etc of requests of one
@@ -21924,7 +21948,7 @@ define((function () { 'use strict';
21924
21948
  */
21925
21949
  RequestBatcher.prototype.flush = function(options) {
21926
21950
  if (this.requestInProgress) {
21927
- logger$6.log('Flush: Request already in progress');
21951
+ logger$7.log('Flush: Request already in progress');
21928
21952
  return PromisePolyfill.resolve();
21929
21953
  }
21930
21954
 
@@ -22101,7 +22125,7 @@ define((function () { 'use strict';
22101
22125
  if (options.unloading) {
22102
22126
  requestOptions.transport = 'sendBeacon';
22103
22127
  }
22104
- logger$6.log('MIXPANEL REQUEST:', dataForRequest);
22128
+ logger$7.log('MIXPANEL REQUEST:', dataForRequest);
22105
22129
  return this.sendRequestPromise(dataForRequest, requestOptions).then(batchSendCallback);
22106
22130
  }, this))
22107
22131
  .catch(_.bind(function(err) {
@@ -22114,7 +22138,7 @@ define((function () { 'use strict';
22114
22138
  * Log error to global logger and optional user-defined logger.
22115
22139
  */
22116
22140
  RequestBatcher.prototype.reportError = function(msg, err) {
22117
- logger$6.error.apply(logger$6.error, arguments);
22141
+ logger$7.error.apply(logger$7.error, arguments);
22118
22142
  if (this.errorReporter) {
22119
22143
  try {
22120
22144
  if (!(err instanceof Error)) {
@@ -22122,7 +22146,7 @@ define((function () { 'use strict';
22122
22146
  }
22123
22147
  this.errorReporter(msg, err);
22124
22148
  } catch(err) {
22125
- logger$6.error(err);
22149
+ logger$7.error(err);
22126
22150
  }
22127
22151
  }
22128
22152
  };
@@ -22267,7 +22291,7 @@ define((function () { 'use strict';
22267
22291
 
22268
22292
  var MAX_DEPTH = 5;
22269
22293
 
22270
- var logger$5 = console_with_prefix('autocapture');
22294
+ var logger$6 = console_with_prefix('autocapture');
22271
22295
 
22272
22296
 
22273
22297
  function getClasses(el) {
@@ -22531,7 +22555,7 @@ define((function () { 'use strict';
22531
22555
  return false;
22532
22556
  }
22533
22557
  } catch (err) {
22534
- logger$5.critical('Error while checking element in allowElementCallback', err);
22558
+ logger$6.critical('Error while checking element in allowElementCallback', err);
22535
22559
  return false;
22536
22560
  }
22537
22561
  }
@@ -22548,7 +22572,7 @@ define((function () { 'use strict';
22548
22572
  return true;
22549
22573
  }
22550
22574
  } catch (err) {
22551
- logger$5.critical('Error while checking selector: ' + sel, err);
22575
+ logger$6.critical('Error while checking selector: ' + sel, err);
22552
22576
  }
22553
22577
  }
22554
22578
  return false;
@@ -22563,7 +22587,7 @@ define((function () { 'use strict';
22563
22587
  return true;
22564
22588
  }
22565
22589
  } catch (err) {
22566
- logger$5.critical('Error while checking element in blockElementCallback', err);
22590
+ logger$6.critical('Error while checking element in blockElementCallback', err);
22567
22591
  return true;
22568
22592
  }
22569
22593
  }
@@ -22577,7 +22601,7 @@ define((function () { 'use strict';
22577
22601
  return true;
22578
22602
  }
22579
22603
  } catch (err) {
22580
- logger$5.critical('Error while checking selector: ' + sel, err);
22604
+ logger$6.critical('Error while checking selector: ' + sel, err);
22581
22605
  }
22582
22606
  }
22583
22607
  }
@@ -23133,7 +23157,7 @@ define((function () { 'use strict';
23133
23157
  *
23134
23158
  */
23135
23159
 
23136
- var logger$4 = console_with_prefix('network-plugin');
23160
+ var logger$5 = console_with_prefix('network-plugin');
23137
23161
 
23138
23162
  /**
23139
23163
  * Get the time origin for converting performance timestamps to absolute timestamps.
@@ -23285,7 +23309,7 @@ define((function () { 'use strict';
23285
23309
  return str;
23286
23310
  }
23287
23311
  if (str.length > MAX_BODY_SIZE) {
23288
- logger$4.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23312
+ logger$5.error('Body truncated from ' + str.length + ' to ' + MAX_BODY_SIZE + ' characters');
23289
23313
  return str.substring(0, MAX_BODY_SIZE) + '... [truncated]';
23290
23314
  }
23291
23315
  return str;
@@ -23299,7 +23323,7 @@ define((function () { 'use strict';
23299
23323
  */
23300
23324
  function initPerformanceObserver(cb, win, options) {
23301
23325
  if (!win.PerformanceObserver) {
23302
- logger$4.error('PerformanceObserver not supported');
23326
+ logger$5.error('PerformanceObserver not supported');
23303
23327
  return function() {
23304
23328
  //
23305
23329
  };
@@ -23452,7 +23476,7 @@ define((function () { 'use strict';
23452
23476
  attempt = 0;
23453
23477
  }
23454
23478
  if (attempt > 10) {
23455
- logger$4.error('Cannot find performance entry');
23479
+ logger$5.error('Cannot find performance entry');
23456
23480
  return Promise.resolve(null);
23457
23481
  }
23458
23482
  var urlPerformanceEntries = /** @type {PerformanceResourceTiming[]} */ (
@@ -23573,7 +23597,7 @@ define((function () { 'use strict';
23573
23597
  )
23574
23598
  .then(function(entry) {
23575
23599
  if (!entry) {
23576
- logger$4.error('Failed to get performance entry for XHR request to ' + req.url);
23600
+ logger$5.error('Failed to get performance entry for XHR request to ' + req.url);
23577
23601
  return;
23578
23602
  }
23579
23603
  /** @type {NetworkRequest} */
@@ -23593,7 +23617,7 @@ define((function () { 'use strict';
23593
23617
  cb({ requests: [request] });
23594
23618
  })
23595
23619
  .catch(function(e) {
23596
- logger$4.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23620
+ logger$5.error('Error recording XHR request to ' + req.url + ': ' + String(e));
23597
23621
  });
23598
23622
  });
23599
23623
 
@@ -23685,7 +23709,7 @@ define((function () { 'use strict';
23685
23709
  })
23686
23710
  .then(function(entry) {
23687
23711
  if (!entry) {
23688
- logger$4.error('Failed to get performance entry for fetch request to ' + req.url);
23712
+ logger$5.error('Failed to get performance entry for fetch request to ' + req.url);
23689
23713
  return;
23690
23714
  }
23691
23715
  /** @type {NetworkRequest} */
@@ -23705,7 +23729,7 @@ define((function () { 'use strict';
23705
23729
  cb({ requests: [request] });
23706
23730
  })
23707
23731
  .catch(function (e) {
23708
- logger$4.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23732
+ logger$5.error('Error recording fetch request to ' + req.url + ': ' + String(e));
23709
23733
  });
23710
23734
 
23711
23735
  return originalFetchPromise;
@@ -23778,7 +23802,7 @@ define((function () { 'use strict';
23778
23802
  */
23779
23803
 
23780
23804
 
23781
- var logger$3 = console_with_prefix('recorder');
23805
+ var logger$4 = console_with_prefix('recorder');
23782
23806
  var CompressionStream = win['CompressionStream'];
23783
23807
 
23784
23808
  var RECORDER_BATCHER_LIB_CONFIG = {
@@ -23872,14 +23896,15 @@ define((function () { 'use strict';
23872
23896
 
23873
23897
  this.recordMaxMs = MAX_RECORDING_MS;
23874
23898
  this.recordMinMs = 0;
23899
+ this._recordMinMsCheckStart = null;
23875
23900
 
23876
23901
  // disable persistence if localStorage is not supported
23877
23902
  // request-queue will automatically disable persistence if indexedDB fails to initialize
23878
- var usePersistence = localStorageSupported(options.sharedLockStorage, true) && !this.getConfig('disable_persistence');
23903
+ var usePersistence = localStorageSupported(options.sharedLockStorage || getLocalStorage(), true) && !this.getConfig('disable_persistence');
23879
23904
 
23880
23905
  // each replay has its own batcher key to avoid conflicts between rrweb events of different recordings
23881
23906
  this.batcherKey = '__mprec_' + this.getConfig('name') + '_' + this.getConfig('token') + '_' + this.replayId;
23882
- this.queueStorage = new IDBStorageWrapper(RECORDING_EVENTS_STORE_NAME);
23907
+ this.queueStorage = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_EVENTS_STORE_NAME, RECORDER_VERSION_DATA);
23883
23908
  this.batcher = new RequestBatcher(this.batcherKey, {
23884
23909
  errorReporter: this.reportError.bind(this),
23885
23910
  flushOnlyOnInterval: true,
@@ -23958,14 +23983,14 @@ define((function () { 'use strict';
23958
23983
  }
23959
23984
 
23960
23985
  if (this._stopRecording !== null) {
23961
- logger$3.log('Recording already in progress, skipping startRecording.');
23986
+ logger$4.log('Recording already in progress, skipping startRecording.');
23962
23987
  return;
23963
23988
  }
23964
23989
 
23965
23990
  this.recordMaxMs = this.getConfig('record_max_ms');
23966
23991
  if (this.recordMaxMs > MAX_RECORDING_MS) {
23967
23992
  this.recordMaxMs = MAX_RECORDING_MS;
23968
- logger$3.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23993
+ logger$4.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
23969
23994
  }
23970
23995
 
23971
23996
  if (!this.maxExpires) {
@@ -23987,6 +24012,7 @@ define((function () { 'use strict';
23987
24012
  // this also applies if the minimum recording length has not been hit yet
23988
24013
  // so that we don't send data until we know the recording will be long enough
23989
24014
  this.batcher.stop();
24015
+ this._recordMinMsCheckStart = null;
23990
24016
  } else {
23991
24017
  this.batcher.start();
23992
24018
  }
@@ -24029,7 +24055,7 @@ define((function () { 'use strict';
24029
24055
  );
24030
24056
  }
24031
24057
 
24032
- var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$3);
24058
+ var validatedOrigins = validateAllowedOrigins(this.getConfig('record_allowed_iframe_origins'), logger$4);
24033
24059
 
24034
24060
  try {
24035
24061
  this._stopRecording = this._rrwebRecord({
@@ -24038,9 +24064,11 @@ define((function () { 'use strict';
24038
24064
  this._onIdleTimeout();
24039
24065
  return;
24040
24066
  }
24067
+ if (this._recordMinMsCheckStart === null) {
24068
+ this._recordMinMsCheckStart = ev.timestamp;
24069
+ }
24041
24070
  if (isUserEvent(ev)) {
24042
- if (this.batcher.stopped && new Date().getTime() - this.replayStartTime >= this.recordMinMs) {
24043
- // start flushing again after user activity
24071
+ if (this.batcher.stopped && ev.timestamp - this._recordMinMsCheckStart >= this.recordMinMs) {
24044
24072
  this.batcher.start();
24045
24073
  }
24046
24074
  resetIdleTimeout();
@@ -24291,14 +24319,14 @@ define((function () { 'use strict';
24291
24319
 
24292
24320
 
24293
24321
  SessionRecording.prototype.reportError = function(msg, err) {
24294
- logger$3.error.apply(logger$3.error, arguments);
24322
+ logger$4.error.apply(logger$4.error, arguments);
24295
24323
  try {
24296
24324
  if (!err && !(msg instanceof Error)) {
24297
24325
  msg = new Error(msg);
24298
24326
  }
24299
24327
  this.getConfig('error_reporter')(msg, err);
24300
24328
  } catch(err) {
24301
- logger$3.error(err);
24329
+ logger$4.error(err);
24302
24330
  }
24303
24331
  };
24304
24332
 
@@ -24327,7 +24355,7 @@ define((function () { 'use strict';
24327
24355
  var configValue = this.getConfig('record_min_ms');
24328
24356
 
24329
24357
  if (configValue > MAX_VALUE_FOR_MIN_RECORDING_MS) {
24330
- logger$3.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24358
+ logger$4.critical('record_min_ms cannot be greater than ' + MAX_VALUE_FOR_MIN_RECORDING_MS + 'ms. Capping value.');
24331
24359
  return MAX_VALUE_FOR_MIN_RECORDING_MS;
24332
24360
  }
24333
24361
 
@@ -24369,7 +24397,7 @@ define((function () { 'use strict';
24369
24397
  */
24370
24398
  var RecordingRegistry = function (options) {
24371
24399
  /** @type {IDBStorageWrapper} */
24372
- this.idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
24400
+ this.idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
24373
24401
  this.errorReporter = options.errorReporter;
24374
24402
  this.mixpanelInstance = options.mixpanelInstance;
24375
24403
  this.sharedLockStorage = options.sharedLockStorage;
@@ -24490,7 +24518,7 @@ define((function () { 'use strict';
24490
24518
  .catch(this.handleError.bind(this));
24491
24519
  };
24492
24520
 
24493
- var logger$2 = console_with_prefix('recorder');
24521
+ var logger$3 = console_with_prefix('recorder');
24494
24522
 
24495
24523
  /**
24496
24524
  * Recorder API: bundles rrweb and and exposes methods to start and stop recordings.
@@ -24506,7 +24534,7 @@ define((function () { 'use strict';
24506
24534
  */
24507
24535
  this.recordingRegistry = new RecordingRegistry({
24508
24536
  mixpanelInstance: this.mixpanelInstance,
24509
- errorReporter: logger$2.error,
24537
+ errorReporter: logger$3.error,
24510
24538
  sharedLockStorage: sharedLockStorage
24511
24539
  });
24512
24540
  this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
@@ -24518,17 +24546,17 @@ define((function () { 'use strict';
24518
24546
  MixpanelRecorder.prototype.startRecording = function(options) {
24519
24547
  options = options || {};
24520
24548
  if (this.activeRecording && !this.activeRecording.isRrwebStopped()) {
24521
- logger$2.log('Recording already in progress, skipping startRecording.');
24549
+ logger$3.log('Recording already in progress, skipping startRecording.');
24522
24550
  return;
24523
24551
  }
24524
24552
 
24525
24553
  var onIdleTimeout = function () {
24526
- logger$2.log('Idle timeout reached, restarting recording.');
24554
+ logger$3.log('Idle timeout reached, restarting recording.');
24527
24555
  this.resetRecording();
24528
24556
  }.bind(this);
24529
24557
 
24530
24558
  var onMaxLengthReached = function () {
24531
- logger$2.log('Max recording length reached, stopping recording.');
24559
+ logger$3.log('Max recording length reached, stopping recording.');
24532
24560
  this.resetRecording();
24533
24561
  }.bind(this);
24534
24562
 
@@ -24598,7 +24626,7 @@ define((function () { 'use strict';
24598
24626
  } else if (startNewIfInactive) {
24599
24627
  return this.startRecording({shouldStopBatcher: false});
24600
24628
  } else {
24601
- logger$2.log('No resumable recording found.');
24629
+ logger$3.log('No resumable recording found.');
24602
24630
  return null;
24603
24631
  }
24604
24632
  }.bind(this));
@@ -25263,7 +25291,7 @@ define((function () { 'use strict';
25263
25291
  observer.observe(shadowRoot, this.observerConfig);
25264
25292
  this.shadowObservers.push(observer);
25265
25293
  } catch (e) {
25266
- logger$5.critical('Error while observing shadow root', e);
25294
+ logger$6.critical('Error while observing shadow root', e);
25267
25295
  }
25268
25296
  };
25269
25297
 
@@ -25274,7 +25302,7 @@ define((function () { 'use strict';
25274
25302
  }
25275
25303
 
25276
25304
  if (!weakSetSupported()) {
25277
- logger$5.critical('Shadow DOM observation unavailable: WeakSet not supported');
25305
+ logger$6.critical('Shadow DOM observation unavailable: WeakSet not supported');
25278
25306
  return;
25279
25307
  }
25280
25308
 
@@ -25290,7 +25318,7 @@ define((function () { 'use strict';
25290
25318
  try {
25291
25319
  this.shadowObservers[i].disconnect();
25292
25320
  } catch (e) {
25293
- logger$5.critical('Error while disconnecting shadow DOM observer', e);
25321
+ logger$6.critical('Error while disconnecting shadow DOM observer', e);
25294
25322
  }
25295
25323
  }
25296
25324
  this.shadowObservers = [];
@@ -25478,7 +25506,7 @@ define((function () { 'use strict';
25478
25506
 
25479
25507
  this.mutationObserver.observe(document.body || document.documentElement, MUTATION_OBSERVER_CONFIG);
25480
25508
  } catch (e) {
25481
- logger$5.critical('Error while setting up mutation observer', e);
25509
+ logger$6.critical('Error while setting up mutation observer', e);
25482
25510
  }
25483
25511
  }
25484
25512
 
@@ -25493,7 +25521,7 @@ define((function () { 'use strict';
25493
25521
  );
25494
25522
  this.shadowDOMObserver.start();
25495
25523
  } catch (e) {
25496
- logger$5.critical('Error while setting up shadow DOM observer', e);
25524
+ logger$6.critical('Error while setting up shadow DOM observer', e);
25497
25525
  this.shadowDOMObserver = null;
25498
25526
  }
25499
25527
  }
@@ -25520,7 +25548,7 @@ define((function () { 'use strict';
25520
25548
  try {
25521
25549
  listener.target.removeEventListener(listener.event, listener.handler, listener.options);
25522
25550
  } catch (e) {
25523
- logger$5.critical('Error while removing event listener', e);
25551
+ logger$6.critical('Error while removing event listener', e);
25524
25552
  }
25525
25553
  }
25526
25554
  this.eventListeners = [];
@@ -25529,7 +25557,7 @@ define((function () { 'use strict';
25529
25557
  try {
25530
25558
  this.mutationObserver.disconnect();
25531
25559
  } catch (e) {
25532
- logger$5.critical('Error while disconnecting mutation observer', e);
25560
+ logger$6.critical('Error while disconnecting mutation observer', e);
25533
25561
  }
25534
25562
  this.mutationObserver = null;
25535
25563
  }
@@ -25538,7 +25566,7 @@ define((function () { 'use strict';
25538
25566
  try {
25539
25567
  this.shadowDOMObserver.stop();
25540
25568
  } catch (e) {
25541
- logger$5.critical('Error while stopping shadow DOM observer', e);
25569
+ logger$6.critical('Error while stopping shadow DOM observer', e);
25542
25570
  }
25543
25571
  this.shadowDOMObserver = null;
25544
25572
  }
@@ -25616,7 +25644,7 @@ define((function () { 'use strict';
25616
25644
 
25617
25645
  Autocapture.prototype.init = function() {
25618
25646
  if (!minDOMApisSupported()) {
25619
- logger$5.critical('Autocapture unavailable: missing required DOM APIs');
25647
+ logger$6.critical('Autocapture unavailable: missing required DOM APIs');
25620
25648
  return;
25621
25649
  }
25622
25650
  this.initPageListeners();
@@ -25656,7 +25684,7 @@ define((function () { 'use strict';
25656
25684
  try {
25657
25685
  return !urlMatchesRegexList(currentUrl, allowUrlRegexes);
25658
25686
  } catch (err) {
25659
- logger$5.critical('Error while checking block URL regexes: ', err);
25687
+ logger$6.critical('Error while checking block URL regexes: ', err);
25660
25688
  return true;
25661
25689
  }
25662
25690
  }
@@ -25669,7 +25697,7 @@ define((function () { 'use strict';
25669
25697
  try {
25670
25698
  return urlMatchesRegexList(currentUrl, blockUrlRegexes);
25671
25699
  } catch (err) {
25672
- logger$5.critical('Error while checking block URL regexes: ', err);
25700
+ logger$6.critical('Error while checking block URL regexes: ', err);
25673
25701
  return true;
25674
25702
  }
25675
25703
  };
@@ -25807,7 +25835,7 @@ define((function () { 'use strict';
25807
25835
  return;
25808
25836
  }
25809
25837
 
25810
- logger$5.log('Initializing scroll depth tracking');
25838
+ logger$6.log('Initializing scroll depth tracking');
25811
25839
 
25812
25840
  this.maxScrollViewDepth = Math.max(document$1.documentElement.clientHeight, win.innerHeight || 0);
25813
25841
 
@@ -25828,12 +25856,12 @@ define((function () { 'use strict';
25828
25856
  };
25829
25857
 
25830
25858
  Autocapture.prototype.initClickTracking = function() {
25831
- win.removeEventListener(EV_CLICK, this.listenerClick);
25859
+ win.removeEventListener(EV_CLICK, this.listenerClick, true);
25832
25860
 
25833
25861
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
25834
25862
  return;
25835
25863
  }
25836
- logger$5.log('Initializing click tracking');
25864
+ logger$6.log('Initializing click tracking');
25837
25865
 
25838
25866
  this.listenerClick = function(ev) {
25839
25867
  if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
@@ -25841,7 +25869,7 @@ define((function () { 'use strict';
25841
25869
  }
25842
25870
  this.trackDomEvent(ev, MP_EV_CLICK);
25843
25871
  }.bind(this);
25844
- win.addEventListener(EV_CLICK, this.listenerClick);
25872
+ win.addEventListener(EV_CLICK, this.listenerClick, true);
25845
25873
  };
25846
25874
 
25847
25875
  Autocapture.prototype.initDeadClickTracking = function() {
@@ -25852,7 +25880,7 @@ define((function () { 'use strict';
25852
25880
  return;
25853
25881
  }
25854
25882
 
25855
- logger$5.log('Initializing dead click tracking');
25883
+ logger$6.log('Initializing dead click tracking');
25856
25884
  if (!this._deadClickTracker) {
25857
25885
  this._deadClickTracker = new DeadClickTracker(function(deadClickEvent) {
25858
25886
  this.trackDomEvent(deadClickEvent, MP_EV_DEAD_CLICK);
@@ -25876,17 +25904,17 @@ define((function () { 'use strict';
25876
25904
  }
25877
25905
  this._deadClickTracker.trackClick(ev, normalizedConfig);
25878
25906
  }.bind(this);
25879
- win.addEventListener(EV_CLICK, this.listenerDeadClick);
25907
+ win.addEventListener(EV_CLICK, this.listenerDeadClick, true);
25880
25908
  }
25881
25909
  };
25882
25910
 
25883
25911
  Autocapture.prototype.initInputTracking = function() {
25884
- win.removeEventListener(EV_CHANGE, this.listenerChange);
25912
+ win.removeEventListener(EV_CHANGE, this.listenerChange, true);
25885
25913
 
25886
25914
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
25887
25915
  return;
25888
25916
  }
25889
- logger$5.log('Initializing input tracking');
25917
+ logger$6.log('Initializing input tracking');
25890
25918
 
25891
25919
  this.listenerChange = function(ev) {
25892
25920
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -25894,20 +25922,21 @@ define((function () { 'use strict';
25894
25922
  }
25895
25923
  this.trackDomEvent(ev, MP_EV_INPUT);
25896
25924
  }.bind(this);
25897
- win.addEventListener(EV_CHANGE, this.listenerChange);
25925
+ win.addEventListener(EV_CHANGE, this.listenerChange, true);
25898
25926
  };
25899
25927
 
25900
25928
  Autocapture.prototype.initPageviewTracking = function() {
25901
25929
  win.removeEventListener(EV_MP_LOCATION_CHANGE, this.listenerLocationchange);
25902
25930
 
25903
- if (!this.pageviewTrackingConfig()) {
25931
+ if (!this.pageviewTrackingConfig() && !this.mp.get_config('record_heatmap_data')) {
25904
25932
  return;
25905
25933
  }
25906
- logger$5.log('Initializing pageview tracking');
25934
+ logger$6.log('Initializing pageview tracking');
25907
25935
 
25908
25936
  var previousTrackedUrl = '';
25909
25937
  var tracked = false;
25910
- if (!this.currentUrlBlocked()) {
25938
+ // Track initial pageview if pageview tracking enabled OR heatmap recording is active
25939
+ if ((this.pageviewTrackingConfig() || this.mp.is_recording_heatmap_data()) && !this.currentUrlBlocked()) {
25911
25940
  tracked = this.mp.track_pageview(DEFAULT_PROPS);
25912
25941
  }
25913
25942
  if (tracked) {
@@ -25923,6 +25952,10 @@ define((function () { 'use strict';
25923
25952
  var shouldTrack = false;
25924
25953
  var didPathChange = currentUrl.split('#')[0].split('?')[0] !== previousTrackedUrl.split('#')[0].split('?')[0];
25925
25954
  var trackPageviewOption = this.pageviewTrackingConfig();
25955
+ if (!trackPageviewOption && this.mp.is_recording_heatmap_data()) {
25956
+ trackPageviewOption = PAGEVIEW_OPTION_FULL_URL;
25957
+ }
25958
+
25926
25959
  if (trackPageviewOption === PAGEVIEW_OPTION_FULL_URL) {
25927
25960
  shouldTrack = currentUrl !== previousTrackedUrl;
25928
25961
  } else if (trackPageviewOption === PAGEVIEW_OPTION_URL_WITH_PATH_AND_QUERY_STRING) {
@@ -25938,7 +25971,7 @@ define((function () { 'use strict';
25938
25971
  }
25939
25972
  if (didPathChange) {
25940
25973
  this.lastScrollCheckpoint = 0;
25941
- logger$5.log('Path change: re-initializing scroll depth checkpoints');
25974
+ logger$6.log('Path change: re-initializing scroll depth checkpoints');
25942
25975
  }
25943
25976
  }
25944
25977
  }.bind(this));
@@ -25946,14 +25979,14 @@ define((function () { 'use strict';
25946
25979
  };
25947
25980
 
25948
25981
  Autocapture.prototype.initRageClickTracking = function() {
25949
- win.removeEventListener(EV_CLICK, this.listenerRageClick);
25982
+ win.removeEventListener(EV_CLICK, this.listenerRageClick, true);
25950
25983
 
25951
25984
  var rageClickConfig = this._getClickTrackingConfig(CONFIG_TRACK_RAGE_CLICK);
25952
25985
  if (!rageClickConfig && !this.mp.get_config('record_heatmap_data')) {
25953
25986
  return;
25954
25987
  }
25955
25988
 
25956
- logger$5.log('Initializing rage click tracking');
25989
+ logger$6.log('Initializing rage click tracking');
25957
25990
  if (!this._rageClickTracker) {
25958
25991
  this._rageClickTracker = new RageClickTracker();
25959
25992
  }
@@ -25972,7 +26005,7 @@ define((function () { 'use strict';
25972
26005
  this.trackDomEvent(ev, MP_EV_RAGE_CLICK);
25973
26006
  }
25974
26007
  }.bind(this);
25975
- win.addEventListener(EV_CLICK, this.listenerRageClick);
26008
+ win.addEventListener(EV_CLICK, this.listenerRageClick, true);
25976
26009
  };
25977
26010
 
25978
26011
  Autocapture.prototype.initScrollTracking = function() {
@@ -25983,7 +26016,7 @@ define((function () { 'use strict';
25983
26016
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
25984
26017
  return;
25985
26018
  }
25986
- logger$5.log('Initializing scroll tracking');
26019
+ logger$6.log('Initializing scroll tracking');
25987
26020
  this.lastScrollCheckpoint = 0;
25988
26021
 
25989
26022
  var scrollTrackFunction = function() {
@@ -26020,7 +26053,7 @@ define((function () { 'use strict';
26020
26053
  }
26021
26054
  }
26022
26055
  } catch (err) {
26023
- logger$5.critical('Error while calculating scroll percentage', err);
26056
+ logger$6.critical('Error while calculating scroll percentage', err);
26024
26057
  }
26025
26058
  if (shouldTrack) {
26026
26059
  this.mp.track(MP_EV_SCROLL, props);
@@ -26033,12 +26066,12 @@ define((function () { 'use strict';
26033
26066
  };
26034
26067
 
26035
26068
  Autocapture.prototype.initSubmitTracking = function() {
26036
- win.removeEventListener(EV_SUBMIT, this.listenerSubmit);
26069
+ win.removeEventListener(EV_SUBMIT, this.listenerSubmit, true);
26037
26070
 
26038
26071
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
26039
26072
  return;
26040
26073
  }
26041
- logger$5.log('Initializing submit tracking');
26074
+ logger$6.log('Initializing submit tracking');
26042
26075
 
26043
26076
  this.listenerSubmit = function(ev) {
26044
26077
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -26046,7 +26079,7 @@ define((function () { 'use strict';
26046
26079
  }
26047
26080
  this.trackDomEvent(ev, MP_EV_SUBMIT);
26048
26081
  }.bind(this);
26049
- win.addEventListener(EV_SUBMIT, this.listenerSubmit);
26082
+ win.addEventListener(EV_SUBMIT, this.listenerSubmit, true);
26050
26083
  };
26051
26084
 
26052
26085
  Autocapture.prototype.initPageLeaveTracking = function() {
@@ -26060,7 +26093,7 @@ define((function () { 'use strict';
26060
26093
  return;
26061
26094
  }
26062
26095
 
26063
- logger$5.log('Initializing page visibility tracking.');
26096
+ logger$6.log('Initializing page visibility tracking.');
26064
26097
  this._initScrollDepthTracking();
26065
26098
  var previousTrackedUrl = _.info.currentUrl();
26066
26099
 
@@ -26102,7 +26135,7 @@ define((function () { 'use strict';
26102
26135
 
26103
26136
  Autocapture.prototype.stopDeadClickTracking = function() {
26104
26137
  if (this.listenerDeadClick) {
26105
- win.removeEventListener(EV_CLICK, this.listenerDeadClick);
26138
+ win.removeEventListener(EV_CLICK, this.listenerDeadClick, true);
26106
26139
  this.listenerDeadClick = null;
26107
26140
  }
26108
26141
 
@@ -26145,10 +26178,183 @@ define((function () { 'use strict';
26145
26178
  return win[TARGETING_GLOBAL_NAME];
26146
26179
  };
26147
26180
 
26181
+ var logger$2 = console_with_prefix('flags');
26182
+
26183
+ var MIXPANEL_FLAGS_DB_NAME = 'mixpanelFlagsDb';
26184
+ var FLAGS_STORE_NAME = 'mixpanelFlags';
26185
+
26186
+ // Keeping these two properties closeby, as adding additional stores to a DB in IndexedDB requires a version increment
26187
+ var FLAGS_VERSION_DATA = { version: 1, storeNames: [FLAGS_STORE_NAME] };
26188
+
26189
+ var PERSISTED_VARIANTS_KEY_PREFIX = 'persisted_variants_for_';
26190
+ var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
26191
+
26192
+ var VariantLookupPolicy = Object.freeze({
26193
+ NETWORK_ONLY: 'networkOnly',
26194
+ NETWORK_FIRST: 'networkFirst',
26195
+ PERSISTENCE_UNTIL_NETWORK_SUCCESS: 'persistenceUntilNetworkSuccess'
26196
+ });
26197
+
26198
+ var VALID_POLICIES = [
26199
+ VariantLookupPolicy.NETWORK_ONLY,
26200
+ VariantLookupPolicy.NETWORK_FIRST,
26201
+ VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS
26202
+ ];
26203
+
26204
+ /**
26205
+ * Module for handling the storage and retrieval of persisted feature flag variants.
26206
+ */
26207
+ var FeatureFlagPersistence = function(persistenceConfig, token, isGloballyDisabled) {
26208
+ this.idb = new IDBStorageWrapper(MIXPANEL_FLAGS_DB_NAME, FLAGS_STORE_NAME, FLAGS_VERSION_DATA);
26209
+ this.persistenceConfig = persistenceConfig;
26210
+ this.persistedVariantsKey = PERSISTED_VARIANTS_KEY_PREFIX + token;
26211
+ this.isGloballyDisabled = isGloballyDisabled || function() { return false; };
26212
+ };
26213
+
26214
+ FeatureFlagPersistence.prototype.getPolicy = function() {
26215
+ if (this.isGloballyDisabled() || !this._isConfigValid()) {
26216
+ return VariantLookupPolicy.NETWORK_ONLY;
26217
+ }
26218
+ return this.persistenceConfig['variantLookupPolicy'];
26219
+ };
26220
+
26221
+ FeatureFlagPersistence.prototype.getTtlMs = function() {
26222
+ if (!this._isConfigValid()) {
26223
+ return DEFAULT_TTL_MS;
26224
+ }
26225
+ var configuredTtl = this.persistenceConfig['persistenceTtlMs'];
26226
+ return (configuredTtl === undefined || configuredTtl === null) ? DEFAULT_TTL_MS : configuredTtl;
26227
+ };
26228
+
26229
+ FeatureFlagPersistence.prototype._isConfigValid = function() {
26230
+ var config = this.persistenceConfig;
26231
+ if (!config) {
26232
+ return false;
26233
+ }
26234
+
26235
+ if (VALID_POLICIES.indexOf(config['variantLookupPolicy']) === -1) {
26236
+ logger$2.error('Invalid variantLookupPolicy:', config['variantLookupPolicy']);
26237
+ return false;
26238
+ }
26239
+
26240
+ if (config['persistenceTtlMs'] !== undefined &&
26241
+ config['persistenceTtlMs'] !== null &&
26242
+ config['persistenceTtlMs'] <= 0) {
26243
+ logger$2.error('If provided, persistenceTtlMs must be a positive number. Provided value:', config['persistenceTtlMs']);
26244
+ return false;
26245
+ }
26246
+
26247
+ return true;
26248
+ };
26249
+
26250
+ FeatureFlagPersistence.prototype.loadFlagsFromStorage = function(context) {
26251
+ var clearAndReturnNull = _.bind(function() {
26252
+ return this.clear().then(function() { return null; }).catch(function() { return null; });
26253
+ }, this);
26254
+
26255
+ if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
26256
+ return clearAndReturnNull();
26257
+ }
26258
+
26259
+ var ttlMs = this.getTtlMs();
26260
+
26261
+ return this.idb.init().then(_.bind(function() {
26262
+ return this.idb.getItem(this.persistedVariantsKey);
26263
+ }, this)).then(_.bind(function(data) {
26264
+ if (!data) {
26265
+ logger$2.log('No persisted variants found in IndexedDB');
26266
+ return null;
26267
+ }
26268
+
26269
+ if (ttlMs && Date.now() - data['persistedAt'] >= ttlMs) {
26270
+ logger$2.log('Persisted variants are expiring');
26271
+ return null;
26272
+ }
26273
+
26274
+ if (!context || data['distinctId'] !== context['distinct_id']) {
26275
+ logger$2.log('Persisted variants found, but for a different distinct_id so clearing.');
26276
+ return clearAndReturnNull();
26277
+ }
26278
+
26279
+ var persistedFlags = new Map();
26280
+ _.each(data['flagVariants'], function(variantData, key) {
26281
+ persistedFlags.set(key, {
26282
+ 'key': variantData['variant_key'],
26283
+ 'value': variantData['variant_value'],
26284
+ 'experiment_id': variantData['experiment_id'],
26285
+ 'is_experiment_active': variantData['is_experiment_active'],
26286
+ 'is_qa_tester': variantData['is_qa_tester'],
26287
+ 'variant_source': 'persistence',
26288
+ 'persisted_at_in_ms': data['persistedAt'],
26289
+ 'ttl_in_ms': ttlMs
26290
+ });
26291
+ });
26292
+
26293
+ logger$2.log('Loaded', persistedFlags.size, 'variants from IndexedDB for distinct_id', data['distinctId']);
26294
+
26295
+ return {
26296
+ flags: persistedFlags,
26297
+ pendingFirstTimeEvents: data['pendingFirstTimeEvents'] || {},
26298
+ persistedAtMs: data['persistedAt'],
26299
+ ttlMs: ttlMs
26300
+ };
26301
+ }, this)).catch(_.bind(function(error) {
26302
+ logger$2.error('Failed to load persisted variants from IndexedDB, so clearing', error);
26303
+ return clearAndReturnNull();
26304
+ }, this));
26305
+ };
26306
+
26307
+ FeatureFlagPersistence.prototype.save = function(context, flagsMap, pendingFirstTimeEvents) {
26308
+ if (this.getPolicy() === VariantLookupPolicy.NETWORK_ONLY) {
26309
+ return Promise.resolve();
26310
+ }
26311
+
26312
+ var flagVariants = {};
26313
+ flagsMap.forEach(function(variant, key) {
26314
+ flagVariants[key] = {
26315
+ 'variant_key': variant['key'],
26316
+ 'variant_value': variant['value'],
26317
+ 'experiment_id': variant['experiment_id'],
26318
+ 'is_experiment_active': variant['is_experiment_active'],
26319
+ 'is_qa_tester': variant['is_qa_tester']
26320
+ };
26321
+ });
26322
+
26323
+ var data = {
26324
+ 'persistedAt': Date.now(),
26325
+ 'distinctId': context && context['distinct_id'],
26326
+ 'context': context,
26327
+ 'flagVariants': flagVariants,
26328
+ 'pendingFirstTimeEvents': pendingFirstTimeEvents || {}
26329
+ };
26330
+
26331
+ return this.idb.init().then(_.bind(function() {
26332
+ return this.idb.setItem(this.persistedVariantsKey, data);
26333
+ }, this)).then(function() {
26334
+ logger$2.log('Saved', flagsMap.size, 'variants to IndexedDB for distinct_id', data['distinctId']);
26335
+ }).catch(function(error) {
26336
+ logger$2.error('Failed to persist variants to IndexedDB:', error);
26337
+ });
26338
+ };
26339
+
26340
+ FeatureFlagPersistence.prototype.clear = function() {
26341
+ if (this.isGloballyDisabled()) {
26342
+ return Promise.resolve();
26343
+ }
26344
+ return this.idb.init().then(_.bind(function() {
26345
+ return this.idb.removeItem(this.persistedVariantsKey);
26346
+ }, this)).then(function() {
26347
+ logger$2.log('Cleared persisted variants from IndexedDB');
26348
+ }).catch(function(error) {
26349
+ logger$2.error('Failed to clear persisted variants from IndexedDB:', error);
26350
+ });
26351
+ };
26352
+
26148
26353
  var logger$1 = console_with_prefix('flags');
26149
26354
  var FLAGS_CONFIG_KEY = 'flags';
26150
26355
 
26151
26356
  var CONFIG_CONTEXT = 'context';
26357
+ var CONFIG_PERSISTENCE = 'persistence';
26152
26358
  var CONFIG_DEFAULTS = {};
26153
26359
  CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
26154
26360
 
@@ -26171,6 +26377,13 @@ define((function () { 'use strict';
26171
26377
  return eventKey.split(':')[0];
26172
26378
  };
26173
26379
 
26380
+ var withFallbackSource = function(fallback) {
26381
+ if (_.isObject(fallback)) {
26382
+ return _.extend({}, fallback, {'variant_source': 'fallback'});
26383
+ }
26384
+ return {'value': fallback, 'variant_source': 'fallback'};
26385
+ };
26386
+
26174
26387
  /**
26175
26388
  * FeatureFlagManager: support for Mixpanel's feature flagging product
26176
26389
  * @constructor
@@ -26193,13 +26406,63 @@ define((function () { 'use strict';
26193
26406
  }
26194
26407
 
26195
26408
  this.flags = null;
26196
- this.fetchFlags().catch(function() {
26197
- logger$1.error('Error fetching flags during init');
26198
- });
26199
-
26200
26409
  this.trackedFeatures = new Set();
26201
26410
  this.pendingFirstTimeEvents = {};
26202
26411
  this.activatedFirstTimeEvents = {};
26412
+ this._loadedPersistedAtMs = null;
26413
+ this._loadedTtlMs = null;
26414
+
26415
+ this.persistence = new FeatureFlagPersistence(
26416
+ this.getConfig(CONFIG_PERSISTENCE),
26417
+ this.getMpConfig('token'),
26418
+ _.bind(function() { return this.getMpConfig('disable_persistence'); }, this)
26419
+ );
26420
+
26421
+ this.persistenceLoadedPromise = this.persistence.loadFlagsFromStorage(this._buildContext())
26422
+ .then(_.bind(function(loaded) {
26423
+ if (loaded) {
26424
+ this.flags = loaded.flags;
26425
+ this.pendingFirstTimeEvents = loaded.pendingFirstTimeEvents;
26426
+ this._loadedPersistedAtMs = loaded.persistedAtMs;
26427
+ this._loadedTtlMs = loaded.ttlMs;
26428
+ }
26429
+ }, this));
26430
+
26431
+ return this.persistenceLoadedPromise
26432
+ .then(_.bind(function() {
26433
+ return this.fetchFlags();
26434
+ }, this))
26435
+ .catch(function() {
26436
+ logger$1.error('Error initializing feature flags');
26437
+ });
26438
+ };
26439
+
26440
+ FeatureFlagManager.prototype._buildContext = function() {
26441
+ return _.extend(
26442
+ {'distinct_id': this.getMpProperty('distinct_id'), 'device_id': this.getMpProperty('$device_id')},
26443
+ this.getConfig(CONFIG_CONTEXT)
26444
+ );
26445
+ };
26446
+
26447
+ FeatureFlagManager.prototype.reset = function() {
26448
+ if (!this.persistence) {
26449
+ return Promise.resolve();
26450
+ }
26451
+
26452
+ this.flags = null;
26453
+ this.pendingFirstTimeEvents = {};
26454
+ this.activatedFirstTimeEvents = {};
26455
+ this.trackedFeatures = new Set();
26456
+ this.fetchPromise = null;
26457
+ this._fetchInProgressStartTime = null;
26458
+ this._loadedPersistedAtMs = null;
26459
+ this._loadedTtlMs = null;
26460
+
26461
+ return this.persistence.clear().then(_.bind(function() {
26462
+ return this.fetchFlags();
26463
+ }, this)).catch(function() {
26464
+ logger$1.error('Error during flags reset');
26465
+ });
26203
26466
  };
26204
26467
 
26205
26468
  FeatureFlagManager.prototype.getFullConfig = function() {
@@ -26256,12 +26519,11 @@ define((function () { 'use strict';
26256
26519
  return Promise.resolve();
26257
26520
  }
26258
26521
 
26259
- var distinctId = this.getMpProperty('distinct_id');
26260
- var deviceId = this.getMpProperty('$device_id');
26522
+ var context = this._buildContext();
26523
+ var distinctId = context['distinct_id'];
26261
26524
  var traceparent = generateTraceparent();
26262
26525
  logger$1.log('Fetching flags for distinct ID: ' + distinctId);
26263
26526
 
26264
- var context = _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT));
26265
26527
  var searchParams = new URLSearchParams();
26266
26528
  searchParams.set('context', JSON.stringify(context));
26267
26529
  searchParams.set('token', this.getMpConfig('token'));
@@ -26311,7 +26573,8 @@ define((function () { 'use strict';
26311
26573
  'value': data['variant_value'],
26312
26574
  'experiment_id': data['experiment_id'],
26313
26575
  'is_experiment_active': data['is_experiment_active'],
26314
- 'is_qa_tester': data['is_qa_tester']
26576
+ 'is_qa_tester': data['is_qa_tester'],
26577
+ 'variant_source': 'network'
26315
26578
  });
26316
26579
  }
26317
26580
  }, this);
@@ -26353,10 +26616,15 @@ define((function () { 'use strict';
26353
26616
  }
26354
26617
 
26355
26618
  this.flags = flags;
26619
+ this.trackedFeatures = new Set();
26356
26620
  this.pendingFirstTimeEvents = pendingFirstTimeEvents;
26621
+ this._loadedPersistedAtMs = null;
26622
+ this._loadedTtlMs = null;
26357
26623
  this._traceparent = traceparent;
26358
26624
 
26359
26625
  this._loadTargetingIfNeeded();
26626
+
26627
+ this.persistence.save(context, this.flags, this.pendingFirstTimeEvents);
26360
26628
  }.bind(this)).catch(function(error) {
26361
26629
  if (this._fetchInProgressStartTime) {
26362
26630
  this.markFetchComplete();
@@ -26516,6 +26784,7 @@ define((function () { 'use strict';
26516
26784
  };
26517
26785
 
26518
26786
  this.flags.set(flagKey, newVariant);
26787
+ this.trackedFeatures.delete(flagKey);
26519
26788
  this.activatedFirstTimeEvents[eventKey] = true;
26520
26789
 
26521
26790
  this.recordFirstTimeEvent(
@@ -26527,8 +26796,8 @@ define((function () { 'use strict';
26527
26796
  };
26528
26797
 
26529
26798
  FeatureFlagManager.prototype.getFirstTimeEventApiRoute = function(flagId) {
26530
- // Construct URL: {api_host}/flags/{flagId}/first-time-events
26531
- return this.getFullApiRoute() + '/' + flagId + '/first-time-events';
26799
+ var base = this.getFullApiRoute().replace(/\/$/, '');
26800
+ return base + '/' + flagId + '/first-time-events';
26532
26801
  };
26533
26802
 
26534
26803
  FeatureFlagManager.prototype.recordFirstTimeEvent = function(flagId, projectId, firstTimeEventHash) {
@@ -26565,35 +26834,106 @@ define((function () { 'use strict';
26565
26834
  };
26566
26835
 
26567
26836
  FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
26568
- if (!this.fetchPromise) {
26837
+ if (!this.persistenceLoadedPromise) {
26569
26838
  return new Promise(function(resolve) {
26570
26839
  logger$1.critical('Feature Flags not initialized');
26571
- resolve(fallback);
26840
+ resolve(withFallbackSource(fallback));
26572
26841
  });
26573
26842
  }
26574
26843
 
26575
- return this.fetchPromise.then(function() {
26576
- return this.getVariantSync(featureName, fallback);
26577
- }.bind(this)).catch(function(error) {
26578
- logger$1.error(error);
26579
- return fallback;
26580
- });
26844
+ var policy = this.persistence.getPolicy();
26845
+
26846
+ return this.persistenceLoadedPromise.then(_.bind(function() {
26847
+ // Serve from persistence until the network completes a successful fetch. If a non-expired cached value is available, return it without waiting on the in-flight fetch.
26848
+ if (policy === VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS) {
26849
+ if (this.areFlagsReady() && !this._loadedPersistenceIsStale()) {
26850
+ return this.getVariantSync(featureName, fallback);
26851
+ }
26852
+ if (!this.fetchPromise) {
26853
+ return withFallbackSource(fallback);
26854
+ }
26855
+ return this.fetchPromise.then(_.bind(function() {
26856
+ return this.getVariantSync(featureName, fallback);
26857
+ }, this)).catch(function(error) {
26858
+ logger$1.error(error);
26859
+ return withFallbackSource(fallback);
26860
+ });
26861
+ }
26862
+
26863
+ var serve = _.bind(function() { return this.getVariantSync(featureName, fallback); }, this);
26864
+ if (!this.fetchPromise) {
26865
+ return withFallbackSource(fallback);
26866
+ }
26867
+ return this.fetchPromise.then(serve).catch(serve);
26868
+ }, this));
26869
+ };
26870
+
26871
+ FeatureFlagManager.prototype._loadedPersistenceIsStale = function() {
26872
+ if (!this._loadedPersistedAtMs || !this._loadedTtlMs) {
26873
+ return false;
26874
+ }
26875
+ return Date.now() - this._loadedPersistedAtMs >= this._loadedTtlMs;
26581
26876
  };
26582
26877
 
26583
26878
  FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
26879
+ if (this._loadedPersistenceIsStale()) {
26880
+ logger$1.log('Loaded persisted variants are past TTL so returning fallback for "' + featureName + '"');
26881
+ return withFallbackSource(fallback);
26882
+ }
26584
26883
  if (!this.areFlagsReady()) {
26585
26884
  logger$1.log('Flags not loaded yet');
26586
- return fallback;
26885
+ return withFallbackSource(fallback);
26587
26886
  }
26588
26887
  var feature = this.flags.get(featureName);
26589
26888
  if (!feature) {
26590
26889
  logger$1.log('No flag found: "' + featureName + '"');
26591
- return fallback;
26890
+ return withFallbackSource(fallback);
26592
26891
  }
26593
26892
  this.trackFeatureCheck(featureName, feature);
26594
26893
  return feature;
26595
26894
  };
26596
26895
 
26896
+ FeatureFlagManager.prototype.getAllVariants = function() {
26897
+ if (!this.persistenceLoadedPromise) {
26898
+ logger$1.critical('Feature Flags not initialized');
26899
+ return Promise.resolve(new Map());
26900
+ }
26901
+
26902
+ var policy = this.persistence.getPolicy();
26903
+
26904
+ return this.persistenceLoadedPromise.then(_.bind(function() {
26905
+ // Serve from persistence until the network completes a successful fetch. If a non-expired cached value is available, return it without waiting on the in-flight fetch.
26906
+ if (policy === VariantLookupPolicy.PERSISTENCE_UNTIL_NETWORK_SUCCESS) {
26907
+ if (this.areFlagsReady() && !this._loadedPersistenceIsStale()) {
26908
+ return this.getAllVariantsSync();
26909
+ }
26910
+ if (!this.fetchPromise) {
26911
+ return new Map();
26912
+ }
26913
+ return this.fetchPromise.then(_.bind(function() {
26914
+ return this.getAllVariantsSync();
26915
+ }, this)).catch(function(error) {
26916
+ logger$1.error(error);
26917
+ return new Map();
26918
+ });
26919
+ }
26920
+
26921
+ var serve = _.bind(this.getAllVariantsSync, this);
26922
+ if (!this.fetchPromise) {
26923
+ return new Map();
26924
+ }
26925
+ return this.fetchPromise.then(serve).catch(serve);
26926
+ }, this));
26927
+ };
26928
+
26929
+ FeatureFlagManager.prototype.getAllVariantsSync = function() {
26930
+ if (this._loadedPersistenceIsStale()) {
26931
+ logger$1.log('Loaded persisted variants are past TTL so returning empty Map');
26932
+ return new Map();
26933
+ }
26934
+ return this.flags || new Map();
26935
+ };
26936
+
26597
26937
  FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackValue) {
26598
26938
  return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
26599
26939
  return feature['value'];
@@ -26632,6 +26972,10 @@ define((function () { 'use strict';
26632
26972
  return val;
26633
26973
  };
26634
26974
 
26975
+ function isPresent(v) {
26976
+ return v !== undefined && v !== null;
26977
+ }
26978
+
26635
26979
  FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
26636
26980
  if (this.trackedFeatures.has(featureName)) {
26637
26981
  return;
@@ -26642,21 +26986,30 @@ define((function () { 'use strict';
26642
26986
  'Experiment name': featureName,
26643
26987
  'Variant name': feature['key'],
26644
26988
  '$experiment_type': 'feature_flag',
26645
- 'Variant fetch start time': new Date(this._fetchStartTime).toISOString(),
26646
- 'Variant fetch complete time': new Date(this._fetchCompleteTime).toISOString(),
26989
+ 'Variant fetch start time': isPresent(this._fetchStartTime) ? new Date(this._fetchStartTime).toISOString() : null,
26990
+ 'Variant fetch complete time': isPresent(this._fetchCompleteTime) ? new Date(this._fetchCompleteTime).toISOString() : null,
26647
26991
  'Variant fetch latency (ms)': this._fetchLatency,
26648
26992
  'Variant fetch traceparent': this._traceparent,
26649
26993
  };
26650
26994
 
26651
- if (feature['experiment_id'] !== 'undefined') {
26995
+ if (isPresent(feature['experiment_id'])) {
26652
26996
  trackingProperties['$experiment_id'] = feature['experiment_id'];
26653
26997
  }
26654
- if (feature['is_experiment_active'] !== 'undefined') {
26998
+ if (isPresent(feature['is_experiment_active'])) {
26655
26999
  trackingProperties['$is_experiment_active'] = feature['is_experiment_active'];
26656
27000
  }
26657
- if (feature['is_qa_tester'] !== 'undefined') {
27001
+ if (isPresent(feature['is_qa_tester'])) {
26658
27002
  trackingProperties['$is_qa_tester'] = feature['is_qa_tester'];
26659
27003
  }
27004
+ if (isPresent(feature['variant_source'])) {
27005
+ trackingProperties['$variant_source'] = feature['variant_source'];
27006
+ }
27007
+ if (isPresent(feature['persisted_at_in_ms'])) {
27008
+ trackingProperties['$persisted_at_in_ms'] = feature['persisted_at_in_ms'];
27009
+ }
27010
+ if (isPresent(feature['ttl_in_ms'])) {
27011
+ trackingProperties['$ttl_in_ms'] = feature['ttl_in_ms'];
27012
+ }
26660
27013
 
26661
27014
  this.track('$experiment_started', trackingProperties);
26662
27015
  };
@@ -26680,6 +27033,8 @@ define((function () { 'use strict';
26680
27033
  FeatureFlagManager.prototype['are_flags_ready'] = FeatureFlagManager.prototype.areFlagsReady;
26681
27034
  FeatureFlagManager.prototype['get_variant'] = FeatureFlagManager.prototype.getVariant;
26682
27035
  FeatureFlagManager.prototype['get_variant_sync'] = FeatureFlagManager.prototype.getVariantSync;
27036
+ FeatureFlagManager.prototype['get_all_variants'] = FeatureFlagManager.prototype.getAllVariants;
27037
+ FeatureFlagManager.prototype['get_all_variants_sync'] = FeatureFlagManager.prototype.getAllVariantsSync;
26683
27038
  FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype.getVariantValue;
26684
27039
  FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
26685
27040
  FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
@@ -26732,7 +27087,7 @@ define((function () { 'use strict';
26732
27087
  return PromisePolyfill.resolve(false);
26733
27088
  }
26734
27089
 
26735
- var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
27090
+ var recording_registry_idb = new IDBStorageWrapper(MIXPANEL_BROWSER_DB_NAME, RECORDING_REGISTRY_STORE_NAME, RECORDER_VERSION_DATA);
26736
27091
  var tab_id = this.getTabId();
26737
27092
  return recording_registry_idb.init()
26738
27093
  .then(function () {
@@ -28659,6 +29014,7 @@ define((function () { 'use strict';
28659
29014
  'disable_all_events': false,
28660
29015
  'identify_called': false
28661
29016
  };
29017
+ this._remote_settings_strict_disabled = false;
28662
29018
 
28663
29019
  // set up request queueing/batching
28664
29020
  this.request_batchers = {};
@@ -28733,9 +29089,6 @@ define((function () { 'use strict';
28733
29089
  this.flags.init();
28734
29090
  this['flags'] = this.flags;
28735
29091
 
28736
- this.autocapture = new Autocapture(this);
28737
- this.autocapture.init();
28738
-
28739
29092
  this._init_tab_id();
28740
29093
 
28741
29094
  // Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
@@ -28747,6 +29100,9 @@ define((function () { 'use strict';
28747
29100
  } else {
28748
29101
  this.__session_recording_init_promise = this._check_and_start_session_recording();
28749
29102
  }
29103
+
29104
+ this.autocapture = new Autocapture(this);
29105
+ this.autocapture.init();
28750
29106
  };
28751
29107
 
28752
29108
  /**
@@ -28793,9 +29149,19 @@ define((function () { 'use strict';
28793
29149
  return this.recorderManager.checkAndStartSessionRecording(force_start);
28794
29150
  });
28795
29151
 
28796
- MixpanelLib.prototype._start_recording_on_event = function(event_name, properties) {
28797
- return this.recorderManager.startRecordingOnEvent(event_name, properties);
28798
- };
29152
+ MixpanelLib.prototype._start_recording_on_event = safewrap(function(event_name, properties) {
29153
+ // Wait for recording init to complete before evaluating event triggers.
29154
+ // This ensures recording_event_triggers config is fully loaded when remote settings are used.
29155
+ if (this.__session_recording_init_promise) {
29156
+ this.__session_recording_init_promise.then(_.bind(function() {
29157
+ // In strict mode, skip recording if remote settings failed
29158
+ if (this._remote_settings_strict_disabled) {
29159
+ return;
29160
+ }
29161
+ return this.recorderManager.startRecordingOnEvent(event_name, properties);
29162
+ }, this));
29163
+ }
29164
+ });
28799
29165
 
28800
29166
  MixpanelLib.prototype.start_session_recording = function () {
28801
29167
  return this._check_and_start_session_recording(true);
@@ -29094,6 +29460,7 @@ define((function () { 'use strict';
29094
29460
  var disableRecordingIfStrict = function() {
29095
29461
  if (mode === 'strict') {
29096
29462
  self.set_config({'record_sessions_percent': 0});
29463
+ self._remote_settings_strict_disabled = true;
29097
29464
  }
29098
29465
  };
29099
29466
 
@@ -29719,6 +30086,10 @@ define((function () { 'use strict';
29719
30086
  properties
29720
30087
  );
29721
30088
 
30089
+ if (this.is_recording_heatmap_data()) {
30090
+ event_properties['$captured_for_heatmap'] = true;
30091
+ }
30092
+
29722
30093
  return this.track(event_name, event_properties);
29723
30094
  });
29724
30095
 
@@ -30062,6 +30433,7 @@ define((function () { 'use strict';
30062
30433
  '$device_id': uuid
30063
30434
  }, '');
30064
30435
  this._check_and_start_session_recording();
30436
+ this.flags.reset();
30065
30437
  };
30066
30438
 
30067
30439
  /**