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