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.
@@ -3,16 +3,18 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.49.0'
6
+ LIB_VERSION: '2.50.0'
7
7
  };
8
8
 
9
+ /* eslint camelcase: "off", eqeqeq: "off" */
10
+
9
11
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
10
- var window$1;
12
+ var win;
11
13
  if (typeof(window) === 'undefined') {
12
14
  var loc = {
13
15
  hostname: ''
14
16
  };
15
- window$1 = {
17
+ win = {
16
18
  navigator: { userAgent: '' },
17
19
  document: {
18
20
  location: loc,
@@ -22,32 +24,37 @@
22
24
  location: loc
23
25
  };
24
26
  } else {
25
- window$1 = window;
27
+ win = window;
26
28
  }
27
29
 
30
+ // Maximum allowed session recording length
31
+ var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours
32
+
28
33
  /*
29
34
  * Saved references to long variable names, so that closure compiler can
30
35
  * minimize file size.
31
36
  */
32
37
 
33
- var ArrayProto = Array.prototype;
34
- var FuncProto = Function.prototype;
35
- var ObjProto = Object.prototype;
36
- var slice = ArrayProto.slice;
37
- var toString = ObjProto.toString;
38
- var hasOwnProperty = ObjProto.hasOwnProperty;
39
- var windowConsole = window$1.console;
40
- var navigator = window$1.navigator;
41
- var document$1 = window$1.document;
42
- var windowOpera = window$1.opera;
43
- var screen = window$1.screen;
44
- var userAgent = navigator.userAgent;
45
- var nativeBind = FuncProto.bind;
46
- var nativeForEach = ArrayProto.forEach;
47
- var nativeIndexOf = ArrayProto.indexOf;
48
- var nativeMap = ArrayProto.map;
49
- var nativeIsArray = Array.isArray;
50
- var breaker = {};
38
+ var ArrayProto = Array.prototype,
39
+ FuncProto = Function.prototype,
40
+ ObjProto = Object.prototype,
41
+ slice = ArrayProto.slice,
42
+ toString = ObjProto.toString,
43
+ hasOwnProperty = ObjProto.hasOwnProperty,
44
+ windowConsole = win.console,
45
+ navigator = win.navigator,
46
+ document$1 = win.document,
47
+ windowOpera = win.opera,
48
+ screen = win.screen,
49
+ userAgent = navigator.userAgent;
50
+
51
+ var nativeBind = FuncProto.bind,
52
+ nativeForEach = ArrayProto.forEach,
53
+ nativeIndexOf = ArrayProto.indexOf,
54
+ nativeMap = ArrayProto.map,
55
+ nativeIsArray = Array.isArray,
56
+ breaker = {};
57
+
51
58
  var _ = {
52
59
  trim: function(str) {
53
60
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
@@ -837,8 +844,8 @@
837
844
  var T = function() {
838
845
  var time = 1 * new Date(); // cross-browser version of Date.now()
839
846
  var ticks;
840
- if (window$1.performance && window$1.performance.now) {
841
- ticks = window$1.performance.now();
847
+ if (win.performance && win.performance.now) {
848
+ ticks = win.performance.now();
842
849
  } else {
843
850
  // fall back to busy loop
844
851
  ticks = 0;
@@ -1624,7 +1631,7 @@
1624
1631
  },
1625
1632
 
1626
1633
  currentUrl: function() {
1627
- return window$1.location.href;
1634
+ return win.location.href;
1628
1635
  },
1629
1636
 
1630
1637
  properties: function(extra_props) {
@@ -1661,10 +1668,10 @@
1661
1668
  mpPageViewProperties: function() {
1662
1669
  return _.strip_empty_properties({
1663
1670
  'current_page_title': document$1.title,
1664
- 'current_domain': window$1.location.hostname,
1665
- 'current_url_path': window$1.location.pathname,
1666
- 'current_url_protocol': window$1.location.protocol,
1667
- 'current_url_search': window$1.location.search
1671
+ 'current_domain': win.location.hostname,
1672
+ 'current_url_path': win.location.pathname,
1673
+ 'current_url_protocol': win.location.protocol,
1674
+ 'current_url_search': win.location.search
1668
1675
  });
1669
1676
  }
1670
1677
  };
@@ -1702,8 +1709,7 @@
1702
1709
  return matches ? matches[0] : '';
1703
1710
  };
1704
1711
 
1705
- var JSONStringify = null;
1706
- var JSONParse = null;
1712
+ var JSONStringify = null, JSONParse = null;
1707
1713
  if (typeof JSON !== 'undefined') {
1708
1714
  JSONStringify = JSON.stringify;
1709
1715
  JSONParse = JSON.parse;
@@ -1724,6 +1730,8 @@
1724
1730
  _['info']['browserVersion'] = _.info.browserVersion;
1725
1731
  _['info']['properties'] = _.info.properties;
1726
1732
 
1733
+ /* eslint camelcase: "off" */
1734
+
1727
1735
  /**
1728
1736
  * DomTracker Object
1729
1737
  * @constructor
@@ -1873,8 +1881,6 @@
1873
1881
  }, 0);
1874
1882
  };
1875
1883
 
1876
- // eslint-disable-line camelcase
1877
-
1878
1884
  var logger$2 = console_with_prefix('lock');
1879
1885
 
1880
1886
  /**
@@ -2021,8 +2027,6 @@
2021
2027
  }
2022
2028
  };
2023
2029
 
2024
- // eslint-disable-line camelcase
2025
-
2026
2030
  var logger$1 = console_with_prefix('batch');
2027
2031
 
2028
2032
  /**
@@ -2300,8 +2304,6 @@
2300
2304
  this.storage.removeItem(this.storageKey);
2301
2305
  };
2302
2306
 
2303
- // eslint-disable-line camelcase
2304
-
2305
2307
  // maximum interval between request retries after exponential backoff
2306
2308
  var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
2307
2309
 
@@ -2596,6 +2598,19 @@
2596
2598
  }
2597
2599
  };
2598
2600
 
2601
+ /**
2602
+ * GDPR utils
2603
+ *
2604
+ * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection
2605
+ * and privacy for all individuals within the European Union. It addresses the export of personal
2606
+ * data outside the EU. The GDPR aims primarily to give control back to citizens and residents
2607
+ * over their personal data and to simplify the regulatory environment for international business
2608
+ * by unifying the regulation within the EU.
2609
+ *
2610
+ * This set of utilities is intended to enable opt in/out functionality in the Mixpanel JS SDK.
2611
+ * These functions are used internally by the SDK and are not intended to be publicly exposed.
2612
+ */
2613
+
2599
2614
  /**
2600
2615
  * A function used to track a Mixpanel event (e.g. MixpanelLib.track)
2601
2616
  * @callback trackFunction
@@ -2781,14 +2796,14 @@
2781
2796
  if (options && options.ignoreDnt) {
2782
2797
  return false;
2783
2798
  }
2784
- var win = (options && options.window) || window$1;
2785
- var nav = win['navigator'] || {};
2799
+ var win$1 = (options && options.window) || win;
2800
+ var nav = win$1['navigator'] || {};
2786
2801
  var hasDntOn = false;
2787
2802
 
2788
2803
  _.each([
2789
2804
  nav['doNotTrack'], // standard
2790
2805
  nav['msDoNotTrack'],
2791
- win['doNotTrack']
2806
+ win$1['doNotTrack']
2792
2807
  ], function(dntValue) {
2793
2808
  if (_.includes([true, 1, '1', 'yes'], dntValue)) {
2794
2809
  hasDntOn = true;
@@ -2882,6 +2897,8 @@
2882
2897
  };
2883
2898
  }
2884
2899
 
2900
+ /* eslint camelcase: "off" */
2901
+
2885
2902
  /** @const */ var SET_ACTION = '$set';
2886
2903
  /** @const */ var SET_ONCE_ACTION = '$set_once';
2887
2904
  /** @const */ var UNSET_ACTION = '$unset';
@@ -2999,6 +3016,8 @@
2999
3016
  }
3000
3017
  };
3001
3018
 
3019
+ /* eslint camelcase: "off" */
3020
+
3002
3021
  /**
3003
3022
  * Mixpanel Group Object
3004
3023
  * @constructor
@@ -3167,6 +3186,8 @@
3167
3186
  MixpanelGroup.prototype['unset'] = MixpanelGroup.prototype.unset;
3168
3187
  MixpanelGroup.prototype['toString'] = MixpanelGroup.prototype.toString;
3169
3188
 
3189
+ /* eslint camelcase: "off" */
3190
+
3170
3191
  /**
3171
3192
  * Mixpanel People Object
3172
3193
  * @constructor
@@ -3635,6 +3656,8 @@
3635
3656
  MixpanelPeople.prototype['delete_user'] = MixpanelPeople.prototype.delete_user;
3636
3657
  MixpanelPeople.prototype['toString'] = MixpanelPeople.prototype.toString;
3637
3658
 
3659
+ /* eslint camelcase: "off" */
3660
+
3638
3661
  /*
3639
3662
  * Constants
3640
3663
  */
@@ -4084,6 +4107,8 @@
4084
4107
  return timestamp;
4085
4108
  };
4086
4109
 
4110
+ /* eslint camelcase: "off" */
4111
+
4087
4112
  /*
4088
4113
  * Mixpanel JS Library
4089
4114
  *
@@ -4130,7 +4155,7 @@
4130
4155
  */
4131
4156
  // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
4132
4157
  // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials
4133
- var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
4158
+ var USE_XHR = (win.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
4134
4159
 
4135
4160
  // IE<10 does not support cross-origin XHR's but script tags
4136
4161
  // with defer won't block window.onload; ENQUEUE_REQUESTS
@@ -4149,7 +4174,8 @@
4149
4174
  var DEFAULT_API_ROUTES = {
4150
4175
  'track': 'track/',
4151
4176
  'engage': 'engage/',
4152
- 'groups': 'groups/'
4177
+ 'groups': 'groups/',
4178
+ 'record': 'record/'
4153
4179
  };
4154
4180
 
4155
4181
  /*
@@ -4201,7 +4227,12 @@
4201
4227
  'batch_flush_interval_ms': 5000,
4202
4228
  'batch_request_timeout_ms': 90000,
4203
4229
  'batch_autostart': true,
4204
- 'hooks': {}
4230
+ 'hooks': {},
4231
+ 'record_sessions_percent': 0,
4232
+ 'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
4233
+ 'record_max_ms': MAX_RECORDING_MS,
4234
+ 'record_mask_text_selector': '*',
4235
+ 'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
4205
4236
  };
4206
4237
 
4207
4238
  var DOM_LOADED = false;
@@ -4364,7 +4395,7 @@
4364
4395
  });
4365
4396
  } else {
4366
4397
  this.init_batchers();
4367
- if (sendBeacon && window$1.addEventListener) {
4398
+ if (sendBeacon && win.addEventListener) {
4368
4399
  // Before page closes or hides (user tabs away etc), attempt to flush any events
4369
4400
  // queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
4370
4401
  // events will not be removed from the persistent store; if the site is loaded again,
@@ -4381,12 +4412,12 @@
4381
4412
  this.request_batchers.events.flush({unloading: true});
4382
4413
  }
4383
4414
  }, this);
4384
- window$1.addEventListener('pagehide', function(ev) {
4415
+ win.addEventListener('pagehide', function(ev) {
4385
4416
  if (ev['persisted']) {
4386
4417
  flush_on_unload();
4387
4418
  }
4388
4419
  });
4389
- window$1.addEventListener('visibilitychange', function() {
4420
+ win.addEventListener('visibilitychange', function() {
4390
4421
  if (document$1['visibilityState'] === 'hidden') {
4391
4422
  flush_on_unload();
4392
4423
  }
@@ -4414,6 +4445,41 @@
4414
4445
  if (track_pageview_option) {
4415
4446
  this._init_url_change_tracking(track_pageview_option);
4416
4447
  }
4448
+
4449
+ if (this.get_config('record_sessions_percent') > 0 && Math.random() * 100 <= this.get_config('record_sessions_percent')) {
4450
+ this.start_session_recording();
4451
+ }
4452
+ };
4453
+
4454
+ MixpanelLib.prototype.start_session_recording = addOptOutCheckMixpanelLib(function () {
4455
+ if (!win['MutationObserver']) {
4456
+ console.critical('Browser does not support MutationObserver; skipping session recording');
4457
+ return;
4458
+ }
4459
+
4460
+ var handleLoadedRecorder = _.bind(function() {
4461
+ this._recorder = this._recorder || new win['__mp_recorder'](this);
4462
+ this._recorder['startRecording']();
4463
+ }, this);
4464
+
4465
+ if (_.isUndefined(win['__mp_recorder'])) {
4466
+ var scriptEl = document$1.createElement('script');
4467
+ scriptEl.type = 'text/javascript';
4468
+ scriptEl.async = true;
4469
+ scriptEl.onload = handleLoadedRecorder;
4470
+ scriptEl.src = this.get_config('recorder_src');
4471
+ document$1.head.appendChild(scriptEl);
4472
+ } else {
4473
+ handleLoadedRecorder();
4474
+ }
4475
+ });
4476
+
4477
+ MixpanelLib.prototype.stop_session_recording = function () {
4478
+ if (this._recorder) {
4479
+ this._recorder['stopRecording']();
4480
+ } else {
4481
+ console.critical('Session recorder module not loaded');
4482
+ }
4417
4483
  };
4418
4484
 
4419
4485
  // Private methods
@@ -4485,27 +4551,27 @@
4485
4551
  }
4486
4552
 
4487
4553
  if (_.include(['full-url', 'url-with-path-and-query-string', 'url-with-path'], track_pageview_option)) {
4488
- window$1.addEventListener('popstate', function() {
4489
- window$1.dispatchEvent(new Event('mp_locationchange'));
4554
+ win.addEventListener('popstate', function() {
4555
+ win.dispatchEvent(new Event('mp_locationchange'));
4490
4556
  });
4491
- window$1.addEventListener('hashchange', function() {
4492
- window$1.dispatchEvent(new Event('mp_locationchange'));
4557
+ win.addEventListener('hashchange', function() {
4558
+ win.dispatchEvent(new Event('mp_locationchange'));
4493
4559
  });
4494
- var nativePushState = window$1.history.pushState;
4560
+ var nativePushState = win.history.pushState;
4495
4561
  if (typeof nativePushState === 'function') {
4496
- window$1.history.pushState = function(state, unused, url) {
4497
- nativePushState.call(window$1.history, state, unused, url);
4498
- window$1.dispatchEvent(new Event('mp_locationchange'));
4562
+ win.history.pushState = function(state, unused, url) {
4563
+ nativePushState.call(win.history, state, unused, url);
4564
+ win.dispatchEvent(new Event('mp_locationchange'));
4499
4565
  };
4500
4566
  }
4501
- var nativeReplaceState = window$1.history.replaceState;
4567
+ var nativeReplaceState = win.history.replaceState;
4502
4568
  if (typeof nativeReplaceState === 'function') {
4503
- window$1.history.replaceState = function(state, unused, url) {
4504
- nativeReplaceState.call(window$1.history, state, unused, url);
4505
- window$1.dispatchEvent(new Event('mp_locationchange'));
4569
+ win.history.replaceState = function(state, unused, url) {
4570
+ nativeReplaceState.call(win.history, state, unused, url);
4571
+ win.dispatchEvent(new Event('mp_locationchange'));
4506
4572
  };
4507
4573
  }
4508
- window$1.addEventListener('mp_locationchange', function() {
4574
+ win.addEventListener('mp_locationchange', function() {
4509
4575
  var current_url = _.info.currentUrl();
4510
4576
  var should_track = false;
4511
4577
  if (track_pageview_option === 'full-url') {
@@ -4987,6 +5053,13 @@
4987
5053
  ? _.info.marketingParams()
4988
5054
  : {};
4989
5055
 
5056
+ if (this._recorder) {
5057
+ var replay_id = this._recorder['replayId'];
5058
+ if (replay_id) {
5059
+ properties['$mp_replay_id'] = replay_id;
5060
+ }
5061
+ }
5062
+
4990
5063
  // note: extend writes to the first object, so lets make sure we
4991
5064
  // don't write to the persistence properties object and info
4992
5065
  // properties object by passing in a new object
@@ -6136,6 +6209,8 @@
6136
6209
  MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
6137
6210
  MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
6138
6211
  MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6212
+ MixpanelLib.prototype['start_session_recording'] = MixpanelLib.prototype.start_session_recording;
6213
+ MixpanelLib.prototype['stop_session_recording'] = MixpanelLib.prototype.stop_session_recording;
6139
6214
  MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
6140
6215
 
6141
6216
  // MixpanelPersistence Exports
@@ -6183,7 +6258,7 @@
6183
6258
 
6184
6259
  mixpanel_master = instance;
6185
6260
  if (init_type === INIT_SNIPPET) {
6186
- window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
6261
+ win[PRIMARY_INSTANCE_NAME] = mixpanel_master;
6187
6262
  }
6188
6263
  extend_mp();
6189
6264
  }
@@ -6233,7 +6308,7 @@
6233
6308
  // check to make sure we arn't in a frame
6234
6309
  var toplevel = false;
6235
6310
  try {
6236
- toplevel = window$1.frameElement === null;
6311
+ toplevel = win.frameElement === null;
6237
6312
  } catch(e) {
6238
6313
  // noop
6239
6314
  }
@@ -6244,12 +6319,12 @@
6244
6319
  }
6245
6320
 
6246
6321
  // fallback handler, always will work
6247
- _.register_event(window$1, 'load', dom_loaded_handler, true);
6322
+ _.register_event(win, 'load', dom_loaded_handler, true);
6248
6323
  };
6249
6324
 
6250
6325
  function init_from_snippet() {
6251
6326
  init_type = INIT_SNIPPET;
6252
- mixpanel_master = window$1[PRIMARY_INSTANCE_NAME];
6327
+ mixpanel_master = win[PRIMARY_INSTANCE_NAME];
6253
6328
 
6254
6329
  // Initialization
6255
6330
  if (_.isUndefined(mixpanel_master)) {
@@ -6287,6 +6362,8 @@
6287
6362
  add_dom_loaded_handler();
6288
6363
  }
6289
6364
 
6365
+ /* eslint camelcase: "off" */
6366
+
6290
6367
  init_from_snippet();
6291
6368
 
6292
- }());
6369
+ })();