mixpanel-browser 2.63.0 → 2.64.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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  var Config = {
4
4
  DEBUG: false,
5
- LIB_VERSION: '2.63.0'
5
+ LIB_VERSION: '2.64.0'
6
6
  };
7
7
 
8
8
  // since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
@@ -2158,7 +2158,7 @@ var TRACKED_ATTRS = [
2158
2158
  'href', 'name', 'role', 'title', 'type'
2159
2159
  ];
2160
2160
 
2161
- var logger$3 = console_with_prefix('autocapture');
2161
+ var logger$4 = console_with_prefix('autocapture');
2162
2162
 
2163
2163
 
2164
2164
  function getClasses(el) {
@@ -2244,6 +2244,7 @@ function getPropsForDOMEvent(ev, config) {
2244
2244
  var blockSelectors = config.blockSelectors || [];
2245
2245
  var captureTextContent = config.captureTextContent || false;
2246
2246
  var captureExtraAttrs = config.captureExtraAttrs || [];
2247
+ var capturedForHeatMap = config.capturedForHeatMap || false;
2247
2248
 
2248
2249
  // convert array to set every time, as the config may have changed
2249
2250
  var blockAttrsSet = {};
@@ -2322,6 +2323,9 @@ function getPropsForDOMEvent(ev, config) {
2322
2323
  props['$' + prop] = ev[prop];
2323
2324
  }
2324
2325
  });
2326
+ if (capturedForHeatMap) {
2327
+ props['$captured_for_heatmap'] = true;
2328
+ }
2325
2329
  target = guessRealClickTarget(ev);
2326
2330
  }
2327
2331
  // prioritize text content from "real" click target if different from original target
@@ -2416,7 +2420,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
2416
2420
  return false;
2417
2421
  }
2418
2422
  } catch (err) {
2419
- logger$3.critical('Error while checking element in allowElementCallback', err);
2423
+ logger$4.critical('Error while checking element in allowElementCallback', err);
2420
2424
  return false;
2421
2425
  }
2422
2426
  }
@@ -2433,7 +2437,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
2433
2437
  return true;
2434
2438
  }
2435
2439
  } catch (err) {
2436
- logger$3.critical('Error while checking selector: ' + sel, err);
2440
+ logger$4.critical('Error while checking selector: ' + sel, err);
2437
2441
  }
2438
2442
  }
2439
2443
  return false;
@@ -2448,7 +2452,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
2448
2452
  return true;
2449
2453
  }
2450
2454
  } catch (err) {
2451
- logger$3.critical('Error while checking element in blockElementCallback', err);
2455
+ logger$4.critical('Error while checking element in blockElementCallback', err);
2452
2456
  return true;
2453
2457
  }
2454
2458
  }
@@ -2462,7 +2466,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
2462
2466
  return true;
2463
2467
  }
2464
2468
  } catch (err) {
2465
- logger$3.critical('Error while checking selector: ' + sel, err);
2469
+ logger$4.critical('Error while checking selector: ' + sel, err);
2466
2470
  }
2467
2471
  }
2468
2472
  }
@@ -2668,22 +2672,22 @@ var CONFIG_TRACK_PAGEVIEW = 'pageview';
2668
2672
  var CONFIG_TRACK_SCROLL = 'scroll';
2669
2673
  var CONFIG_TRACK_SUBMIT = 'submit';
2670
2674
 
2671
- var CONFIG_DEFAULTS = {};
2672
- CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
2673
- CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
2674
- CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
2675
- CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
2676
- CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
2677
- CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
2678
- CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
2679
- CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
2680
- CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
2681
- CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2682
- CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
2683
- CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
2684
- CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2685
- CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
2686
- CONFIG_DEFAULTS[CONFIG_TRACK_SUBMIT] = true;
2675
+ var CONFIG_DEFAULTS$1 = {};
2676
+ CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
2677
+ CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
2678
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
2679
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
2680
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
2681
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
2682
+ CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
2683
+ CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
2684
+ CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
2685
+ CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2686
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
2687
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
2688
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2689
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
2690
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
2687
2691
 
2688
2692
  var DEFAULT_PROPS = {
2689
2693
  '$mp_autocapture': true
@@ -2704,7 +2708,7 @@ var Autocapture = function(mp) {
2704
2708
 
2705
2709
  Autocapture.prototype.init = function() {
2706
2710
  if (!minDOMApisSupported()) {
2707
- logger$3.critical('Autocapture unavailable: missing required DOM APIs');
2711
+ logger$4.critical('Autocapture unavailable: missing required DOM APIs');
2708
2712
  return;
2709
2713
  }
2710
2714
 
@@ -2721,10 +2725,10 @@ Autocapture.prototype.getFullConfig = function() {
2721
2725
  // Autocapture is completely off
2722
2726
  return {};
2723
2727
  } else if (_.isObject(autocaptureConfig)) {
2724
- return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
2728
+ return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
2725
2729
  } else {
2726
2730
  // Autocapture config is non-object truthy value, return default
2727
- return CONFIG_DEFAULTS;
2731
+ return CONFIG_DEFAULTS$1;
2728
2732
  }
2729
2733
  };
2730
2734
 
@@ -2748,7 +2752,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
2748
2752
  break;
2749
2753
  }
2750
2754
  } catch (err) {
2751
- logger$3.critical('Error while checking block URL regex: ' + allowRegex, err);
2755
+ logger$4.critical('Error while checking block URL regex: ' + allowRegex, err);
2752
2756
  return true;
2753
2757
  }
2754
2758
  }
@@ -2769,7 +2773,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
2769
2773
  return true;
2770
2774
  }
2771
2775
  } catch (err) {
2772
- logger$3.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
2776
+ logger$4.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
2773
2777
  return true;
2774
2778
  }
2775
2779
  }
@@ -2798,7 +2802,8 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
2798
2802
  blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
2799
2803
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
2800
2804
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
2801
- captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
2805
+ captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
2806
+ capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
2802
2807
  });
2803
2808
  if (props) {
2804
2809
  _.extend(props, DEFAULT_PROPS);
@@ -2809,13 +2814,13 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
2809
2814
  Autocapture.prototype.initClickTracking = function() {
2810
2815
  win.removeEventListener(EV_CLICK, this.listenerClick);
2811
2816
 
2812
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2817
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
2813
2818
  return;
2814
2819
  }
2815
- logger$3.log('Initializing click tracking');
2820
+ logger$4.log('Initializing click tracking');
2816
2821
 
2817
2822
  this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
2818
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2823
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
2819
2824
  return;
2820
2825
  }
2821
2826
  this.trackDomEvent(ev, MP_EV_CLICK);
@@ -2828,7 +2833,7 @@ Autocapture.prototype.initInputTracking = function() {
2828
2833
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
2829
2834
  return;
2830
2835
  }
2831
- logger$3.log('Initializing input tracking');
2836
+ logger$4.log('Initializing input tracking');
2832
2837
 
2833
2838
  this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
2834
2839
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -2846,7 +2851,7 @@ Autocapture.prototype.initPageviewTracking = function() {
2846
2851
  if (!this.pageviewTrackingConfig()) {
2847
2852
  return;
2848
2853
  }
2849
- logger$3.log('Initializing pageview tracking');
2854
+ logger$4.log('Initializing pageview tracking');
2850
2855
 
2851
2856
  var previousTrackedUrl = '';
2852
2857
  var tracked = false;
@@ -2901,7 +2906,7 @@ Autocapture.prototype.initPageviewTracking = function() {
2901
2906
  }
2902
2907
  if (didPathChange) {
2903
2908
  this.lastScrollCheckpoint = 0;
2904
- logger$3.log('Path change: re-initializing scroll depth checkpoints');
2909
+ logger$4.log('Path change: re-initializing scroll depth checkpoints');
2905
2910
  }
2906
2911
  }
2907
2912
  }.bind(this)));
@@ -2913,7 +2918,7 @@ Autocapture.prototype.initScrollTracking = function() {
2913
2918
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
2914
2919
  return;
2915
2920
  }
2916
- logger$3.log('Initializing scroll tracking');
2921
+ logger$4.log('Initializing scroll tracking');
2917
2922
  this.lastScrollCheckpoint = 0;
2918
2923
 
2919
2924
  this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
@@ -2950,7 +2955,7 @@ Autocapture.prototype.initScrollTracking = function() {
2950
2955
  }
2951
2956
  }
2952
2957
  } catch (err) {
2953
- logger$3.critical('Error while calculating scroll percentage', err);
2958
+ logger$4.critical('Error while calculating scroll percentage', err);
2954
2959
  }
2955
2960
  if (shouldTrack) {
2956
2961
  this.mp.track(MP_EV_SCROLL, props);
@@ -2964,7 +2969,7 @@ Autocapture.prototype.initSubmitTracking = function() {
2964
2969
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
2965
2970
  return;
2966
2971
  }
2967
- logger$3.log('Initializing submit tracking');
2972
+ logger$4.log('Initializing submit tracking');
2968
2973
 
2969
2974
  this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
2970
2975
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -2977,6 +2982,193 @@ Autocapture.prototype.initSubmitTracking = function() {
2977
2982
  // TODO integrate error_reporter from mixpanel instance
2978
2983
  safewrapClass(Autocapture);
2979
2984
 
2985
+ var fetch = win['fetch'];
2986
+ var logger$3 = console_with_prefix('flags');
2987
+
2988
+ var FLAGS_CONFIG_KEY = 'flags';
2989
+
2990
+ var CONFIG_CONTEXT = 'context';
2991
+ var CONFIG_DEFAULTS = {};
2992
+ CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
2993
+
2994
+ /**
2995
+ * FeatureFlagManager: support for Mixpanel's feature flagging product
2996
+ * @constructor
2997
+ */
2998
+ var FeatureFlagManager = function(initOptions) {
2999
+ this.getMpConfig = initOptions.getConfigFunc;
3000
+ this.getDistinctId = initOptions.getDistinctIdFunc;
3001
+ this.track = initOptions.trackingFunc;
3002
+ };
3003
+
3004
+ FeatureFlagManager.prototype.init = function() {
3005
+ if (!minApisSupported()) {
3006
+ logger$3.critical('Feature Flags unavailable: missing minimum required APIs');
3007
+ return;
3008
+ }
3009
+
3010
+ this.flags = null;
3011
+ this.fetchFlags();
3012
+
3013
+ this.trackedFeatures = new Set();
3014
+ };
3015
+
3016
+ FeatureFlagManager.prototype.getFullConfig = function() {
3017
+ var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
3018
+ if (!ffConfig) {
3019
+ // flags are completely off
3020
+ return {};
3021
+ } else if (_.isObject(ffConfig)) {
3022
+ return _.extend({}, CONFIG_DEFAULTS, ffConfig);
3023
+ } else {
3024
+ // config is non-object truthy value, return default
3025
+ return CONFIG_DEFAULTS;
3026
+ }
3027
+ };
3028
+
3029
+ FeatureFlagManager.prototype.getConfig = function(key) {
3030
+ return this.getFullConfig()[key];
3031
+ };
3032
+
3033
+ FeatureFlagManager.prototype.isEnabled = function() {
3034
+ return !!this.getMpConfig(FLAGS_CONFIG_KEY);
3035
+ };
3036
+
3037
+ FeatureFlagManager.prototype.areFeaturesReady = function() {
3038
+ if (!this.isEnabled()) {
3039
+ logger$3.error('Feature Flags not enabled');
3040
+ }
3041
+ return !!this.flags;
3042
+ };
3043
+
3044
+ FeatureFlagManager.prototype.fetchFlags = function() {
3045
+ if (!this.isEnabled()) {
3046
+ return;
3047
+ }
3048
+
3049
+ var distinctId = this.getDistinctId();
3050
+ logger$3.log('Fetching flags for distinct ID: ' + distinctId);
3051
+ var reqParams = {
3052
+ 'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
3053
+ };
3054
+ this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
3055
+ 'method': 'POST',
3056
+ 'headers': {
3057
+ 'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
3058
+ 'Content-Type': 'application/octet-stream'
3059
+ },
3060
+ 'body': JSON.stringify(reqParams)
3061
+ }).then(function(response) {
3062
+ return response.json().then(function(responseBody) {
3063
+ var responseFlags = responseBody['flags'];
3064
+ if (!responseFlags) {
3065
+ throw new Error('No flags in API response');
3066
+ }
3067
+ var flags = new Map();
3068
+ _.each(responseFlags, function(data, key) {
3069
+ flags.set(key, {
3070
+ 'key': data['variant_key'],
3071
+ 'data': data['variant_value']
3072
+ });
3073
+ });
3074
+ this.flags = flags;
3075
+ }.bind(this)).catch(function(error) {
3076
+ logger$3.error(error);
3077
+ });
3078
+ }.bind(this)).catch(function() {});
3079
+ };
3080
+
3081
+ FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
3082
+ if (!this.fetchPromise) {
3083
+ return new Promise(function(resolve) {
3084
+ logger$3.critical('Feature Flags not initialized');
3085
+ resolve(fallback);
3086
+ });
3087
+ }
3088
+
3089
+ return this.fetchPromise.then(function() {
3090
+ return this.getFeatureSync(featureName, fallback);
3091
+ }.bind(this)).catch(function(error) {
3092
+ logger$3.error(error);
3093
+ return fallback;
3094
+ });
3095
+ };
3096
+
3097
+ FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
3098
+ if (!this.areFeaturesReady()) {
3099
+ logger$3.log('Flags not loaded yet');
3100
+ return fallback;
3101
+ }
3102
+ var feature = this.flags.get(featureName);
3103
+ if (!feature) {
3104
+ logger$3.log('No flag found: "' + featureName + '"');
3105
+ return fallback;
3106
+ }
3107
+ this.trackFeatureCheck(featureName, feature);
3108
+ return feature;
3109
+ };
3110
+
3111
+ FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
3112
+ return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
3113
+ return feature['data'];
3114
+ }).catch(function(error) {
3115
+ logger$3.error(error);
3116
+ return fallbackValue;
3117
+ });
3118
+ };
3119
+
3120
+ FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
3121
+ return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
3122
+ };
3123
+
3124
+ FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
3125
+ return this.getFeatureData(featureName).then(function() {
3126
+ return this.isFeatureEnabledSync(featureName, fallbackValue);
3127
+ }.bind(this)).catch(function(error) {
3128
+ logger$3.error(error);
3129
+ return fallbackValue;
3130
+ });
3131
+ };
3132
+
3133
+ FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
3134
+ fallbackValue = fallbackValue || false;
3135
+ var val = this.getFeatureDataSync(featureName, fallbackValue);
3136
+ if (val !== true && val !== false) {
3137
+ logger$3.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
3138
+ val = fallbackValue;
3139
+ }
3140
+ return val;
3141
+ };
3142
+
3143
+ FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
3144
+ if (this.trackedFeatures.has(featureName)) {
3145
+ return;
3146
+ }
3147
+ this.trackedFeatures.add(featureName);
3148
+ this.track('$experiment_started', {
3149
+ 'Experiment name': featureName,
3150
+ 'Variant name': feature['key'],
3151
+ '$experiment_type': 'feature_flag'
3152
+ });
3153
+ };
3154
+
3155
+ function minApisSupported() {
3156
+ return !!fetch &&
3157
+ typeof Promise !== 'undefined' &&
3158
+ typeof Map !== 'undefined' &&
3159
+ typeof Set !== 'undefined';
3160
+ }
3161
+
3162
+ safewrapClass(FeatureFlagManager);
3163
+
3164
+ FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
3165
+ FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
3166
+ FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
3167
+ FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
3168
+ FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
3169
+ FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
3170
+ FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
3171
+
2980
3172
  /* eslint camelcase: "off" */
2981
3173
 
2982
3174
 
@@ -5692,10 +5884,11 @@ if (navigator['sendBeacon']) {
5692
5884
  }
5693
5885
 
5694
5886
  var DEFAULT_API_ROUTES = {
5695
- 'track': 'track/',
5887
+ 'track': 'track/',
5696
5888
  'engage': 'engage/',
5697
5889
  'groups': 'groups/',
5698
- 'record': 'record/'
5890
+ 'record': 'record/',
5891
+ 'flags': 'flags/'
5699
5892
  };
5700
5893
 
5701
5894
  /*
@@ -5713,6 +5906,7 @@ var DEFAULT_CONFIG = {
5713
5906
  'cross_site_cookie': false,
5714
5907
  'cross_subdomain_cookie': true,
5715
5908
  'error_reporter': NOOP_FUNC,
5909
+ 'flags': false,
5716
5910
  'persistence': 'cookie',
5717
5911
  'persistence_name': '',
5718
5912
  'cookie_domain': '',
@@ -5753,6 +5947,7 @@ var DEFAULT_CONFIG = {
5753
5947
  'record_block_selector': 'img, video',
5754
5948
  'record_canvas': false,
5755
5949
  'record_collect_fonts': false,
5950
+ 'record_heatmap_data': false,
5756
5951
  'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
5757
5952
  'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
5758
5953
  'record_mask_text_selector': '*',
@@ -5968,6 +6163,14 @@ MixpanelLib.prototype._init = function(token, config, name) {
5968
6163
  }, '');
5969
6164
  }
5970
6165
 
6166
+ this.flags = new FeatureFlagManager({
6167
+ getConfigFunc: _.bind(this.get_config, this),
6168
+ getDistinctIdFunc: _.bind(this.get_distinct_id, this),
6169
+ trackingFunc: _.bind(this.track, this)
6170
+ });
6171
+ this.flags.init();
6172
+ this['flags'] = this.flags;
6173
+
5971
6174
  this.autocapture = new Autocapture(this);
5972
6175
  this.autocapture.init();
5973
6176
 
@@ -6093,6 +6296,10 @@ MixpanelLib.prototype.resume_session_recording = function () {
6093
6296
  }
6094
6297
  };
6095
6298
 
6299
+ MixpanelLib.prototype.is_recording_heatmap_data = function () {
6300
+ return this._get_session_replay_id() && this.get_config('record_heatmap_data');
6301
+ };
6302
+
6096
6303
  MixpanelLib.prototype.get_session_recording_properties = function () {
6097
6304
  var props = {};
6098
6305
  var replay_id = this._get_session_replay_id();
@@ -7174,6 +7381,11 @@ MixpanelLib.prototype.identify = function(
7174
7381
  '$anon_distinct_id': previous_distinct_id
7175
7382
  }, {skip_hooks: true});
7176
7383
  }
7384
+
7385
+ // check feature flags again if distinct id has changed
7386
+ if (new_distinct_id !== previous_distinct_id) {
7387
+ this.flags.fetchFlags();
7388
+ }
7177
7389
  };
7178
7390
 
7179
7391
  /**
@@ -7448,7 +7660,7 @@ MixpanelLib.prototype.set_config = function(config) {
7448
7660
  }
7449
7661
  Config.DEBUG = Config.DEBUG || this.get_config('debug');
7450
7662
 
7451
- if ('autocapture' in config && this.autocapture) {
7663
+ if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
7452
7664
  this.autocapture.init();
7453
7665
  }
7454
7666
  }