mixpanel-browser 2.46.0 → 2.48.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.
@@ -6,7 +6,7 @@
6
6
 
7
7
  var Config = {
8
8
  DEBUG: false,
9
- LIB_VERSION: '2.46.0'
9
+ LIB_VERSION: '2.48.0'
10
10
  };
11
11
 
12
12
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -836,20 +836,24 @@
836
836
 
837
837
  _.UUID = (function() {
838
838
 
839
- // Time/ticks information
840
- // 1*new Date() is a cross browser version of Date.now()
839
+ // Time-based entropy
841
840
  var T = function() {
842
- var d = 1 * new Date(),
843
- i = 0;
844
-
845
- // this while loop figures how many browser ticks go by
846
- // before 1*new Date() returns a new number, ie the amount
847
- // of ticks that go by per millisecond
848
- while (d == 1 * new Date()) {
849
- i++;
841
+ var time = 1 * new Date(); // cross-browser version of Date.now()
842
+ var ticks;
843
+ if (window$1.performance && window$1.performance.now) {
844
+ ticks = window$1.performance.now();
845
+ } else {
846
+ // fall back to busy loop
847
+ ticks = 0;
848
+
849
+ // this while loop figures how many browser ticks go by
850
+ // before 1*new Date() returns a new number, ie the amount
851
+ // of ticks that go by per millisecond
852
+ while (time == 1 * new Date()) {
853
+ ticks++;
854
+ }
850
855
  }
851
-
852
- return d.toString(16) + i.toString(16);
856
+ return time.toString(16) + Math.floor(ticks).toString(16);
853
857
  };
854
858
 
855
859
  // Math.Random entropy
@@ -904,6 +908,7 @@
904
908
  'baiduspider',
905
909
  'bingbot',
906
910
  'bingpreview',
911
+ 'chrome-lighthouse',
907
912
  'facebookexternal',
908
913
  'petalbot',
909
914
  'pinterest',
@@ -1416,21 +1421,42 @@
1416
1421
  };
1417
1422
  })();
1418
1423
 
1424
+ var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
1425
+ var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid'];
1426
+
1419
1427
  _.info = {
1420
- campaignParams: function() {
1421
- var campaign_keywords = 'utm_source utm_medium utm_campaign utm_content utm_term'.split(' '),
1422
- kw = '',
1428
+ campaignParams: function(default_value) {
1429
+ var kw = '',
1423
1430
  params = {};
1424
- _.each(campaign_keywords, function(kwkey) {
1431
+ _.each(CAMPAIGN_KEYWORDS, function(kwkey) {
1425
1432
  kw = _.getQueryParam(document$1.URL, kwkey);
1426
1433
  if (kw.length) {
1427
1434
  params[kwkey] = kw;
1435
+ } else if (default_value !== undefined) {
1436
+ params[kwkey] = default_value;
1437
+ }
1438
+ });
1439
+
1440
+ return params;
1441
+ },
1442
+
1443
+ clickParams: function() {
1444
+ var id = '',
1445
+ params = {};
1446
+ _.each(CLICK_IDS, function(idkey) {
1447
+ id = _.getQueryParam(document$1.URL, idkey);
1448
+ if (id.length) {
1449
+ params[idkey] = id;
1428
1450
  }
1429
1451
  });
1430
1452
 
1431
1453
  return params;
1432
1454
  },
1433
1455
 
1456
+ marketingParams: function() {
1457
+ return _.extend(_.info.campaignParams(), _.info.clickParams());
1458
+ },
1459
+
1434
1460
  searchEngine: function(referrer) {
1435
1461
  if (referrer.search('https?://(.*)google.([^/?]*)') === 0) {
1436
1462
  return 'google';
@@ -1627,12 +1653,13 @@
1627
1653
  });
1628
1654
  },
1629
1655
 
1630
- pageviewInfo: function(page) {
1656
+ mpPageViewProperties: function() {
1631
1657
  return _.strip_empty_properties({
1632
- 'mp_page': page,
1633
- 'mp_referrer': document$1.referrer,
1634
- 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera),
1635
- 'mp_platform': _.info.os()
1658
+ 'current_page_title': document$1.title,
1659
+ 'current_domain': window$1.location.hostname,
1660
+ 'current_url_path': window$1.location.pathname,
1661
+ 'current_url_protocol': window$1.location.protocol,
1662
+ 'current_url_search': window$1.location.search
1636
1663
  });
1637
1664
  }
1638
1665
  };
@@ -3110,7 +3137,7 @@
3110
3137
  return this._mixpanel._track_or_batch({
3111
3138
  type: 'groups',
3112
3139
  data: date_encoded_data,
3113
- endpoint: this._get_config('api_host') + '/groups/',
3140
+ endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['groups'],
3114
3141
  batcher: this._mixpanel.request_batchers.groups
3115
3142
  }, callback);
3116
3143
  };
@@ -3471,7 +3498,7 @@
3471
3498
  return this._mixpanel._track_or_batch({
3472
3499
  type: 'people',
3473
3500
  data: date_encoded_data,
3474
- endpoint: this._get_config('api_host') + '/engage/',
3501
+ endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['engage'],
3475
3502
  batcher: this._mixpanel.request_batchers.people
3476
3503
  }, callback);
3477
3504
  };
@@ -3507,11 +3534,12 @@
3507
3534
 
3508
3535
  MixpanelPeople.prototype._flush_one_queue = function(action, action_method, callback, queue_to_params_fn) {
3509
3536
  var _this = this;
3510
- var queued_data = _.extend({}, this._mixpanel['persistence']._get_queue(action));
3537
+ var queued_data = _.extend({}, this._mixpanel['persistence'].load_queue(action));
3511
3538
  var action_params = queued_data;
3512
3539
 
3513
3540
  if (!_.isUndefined(queued_data) && _.isObject(queued_data) && !_.isEmptyObject(queued_data)) {
3514
3541
  _this._mixpanel['persistence']._pop_from_people_queue(action, queued_data);
3542
+ _this._mixpanel['persistence'].save();
3515
3543
  if (queue_to_params_fn) {
3516
3544
  action_params = queue_to_params_fn(queued_data);
3517
3545
  }
@@ -3533,8 +3561,6 @@
3533
3561
  _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
3534
3562
  ) {
3535
3563
  var _this = this;
3536
- var $append_queue = this._mixpanel['persistence']._get_queue(APPEND_ACTION);
3537
- var $remove_queue = this._mixpanel['persistence']._get_queue(REMOVE_ACTION);
3538
3564
 
3539
3565
  this._flush_one_queue(SET_ACTION, this.set, _set_callback);
3540
3566
  this._flush_one_queue(SET_ONCE_ACTION, this.set_once, _set_once_callback);
@@ -3544,6 +3570,7 @@
3544
3570
 
3545
3571
  // we have to fire off each $append individually since there is
3546
3572
  // no concat method server side
3573
+ var $append_queue = this._mixpanel['persistence'].load_queue(APPEND_ACTION);
3547
3574
  if (!_.isUndefined($append_queue) && _.isArray($append_queue) && $append_queue.length) {
3548
3575
  var $append_item;
3549
3576
  var append_callback = function(response, data) {
@@ -3555,16 +3582,17 @@
3555
3582
  }
3556
3583
  };
3557
3584
  for (var i = $append_queue.length - 1; i >= 0; i--) {
3585
+ $append_queue = this._mixpanel['persistence'].load_queue(APPEND_ACTION);
3558
3586
  $append_item = $append_queue.pop();
3587
+ _this._mixpanel['persistence'].save();
3559
3588
  if (!_.isEmptyObject($append_item)) {
3560
3589
  _this.append($append_item, append_callback);
3561
3590
  }
3562
3591
  }
3563
- // Save the shortened append queue
3564
- _this._mixpanel['persistence'].save();
3565
3592
  }
3566
3593
 
3567
3594
  // same for $remove
3595
+ var $remove_queue = this._mixpanel['persistence'].load_queue(REMOVE_ACTION);
3568
3596
  if (!_.isUndefined($remove_queue) && _.isArray($remove_queue) && $remove_queue.length) {
3569
3597
  var $remove_item;
3570
3598
  var remove_callback = function(response, data) {
@@ -3576,12 +3604,13 @@
3576
3604
  }
3577
3605
  };
3578
3606
  for (var j = $remove_queue.length - 1; j >= 0; j--) {
3607
+ $remove_queue = this._mixpanel['persistence'].load_queue(REMOVE_ACTION);
3579
3608
  $remove_item = $remove_queue.pop();
3609
+ _this._mixpanel['persistence'].save();
3580
3610
  if (!_.isEmptyObject($remove_item)) {
3581
3611
  _this.remove($remove_item, remove_callback);
3582
3612
  }
3583
3613
  }
3584
- _this._mixpanel['persistence'].save();
3585
3614
  }
3586
3615
  };
3587
3616
 
@@ -3663,6 +3692,9 @@
3663
3692
 
3664
3693
  MixpanelPersistence.prototype.properties = function() {
3665
3694
  var p = {};
3695
+
3696
+ this.load();
3697
+
3666
3698
  // Filter out reserved properties
3667
3699
  _.each(this['props'], function(v, k) {
3668
3700
  if (!_.include(RESERVED_PROPERTIES, k)) {
@@ -3739,6 +3771,7 @@
3739
3771
 
3740
3772
  MixpanelPersistence.prototype.save = function() {
3741
3773
  if (this.disabled) { return; }
3774
+
3742
3775
  this.storage.set(
3743
3776
  this.name,
3744
3777
  _.JSONEncode(this['props']),
@@ -3750,6 +3783,11 @@
3750
3783
  );
3751
3784
  };
3752
3785
 
3786
+ MixpanelPersistence.prototype.load_prop = function(key) {
3787
+ this.load();
3788
+ return this['props'][key];
3789
+ };
3790
+
3753
3791
  MixpanelPersistence.prototype.remove = function() {
3754
3792
  // remove both domain and subdomain cookies
3755
3793
  this.storage.remove(this.name, false, this.cookie_domain);
@@ -3773,6 +3811,8 @@
3773
3811
  if (typeof(default_value) === 'undefined') { default_value = 'None'; }
3774
3812
  this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
3775
3813
 
3814
+ this.load();
3815
+
3776
3816
  _.each(props, function(val, prop) {
3777
3817
  if (!this['props'].hasOwnProperty(prop) || this['props'][prop] === default_value) {
3778
3818
  this['props'][prop] = val;
@@ -3794,8 +3834,8 @@
3794
3834
  if (_.isObject(props)) {
3795
3835
  this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
3796
3836
 
3837
+ this.load();
3797
3838
  _.extend(this['props'], props);
3798
-
3799
3839
  this.save();
3800
3840
 
3801
3841
  return true;
@@ -3804,19 +3844,13 @@
3804
3844
  };
3805
3845
 
3806
3846
  MixpanelPersistence.prototype.unregister = function(prop) {
3847
+ this.load();
3807
3848
  if (prop in this['props']) {
3808
3849
  delete this['props'][prop];
3809
3850
  this.save();
3810
3851
  }
3811
3852
  };
3812
3853
 
3813
- MixpanelPersistence.prototype.update_campaign_params = function() {
3814
- if (!this.campaign_params_saved) {
3815
- this.register_once(_.info.campaignParams());
3816
- this.campaign_params_saved = true;
3817
- }
3818
- };
3819
-
3820
3854
  MixpanelPersistence.prototype.update_search_keyword = function(referrer) {
3821
3855
  this.register(_.info.searchInfo(referrer));
3822
3856
  };
@@ -3837,19 +3871,6 @@
3837
3871
  });
3838
3872
  };
3839
3873
 
3840
- // safely fills the passed in object with stored properties,
3841
- // does not override any properties defined in both
3842
- // returns the passed in object
3843
- MixpanelPersistence.prototype.safe_merge = function(props) {
3844
- _.each(this['props'], function(val, prop) {
3845
- if (!(prop in props)) {
3846
- props[prop] = val;
3847
- }
3848
- });
3849
-
3850
- return props;
3851
- };
3852
-
3853
3874
  MixpanelPersistence.prototype.update_config = function(config) {
3854
3875
  this.default_expiry = this.expire_days = config['cookie_expiration'];
3855
3876
  this.set_disabled(config['disable_persistence']);
@@ -3993,7 +4014,7 @@
3993
4014
  };
3994
4015
 
3995
4016
  MixpanelPersistence.prototype._pop_from_people_queue = function(queue, data) {
3996
- var q = this._get_queue(queue);
4017
+ var q = this['props'][this._get_queue_key(queue)];
3997
4018
  if (!_.isUndefined(q)) {
3998
4019
  _.each(data, function(v, k) {
3999
4020
  if (queue === APPEND_ACTION || queue === REMOVE_ACTION) {
@@ -4009,11 +4030,13 @@
4009
4030
  delete q[k];
4010
4031
  }
4011
4032
  }, this);
4012
-
4013
- this.save();
4014
4033
  }
4015
4034
  };
4016
4035
 
4036
+ MixpanelPersistence.prototype.load_queue = function(queue) {
4037
+ return this.load_prop(this._get_queue_key(queue));
4038
+ };
4039
+
4017
4040
  MixpanelPersistence.prototype._get_queue_key = function(queue) {
4018
4041
  if (queue === SET_ACTION) {
4019
4042
  return SET_QUEUE_KEY;
@@ -4034,25 +4057,21 @@
4034
4057
  }
4035
4058
  };
4036
4059
 
4037
- MixpanelPersistence.prototype._get_queue = function(queue) {
4038
- return this['props'][this._get_queue_key(queue)];
4039
- };
4040
4060
  MixpanelPersistence.prototype._get_or_create_queue = function(queue, default_val) {
4041
4061
  var key = this._get_queue_key(queue);
4042
4062
  default_val = _.isUndefined(default_val) ? {} : default_val;
4043
-
4044
4063
  return this['props'][key] || (this['props'][key] = default_val);
4045
4064
  };
4046
4065
 
4047
4066
  MixpanelPersistence.prototype.set_event_timer = function(event_name, timestamp) {
4048
- var timers = this['props'][EVENT_TIMERS_KEY] || {};
4067
+ var timers = this.load_prop(EVENT_TIMERS_KEY) || {};
4049
4068
  timers[event_name] = timestamp;
4050
4069
  this['props'][EVENT_TIMERS_KEY] = timers;
4051
4070
  this.save();
4052
4071
  };
4053
4072
 
4054
4073
  MixpanelPersistence.prototype.remove_event_timer = function(event_name) {
4055
- var timers = this['props'][EVENT_TIMERS_KEY] || {};
4074
+ var timers = this.load_prop(EVENT_TIMERS_KEY) || {};
4056
4075
  var timestamp = timers[event_name];
4057
4076
  if (!_.isUndefined(timestamp)) {
4058
4077
  delete this['props'][EVENT_TIMERS_KEY][event_name];
@@ -4123,11 +4142,18 @@
4123
4142
  };
4124
4143
  }
4125
4144
 
4145
+ var DEFAULT_API_ROUTES = {
4146
+ 'track': 'track/',
4147
+ 'engage': 'engage/',
4148
+ 'groups': 'groups/'
4149
+ };
4150
+
4126
4151
  /*
4127
4152
  * Module-level globals
4128
4153
  */
4129
4154
  var DEFAULT_CONFIG = {
4130
4155
  'api_host': 'https://api-js.mixpanel.com',
4156
+ 'api_routes': DEFAULT_API_ROUTES,
4131
4157
  'api_method': 'POST',
4132
4158
  'api_transport': 'XHR',
4133
4159
  'api_payload_format': PAYLOAD_TYPE_BASE64,
@@ -4141,6 +4167,9 @@
4141
4167
  'cookie_domain': '',
4142
4168
  'cookie_name': '',
4143
4169
  'loaded': NOOP_FUNC,
4170
+ 'track_marketing': true,
4171
+ 'track_pageview': false,
4172
+ 'skip_first_touch_marketing': false,
4144
4173
  'store_google': true,
4145
4174
  'save_referrer': true,
4146
4175
  'test': false,
@@ -4207,6 +4236,25 @@
4207
4236
  instance['people'] = new MixpanelPeople();
4208
4237
  instance['people']._init(instance);
4209
4238
 
4239
+ if (!instance.get_config('skip_first_touch_marketing')) {
4240
+ // We need null UTM params in the object because
4241
+ // UTM parameters act as a tuple. If any UTM param
4242
+ // is present, then we set all UTM params including
4243
+ // empty ones together
4244
+ var utm_params = _.info.campaignParams(null);
4245
+ var initial_utm_params = {};
4246
+ var has_utm = false;
4247
+ _.each(utm_params, function(utm_value, utm_key) {
4248
+ initial_utm_params['initial_' + utm_key] = utm_value;
4249
+ if (utm_value) {
4250
+ has_utm = true;
4251
+ }
4252
+ });
4253
+ if (has_utm) {
4254
+ instance['people'].set_once(initial_utm_params);
4255
+ }
4256
+ }
4257
+
4210
4258
  // if any instance on the page has debug = true, we set the
4211
4259
  // global debug to be true
4212
4260
  Config.DEBUG = Config.DEBUG || instance.get_config('debug');
@@ -4238,7 +4286,7 @@
4238
4286
  * mixpanel.library_name.track(...);
4239
4287
  *
4240
4288
  * @param {String} token Your Mixpanel API token
4241
- * @param {Object} [config] A dictionary of config options to override. <a href="https://github.com/mixpanel/mixpanel-js/blob/8b2e1f7b/src/mixpanel-core.js#L87-L110">See a list of default config options</a>.
4289
+ * @param {Object} [config] A dictionary of config options to override. <a href="https://github.com/mixpanel/mixpanel-js/blob/v2.46.0/src/mixpanel-core.js#L88-L127">See a list of default config options</a>.
4242
4290
  * @param {String} [name] The name for the new mixpanel instance that you want created
4243
4291
  */
4244
4292
  MixpanelLib.prototype.init = function (token, config, name) {
@@ -4276,7 +4324,7 @@
4276
4324
  // default to JSON payload for standard mixpanel.com API hosts
4277
4325
  if (!('api_payload_format' in config)) {
4278
4326
  var api_host = config['api_host'] || DEFAULT_CONFIG['api_host'];
4279
- if (api_host.match(/\.mixpanel\.com$/)) {
4327
+ if (api_host.match(/\.mixpanel\.com/)) {
4280
4328
  variable_features['api_payload_format'] = PAYLOAD_TYPE_JSON;
4281
4329
  }
4282
4330
  }
@@ -4304,6 +4352,10 @@
4304
4352
  if (!_.localStorage.is_supported(true) || !USE_XHR) {
4305
4353
  this._batch_requests = false;
4306
4354
  console.log('Turning off Mixpanel request-queueing; needs XHR and localStorage support');
4355
+ _.each(this.get_batcher_configs(), function(batcher_config) {
4356
+ console.log('Clearing batch queue ' + batcher_config.queue_key);
4357
+ _.localStorage.remove(batcher_config.queue_key);
4358
+ });
4307
4359
  } else {
4308
4360
  this.init_batchers();
4309
4361
  if (sendBeacon && window$1.addEventListener) {
@@ -4351,6 +4403,10 @@
4351
4403
  '$device_id': uuid
4352
4404
  }, '');
4353
4405
  }
4406
+
4407
+ if (this.get_config('track_pageview')) {
4408
+ this.track_pageview();
4409
+ }
4354
4410
  };
4355
4411
 
4356
4412
  // Private methods
@@ -4364,7 +4420,7 @@
4364
4420
  MixpanelLib.prototype._set_default_superprops = function() {
4365
4421
  this['persistence'].update_search_keyword(document$1.referrer);
4366
4422
  if (this.get_config('store_google')) {
4367
- this['persistence'].update_campaign_params();
4423
+ this.register(_.info.campaignParams(), {persistent: false});
4368
4424
  }
4369
4425
  if (this.get_config('save_referrer')) {
4370
4426
  this['persistence'].update_referrer_info(document$1.referrer);
@@ -4647,12 +4703,22 @@
4647
4703
  return !!this.request_batchers.events;
4648
4704
  };
4649
4705
 
4706
+ MixpanelLib.prototype.get_batcher_configs = function() {
4707
+ var queue_prefix = '__mpq_' + this.get_config('token');
4708
+ var api_routes = this.get_config('api_routes');
4709
+ this._batcher_configs = this._batcher_configs || {
4710
+ events: {type: 'events', endpoint: '/' + api_routes['track'], queue_key: queue_prefix + '_ev'},
4711
+ people: {type: 'people', endpoint: '/' + api_routes['engage'], queue_key: queue_prefix + '_pp'},
4712
+ groups: {type: 'groups', endpoint: '/' + api_routes['groups'], queue_key: queue_prefix + '_gr'}
4713
+ };
4714
+ return this._batcher_configs;
4715
+ };
4716
+
4650
4717
  MixpanelLib.prototype.init_batchers = function() {
4651
- var token = this.get_config('token');
4652
4718
  if (!this.are_batchers_initialized()) {
4653
4719
  var batcher_for = _.bind(function(attrs) {
4654
4720
  return new RequestBatcher(
4655
- '__mpq_' + token + attrs.queue_suffix,
4721
+ attrs.queue_key,
4656
4722
  {
4657
4723
  libConfig: this['config'],
4658
4724
  sendRequestFunc: _.bind(function(data, options, cb) {
@@ -4671,10 +4737,11 @@
4671
4737
  }
4672
4738
  );
4673
4739
  }, this);
4740
+ var batcher_configs = this.get_batcher_configs();
4674
4741
  this.request_batchers = {
4675
- events: batcher_for({type: 'events', endpoint: '/track/', queue_suffix: '_ev'}),
4676
- people: batcher_for({type: 'people', endpoint: '/engage/', queue_suffix: '_pp'}),
4677
- groups: batcher_for({type: 'groups', endpoint: '/groups/', queue_suffix: '_gr'})
4742
+ events: batcher_for(batcher_configs.events),
4743
+ people: batcher_for(batcher_configs.people),
4744
+ groups: batcher_for(batcher_configs.groups)
4678
4745
  };
4679
4746
  }
4680
4747
  if (this.get_config('batch_autostart')) {
@@ -4683,6 +4750,7 @@
4683
4750
  };
4684
4751
 
4685
4752
  MixpanelLib.prototype.start_batch_senders = function() {
4753
+ this._batchers_were_started = true;
4686
4754
  if (this.are_batchers_initialized()) {
4687
4755
  this._batch_requests = true;
4688
4756
  _.each(this.request_batchers, function(batcher) {
@@ -4834,7 +4902,7 @@
4834
4902
  }
4835
4903
 
4836
4904
  // set defaults
4837
- properties = properties || {};
4905
+ properties = _.extend({}, properties);
4838
4906
  properties['token'] = this.get_config('token');
4839
4907
 
4840
4908
  // set $duration if time_event was previously called for this event
@@ -4846,6 +4914,10 @@
4846
4914
 
4847
4915
  this._set_default_superprops();
4848
4916
 
4917
+ var marketing_properties = this.get_config('track_marketing')
4918
+ ? _.info.marketingParams()
4919
+ : {};
4920
+
4849
4921
  // note: extend writes to the first object, so lets make sure we
4850
4922
  // don't write to the persistence properties object and info
4851
4923
  // properties object by passing in a new object
@@ -4854,6 +4926,7 @@
4854
4926
  properties = _.extend(
4855
4927
  {},
4856
4928
  _.info.properties(),
4929
+ marketing_properties,
4857
4930
  this['persistence'].properties(),
4858
4931
  this.unpersisted_superprops,
4859
4932
  properties
@@ -4875,7 +4948,7 @@
4875
4948
  var ret = this._track_or_batch({
4876
4949
  type: 'events',
4877
4950
  data: data,
4878
- endpoint: this.get_config('api_host') + '/track/',
4951
+ endpoint: this.get_config('api_host') + '/' + this.get_config('api_routes')['track'],
4879
4952
  batcher: this.request_batchers.events,
4880
4953
  should_send_immediately: should_send_immediately,
4881
4954
  send_request_options: options
@@ -4921,13 +4994,14 @@
4921
4994
  */
4922
4995
  MixpanelLib.prototype.add_group = addOptOutCheckMixpanelLib(function(group_key, group_id, callback) {
4923
4996
  var old_values = this.get_property(group_key);
4997
+ var prop = {};
4924
4998
  if (old_values === undefined) {
4925
- var prop = {};
4926
4999
  prop[group_key] = [group_id];
4927
5000
  this.register(prop);
4928
5001
  } else {
4929
5002
  if (old_values.indexOf(group_id) === -1) {
4930
5003
  old_values.push(group_id);
5004
+ prop[group_key] = old_values;
4931
5005
  this.register(prop);
4932
5006
  }
4933
5007
  }
@@ -5014,17 +5088,54 @@
5014
5088
  };
5015
5089
 
5016
5090
  /**
5017
- * Track mp_page_view event. This is now ignored by the server.
5091
+ * Track a default Mixpanel page view event, which includes extra default event properties to
5092
+ * improve page view data. The `config.track_pageview` option for <a href="#mixpanelinit">mixpanel.init()</a>
5093
+ * may be turned on for tracking page loads automatically.
5018
5094
  *
5019
- * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
5020
- * @deprecated
5095
+ * ### Usage
5096
+ *
5097
+ * // track a default $mp_web_page_view event
5098
+ * mixpanel.track_pageview();
5099
+ *
5100
+ * // track a page view event with additional event properties
5101
+ * mixpanel.track_pageview({'ab_test_variant': 'card-layout-b'});
5102
+ *
5103
+ * // example approach to track page views on different page types as event properties
5104
+ * mixpanel.track_pageview({'page': 'pricing'});
5105
+ * mixpanel.track_pageview({'page': 'homepage'});
5106
+ *
5107
+ * // UNCOMMON: Tracking a page view event with a custom event_name option. NOT expected to be used for
5108
+ * // individual pages on the same site or product. Use cases for custom event_name may be page
5109
+ * // views on different products or internal applications that are considered completely separate
5110
+ * mixpanel.track_pageview({'page': 'customer-search'}, {'event_name': '[internal] Admin Page View'});
5111
+ *
5112
+ * @param {Object} [properties] An optional set of additional properties to send with the page view event
5113
+ * @param {Object} [options] Page view tracking options
5114
+ * @param {String} [options.event_name] - Alternate name for the tracking event
5115
+ * @returns {Boolean|Object} If the tracking request was successfully initiated/queued, an object
5116
+ * with the tracking payload sent to the API server is returned; otherwise false.
5021
5117
  */
5022
- MixpanelLib.prototype.track_pageview = function(page) {
5023
- if (_.isUndefined(page)) {
5024
- page = document$1.location.href;
5118
+ MixpanelLib.prototype.track_pageview = addOptOutCheckMixpanelLib(function(properties, options) {
5119
+ if (typeof properties !== 'object') {
5120
+ properties = {};
5025
5121
  }
5026
- this.track('mp_page_view', _.info.pageviewInfo(page));
5027
- };
5122
+ options = options || {};
5123
+ var event_name = options['event_name'] || '$mp_web_page_view';
5124
+
5125
+ var default_page_properties = _.extend(
5126
+ _.info.mpPageViewProperties(),
5127
+ _.info.campaignParams(),
5128
+ _.info.clickParams()
5129
+ );
5130
+
5131
+ var event_properties = _.extend(
5132
+ {},
5133
+ default_page_properties,
5134
+ properties
5135
+ );
5136
+
5137
+ return this.track(event_name, event_properties);
5138
+ });
5028
5139
 
5029
5140
  /**
5030
5141
  * Track clicks on a set of document elements. Selector must be a
@@ -5435,6 +5546,16 @@
5435
5546
  * The default config is:
5436
5547
  *
5437
5548
  * {
5549
+ * // host for requests (customizable for e.g. a local proxy)
5550
+ * api_host: 'https://api-js.mixpanel.com',
5551
+ *
5552
+ * // endpoints for different types of requests
5553
+ * api_routes: {
5554
+ * track: 'track/',
5555
+ * engage: 'engage/',
5556
+ * groups: 'groups/',
5557
+ * }
5558
+ *
5438
5559
  * // HTTP method for tracking requests
5439
5560
  * api_method: 'POST'
5440
5561
  *
@@ -5520,10 +5641,20 @@
5520
5641
  * // secure, meaning they will only be transmitted over https
5521
5642
  * secure_cookie: false
5522
5643
  *
5644
+ * // disables enriching user profiles with first touch marketing data
5645
+ * skip_first_touch_marketing: false
5646
+ *
5523
5647
  * // the amount of time track_links will
5524
5648
  * // wait for Mixpanel's servers to respond
5525
5649
  * track_links_timeout: 300
5526
5650
  *
5651
+ * // adds any UTM parameters and click IDs present on the page to any events fired
5652
+ * track_marketing: true
5653
+ *
5654
+ * // enables automatic page view tracking using default page view events through
5655
+ * // the track_pageview() method
5656
+ * track_pageview: false
5657
+ *
5527
5658
  * // if you set upgrade to be true, the library will check for
5528
5659
  * // a cookie from our old js library and import super
5529
5660
  * // properties from it, then the old cookie is deleted
@@ -5608,7 +5739,7 @@
5608
5739
  * @param {String} property_name The name of the super property you want to retrieve
5609
5740
  */
5610
5741
  MixpanelLib.prototype.get_property = function(property_name) {
5611
- return this['persistence']['props'][property_name];
5742
+ return this['persistence'].load_prop([property_name]);
5612
5743
  };
5613
5744
 
5614
5745
  MixpanelLib.prototype.toString = function() {
@@ -5681,9 +5812,13 @@
5681
5812
  }
5682
5813
 
5683
5814
  if (disabled) {
5684
- _.each(this.request_batchers, function(batcher) {
5685
- batcher.clear();
5686
- });
5815
+ this.stop_batch_senders();
5816
+ } else {
5817
+ // only start batchers after opt-in if they have previously been started
5818
+ // in order to avoid unintentionally starting up batching for the first time
5819
+ if (this._batchers_were_started) {
5820
+ this.start_batch_senders();
5821
+ }
5687
5822
  }
5688
5823
  };
5689
5824
 
@@ -5885,37 +6020,38 @@
5885
6020
  // EXPORTS (for closure compiler)
5886
6021
 
5887
6022
  // MixpanelLib Exports
5888
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
5889
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
5890
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
5891
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
5892
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
5893
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
5894
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
5895
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
5896
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
5897
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
5898
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
5899
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
5900
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
5901
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
5902
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
5903
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
5904
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
5905
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
5906
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
5907
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
5908
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
5909
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
5910
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
5911
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
5912
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
5913
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
5914
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
5915
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
5916
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
5917
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
5918
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6023
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
6024
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
6025
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
6026
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
6027
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
6028
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
6029
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
6030
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
6031
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
6032
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
6033
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
6034
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
6035
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
6036
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
6037
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
6038
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
6039
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
6040
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
6041
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
6042
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
6043
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
6044
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
6045
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
6046
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
6047
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
6048
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
6049
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
6050
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
6051
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
6052
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
6053
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6054
+ MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
5919
6055
 
5920
6056
  // MixpanelPersistence Exports
5921
6057
  MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;