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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.46.0'
6
+ LIB_VERSION: '2.48.0'
7
7
  };
8
8
 
9
9
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -833,20 +833,24 @@
833
833
 
834
834
  _.UUID = (function() {
835
835
 
836
- // Time/ticks information
837
- // 1*new Date() is a cross browser version of Date.now()
836
+ // Time-based entropy
838
837
  var T = function() {
839
- var d = 1 * new Date(),
840
- i = 0;
841
-
842
- // this while loop figures how many browser ticks go by
843
- // before 1*new Date() returns a new number, ie the amount
844
- // of ticks that go by per millisecond
845
- while (d == 1 * new Date()) {
846
- i++;
838
+ var time = 1 * new Date(); // cross-browser version of Date.now()
839
+ var ticks;
840
+ if (window$1.performance && window$1.performance.now) {
841
+ ticks = window$1.performance.now();
842
+ } else {
843
+ // fall back to busy loop
844
+ ticks = 0;
845
+
846
+ // this while loop figures how many browser ticks go by
847
+ // before 1*new Date() returns a new number, ie the amount
848
+ // of ticks that go by per millisecond
849
+ while (time == 1 * new Date()) {
850
+ ticks++;
851
+ }
847
852
  }
848
-
849
- return d.toString(16) + i.toString(16);
853
+ return time.toString(16) + Math.floor(ticks).toString(16);
850
854
  };
851
855
 
852
856
  // Math.Random entropy
@@ -901,6 +905,7 @@
901
905
  'baiduspider',
902
906
  'bingbot',
903
907
  'bingpreview',
908
+ 'chrome-lighthouse',
904
909
  'facebookexternal',
905
910
  'petalbot',
906
911
  'pinterest',
@@ -1413,21 +1418,42 @@
1413
1418
  };
1414
1419
  })();
1415
1420
 
1421
+ var CAMPAIGN_KEYWORDS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
1422
+ var CLICK_IDS = ['dclid', 'fbclid', 'gclid', 'ko_click_id', 'li_fat_id', 'msclkid', 'ttclid', 'twclid', 'wbraid'];
1423
+
1416
1424
  _.info = {
1417
- campaignParams: function() {
1418
- var campaign_keywords = 'utm_source utm_medium utm_campaign utm_content utm_term'.split(' '),
1419
- kw = '',
1425
+ campaignParams: function(default_value) {
1426
+ var kw = '',
1420
1427
  params = {};
1421
- _.each(campaign_keywords, function(kwkey) {
1428
+ _.each(CAMPAIGN_KEYWORDS, function(kwkey) {
1422
1429
  kw = _.getQueryParam(document$1.URL, kwkey);
1423
1430
  if (kw.length) {
1424
1431
  params[kwkey] = kw;
1432
+ } else if (default_value !== undefined) {
1433
+ params[kwkey] = default_value;
1434
+ }
1435
+ });
1436
+
1437
+ return params;
1438
+ },
1439
+
1440
+ clickParams: function() {
1441
+ var id = '',
1442
+ params = {};
1443
+ _.each(CLICK_IDS, function(idkey) {
1444
+ id = _.getQueryParam(document$1.URL, idkey);
1445
+ if (id.length) {
1446
+ params[idkey] = id;
1425
1447
  }
1426
1448
  });
1427
1449
 
1428
1450
  return params;
1429
1451
  },
1430
1452
 
1453
+ marketingParams: function() {
1454
+ return _.extend(_.info.campaignParams(), _.info.clickParams());
1455
+ },
1456
+
1431
1457
  searchEngine: function(referrer) {
1432
1458
  if (referrer.search('https?://(.*)google.([^/?]*)') === 0) {
1433
1459
  return 'google';
@@ -1624,12 +1650,13 @@
1624
1650
  });
1625
1651
  },
1626
1652
 
1627
- pageviewInfo: function(page) {
1653
+ mpPageViewProperties: function() {
1628
1654
  return _.strip_empty_properties({
1629
- 'mp_page': page,
1630
- 'mp_referrer': document$1.referrer,
1631
- 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera),
1632
- 'mp_platform': _.info.os()
1655
+ 'current_page_title': document$1.title,
1656
+ 'current_domain': window$1.location.hostname,
1657
+ 'current_url_path': window$1.location.pathname,
1658
+ 'current_url_protocol': window$1.location.protocol,
1659
+ 'current_url_search': window$1.location.search
1633
1660
  });
1634
1661
  }
1635
1662
  };
@@ -3107,7 +3134,7 @@
3107
3134
  return this._mixpanel._track_or_batch({
3108
3135
  type: 'groups',
3109
3136
  data: date_encoded_data,
3110
- endpoint: this._get_config('api_host') + '/groups/',
3137
+ endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['groups'],
3111
3138
  batcher: this._mixpanel.request_batchers.groups
3112
3139
  }, callback);
3113
3140
  };
@@ -3468,7 +3495,7 @@
3468
3495
  return this._mixpanel._track_or_batch({
3469
3496
  type: 'people',
3470
3497
  data: date_encoded_data,
3471
- endpoint: this._get_config('api_host') + '/engage/',
3498
+ endpoint: this._get_config('api_host') + '/' + this._get_config('api_routes')['engage'],
3472
3499
  batcher: this._mixpanel.request_batchers.people
3473
3500
  }, callback);
3474
3501
  };
@@ -3504,11 +3531,12 @@
3504
3531
 
3505
3532
  MixpanelPeople.prototype._flush_one_queue = function(action, action_method, callback, queue_to_params_fn) {
3506
3533
  var _this = this;
3507
- var queued_data = _.extend({}, this._mixpanel['persistence']._get_queue(action));
3534
+ var queued_data = _.extend({}, this._mixpanel['persistence'].load_queue(action));
3508
3535
  var action_params = queued_data;
3509
3536
 
3510
3537
  if (!_.isUndefined(queued_data) && _.isObject(queued_data) && !_.isEmptyObject(queued_data)) {
3511
3538
  _this._mixpanel['persistence']._pop_from_people_queue(action, queued_data);
3539
+ _this._mixpanel['persistence'].save();
3512
3540
  if (queue_to_params_fn) {
3513
3541
  action_params = queue_to_params_fn(queued_data);
3514
3542
  }
@@ -3530,8 +3558,6 @@
3530
3558
  _set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
3531
3559
  ) {
3532
3560
  var _this = this;
3533
- var $append_queue = this._mixpanel['persistence']._get_queue(APPEND_ACTION);
3534
- var $remove_queue = this._mixpanel['persistence']._get_queue(REMOVE_ACTION);
3535
3561
 
3536
3562
  this._flush_one_queue(SET_ACTION, this.set, _set_callback);
3537
3563
  this._flush_one_queue(SET_ONCE_ACTION, this.set_once, _set_once_callback);
@@ -3541,6 +3567,7 @@
3541
3567
 
3542
3568
  // we have to fire off each $append individually since there is
3543
3569
  // no concat method server side
3570
+ var $append_queue = this._mixpanel['persistence'].load_queue(APPEND_ACTION);
3544
3571
  if (!_.isUndefined($append_queue) && _.isArray($append_queue) && $append_queue.length) {
3545
3572
  var $append_item;
3546
3573
  var append_callback = function(response, data) {
@@ -3552,16 +3579,17 @@
3552
3579
  }
3553
3580
  };
3554
3581
  for (var i = $append_queue.length - 1; i >= 0; i--) {
3582
+ $append_queue = this._mixpanel['persistence'].load_queue(APPEND_ACTION);
3555
3583
  $append_item = $append_queue.pop();
3584
+ _this._mixpanel['persistence'].save();
3556
3585
  if (!_.isEmptyObject($append_item)) {
3557
3586
  _this.append($append_item, append_callback);
3558
3587
  }
3559
3588
  }
3560
- // Save the shortened append queue
3561
- _this._mixpanel['persistence'].save();
3562
3589
  }
3563
3590
 
3564
3591
  // same for $remove
3592
+ var $remove_queue = this._mixpanel['persistence'].load_queue(REMOVE_ACTION);
3565
3593
  if (!_.isUndefined($remove_queue) && _.isArray($remove_queue) && $remove_queue.length) {
3566
3594
  var $remove_item;
3567
3595
  var remove_callback = function(response, data) {
@@ -3573,12 +3601,13 @@
3573
3601
  }
3574
3602
  };
3575
3603
  for (var j = $remove_queue.length - 1; j >= 0; j--) {
3604
+ $remove_queue = this._mixpanel['persistence'].load_queue(REMOVE_ACTION);
3576
3605
  $remove_item = $remove_queue.pop();
3606
+ _this._mixpanel['persistence'].save();
3577
3607
  if (!_.isEmptyObject($remove_item)) {
3578
3608
  _this.remove($remove_item, remove_callback);
3579
3609
  }
3580
3610
  }
3581
- _this._mixpanel['persistence'].save();
3582
3611
  }
3583
3612
  };
3584
3613
 
@@ -3660,6 +3689,9 @@
3660
3689
 
3661
3690
  MixpanelPersistence.prototype.properties = function() {
3662
3691
  var p = {};
3692
+
3693
+ this.load();
3694
+
3663
3695
  // Filter out reserved properties
3664
3696
  _.each(this['props'], function(v, k) {
3665
3697
  if (!_.include(RESERVED_PROPERTIES, k)) {
@@ -3736,6 +3768,7 @@
3736
3768
 
3737
3769
  MixpanelPersistence.prototype.save = function() {
3738
3770
  if (this.disabled) { return; }
3771
+
3739
3772
  this.storage.set(
3740
3773
  this.name,
3741
3774
  _.JSONEncode(this['props']),
@@ -3747,6 +3780,11 @@
3747
3780
  );
3748
3781
  };
3749
3782
 
3783
+ MixpanelPersistence.prototype.load_prop = function(key) {
3784
+ this.load();
3785
+ return this['props'][key];
3786
+ };
3787
+
3750
3788
  MixpanelPersistence.prototype.remove = function() {
3751
3789
  // remove both domain and subdomain cookies
3752
3790
  this.storage.remove(this.name, false, this.cookie_domain);
@@ -3770,6 +3808,8 @@
3770
3808
  if (typeof(default_value) === 'undefined') { default_value = 'None'; }
3771
3809
  this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
3772
3810
 
3811
+ this.load();
3812
+
3773
3813
  _.each(props, function(val, prop) {
3774
3814
  if (!this['props'].hasOwnProperty(prop) || this['props'][prop] === default_value) {
3775
3815
  this['props'][prop] = val;
@@ -3791,8 +3831,8 @@
3791
3831
  if (_.isObject(props)) {
3792
3832
  this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
3793
3833
 
3834
+ this.load();
3794
3835
  _.extend(this['props'], props);
3795
-
3796
3836
  this.save();
3797
3837
 
3798
3838
  return true;
@@ -3801,19 +3841,13 @@
3801
3841
  };
3802
3842
 
3803
3843
  MixpanelPersistence.prototype.unregister = function(prop) {
3844
+ this.load();
3804
3845
  if (prop in this['props']) {
3805
3846
  delete this['props'][prop];
3806
3847
  this.save();
3807
3848
  }
3808
3849
  };
3809
3850
 
3810
- MixpanelPersistence.prototype.update_campaign_params = function() {
3811
- if (!this.campaign_params_saved) {
3812
- this.register_once(_.info.campaignParams());
3813
- this.campaign_params_saved = true;
3814
- }
3815
- };
3816
-
3817
3851
  MixpanelPersistence.prototype.update_search_keyword = function(referrer) {
3818
3852
  this.register(_.info.searchInfo(referrer));
3819
3853
  };
@@ -3834,19 +3868,6 @@
3834
3868
  });
3835
3869
  };
3836
3870
 
3837
- // safely fills the passed in object with stored properties,
3838
- // does not override any properties defined in both
3839
- // returns the passed in object
3840
- MixpanelPersistence.prototype.safe_merge = function(props) {
3841
- _.each(this['props'], function(val, prop) {
3842
- if (!(prop in props)) {
3843
- props[prop] = val;
3844
- }
3845
- });
3846
-
3847
- return props;
3848
- };
3849
-
3850
3871
  MixpanelPersistence.prototype.update_config = function(config) {
3851
3872
  this.default_expiry = this.expire_days = config['cookie_expiration'];
3852
3873
  this.set_disabled(config['disable_persistence']);
@@ -3990,7 +4011,7 @@
3990
4011
  };
3991
4012
 
3992
4013
  MixpanelPersistence.prototype._pop_from_people_queue = function(queue, data) {
3993
- var q = this._get_queue(queue);
4014
+ var q = this['props'][this._get_queue_key(queue)];
3994
4015
  if (!_.isUndefined(q)) {
3995
4016
  _.each(data, function(v, k) {
3996
4017
  if (queue === APPEND_ACTION || queue === REMOVE_ACTION) {
@@ -4006,11 +4027,13 @@
4006
4027
  delete q[k];
4007
4028
  }
4008
4029
  }, this);
4009
-
4010
- this.save();
4011
4030
  }
4012
4031
  };
4013
4032
 
4033
+ MixpanelPersistence.prototype.load_queue = function(queue) {
4034
+ return this.load_prop(this._get_queue_key(queue));
4035
+ };
4036
+
4014
4037
  MixpanelPersistence.prototype._get_queue_key = function(queue) {
4015
4038
  if (queue === SET_ACTION) {
4016
4039
  return SET_QUEUE_KEY;
@@ -4031,25 +4054,21 @@
4031
4054
  }
4032
4055
  };
4033
4056
 
4034
- MixpanelPersistence.prototype._get_queue = function(queue) {
4035
- return this['props'][this._get_queue_key(queue)];
4036
- };
4037
4057
  MixpanelPersistence.prototype._get_or_create_queue = function(queue, default_val) {
4038
4058
  var key = this._get_queue_key(queue);
4039
4059
  default_val = _.isUndefined(default_val) ? {} : default_val;
4040
-
4041
4060
  return this['props'][key] || (this['props'][key] = default_val);
4042
4061
  };
4043
4062
 
4044
4063
  MixpanelPersistence.prototype.set_event_timer = function(event_name, timestamp) {
4045
- var timers = this['props'][EVENT_TIMERS_KEY] || {};
4064
+ var timers = this.load_prop(EVENT_TIMERS_KEY) || {};
4046
4065
  timers[event_name] = timestamp;
4047
4066
  this['props'][EVENT_TIMERS_KEY] = timers;
4048
4067
  this.save();
4049
4068
  };
4050
4069
 
4051
4070
  MixpanelPersistence.prototype.remove_event_timer = function(event_name) {
4052
- var timers = this['props'][EVENT_TIMERS_KEY] || {};
4071
+ var timers = this.load_prop(EVENT_TIMERS_KEY) || {};
4053
4072
  var timestamp = timers[event_name];
4054
4073
  if (!_.isUndefined(timestamp)) {
4055
4074
  delete this['props'][EVENT_TIMERS_KEY][event_name];
@@ -4120,11 +4139,18 @@
4120
4139
  };
4121
4140
  }
4122
4141
 
4142
+ var DEFAULT_API_ROUTES = {
4143
+ 'track': 'track/',
4144
+ 'engage': 'engage/',
4145
+ 'groups': 'groups/'
4146
+ };
4147
+
4123
4148
  /*
4124
4149
  * Module-level globals
4125
4150
  */
4126
4151
  var DEFAULT_CONFIG = {
4127
4152
  'api_host': 'https://api-js.mixpanel.com',
4153
+ 'api_routes': DEFAULT_API_ROUTES,
4128
4154
  'api_method': 'POST',
4129
4155
  'api_transport': 'XHR',
4130
4156
  'api_payload_format': PAYLOAD_TYPE_BASE64,
@@ -4138,6 +4164,9 @@
4138
4164
  'cookie_domain': '',
4139
4165
  'cookie_name': '',
4140
4166
  'loaded': NOOP_FUNC,
4167
+ 'track_marketing': true,
4168
+ 'track_pageview': false,
4169
+ 'skip_first_touch_marketing': false,
4141
4170
  'store_google': true,
4142
4171
  'save_referrer': true,
4143
4172
  'test': false,
@@ -4204,6 +4233,25 @@
4204
4233
  instance['people'] = new MixpanelPeople();
4205
4234
  instance['people']._init(instance);
4206
4235
 
4236
+ if (!instance.get_config('skip_first_touch_marketing')) {
4237
+ // We need null UTM params in the object because
4238
+ // UTM parameters act as a tuple. If any UTM param
4239
+ // is present, then we set all UTM params including
4240
+ // empty ones together
4241
+ var utm_params = _.info.campaignParams(null);
4242
+ var initial_utm_params = {};
4243
+ var has_utm = false;
4244
+ _.each(utm_params, function(utm_value, utm_key) {
4245
+ initial_utm_params['initial_' + utm_key] = utm_value;
4246
+ if (utm_value) {
4247
+ has_utm = true;
4248
+ }
4249
+ });
4250
+ if (has_utm) {
4251
+ instance['people'].set_once(initial_utm_params);
4252
+ }
4253
+ }
4254
+
4207
4255
  // if any instance on the page has debug = true, we set the
4208
4256
  // global debug to be true
4209
4257
  Config.DEBUG = Config.DEBUG || instance.get_config('debug');
@@ -4235,7 +4283,7 @@
4235
4283
  * mixpanel.library_name.track(...);
4236
4284
  *
4237
4285
  * @param {String} token Your Mixpanel API token
4238
- * @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>.
4286
+ * @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>.
4239
4287
  * @param {String} [name] The name for the new mixpanel instance that you want created
4240
4288
  */
4241
4289
  MixpanelLib.prototype.init = function (token, config, name) {
@@ -4273,7 +4321,7 @@
4273
4321
  // default to JSON payload for standard mixpanel.com API hosts
4274
4322
  if (!('api_payload_format' in config)) {
4275
4323
  var api_host = config['api_host'] || DEFAULT_CONFIG['api_host'];
4276
- if (api_host.match(/\.mixpanel\.com$/)) {
4324
+ if (api_host.match(/\.mixpanel\.com/)) {
4277
4325
  variable_features['api_payload_format'] = PAYLOAD_TYPE_JSON;
4278
4326
  }
4279
4327
  }
@@ -4301,6 +4349,10 @@
4301
4349
  if (!_.localStorage.is_supported(true) || !USE_XHR) {
4302
4350
  this._batch_requests = false;
4303
4351
  console.log('Turning off Mixpanel request-queueing; needs XHR and localStorage support');
4352
+ _.each(this.get_batcher_configs(), function(batcher_config) {
4353
+ console.log('Clearing batch queue ' + batcher_config.queue_key);
4354
+ _.localStorage.remove(batcher_config.queue_key);
4355
+ });
4304
4356
  } else {
4305
4357
  this.init_batchers();
4306
4358
  if (sendBeacon && window$1.addEventListener) {
@@ -4348,6 +4400,10 @@
4348
4400
  '$device_id': uuid
4349
4401
  }, '');
4350
4402
  }
4403
+
4404
+ if (this.get_config('track_pageview')) {
4405
+ this.track_pageview();
4406
+ }
4351
4407
  };
4352
4408
 
4353
4409
  // Private methods
@@ -4361,7 +4417,7 @@
4361
4417
  MixpanelLib.prototype._set_default_superprops = function() {
4362
4418
  this['persistence'].update_search_keyword(document$1.referrer);
4363
4419
  if (this.get_config('store_google')) {
4364
- this['persistence'].update_campaign_params();
4420
+ this.register(_.info.campaignParams(), {persistent: false});
4365
4421
  }
4366
4422
  if (this.get_config('save_referrer')) {
4367
4423
  this['persistence'].update_referrer_info(document$1.referrer);
@@ -4644,12 +4700,22 @@
4644
4700
  return !!this.request_batchers.events;
4645
4701
  };
4646
4702
 
4703
+ MixpanelLib.prototype.get_batcher_configs = function() {
4704
+ var queue_prefix = '__mpq_' + this.get_config('token');
4705
+ var api_routes = this.get_config('api_routes');
4706
+ this._batcher_configs = this._batcher_configs || {
4707
+ events: {type: 'events', endpoint: '/' + api_routes['track'], queue_key: queue_prefix + '_ev'},
4708
+ people: {type: 'people', endpoint: '/' + api_routes['engage'], queue_key: queue_prefix + '_pp'},
4709
+ groups: {type: 'groups', endpoint: '/' + api_routes['groups'], queue_key: queue_prefix + '_gr'}
4710
+ };
4711
+ return this._batcher_configs;
4712
+ };
4713
+
4647
4714
  MixpanelLib.prototype.init_batchers = function() {
4648
- var token = this.get_config('token');
4649
4715
  if (!this.are_batchers_initialized()) {
4650
4716
  var batcher_for = _.bind(function(attrs) {
4651
4717
  return new RequestBatcher(
4652
- '__mpq_' + token + attrs.queue_suffix,
4718
+ attrs.queue_key,
4653
4719
  {
4654
4720
  libConfig: this['config'],
4655
4721
  sendRequestFunc: _.bind(function(data, options, cb) {
@@ -4668,10 +4734,11 @@
4668
4734
  }
4669
4735
  );
4670
4736
  }, this);
4737
+ var batcher_configs = this.get_batcher_configs();
4671
4738
  this.request_batchers = {
4672
- events: batcher_for({type: 'events', endpoint: '/track/', queue_suffix: '_ev'}),
4673
- people: batcher_for({type: 'people', endpoint: '/engage/', queue_suffix: '_pp'}),
4674
- groups: batcher_for({type: 'groups', endpoint: '/groups/', queue_suffix: '_gr'})
4739
+ events: batcher_for(batcher_configs.events),
4740
+ people: batcher_for(batcher_configs.people),
4741
+ groups: batcher_for(batcher_configs.groups)
4675
4742
  };
4676
4743
  }
4677
4744
  if (this.get_config('batch_autostart')) {
@@ -4680,6 +4747,7 @@
4680
4747
  };
4681
4748
 
4682
4749
  MixpanelLib.prototype.start_batch_senders = function() {
4750
+ this._batchers_were_started = true;
4683
4751
  if (this.are_batchers_initialized()) {
4684
4752
  this._batch_requests = true;
4685
4753
  _.each(this.request_batchers, function(batcher) {
@@ -4831,7 +4899,7 @@
4831
4899
  }
4832
4900
 
4833
4901
  // set defaults
4834
- properties = properties || {};
4902
+ properties = _.extend({}, properties);
4835
4903
  properties['token'] = this.get_config('token');
4836
4904
 
4837
4905
  // set $duration if time_event was previously called for this event
@@ -4843,6 +4911,10 @@
4843
4911
 
4844
4912
  this._set_default_superprops();
4845
4913
 
4914
+ var marketing_properties = this.get_config('track_marketing')
4915
+ ? _.info.marketingParams()
4916
+ : {};
4917
+
4846
4918
  // note: extend writes to the first object, so lets make sure we
4847
4919
  // don't write to the persistence properties object and info
4848
4920
  // properties object by passing in a new object
@@ -4851,6 +4923,7 @@
4851
4923
  properties = _.extend(
4852
4924
  {},
4853
4925
  _.info.properties(),
4926
+ marketing_properties,
4854
4927
  this['persistence'].properties(),
4855
4928
  this.unpersisted_superprops,
4856
4929
  properties
@@ -4872,7 +4945,7 @@
4872
4945
  var ret = this._track_or_batch({
4873
4946
  type: 'events',
4874
4947
  data: data,
4875
- endpoint: this.get_config('api_host') + '/track/',
4948
+ endpoint: this.get_config('api_host') + '/' + this.get_config('api_routes')['track'],
4876
4949
  batcher: this.request_batchers.events,
4877
4950
  should_send_immediately: should_send_immediately,
4878
4951
  send_request_options: options
@@ -4918,13 +4991,14 @@
4918
4991
  */
4919
4992
  MixpanelLib.prototype.add_group = addOptOutCheckMixpanelLib(function(group_key, group_id, callback) {
4920
4993
  var old_values = this.get_property(group_key);
4994
+ var prop = {};
4921
4995
  if (old_values === undefined) {
4922
- var prop = {};
4923
4996
  prop[group_key] = [group_id];
4924
4997
  this.register(prop);
4925
4998
  } else {
4926
4999
  if (old_values.indexOf(group_id) === -1) {
4927
5000
  old_values.push(group_id);
5001
+ prop[group_key] = old_values;
4928
5002
  this.register(prop);
4929
5003
  }
4930
5004
  }
@@ -5011,17 +5085,54 @@
5011
5085
  };
5012
5086
 
5013
5087
  /**
5014
- * Track mp_page_view event. This is now ignored by the server.
5088
+ * Track a default Mixpanel page view event, which includes extra default event properties to
5089
+ * improve page view data. The `config.track_pageview` option for <a href="#mixpanelinit">mixpanel.init()</a>
5090
+ * may be turned on for tracking page loads automatically.
5015
5091
  *
5016
- * @param {String} [page] The url of the page to record. If you don't include this, it defaults to the current url.
5017
- * @deprecated
5092
+ * ### Usage
5093
+ *
5094
+ * // track a default $mp_web_page_view event
5095
+ * mixpanel.track_pageview();
5096
+ *
5097
+ * // track a page view event with additional event properties
5098
+ * mixpanel.track_pageview({'ab_test_variant': 'card-layout-b'});
5099
+ *
5100
+ * // example approach to track page views on different page types as event properties
5101
+ * mixpanel.track_pageview({'page': 'pricing'});
5102
+ * mixpanel.track_pageview({'page': 'homepage'});
5103
+ *
5104
+ * // UNCOMMON: Tracking a page view event with a custom event_name option. NOT expected to be used for
5105
+ * // individual pages on the same site or product. Use cases for custom event_name may be page
5106
+ * // views on different products or internal applications that are considered completely separate
5107
+ * mixpanel.track_pageview({'page': 'customer-search'}, {'event_name': '[internal] Admin Page View'});
5108
+ *
5109
+ * @param {Object} [properties] An optional set of additional properties to send with the page view event
5110
+ * @param {Object} [options] Page view tracking options
5111
+ * @param {String} [options.event_name] - Alternate name for the tracking event
5112
+ * @returns {Boolean|Object} If the tracking request was successfully initiated/queued, an object
5113
+ * with the tracking payload sent to the API server is returned; otherwise false.
5018
5114
  */
5019
- MixpanelLib.prototype.track_pageview = function(page) {
5020
- if (_.isUndefined(page)) {
5021
- page = document$1.location.href;
5115
+ MixpanelLib.prototype.track_pageview = addOptOutCheckMixpanelLib(function(properties, options) {
5116
+ if (typeof properties !== 'object') {
5117
+ properties = {};
5022
5118
  }
5023
- this.track('mp_page_view', _.info.pageviewInfo(page));
5024
- };
5119
+ options = options || {};
5120
+ var event_name = options['event_name'] || '$mp_web_page_view';
5121
+
5122
+ var default_page_properties = _.extend(
5123
+ _.info.mpPageViewProperties(),
5124
+ _.info.campaignParams(),
5125
+ _.info.clickParams()
5126
+ );
5127
+
5128
+ var event_properties = _.extend(
5129
+ {},
5130
+ default_page_properties,
5131
+ properties
5132
+ );
5133
+
5134
+ return this.track(event_name, event_properties);
5135
+ });
5025
5136
 
5026
5137
  /**
5027
5138
  * Track clicks on a set of document elements. Selector must be a
@@ -5432,6 +5543,16 @@
5432
5543
  * The default config is:
5433
5544
  *
5434
5545
  * {
5546
+ * // host for requests (customizable for e.g. a local proxy)
5547
+ * api_host: 'https://api-js.mixpanel.com',
5548
+ *
5549
+ * // endpoints for different types of requests
5550
+ * api_routes: {
5551
+ * track: 'track/',
5552
+ * engage: 'engage/',
5553
+ * groups: 'groups/',
5554
+ * }
5555
+ *
5435
5556
  * // HTTP method for tracking requests
5436
5557
  * api_method: 'POST'
5437
5558
  *
@@ -5517,10 +5638,20 @@
5517
5638
  * // secure, meaning they will only be transmitted over https
5518
5639
  * secure_cookie: false
5519
5640
  *
5641
+ * // disables enriching user profiles with first touch marketing data
5642
+ * skip_first_touch_marketing: false
5643
+ *
5520
5644
  * // the amount of time track_links will
5521
5645
  * // wait for Mixpanel's servers to respond
5522
5646
  * track_links_timeout: 300
5523
5647
  *
5648
+ * // adds any UTM parameters and click IDs present on the page to any events fired
5649
+ * track_marketing: true
5650
+ *
5651
+ * // enables automatic page view tracking using default page view events through
5652
+ * // the track_pageview() method
5653
+ * track_pageview: false
5654
+ *
5524
5655
  * // if you set upgrade to be true, the library will check for
5525
5656
  * // a cookie from our old js library and import super
5526
5657
  * // properties from it, then the old cookie is deleted
@@ -5605,7 +5736,7 @@
5605
5736
  * @param {String} property_name The name of the super property you want to retrieve
5606
5737
  */
5607
5738
  MixpanelLib.prototype.get_property = function(property_name) {
5608
- return this['persistence']['props'][property_name];
5739
+ return this['persistence'].load_prop([property_name]);
5609
5740
  };
5610
5741
 
5611
5742
  MixpanelLib.prototype.toString = function() {
@@ -5678,9 +5809,13 @@
5678
5809
  }
5679
5810
 
5680
5811
  if (disabled) {
5681
- _.each(this.request_batchers, function(batcher) {
5682
- batcher.clear();
5683
- });
5812
+ this.stop_batch_senders();
5813
+ } else {
5814
+ // only start batchers after opt-in if they have previously been started
5815
+ // in order to avoid unintentionally starting up batching for the first time
5816
+ if (this._batchers_were_started) {
5817
+ this.start_batch_senders();
5818
+ }
5684
5819
  }
5685
5820
  };
5686
5821
 
@@ -5882,37 +6017,38 @@
5882
6017
  // EXPORTS (for closure compiler)
5883
6018
 
5884
6019
  // MixpanelLib Exports
5885
- MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
5886
- MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
5887
- MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
5888
- MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
5889
- MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
5890
- MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
5891
- MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
5892
- MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
5893
- MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
5894
- MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
5895
- MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
5896
- MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
5897
- MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
5898
- MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
5899
- MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
5900
- MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
5901
- MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
5902
- MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
5903
- MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
5904
- MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
5905
- MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
5906
- MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
5907
- MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
5908
- MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
5909
- MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
5910
- MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
5911
- MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
5912
- MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
5913
- MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
5914
- MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
5915
- MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6020
+ MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
6021
+ MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
6022
+ MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
6023
+ MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
6024
+ MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
6025
+ MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
6026
+ MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
6027
+ MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
6028
+ MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
6029
+ MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
6030
+ MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
6031
+ MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
6032
+ MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
6033
+ MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
6034
+ MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
6035
+ MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
6036
+ MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
6037
+ MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
6038
+ MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
6039
+ MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
6040
+ MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
6041
+ MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
6042
+ MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
6043
+ MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
6044
+ MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
6045
+ MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
6046
+ MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
6047
+ MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
6048
+ MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
6049
+ MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
6050
+ MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
6051
+ MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
5916
6052
 
5917
6053
  // MixpanelPersistence Exports
5918
6054
  MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;