mixpanel-browser 2.49.0 → 2.50.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.
@@ -1,21 +1,23 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
3
  typeof define === 'function' && define.amd ? define(factory) :
4
- (global.mixpanel = factory());
5
- }(this, function () { 'use strict';
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mixpanel = factory());
5
+ })(this, (function () { 'use strict';
6
6
 
7
7
  var Config = {
8
8
  DEBUG: false,
9
- LIB_VERSION: '2.49.0'
9
+ LIB_VERSION: '2.50.0'
10
10
  };
11
11
 
12
+ /* eslint camelcase: "off", eqeqeq: "off" */
13
+
12
14
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
13
- var window$1;
15
+ var win;
14
16
  if (typeof(window) === 'undefined') {
15
17
  var loc = {
16
18
  hostname: ''
17
19
  };
18
- window$1 = {
20
+ win = {
19
21
  navigator: { userAgent: '' },
20
22
  document: {
21
23
  location: loc,
@@ -25,32 +27,37 @@
25
27
  location: loc
26
28
  };
27
29
  } else {
28
- window$1 = window;
30
+ win = window;
29
31
  }
30
32
 
33
+ // Maximum allowed session recording length
34
+ var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours
35
+
31
36
  /*
32
37
  * Saved references to long variable names, so that closure compiler can
33
38
  * minimize file size.
34
39
  */
35
40
 
36
- var ArrayProto = Array.prototype;
37
- var FuncProto = Function.prototype;
38
- var ObjProto = Object.prototype;
39
- var slice = ArrayProto.slice;
40
- var toString = ObjProto.toString;
41
- var hasOwnProperty = ObjProto.hasOwnProperty;
42
- var windowConsole = window$1.console;
43
- var navigator = window$1.navigator;
44
- var document$1 = window$1.document;
45
- var windowOpera = window$1.opera;
46
- var screen = window$1.screen;
47
- var userAgent = navigator.userAgent;
48
- var nativeBind = FuncProto.bind;
49
- var nativeForEach = ArrayProto.forEach;
50
- var nativeIndexOf = ArrayProto.indexOf;
51
- var nativeMap = ArrayProto.map;
52
- var nativeIsArray = Array.isArray;
53
- var breaker = {};
41
+ var ArrayProto = Array.prototype,
42
+ FuncProto = Function.prototype,
43
+ ObjProto = Object.prototype,
44
+ slice = ArrayProto.slice,
45
+ toString = ObjProto.toString,
46
+ hasOwnProperty = ObjProto.hasOwnProperty,
47
+ windowConsole = win.console,
48
+ navigator = win.navigator,
49
+ document$1 = win.document,
50
+ windowOpera = win.opera,
51
+ screen = win.screen,
52
+ userAgent = navigator.userAgent;
53
+
54
+ var nativeBind = FuncProto.bind,
55
+ nativeForEach = ArrayProto.forEach,
56
+ nativeIndexOf = ArrayProto.indexOf,
57
+ nativeMap = ArrayProto.map,
58
+ nativeIsArray = Array.isArray,
59
+ breaker = {};
60
+
54
61
  var _ = {
55
62
  trim: function(str) {
56
63
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
@@ -840,8 +847,8 @@
840
847
  var T = function() {
841
848
  var time = 1 * new Date(); // cross-browser version of Date.now()
842
849
  var ticks;
843
- if (window$1.performance && window$1.performance.now) {
844
- ticks = window$1.performance.now();
850
+ if (win.performance && win.performance.now) {
851
+ ticks = win.performance.now();
845
852
  } else {
846
853
  // fall back to busy loop
847
854
  ticks = 0;
@@ -1627,7 +1634,7 @@
1627
1634
  },
1628
1635
 
1629
1636
  currentUrl: function() {
1630
- return window$1.location.href;
1637
+ return win.location.href;
1631
1638
  },
1632
1639
 
1633
1640
  properties: function(extra_props) {
@@ -1664,10 +1671,10 @@
1664
1671
  mpPageViewProperties: function() {
1665
1672
  return _.strip_empty_properties({
1666
1673
  'current_page_title': document$1.title,
1667
- 'current_domain': window$1.location.hostname,
1668
- 'current_url_path': window$1.location.pathname,
1669
- 'current_url_protocol': window$1.location.protocol,
1670
- 'current_url_search': window$1.location.search
1674
+ 'current_domain': win.location.hostname,
1675
+ 'current_url_path': win.location.pathname,
1676
+ 'current_url_protocol': win.location.protocol,
1677
+ 'current_url_search': win.location.search
1671
1678
  });
1672
1679
  }
1673
1680
  };
@@ -1705,8 +1712,7 @@
1705
1712
  return matches ? matches[0] : '';
1706
1713
  };
1707
1714
 
1708
- var JSONStringify = null;
1709
- var JSONParse = null;
1715
+ var JSONStringify = null, JSONParse = null;
1710
1716
  if (typeof JSON !== 'undefined') {
1711
1717
  JSONStringify = JSON.stringify;
1712
1718
  JSONParse = JSON.parse;
@@ -1727,6 +1733,8 @@
1727
1733
  _['info']['browserVersion'] = _.info.browserVersion;
1728
1734
  _['info']['properties'] = _.info.properties;
1729
1735
 
1736
+ /* eslint camelcase: "off" */
1737
+
1730
1738
  /**
1731
1739
  * DomTracker Object
1732
1740
  * @constructor
@@ -1876,8 +1884,6 @@
1876
1884
  }, 0);
1877
1885
  };
1878
1886
 
1879
- // eslint-disable-line camelcase
1880
-
1881
1887
  var logger$2 = console_with_prefix('lock');
1882
1888
 
1883
1889
  /**
@@ -2024,8 +2030,6 @@
2024
2030
  }
2025
2031
  };
2026
2032
 
2027
- // eslint-disable-line camelcase
2028
-
2029
2033
  var logger$1 = console_with_prefix('batch');
2030
2034
 
2031
2035
  /**
@@ -2303,8 +2307,6 @@
2303
2307
  this.storage.removeItem(this.storageKey);
2304
2308
  };
2305
2309
 
2306
- // eslint-disable-line camelcase
2307
-
2308
2310
  // maximum interval between request retries after exponential backoff
2309
2311
  var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
2310
2312
 
@@ -2599,6 +2601,19 @@
2599
2601
  }
2600
2602
  };
2601
2603
 
2604
+ /**
2605
+ * GDPR utils
2606
+ *
2607
+ * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection
2608
+ * and privacy for all individuals within the European Union. It addresses the export of personal
2609
+ * data outside the EU. The GDPR aims primarily to give control back to citizens and residents
2610
+ * over their personal data and to simplify the regulatory environment for international business
2611
+ * by unifying the regulation within the EU.
2612
+ *
2613
+ * This set of utilities is intended to enable opt in/out functionality in the Mixpanel JS SDK.
2614
+ * These functions are used internally by the SDK and are not intended to be publicly exposed.
2615
+ */
2616
+
2602
2617
  /**
2603
2618
  * A function used to track a Mixpanel event (e.g. MixpanelLib.track)
2604
2619
  * @callback trackFunction
@@ -2784,14 +2799,14 @@
2784
2799
  if (options && options.ignoreDnt) {
2785
2800
  return false;
2786
2801
  }
2787
- var win = (options && options.window) || window$1;
2788
- var nav = win['navigator'] || {};
2802
+ var win$1 = (options && options.window) || win;
2803
+ var nav = win$1['navigator'] || {};
2789
2804
  var hasDntOn = false;
2790
2805
 
2791
2806
  _.each([
2792
2807
  nav['doNotTrack'], // standard
2793
2808
  nav['msDoNotTrack'],
2794
- win['doNotTrack']
2809
+ win$1['doNotTrack']
2795
2810
  ], function(dntValue) {
2796
2811
  if (_.includes([true, 1, '1', 'yes'], dntValue)) {
2797
2812
  hasDntOn = true;
@@ -2885,6 +2900,8 @@
2885
2900
  };
2886
2901
  }
2887
2902
 
2903
+ /* eslint camelcase: "off" */
2904
+
2888
2905
  /** @const */ var SET_ACTION = '$set';
2889
2906
  /** @const */ var SET_ONCE_ACTION = '$set_once';
2890
2907
  /** @const */ var UNSET_ACTION = '$unset';
@@ -3002,6 +3019,8 @@
3002
3019
  }
3003
3020
  };
3004
3021
 
3022
+ /* eslint camelcase: "off" */
3023
+
3005
3024
  /**
3006
3025
  * Mixpanel Group Object
3007
3026
  * @constructor
@@ -3170,6 +3189,8 @@
3170
3189
  MixpanelGroup.prototype['unset'] = MixpanelGroup.prototype.unset;
3171
3190
  MixpanelGroup.prototype['toString'] = MixpanelGroup.prototype.toString;
3172
3191
 
3192
+ /* eslint camelcase: "off" */
3193
+
3173
3194
  /**
3174
3195
  * Mixpanel People Object
3175
3196
  * @constructor
@@ -3638,6 +3659,8 @@
3638
3659
  MixpanelPeople.prototype['delete_user'] = MixpanelPeople.prototype.delete_user;
3639
3660
  MixpanelPeople.prototype['toString'] = MixpanelPeople.prototype.toString;
3640
3661
 
3662
+ /* eslint camelcase: "off" */
3663
+
3641
3664
  /*
3642
3665
  * Constants
3643
3666
  */
@@ -4087,6 +4110,8 @@
4087
4110
  return timestamp;
4088
4111
  };
4089
4112
 
4113
+ /* eslint camelcase: "off" */
4114
+
4090
4115
  /*
4091
4116
  * Mixpanel JS Library
4092
4117
  *
@@ -4133,7 +4158,7 @@
4133
4158
  */
4134
4159
  // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
4135
4160
  // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials
4136
- var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
4161
+ var USE_XHR = (win.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
4137
4162
 
4138
4163
  // IE<10 does not support cross-origin XHR's but script tags
4139
4164
  // with defer won't block window.onload; ENQUEUE_REQUESTS
@@ -4152,7 +4177,8 @@
4152
4177
  var DEFAULT_API_ROUTES = {
4153
4178
  'track': 'track/',
4154
4179
  'engage': 'engage/',
4155
- 'groups': 'groups/'
4180
+ 'groups': 'groups/',
4181
+ 'record': 'record/'
4156
4182
  };
4157
4183
 
4158
4184
  /*
@@ -4204,7 +4230,12 @@
4204
4230
  'batch_flush_interval_ms': 5000,
4205
4231
  'batch_request_timeout_ms': 90000,
4206
4232
  'batch_autostart': true,
4207
- 'hooks': {}
4233
+ 'hooks': {},
4234
+ 'record_sessions_percent': 0,
4235
+ 'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
4236
+ 'record_max_ms': MAX_RECORDING_MS,
4237
+ 'record_mask_text_selector': '*',
4238
+ 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
4208
4239
  };
4209
4240
 
4210
4241
  var DOM_LOADED = false;
@@ -4367,7 +4398,7 @@
4367
4398
  });
4368
4399
  } else {
4369
4400
  this.init_batchers();
4370
- if (sendBeacon && window$1.addEventListener) {
4401
+ if (sendBeacon && win.addEventListener) {
4371
4402
  // Before page closes or hides (user tabs away etc), attempt to flush any events
4372
4403
  // queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
4373
4404
  // events will not be removed from the persistent store; if the site is loaded again,
@@ -4384,12 +4415,12 @@
4384
4415
  this.request_batchers.events.flush({unloading: true});
4385
4416
  }
4386
4417
  }, this);
4387
- window$1.addEventListener('pagehide', function(ev) {
4418
+ win.addEventListener('pagehide', function(ev) {
4388
4419
  if (ev['persisted']) {
4389
4420
  flush_on_unload();
4390
4421
  }
4391
4422
  });
4392
- window$1.addEventListener('visibilitychange', function() {
4423
+ win.addEventListener('visibilitychange', function() {
4393
4424
  if (document$1['visibilityState'] === 'hidden') {
4394
4425
  flush_on_unload();
4395
4426
  }
@@ -4417,6 +4448,41 @@
4417
4448
  if (track_pageview_option) {
4418
4449
  this._init_url_change_tracking(track_pageview_option);
4419
4450
  }
4451
+
4452
+ if (this.get_config('record_sessions_percent') > 0 && Math.random() * 100 <= this.get_config('record_sessions_percent')) {
4453
+ this.start_session_recording();
4454
+ }
4455
+ };
4456
+
4457
+ MixpanelLib.prototype.start_session_recording = addOptOutCheckMixpanelLib(function () {
4458
+ if (!win['MutationObserver']) {
4459
+ console.critical('Browser does not support MutationObserver; skipping session recording');
4460
+ return;
4461
+ }
4462
+
4463
+ var handleLoadedRecorder = _.bind(function() {
4464
+ this._recorder = this._recorder || new win['__mp_recorder'](this);
4465
+ this._recorder['startRecording']();
4466
+ }, this);
4467
+
4468
+ if (_.isUndefined(win['__mp_recorder'])) {
4469
+ var scriptEl = document$1.createElement('script');
4470
+ scriptEl.type = 'text/javascript';
4471
+ scriptEl.async = true;
4472
+ scriptEl.onload = handleLoadedRecorder;
4473
+ scriptEl.src = this.get_config('recorder_src');
4474
+ document$1.head.appendChild(scriptEl);
4475
+ } else {
4476
+ handleLoadedRecorder();
4477
+ }
4478
+ });
4479
+
4480
+ MixpanelLib.prototype.stop_session_recording = function () {
4481
+ if (this._recorder) {
4482
+ this._recorder['stopRecording']();
4483
+ } else {
4484
+ console.critical('Session recorder module not loaded');
4485
+ }
4420
4486
  };
4421
4487
 
4422
4488
  // Private methods
@@ -4488,27 +4554,27 @@
4488
4554
  }
4489
4555
 
4490
4556
  if (_.include(['full-url', 'url-with-path-and-query-string', 'url-with-path'], track_pageview_option)) {
4491
- window$1.addEventListener('popstate', function() {
4492
- window$1.dispatchEvent(new Event('mp_locationchange'));
4557
+ win.addEventListener('popstate', function() {
4558
+ win.dispatchEvent(new Event('mp_locationchange'));
4493
4559
  });
4494
- window$1.addEventListener('hashchange', function() {
4495
- window$1.dispatchEvent(new Event('mp_locationchange'));
4560
+ win.addEventListener('hashchange', function() {
4561
+ win.dispatchEvent(new Event('mp_locationchange'));
4496
4562
  });
4497
- var nativePushState = window$1.history.pushState;
4563
+ var nativePushState = win.history.pushState;
4498
4564
  if (typeof nativePushState === 'function') {
4499
- window$1.history.pushState = function(state, unused, url) {
4500
- nativePushState.call(window$1.history, state, unused, url);
4501
- window$1.dispatchEvent(new Event('mp_locationchange'));
4565
+ win.history.pushState = function(state, unused, url) {
4566
+ nativePushState.call(win.history, state, unused, url);
4567
+ win.dispatchEvent(new Event('mp_locationchange'));
4502
4568
  };
4503
4569
  }
4504
- var nativeReplaceState = window$1.history.replaceState;
4570
+ var nativeReplaceState = win.history.replaceState;
4505
4571
  if (typeof nativeReplaceState === 'function') {
4506
- window$1.history.replaceState = function(state, unused, url) {
4507
- nativeReplaceState.call(window$1.history, state, unused, url);
4508
- window$1.dispatchEvent(new Event('mp_locationchange'));
4572
+ win.history.replaceState = function(state, unused, url) {
4573
+ nativeReplaceState.call(win.history, state, unused, url);
4574
+ win.dispatchEvent(new Event('mp_locationchange'));
4509
4575
  };
4510
4576
  }
4511
- window$1.addEventListener('mp_locationchange', function() {
4577
+ win.addEventListener('mp_locationchange', function() {
4512
4578
  var current_url = _.info.currentUrl();
4513
4579
  var should_track = false;
4514
4580
  if (track_pageview_option === 'full-url') {
@@ -4990,6 +5056,13 @@
4990
5056
  ? _.info.marketingParams()
4991
5057
  : {};
4992
5058
 
5059
+ if (this._recorder) {
5060
+ var replay_id = this._recorder['replayId'];
5061
+ if (replay_id) {
5062
+ properties['$mp_replay_id'] = replay_id;
5063
+ }
5064
+ }
5065
+
4993
5066
  // note: extend writes to the first object, so lets make sure we
4994
5067
  // don't write to the persistence properties object and info
4995
5068
  // properties object by passing in a new object
@@ -6139,6 +6212,8 @@
6139
6212
  MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
6140
6213
  MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
6141
6214
  MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6215
+ MixpanelLib.prototype['start_session_recording'] = MixpanelLib.prototype.start_session_recording;
6216
+ MixpanelLib.prototype['stop_session_recording'] = MixpanelLib.prototype.stop_session_recording;
6142
6217
  MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
6143
6218
 
6144
6219
  // MixpanelPersistence Exports
@@ -6186,7 +6261,7 @@
6186
6261
 
6187
6262
  mixpanel_master = instance;
6188
6263
  if (init_type === INIT_SNIPPET) {
6189
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
6264
+ win[PRIMARY_INSTANCE_NAME] = mixpanel_master;
6190
6265
  }
6191
6266
  extend_mp();
6192
6267
  }
@@ -6236,7 +6311,7 @@
6236
6311
  // check to make sure we arn't in a frame
6237
6312
  var toplevel = false;
6238
6313
  try {
6239
- toplevel = window$1.frameElement === null;
6314
+ toplevel = win.frameElement === null;
6240
6315
  } catch(e) {
6241
6316
  // noop
6242
6317
  }
@@ -6247,7 +6322,7 @@
6247
6322
  }
6248
6323
 
6249
6324
  // fallback handler, always will work
6250
- _.register_event(window$1, 'load', dom_loaded_handler, true);
6325
+ _.register_event(win, 'load', dom_loaded_handler, true);
6251
6326
  };
6252
6327
 
6253
6328
  function init_as_module() {
@@ -6261,8 +6336,10 @@
6261
6336
  return mixpanel_master;
6262
6337
  }
6263
6338
 
6339
+ /* eslint camelcase: "off" */
6340
+
6264
6341
  var mixpanel = init_as_module();
6265
6342
 
6266
6343
  return mixpanel;
6267
6344
 
6268
- }));
6345
+ }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixpanel-browser",
3
- "version": "2.49.0",
3
+ "version": "2.50.0",
4
4
  "description": "The official Mixpanel JavaScript browser client library",
5
5
  "main": "dist/mixpanel.cjs.js",
6
6
  "directories": {
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "homepage": "https://github.com/mixpanel/mixpanel-js",
34
34
  "devDependencies": {
35
+ "@rollup/plugin-node-resolve": "15.2.3",
35
36
  "babel": "6.5.2",
36
37
  "babel-core": "6.7.2",
37
38
  "babel-preset-es2015": "6.6.0",
@@ -51,10 +52,14 @@
51
52
  "morgan": "1.9.1",
52
53
  "rdme": "7.5.0",
53
54
  "request": "2.88.0",
54
- "rollup": "0.25.8",
55
+ "rollup": "2.79.1",
56
+ "rollup-plugin-esbuild": "4.10.3",
55
57
  "rollup-plugin-npm": "1.4.0",
56
58
  "sinon": "8.1.1",
57
59
  "sinon-chai": "3.5.0",
58
60
  "webpack": "1.12.2"
61
+ },
62
+ "dependencies": {
63
+ "rrweb": "2.0.0-alpha.4"
59
64
  }
60
65
  }
package/src/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var Config = {
2
2
  DEBUG: false,
3
- LIB_VERSION: '2.49.0'
3
+ LIB_VERSION: '2.50.0'
4
4
  };
5
5
 
6
6
  export default Config;
@@ -1,6 +1,6 @@
1
1
  /* eslint camelcase: "off" */
2
2
  import Config from './config';
3
- import { _, console, userAgent, window, document, navigator, slice } from './utils';
3
+ import { MAX_RECORDING_MS, _, console, userAgent, window, document, navigator, slice } from './utils';
4
4
  import { FormTracker, LinkTracker } from './dom-trackers';
5
5
  import { RequestBatcher } from './request-batcher';
6
6
  import { MixpanelGroup } from './mixpanel-group';
@@ -84,7 +84,8 @@ if (navigator['sendBeacon']) {
84
84
  var DEFAULT_API_ROUTES = {
85
85
  'track': 'track/',
86
86
  'engage': 'engage/',
87
- 'groups': 'groups/'
87
+ 'groups': 'groups/',
88
+ 'record': 'record/'
88
89
  };
89
90
 
90
91
  /*
@@ -136,7 +137,12 @@ var DEFAULT_CONFIG = {
136
137
  'batch_flush_interval_ms': 5000,
137
138
  'batch_request_timeout_ms': 90000,
138
139
  'batch_autostart': true,
139
- 'hooks': {}
140
+ 'hooks': {},
141
+ 'record_sessions_percent': 0,
142
+ 'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
143
+ 'record_max_ms': MAX_RECORDING_MS,
144
+ 'record_mask_text_selector': '*',
145
+ 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
140
146
  };
141
147
 
142
148
  var DOM_LOADED = false;
@@ -349,6 +355,41 @@ MixpanelLib.prototype._init = function(token, config, name) {
349
355
  if (track_pageview_option) {
350
356
  this._init_url_change_tracking(track_pageview_option);
351
357
  }
358
+
359
+ if (this.get_config('record_sessions_percent') > 0 && Math.random() * 100 <= this.get_config('record_sessions_percent')) {
360
+ this.start_session_recording();
361
+ }
362
+ };
363
+
364
+ MixpanelLib.prototype.start_session_recording = addOptOutCheckMixpanelLib(function () {
365
+ if (!window['MutationObserver']) {
366
+ console.critical('Browser does not support MutationObserver; skipping session recording');
367
+ return;
368
+ }
369
+
370
+ var handleLoadedRecorder = _.bind(function() {
371
+ this._recorder = this._recorder || new window['__mp_recorder'](this);
372
+ this._recorder['startRecording']();
373
+ }, this);
374
+
375
+ if (_.isUndefined(window['__mp_recorder'])) {
376
+ var scriptEl = document.createElement('script');
377
+ scriptEl.type = 'text/javascript';
378
+ scriptEl.async = true;
379
+ scriptEl.onload = handleLoadedRecorder;
380
+ scriptEl.src = this.get_config('recorder_src');
381
+ document.head.appendChild(scriptEl);
382
+ } else {
383
+ handleLoadedRecorder();
384
+ }
385
+ });
386
+
387
+ MixpanelLib.prototype.stop_session_recording = function () {
388
+ if (this._recorder) {
389
+ this._recorder['stopRecording']();
390
+ } else {
391
+ console.critical('Session recorder module not loaded');
392
+ }
352
393
  };
353
394
 
354
395
  // Private methods
@@ -922,6 +963,13 @@ MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, pro
922
963
  ? _.info.marketingParams()
923
964
  : {};
924
965
 
966
+ if (this._recorder) {
967
+ var replay_id = this._recorder['replayId'];
968
+ if (replay_id) {
969
+ properties['$mp_replay_id'] = replay_id;
970
+ }
971
+ }
972
+
925
973
  // note: extend writes to the first object, so lets make sure we
926
974
  // don't write to the persistence properties object and info
927
975
  // properties object by passing in a new object
@@ -2071,6 +2119,8 @@ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remov
2071
2119
  MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
2072
2120
  MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
2073
2121
  MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
2122
+ MixpanelLib.prototype['start_session_recording'] = MixpanelLib.prototype.start_session_recording;
2123
+ MixpanelLib.prototype['stop_session_recording'] = MixpanelLib.prototype.stop_session_recording;
2074
2124
  MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
2075
2125
 
2076
2126
  // MixpanelPersistence Exports