mixpanel-browser 2.65.0 → 2.66.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/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ **2.66.0** (8 Jul 2025)
2
+ - Add `api_host` configuration option to support different hosts/proxies for different endpoints (thanks @chrisknu)
3
+ - Add types.d.ts from existing public repo
4
+ - Fix race condition when calling `mixpanel.reset()` while a session recording is active
5
+
1
6
  **2.65.0** (20 May 2025)
2
7
  - `mixpanel.people.track_charge()` (deprecated) no longer sets profile property
3
8
  - Adds page height and width tracking to autocapture click tracking
package/README.md CHANGED
@@ -78,4 +78,4 @@ Mixpanel production releases are tested against a large matrix of browsers and o
78
78
  - Publish to readme.io via the [rdme](https://www.npmjs.com/package/rdme) util: `RDME_API_KEY=<API_KEY> RDME_DOC_VERSION=<version> npm run dox-publish`
79
79
 
80
80
  ## Thanks
81
- For patches and support: @bohanyang, @dehau, @drubin, @D1plo1d, @feychenie, @mogstad, @pfhayes, @sandorfr, @stefansedich, @gfx, @pkaminski, @austince, @danielbaker, @mkdai, @wolever, @dpraul, @chriszamierowski, @JoaoGomesTW, @@aliyalcinkaya, @chrisdeely, @dylan-asos
81
+ For patches and support: @bohanyang, @dehau, @drubin, @D1plo1d, @feychenie, @mogstad, @pfhayes, @sandorfr, @stefansedich, @gfx, @pkaminski, @austince, @danielbaker, @mkdai, @wolever, @dpraul, @chriszamierowski, @JoaoGomesTW, @@aliyalcinkaya, @chrisdeely, @dylan-asos, @chrisknu
@@ -2,7 +2,7 @@
2
2
 
3
3
  var Config = {
4
4
  DEBUG: false,
5
- LIB_VERSION: '2.65.0'
5
+ LIB_VERSION: '2.66.0'
6
6
  };
7
7
 
8
8
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -4789,7 +4789,7 @@ MixpanelGroup.prototype._send_request = function(data, callback) {
4789
4789
  return this._mixpanel._track_or_batch({
4790
4790
  type: 'groups',
4791
4791
  data: date_encoded_data,
4792
- endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['groups'],
4792
+ endpoint: this._mixpanel.get_api_host('groups') + '/' + this._get_config('api_routes')['groups'],
4793
4793
  batcher: this._mixpanel.request_batchers.groups
4794
4794
  }, callback);
4795
4795
  };
@@ -5141,7 +5141,7 @@ MixpanelPeople.prototype._send_request = function(data, callback) {
5141
5141
  return this._mixpanel._track_or_batch({
5142
5142
  type: 'people',
5143
5143
  data: date_encoded_data,
5144
- endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['engage'],
5144
+ endpoint: this._mixpanel.get_api_host('people') + '/' + this._get_config('api_routes')['engage'],
5145
5145
  batcher: this._mixpanel.request_batchers.people
5146
5146
  }, callback);
5147
5147
  };
@@ -5901,6 +5901,7 @@ var DEFAULT_API_ROUTES = {
5901
5901
  */
5902
5902
  var DEFAULT_CONFIG = {
5903
5903
  'api_host': 'https://api-js.mixpanel.com',
5904
+ 'api_hosts': {},
5904
5905
  'api_routes': DEFAULT_API_ROUTES,
5905
5906
  'api_extra_query_params': {},
5906
5907
  'api_method': 'POST',
@@ -6286,20 +6287,23 @@ MixpanelLib.prototype.start_session_recording = function () {
6286
6287
 
6287
6288
  MixpanelLib.prototype.stop_session_recording = function () {
6288
6289
  if (this._recorder) {
6289
- this._recorder['stopRecording']();
6290
+ return this._recorder['stopRecording']();
6290
6291
  }
6292
+ return Promise.resolve();
6291
6293
  };
6292
6294
 
6293
6295
  MixpanelLib.prototype.pause_session_recording = function () {
6294
6296
  if (this._recorder) {
6295
- this._recorder['pauseRecording']();
6297
+ return this._recorder['pauseRecording']();
6296
6298
  }
6299
+ return Promise.resolve();
6297
6300
  };
6298
6301
 
6299
6302
  MixpanelLib.prototype.resume_session_recording = function () {
6300
6303
  if (this._recorder) {
6301
- this._recorder['resumeRecording']();
6304
+ return this._recorder['resumeRecording']();
6302
6305
  }
6306
+ return Promise.resolve();
6303
6307
  };
6304
6308
 
6305
6309
  MixpanelLib.prototype.is_recording_heatmap_data = function () {
@@ -6899,7 +6903,7 @@ MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, pro
6899
6903
  var ret = this._track_or_batch({
6900
6904
  type: 'events',
6901
6905
  data: data,
6902
- endpoint: this.get_config('api_host') + '/' + this.get_config('api_routes')['track'],
6906
+ endpoint: this.get_api_host('events') + '/' + this.get_config('api_routes')['track'],
6903
6907
  batcher: this.request_batchers.events,
6904
6908
  should_send_immediately: should_send_immediately,
6905
6909
  send_request_options: options
@@ -7401,15 +7405,31 @@ MixpanelLib.prototype.identify = function(
7401
7405
  * Useful for clearing data when a user logs out.
7402
7406
  */
7403
7407
  MixpanelLib.prototype.reset = function() {
7404
- this['persistence'].clear();
7405
- this._flags.identify_called = false;
7406
- var uuid = _.UUID();
7407
- this.register_once({
7408
- 'distinct_id': DEVICE_ID_PREFIX + uuid,
7409
- '$device_id': uuid
7410
- }, '');
7411
- this.stop_session_recording();
7412
- this._check_and_start_session_recording();
7408
+ var self = this;
7409
+
7410
+ var reset = function () {
7411
+ self['persistence'].clear();
7412
+ self._flags.identify_called = false;
7413
+ var uuid = _.UUID();
7414
+ self.register_once({
7415
+ 'distinct_id': DEVICE_ID_PREFIX + uuid,
7416
+ '$device_id': uuid
7417
+ }, '');
7418
+ };
7419
+
7420
+ if (self._recorder) {
7421
+ self.stop_session_recording()
7422
+ .then(function () {
7423
+ reset();
7424
+ self._check_and_start_session_recording();
7425
+ })
7426
+ .catch(_.bind(function (err) {
7427
+ reset();
7428
+ this.report_error('Error restarting recording session', err);
7429
+ }, this));
7430
+ } else {
7431
+ reset();
7432
+ }
7413
7433
  };
7414
7434
 
7415
7435
  /**
@@ -7720,6 +7740,16 @@ MixpanelLib.prototype.get_property = function(property_name) {
7720
7740
  return this['persistence'].load_prop([property_name]);
7721
7741
  };
7722
7742
 
7743
+ /**
7744
+ * Get the API host for a specific endpoint type, falling back to the default api_host if not specified
7745
+ *
7746
+ * @param {String} endpoint_type The type of endpoint (e.g., "events", "people", "groups")
7747
+ * @returns {String} The API host to use for this endpoint
7748
+ */
7749
+ MixpanelLib.prototype.get_api_host = function(endpoint_type) {
7750
+ return this.get_config('api_hosts')[endpoint_type] || this.get_config('api_host');
7751
+ };
7752
+
7723
7753
  MixpanelLib.prototype.toString = function() {
7724
7754
  var name = this.get_config('name');
7725
7755
  if (name !== PRIMARY_INSTANCE_NAME) {
@@ -8015,6 +8045,7 @@ MixpanelLib.prototype['alias'] = MixpanelLib.protot
8015
8045
  MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
8016
8046
  MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
8017
8047
  MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
8048
+ MixpanelLib.prototype['get_api_host'] = MixpanelLib.prototype.get_api_host;
8018
8049
  MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
8019
8050
  MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
8020
8051
  MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
@@ -13944,7 +13944,7 @@
13944
13944
  }
13945
13945
 
13946
13946
  var Config = {
13947
- LIB_VERSION: '2.65.0'
13947
+ LIB_VERSION: '2.66.0'
13948
13948
  };
13949
13949
 
13950
13950
  /* eslint camelcase: "off", eqeqeq: "off" */
@@ -17167,8 +17167,8 @@
17167
17167
  retryAfter: response.headers.get('Retry-After')
17168
17168
  });
17169
17169
  }.bind(this);
17170
-
17171
- win['fetch'](this.getConfig('api_host') + '/' + this.getConfig('api_routes')['record'] + '?' + new URLSearchParams(reqParams), {
17170
+ var apiHost = (this._mixpanel.get_api_host && this._mixpanel.get_api_host('record')) || this.getConfig('api_host');
17171
+ win['fetch'](apiHost + '/' + this.getConfig('api_routes')['record'] + '?' + new URLSearchParams(reqParams), {
17172
17172
  'method': 'POST',
17173
17173
  'headers': {
17174
17174
  'Authorization': 'Basic ' + btoa(this.getConfig('token') + ':'),
@@ -17385,6 +17385,7 @@
17385
17385
  this._flushInactivePromise = this.recordingRegistry.flushInactiveRecordings();
17386
17386
 
17387
17387
  this.activeRecording = null;
17388
+ this.stopRecordingInProgress = false;
17388
17389
  };
17389
17390
 
17390
17391
  MixpanelRecorder.prototype.startRecording = function(options) {
@@ -17433,19 +17434,26 @@
17433
17434
  };
17434
17435
 
17435
17436
  MixpanelRecorder.prototype.stopRecording = function() {
17436
- var stopPromise = this._stopCurrentRecording(false);
17437
- this.recordingRegistry.clearActiveRecording();
17438
- this.activeRecording = null;
17439
- return stopPromise;
17437
+ // Prevents activeSerializedRecording from being reused when stopping the recording.
17438
+ this.stopRecordingInProgress = true;
17439
+ return this._stopCurrentRecording(false, true).then(function() {
17440
+ return this.recordingRegistry.clearActiveRecording();
17441
+ }.bind(this)).then(function() {
17442
+ this.stopRecordingInProgress = false;
17443
+ }.bind(this));
17440
17444
  };
17441
17445
 
17442
17446
  MixpanelRecorder.prototype.pauseRecording = function() {
17443
17447
  return this._stopCurrentRecording(false);
17444
17448
  };
17445
17449
 
17446
- MixpanelRecorder.prototype._stopCurrentRecording = function(skipFlush) {
17450
+ MixpanelRecorder.prototype._stopCurrentRecording = function(skipFlush, disableActiveRecording) {
17447
17451
  if (this.activeRecording) {
17448
- return this.activeRecording.stopRecording(skipFlush);
17452
+ var stopRecordingPromise = this.activeRecording.stopRecording(skipFlush);
17453
+ if (disableActiveRecording) {
17454
+ this.activeRecording = null;
17455
+ }
17456
+ return stopRecordingPromise;
17449
17457
  }
17450
17458
  return PromisePolyfill.resolve();
17451
17459
  };
@@ -17458,7 +17466,7 @@
17458
17466
 
17459
17467
  return this.recordingRegistry.getActiveRecording()
17460
17468
  .then(function (activeSerializedRecording) {
17461
- if (activeSerializedRecording) {
17469
+ if (activeSerializedRecording && !this.stopRecordingInProgress) {
17462
17470
  return this.startRecording({activeSerializedRecording: activeSerializedRecording});
17463
17471
  } else if (startNewIfInactive) {
17464
17472
  return this.startRecording({shouldStopBatcher: false});