mixpanel-browser 2.62.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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.62.0'
6
+ LIB_VERSION: '2.64.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
@@ -1239,7 +1239,7 @@
1239
1239
  uuid[i] = Math.floor(Math.random() * 16);
1240
1240
  }
1241
1241
  uuid[14] = 4; // set bits 12-15 of time-high-and-version to 0100
1242
- uuid[19] = uuid[19] &= ~(1 << 2); // set bit 6 of clock-seq-and-reserved to zero
1242
+ uuid[19] = uuid[19] &= -5; // set bit 6 of clock-seq-and-reserved to zero
1243
1243
  uuid[19] = uuid[19] |= (1 << 3); // set bit 7 of clock-seq-and-reserved to one
1244
1244
  uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
1245
1245
 
@@ -2132,6 +2132,8 @@
2132
2132
  };
2133
2133
 
2134
2134
  // stateless utils
2135
+ // mostly from https://github.com/mixpanel/mixpanel-js/blob/989ada50f518edab47b9c4fd9535f9fbd5ec5fc0/src/autotrack-utils.js
2136
+
2135
2137
 
2136
2138
  var EV_CHANGE = 'change';
2137
2139
  var EV_CLICK = 'click';
@@ -2157,7 +2159,7 @@
2157
2159
  'href', 'name', 'role', 'title', 'type'
2158
2160
  ];
2159
2161
 
2160
- var logger$3 = console_with_prefix('autocapture');
2162
+ var logger$4 = console_with_prefix('autocapture');
2161
2163
 
2162
2164
 
2163
2165
  function getClasses(el) {
@@ -2243,6 +2245,7 @@
2243
2245
  var blockSelectors = config.blockSelectors || [];
2244
2246
  var captureTextContent = config.captureTextContent || false;
2245
2247
  var captureExtraAttrs = config.captureExtraAttrs || [];
2248
+ var capturedForHeatMap = config.capturedForHeatMap || false;
2246
2249
 
2247
2250
  // convert array to set every time, as the config may have changed
2248
2251
  var blockAttrsSet = {};
@@ -2321,6 +2324,9 @@
2321
2324
  props['$' + prop] = ev[prop];
2322
2325
  }
2323
2326
  });
2327
+ if (capturedForHeatMap) {
2328
+ props['$captured_for_heatmap'] = true;
2329
+ }
2324
2330
  target = guessRealClickTarget(ev);
2325
2331
  }
2326
2332
  // prioritize text content from "real" click target if different from original target
@@ -2415,7 +2421,7 @@
2415
2421
  return false;
2416
2422
  }
2417
2423
  } catch (err) {
2418
- logger$3.critical('Error while checking element in allowElementCallback', err);
2424
+ logger$4.critical('Error while checking element in allowElementCallback', err);
2419
2425
  return false;
2420
2426
  }
2421
2427
  }
@@ -2432,7 +2438,7 @@
2432
2438
  return true;
2433
2439
  }
2434
2440
  } catch (err) {
2435
- logger$3.critical('Error while checking selector: ' + sel, err);
2441
+ logger$4.critical('Error while checking selector: ' + sel, err);
2436
2442
  }
2437
2443
  }
2438
2444
  return false;
@@ -2447,7 +2453,7 @@
2447
2453
  return true;
2448
2454
  }
2449
2455
  } catch (err) {
2450
- logger$3.critical('Error while checking element in blockElementCallback', err);
2456
+ logger$4.critical('Error while checking element in blockElementCallback', err);
2451
2457
  return true;
2452
2458
  }
2453
2459
  }
@@ -2461,7 +2467,7 @@
2461
2467
  return true;
2462
2468
  }
2463
2469
  } catch (err) {
2464
- logger$3.critical('Error while checking selector: ' + sel, err);
2470
+ logger$4.critical('Error while checking selector: ' + sel, err);
2465
2471
  }
2466
2472
  }
2467
2473
  }
@@ -2667,22 +2673,22 @@
2667
2673
  var CONFIG_TRACK_SCROLL = 'scroll';
2668
2674
  var CONFIG_TRACK_SUBMIT = 'submit';
2669
2675
 
2670
- var CONFIG_DEFAULTS = {};
2671
- CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
2672
- CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
2673
- CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
2674
- CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
2675
- CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
2676
- CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
2677
- CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
2678
- CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
2679
- CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
2680
- CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2681
- CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
2682
- CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
2683
- CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2684
- CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
2685
- CONFIG_DEFAULTS[CONFIG_TRACK_SUBMIT] = true;
2676
+ var CONFIG_DEFAULTS$1 = {};
2677
+ CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
2678
+ CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
2679
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
2680
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
2681
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
2682
+ CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
2683
+ CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
2684
+ CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
2685
+ CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
2686
+ CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2687
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
2688
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
2689
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2690
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
2691
+ CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
2686
2692
 
2687
2693
  var DEFAULT_PROPS = {
2688
2694
  '$mp_autocapture': true
@@ -2703,7 +2709,7 @@
2703
2709
 
2704
2710
  Autocapture.prototype.init = function() {
2705
2711
  if (!minDOMApisSupported()) {
2706
- logger$3.critical('Autocapture unavailable: missing required DOM APIs');
2712
+ logger$4.critical('Autocapture unavailable: missing required DOM APIs');
2707
2713
  return;
2708
2714
  }
2709
2715
 
@@ -2720,10 +2726,10 @@
2720
2726
  // Autocapture is completely off
2721
2727
  return {};
2722
2728
  } else if (_.isObject(autocaptureConfig)) {
2723
- return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
2729
+ return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
2724
2730
  } else {
2725
2731
  // Autocapture config is non-object truthy value, return default
2726
- return CONFIG_DEFAULTS;
2732
+ return CONFIG_DEFAULTS$1;
2727
2733
  }
2728
2734
  };
2729
2735
 
@@ -2747,7 +2753,7 @@
2747
2753
  break;
2748
2754
  }
2749
2755
  } catch (err) {
2750
- logger$3.critical('Error while checking block URL regex: ' + allowRegex, err);
2756
+ logger$4.critical('Error while checking block URL regex: ' + allowRegex, err);
2751
2757
  return true;
2752
2758
  }
2753
2759
  }
@@ -2768,7 +2774,7 @@
2768
2774
  return true;
2769
2775
  }
2770
2776
  } catch (err) {
2771
- logger$3.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
2777
+ logger$4.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
2772
2778
  return true;
2773
2779
  }
2774
2780
  }
@@ -2797,7 +2803,8 @@
2797
2803
  blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
2798
2804
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
2799
2805
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
2800
- captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
2806
+ captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
2807
+ capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
2801
2808
  });
2802
2809
  if (props) {
2803
2810
  _.extend(props, DEFAULT_PROPS);
@@ -2808,13 +2815,13 @@
2808
2815
  Autocapture.prototype.initClickTracking = function() {
2809
2816
  win.removeEventListener(EV_CLICK, this.listenerClick);
2810
2817
 
2811
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2818
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
2812
2819
  return;
2813
2820
  }
2814
- logger$3.log('Initializing click tracking');
2821
+ logger$4.log('Initializing click tracking');
2815
2822
 
2816
2823
  this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
2817
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2824
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
2818
2825
  return;
2819
2826
  }
2820
2827
  this.trackDomEvent(ev, MP_EV_CLICK);
@@ -2827,7 +2834,7 @@
2827
2834
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
2828
2835
  return;
2829
2836
  }
2830
- logger$3.log('Initializing input tracking');
2837
+ logger$4.log('Initializing input tracking');
2831
2838
 
2832
2839
  this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
2833
2840
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -2845,7 +2852,7 @@
2845
2852
  if (!this.pageviewTrackingConfig()) {
2846
2853
  return;
2847
2854
  }
2848
- logger$3.log('Initializing pageview tracking');
2855
+ logger$4.log('Initializing pageview tracking');
2849
2856
 
2850
2857
  var previousTrackedUrl = '';
2851
2858
  var tracked = false;
@@ -2900,7 +2907,7 @@
2900
2907
  }
2901
2908
  if (didPathChange) {
2902
2909
  this.lastScrollCheckpoint = 0;
2903
- logger$3.log('Path change: re-initializing scroll depth checkpoints');
2910
+ logger$4.log('Path change: re-initializing scroll depth checkpoints');
2904
2911
  }
2905
2912
  }
2906
2913
  }.bind(this)));
@@ -2912,7 +2919,7 @@
2912
2919
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
2913
2920
  return;
2914
2921
  }
2915
- logger$3.log('Initializing scroll tracking');
2922
+ logger$4.log('Initializing scroll tracking');
2916
2923
  this.lastScrollCheckpoint = 0;
2917
2924
 
2918
2925
  this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
@@ -2949,7 +2956,7 @@
2949
2956
  }
2950
2957
  }
2951
2958
  } catch (err) {
2952
- logger$3.critical('Error while calculating scroll percentage', err);
2959
+ logger$4.critical('Error while calculating scroll percentage', err);
2953
2960
  }
2954
2961
  if (shouldTrack) {
2955
2962
  this.mp.track(MP_EV_SCROLL, props);
@@ -2963,7 +2970,7 @@
2963
2970
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
2964
2971
  return;
2965
2972
  }
2966
- logger$3.log('Initializing submit tracking');
2973
+ logger$4.log('Initializing submit tracking');
2967
2974
 
2968
2975
  this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
2969
2976
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -2976,8 +2983,196 @@
2976
2983
  // TODO integrate error_reporter from mixpanel instance
2977
2984
  safewrapClass(Autocapture);
2978
2985
 
2986
+ var fetch = win['fetch'];
2987
+ var logger$3 = console_with_prefix('flags');
2988
+
2989
+ var FLAGS_CONFIG_KEY = 'flags';
2990
+
2991
+ var CONFIG_CONTEXT = 'context';
2992
+ var CONFIG_DEFAULTS = {};
2993
+ CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
2994
+
2995
+ /**
2996
+ * FeatureFlagManager: support for Mixpanel's feature flagging product
2997
+ * @constructor
2998
+ */
2999
+ var FeatureFlagManager = function(initOptions) {
3000
+ this.getMpConfig = initOptions.getConfigFunc;
3001
+ this.getDistinctId = initOptions.getDistinctIdFunc;
3002
+ this.track = initOptions.trackingFunc;
3003
+ };
3004
+
3005
+ FeatureFlagManager.prototype.init = function() {
3006
+ if (!minApisSupported()) {
3007
+ logger$3.critical('Feature Flags unavailable: missing minimum required APIs');
3008
+ return;
3009
+ }
3010
+
3011
+ this.flags = null;
3012
+ this.fetchFlags();
3013
+
3014
+ this.trackedFeatures = new Set();
3015
+ };
3016
+
3017
+ FeatureFlagManager.prototype.getFullConfig = function() {
3018
+ var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
3019
+ if (!ffConfig) {
3020
+ // flags are completely off
3021
+ return {};
3022
+ } else if (_.isObject(ffConfig)) {
3023
+ return _.extend({}, CONFIG_DEFAULTS, ffConfig);
3024
+ } else {
3025
+ // config is non-object truthy value, return default
3026
+ return CONFIG_DEFAULTS;
3027
+ }
3028
+ };
3029
+
3030
+ FeatureFlagManager.prototype.getConfig = function(key) {
3031
+ return this.getFullConfig()[key];
3032
+ };
3033
+
3034
+ FeatureFlagManager.prototype.isEnabled = function() {
3035
+ return !!this.getMpConfig(FLAGS_CONFIG_KEY);
3036
+ };
3037
+
3038
+ FeatureFlagManager.prototype.areFeaturesReady = function() {
3039
+ if (!this.isEnabled()) {
3040
+ logger$3.error('Feature Flags not enabled');
3041
+ }
3042
+ return !!this.flags;
3043
+ };
3044
+
3045
+ FeatureFlagManager.prototype.fetchFlags = function() {
3046
+ if (!this.isEnabled()) {
3047
+ return;
3048
+ }
3049
+
3050
+ var distinctId = this.getDistinctId();
3051
+ logger$3.log('Fetching flags for distinct ID: ' + distinctId);
3052
+ var reqParams = {
3053
+ 'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
3054
+ };
3055
+ this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
3056
+ 'method': 'POST',
3057
+ 'headers': {
3058
+ 'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
3059
+ 'Content-Type': 'application/octet-stream'
3060
+ },
3061
+ 'body': JSON.stringify(reqParams)
3062
+ }).then(function(response) {
3063
+ return response.json().then(function(responseBody) {
3064
+ var responseFlags = responseBody['flags'];
3065
+ if (!responseFlags) {
3066
+ throw new Error('No flags in API response');
3067
+ }
3068
+ var flags = new Map();
3069
+ _.each(responseFlags, function(data, key) {
3070
+ flags.set(key, {
3071
+ 'key': data['variant_key'],
3072
+ 'data': data['variant_value']
3073
+ });
3074
+ });
3075
+ this.flags = flags;
3076
+ }.bind(this)).catch(function(error) {
3077
+ logger$3.error(error);
3078
+ });
3079
+ }.bind(this)).catch(function() {});
3080
+ };
3081
+
3082
+ FeatureFlagManager.prototype.getFeature = function(featureName, fallback) {
3083
+ if (!this.fetchPromise) {
3084
+ return new Promise(function(resolve) {
3085
+ logger$3.critical('Feature Flags not initialized');
3086
+ resolve(fallback);
3087
+ });
3088
+ }
3089
+
3090
+ return this.fetchPromise.then(function() {
3091
+ return this.getFeatureSync(featureName, fallback);
3092
+ }.bind(this)).catch(function(error) {
3093
+ logger$3.error(error);
3094
+ return fallback;
3095
+ });
3096
+ };
3097
+
3098
+ FeatureFlagManager.prototype.getFeatureSync = function(featureName, fallback) {
3099
+ if (!this.areFeaturesReady()) {
3100
+ logger$3.log('Flags not loaded yet');
3101
+ return fallback;
3102
+ }
3103
+ var feature = this.flags.get(featureName);
3104
+ if (!feature) {
3105
+ logger$3.log('No flag found: "' + featureName + '"');
3106
+ return fallback;
3107
+ }
3108
+ this.trackFeatureCheck(featureName, feature);
3109
+ return feature;
3110
+ };
3111
+
3112
+ FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
3113
+ return this.getFeature(featureName, {'data': fallbackValue}).then(function(feature) {
3114
+ return feature['data'];
3115
+ }).catch(function(error) {
3116
+ logger$3.error(error);
3117
+ return fallbackValue;
3118
+ });
3119
+ };
3120
+
3121
+ FeatureFlagManager.prototype.getFeatureDataSync = function(featureName, fallbackValue) {
3122
+ return this.getFeatureSync(featureName, {'data': fallbackValue})['data'];
3123
+ };
3124
+
3125
+ FeatureFlagManager.prototype.isFeatureEnabled = function(featureName, fallbackValue) {
3126
+ return this.getFeatureData(featureName).then(function() {
3127
+ return this.isFeatureEnabledSync(featureName, fallbackValue);
3128
+ }.bind(this)).catch(function(error) {
3129
+ logger$3.error(error);
3130
+ return fallbackValue;
3131
+ });
3132
+ };
3133
+
3134
+ FeatureFlagManager.prototype.isFeatureEnabledSync = function(featureName, fallbackValue) {
3135
+ fallbackValue = fallbackValue || false;
3136
+ var val = this.getFeatureDataSync(featureName, fallbackValue);
3137
+ if (val !== true && val !== false) {
3138
+ logger$3.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
3139
+ val = fallbackValue;
3140
+ }
3141
+ return val;
3142
+ };
3143
+
3144
+ FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
3145
+ if (this.trackedFeatures.has(featureName)) {
3146
+ return;
3147
+ }
3148
+ this.trackedFeatures.add(featureName);
3149
+ this.track('$experiment_started', {
3150
+ 'Experiment name': featureName,
3151
+ 'Variant name': feature['key'],
3152
+ '$experiment_type': 'feature_flag'
3153
+ });
3154
+ };
3155
+
3156
+ function minApisSupported() {
3157
+ return !!fetch &&
3158
+ typeof Promise !== 'undefined' &&
3159
+ typeof Map !== 'undefined' &&
3160
+ typeof Set !== 'undefined';
3161
+ }
3162
+
3163
+ safewrapClass(FeatureFlagManager);
3164
+
3165
+ FeatureFlagManager.prototype['are_features_ready'] = FeatureFlagManager.prototype.areFeaturesReady;
3166
+ FeatureFlagManager.prototype['get_feature'] = FeatureFlagManager.prototype.getFeature;
3167
+ FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
3168
+ FeatureFlagManager.prototype['get_feature_data_sync'] = FeatureFlagManager.prototype.getFeatureDataSync;
3169
+ FeatureFlagManager.prototype['get_feature_sync'] = FeatureFlagManager.prototype.getFeatureSync;
3170
+ FeatureFlagManager.prototype['is_feature_enabled'] = FeatureFlagManager.prototype.isFeatureEnabled;
3171
+ FeatureFlagManager.prototype['is_feature_enabled_sync'] = FeatureFlagManager.prototype.isFeatureEnabledSync;
3172
+
2979
3173
  /* eslint camelcase: "off" */
2980
3174
 
3175
+
2981
3176
  /**
2982
3177
  * DomTracker Object
2983
3178
  * @constructor
@@ -3281,7 +3476,7 @@
3281
3476
  * @type {import('./wrapper').StorageWrapper}
3282
3477
  */
3283
3478
  var LocalStorageWrapper = function (storageOverride) {
3284
- this.storage = storageOverride || localStorage;
3479
+ this.storage = storageOverride || win.localStorage;
3285
3480
  };
3286
3481
 
3287
3482
  LocalStorageWrapper.prototype.init = function () {
@@ -4028,6 +4223,7 @@
4028
4223
  * These functions are used internally by the SDK and are not intended to be publicly exposed.
4029
4224
  */
4030
4225
 
4226
+
4031
4227
  /**
4032
4228
  * A function used to track a Mixpanel event (e.g. MixpanelLib.track)
4033
4229
  * @callback trackFunction
@@ -4316,6 +4512,7 @@
4316
4512
 
4317
4513
  /* eslint camelcase: "off" */
4318
4514
 
4515
+
4319
4516
  /** @const */ var SET_ACTION = '$set';
4320
4517
  /** @const */ var SET_ONCE_ACTION = '$set_once';
4321
4518
  /** @const */ var UNSET_ACTION = '$unset';
@@ -5075,6 +5272,7 @@
5075
5272
 
5076
5273
  /* eslint camelcase: "off" */
5077
5274
 
5275
+
5078
5276
  /*
5079
5277
  * Constants
5080
5278
  */
@@ -5687,10 +5885,11 @@
5687
5885
  }
5688
5886
 
5689
5887
  var DEFAULT_API_ROUTES = {
5690
- 'track': 'track/',
5888
+ 'track': 'track/',
5691
5889
  'engage': 'engage/',
5692
5890
  'groups': 'groups/',
5693
- 'record': 'record/'
5891
+ 'record': 'record/',
5892
+ 'flags': 'flags/'
5694
5893
  };
5695
5894
 
5696
5895
  /*
@@ -5708,6 +5907,7 @@
5708
5907
  'cross_site_cookie': false,
5709
5908
  'cross_subdomain_cookie': true,
5710
5909
  'error_reporter': NOOP_FUNC,
5910
+ 'flags': false,
5711
5911
  'persistence': 'cookie',
5712
5912
  'persistence_name': '',
5713
5913
  'cookie_domain': '',
@@ -5748,6 +5948,7 @@
5748
5948
  'record_block_selector': 'img, video',
5749
5949
  'record_canvas': false,
5750
5950
  'record_collect_fonts': false,
5951
+ 'record_heatmap_data': false,
5751
5952
  'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
5752
5953
  'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
5753
5954
  'record_mask_text_selector': '*',
@@ -5963,6 +6164,14 @@
5963
6164
  }, '');
5964
6165
  }
5965
6166
 
6167
+ this.flags = new FeatureFlagManager({
6168
+ getConfigFunc: _.bind(this.get_config, this),
6169
+ getDistinctIdFunc: _.bind(this.get_distinct_id, this),
6170
+ trackingFunc: _.bind(this.track, this)
6171
+ });
6172
+ this.flags.init();
6173
+ this['flags'] = this.flags;
6174
+
5966
6175
  this.autocapture = new Autocapture(this);
5967
6176
  this.autocapture.init();
5968
6177
 
@@ -6088,6 +6297,10 @@
6088
6297
  }
6089
6298
  };
6090
6299
 
6300
+ MixpanelLib.prototype.is_recording_heatmap_data = function () {
6301
+ return this._get_session_replay_id() && this.get_config('record_heatmap_data');
6302
+ };
6303
+
6091
6304
  MixpanelLib.prototype.get_session_recording_properties = function () {
6092
6305
  var props = {};
6093
6306
  var replay_id = this._get_session_replay_id();
@@ -7169,6 +7382,11 @@
7169
7382
  '$anon_distinct_id': previous_distinct_id
7170
7383
  }, {skip_hooks: true});
7171
7384
  }
7385
+
7386
+ // check feature flags again if distinct id has changed
7387
+ if (new_distinct_id !== previous_distinct_id) {
7388
+ this.flags.fetchFlags();
7389
+ }
7172
7390
  };
7173
7391
 
7174
7392
  /**
@@ -7443,7 +7661,7 @@
7443
7661
  }
7444
7662
  Config.DEBUG = Config.DEBUG || this.get_config('debug');
7445
7663
 
7446
- if ('autocapture' in config && this.autocapture) {
7664
+ if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
7447
7665
  this.autocapture.init();
7448
7666
  }
7449
7667
  }