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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  var Config = {
5
5
  DEBUG: false,
6
- LIB_VERSION: '2.63.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
@@ -2159,7 +2159,7 @@
2159
2159
  'href', 'name', 'role', 'title', 'type'
2160
2160
  ];
2161
2161
 
2162
- var logger$3 = console_with_prefix('autocapture');
2162
+ var logger$4 = console_with_prefix('autocapture');
2163
2163
 
2164
2164
 
2165
2165
  function getClasses(el) {
@@ -2245,6 +2245,7 @@
2245
2245
  var blockSelectors = config.blockSelectors || [];
2246
2246
  var captureTextContent = config.captureTextContent || false;
2247
2247
  var captureExtraAttrs = config.captureExtraAttrs || [];
2248
+ var capturedForHeatMap = config.capturedForHeatMap || false;
2248
2249
 
2249
2250
  // convert array to set every time, as the config may have changed
2250
2251
  var blockAttrsSet = {};
@@ -2323,6 +2324,9 @@
2323
2324
  props['$' + prop] = ev[prop];
2324
2325
  }
2325
2326
  });
2327
+ if (capturedForHeatMap) {
2328
+ props['$captured_for_heatmap'] = true;
2329
+ }
2326
2330
  target = guessRealClickTarget(ev);
2327
2331
  }
2328
2332
  // prioritize text content from "real" click target if different from original target
@@ -2417,7 +2421,7 @@
2417
2421
  return false;
2418
2422
  }
2419
2423
  } catch (err) {
2420
- logger$3.critical('Error while checking element in allowElementCallback', err);
2424
+ logger$4.critical('Error while checking element in allowElementCallback', err);
2421
2425
  return false;
2422
2426
  }
2423
2427
  }
@@ -2434,7 +2438,7 @@
2434
2438
  return true;
2435
2439
  }
2436
2440
  } catch (err) {
2437
- logger$3.critical('Error while checking selector: ' + sel, err);
2441
+ logger$4.critical('Error while checking selector: ' + sel, err);
2438
2442
  }
2439
2443
  }
2440
2444
  return false;
@@ -2449,7 +2453,7 @@
2449
2453
  return true;
2450
2454
  }
2451
2455
  } catch (err) {
2452
- logger$3.critical('Error while checking element in blockElementCallback', err);
2456
+ logger$4.critical('Error while checking element in blockElementCallback', err);
2453
2457
  return true;
2454
2458
  }
2455
2459
  }
@@ -2463,7 +2467,7 @@
2463
2467
  return true;
2464
2468
  }
2465
2469
  } catch (err) {
2466
- logger$3.critical('Error while checking selector: ' + sel, err);
2470
+ logger$4.critical('Error while checking selector: ' + sel, err);
2467
2471
  }
2468
2472
  }
2469
2473
  }
@@ -2669,22 +2673,22 @@
2669
2673
  var CONFIG_TRACK_SCROLL = 'scroll';
2670
2674
  var CONFIG_TRACK_SUBMIT = 'submit';
2671
2675
 
2672
- var CONFIG_DEFAULTS = {};
2673
- CONFIG_DEFAULTS[CONFIG_ALLOW_SELECTORS] = [];
2674
- CONFIG_DEFAULTS[CONFIG_ALLOW_URL_REGEXES] = [];
2675
- CONFIG_DEFAULTS[CONFIG_BLOCK_ATTRS] = [];
2676
- CONFIG_DEFAULTS[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
2677
- CONFIG_DEFAULTS[CONFIG_BLOCK_SELECTORS] = [];
2678
- CONFIG_DEFAULTS[CONFIG_BLOCK_URL_REGEXES] = [];
2679
- CONFIG_DEFAULTS[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
2680
- CONFIG_DEFAULTS[CONFIG_CAPTURE_TEXT_CONTENT] = false;
2681
- CONFIG_DEFAULTS[CONFIG_SCROLL_CAPTURE_ALL] = false;
2682
- CONFIG_DEFAULTS[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
2683
- CONFIG_DEFAULTS[CONFIG_TRACK_CLICK] = true;
2684
- CONFIG_DEFAULTS[CONFIG_TRACK_INPUT] = true;
2685
- CONFIG_DEFAULTS[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
2686
- CONFIG_DEFAULTS[CONFIG_TRACK_SCROLL] = true;
2687
- 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;
2688
2692
 
2689
2693
  var DEFAULT_PROPS = {
2690
2694
  '$mp_autocapture': true
@@ -2705,7 +2709,7 @@
2705
2709
 
2706
2710
  Autocapture.prototype.init = function() {
2707
2711
  if (!minDOMApisSupported()) {
2708
- logger$3.critical('Autocapture unavailable: missing required DOM APIs');
2712
+ logger$4.critical('Autocapture unavailable: missing required DOM APIs');
2709
2713
  return;
2710
2714
  }
2711
2715
 
@@ -2722,10 +2726,10 @@
2722
2726
  // Autocapture is completely off
2723
2727
  return {};
2724
2728
  } else if (_.isObject(autocaptureConfig)) {
2725
- return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
2729
+ return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
2726
2730
  } else {
2727
2731
  // Autocapture config is non-object truthy value, return default
2728
- return CONFIG_DEFAULTS;
2732
+ return CONFIG_DEFAULTS$1;
2729
2733
  }
2730
2734
  };
2731
2735
 
@@ -2749,7 +2753,7 @@
2749
2753
  break;
2750
2754
  }
2751
2755
  } catch (err) {
2752
- logger$3.critical('Error while checking block URL regex: ' + allowRegex, err);
2756
+ logger$4.critical('Error while checking block URL regex: ' + allowRegex, err);
2753
2757
  return true;
2754
2758
  }
2755
2759
  }
@@ -2770,7 +2774,7 @@
2770
2774
  return true;
2771
2775
  }
2772
2776
  } catch (err) {
2773
- 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);
2774
2778
  return true;
2775
2779
  }
2776
2780
  }
@@ -2799,7 +2803,8 @@
2799
2803
  blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
2800
2804
  blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
2801
2805
  captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
2802
- 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(),
2803
2808
  });
2804
2809
  if (props) {
2805
2810
  _.extend(props, DEFAULT_PROPS);
@@ -2810,13 +2815,13 @@
2810
2815
  Autocapture.prototype.initClickTracking = function() {
2811
2816
  win.removeEventListener(EV_CLICK, this.listenerClick);
2812
2817
 
2813
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2818
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
2814
2819
  return;
2815
2820
  }
2816
- logger$3.log('Initializing click tracking');
2821
+ logger$4.log('Initializing click tracking');
2817
2822
 
2818
2823
  this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
2819
- if (!this.getConfig(CONFIG_TRACK_CLICK)) {
2824
+ if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
2820
2825
  return;
2821
2826
  }
2822
2827
  this.trackDomEvent(ev, MP_EV_CLICK);
@@ -2829,7 +2834,7 @@
2829
2834
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
2830
2835
  return;
2831
2836
  }
2832
- logger$3.log('Initializing input tracking');
2837
+ logger$4.log('Initializing input tracking');
2833
2838
 
2834
2839
  this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
2835
2840
  if (!this.getConfig(CONFIG_TRACK_INPUT)) {
@@ -2847,7 +2852,7 @@
2847
2852
  if (!this.pageviewTrackingConfig()) {
2848
2853
  return;
2849
2854
  }
2850
- logger$3.log('Initializing pageview tracking');
2855
+ logger$4.log('Initializing pageview tracking');
2851
2856
 
2852
2857
  var previousTrackedUrl = '';
2853
2858
  var tracked = false;
@@ -2902,7 +2907,7 @@
2902
2907
  }
2903
2908
  if (didPathChange) {
2904
2909
  this.lastScrollCheckpoint = 0;
2905
- logger$3.log('Path change: re-initializing scroll depth checkpoints');
2910
+ logger$4.log('Path change: re-initializing scroll depth checkpoints');
2906
2911
  }
2907
2912
  }
2908
2913
  }.bind(this)));
@@ -2914,7 +2919,7 @@
2914
2919
  if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
2915
2920
  return;
2916
2921
  }
2917
- logger$3.log('Initializing scroll tracking');
2922
+ logger$4.log('Initializing scroll tracking');
2918
2923
  this.lastScrollCheckpoint = 0;
2919
2924
 
2920
2925
  this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
@@ -2951,7 +2956,7 @@
2951
2956
  }
2952
2957
  }
2953
2958
  } catch (err) {
2954
- logger$3.critical('Error while calculating scroll percentage', err);
2959
+ logger$4.critical('Error while calculating scroll percentage', err);
2955
2960
  }
2956
2961
  if (shouldTrack) {
2957
2962
  this.mp.track(MP_EV_SCROLL, props);
@@ -2965,7 +2970,7 @@
2965
2970
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
2966
2971
  return;
2967
2972
  }
2968
- logger$3.log('Initializing submit tracking');
2973
+ logger$4.log('Initializing submit tracking');
2969
2974
 
2970
2975
  this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
2971
2976
  if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
@@ -2978,6 +2983,193 @@
2978
2983
  // TODO integrate error_reporter from mixpanel instance
2979
2984
  safewrapClass(Autocapture);
2980
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
+
2981
3173
  /* eslint camelcase: "off" */
2982
3174
 
2983
3175
 
@@ -5693,10 +5885,11 @@
5693
5885
  }
5694
5886
 
5695
5887
  var DEFAULT_API_ROUTES = {
5696
- 'track': 'track/',
5888
+ 'track': 'track/',
5697
5889
  'engage': 'engage/',
5698
5890
  'groups': 'groups/',
5699
- 'record': 'record/'
5891
+ 'record': 'record/',
5892
+ 'flags': 'flags/'
5700
5893
  };
5701
5894
 
5702
5895
  /*
@@ -5714,6 +5907,7 @@
5714
5907
  'cross_site_cookie': false,
5715
5908
  'cross_subdomain_cookie': true,
5716
5909
  'error_reporter': NOOP_FUNC,
5910
+ 'flags': false,
5717
5911
  'persistence': 'cookie',
5718
5912
  'persistence_name': '',
5719
5913
  'cookie_domain': '',
@@ -5754,6 +5948,7 @@
5754
5948
  'record_block_selector': 'img, video',
5755
5949
  'record_canvas': false,
5756
5950
  'record_collect_fonts': false,
5951
+ 'record_heatmap_data': false,
5757
5952
  'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
5758
5953
  'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
5759
5954
  'record_mask_text_selector': '*',
@@ -5969,6 +6164,14 @@
5969
6164
  }, '');
5970
6165
  }
5971
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
+
5972
6175
  this.autocapture = new Autocapture(this);
5973
6176
  this.autocapture.init();
5974
6177
 
@@ -6094,6 +6297,10 @@
6094
6297
  }
6095
6298
  };
6096
6299
 
6300
+ MixpanelLib.prototype.is_recording_heatmap_data = function () {
6301
+ return this._get_session_replay_id() && this.get_config('record_heatmap_data');
6302
+ };
6303
+
6097
6304
  MixpanelLib.prototype.get_session_recording_properties = function () {
6098
6305
  var props = {};
6099
6306
  var replay_id = this._get_session_replay_id();
@@ -7175,6 +7382,11 @@
7175
7382
  '$anon_distinct_id': previous_distinct_id
7176
7383
  }, {skip_hooks: true});
7177
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
+ }
7178
7390
  };
7179
7391
 
7180
7392
  /**
@@ -7449,7 +7661,7 @@
7449
7661
  }
7450
7662
  Config.DEBUG = Config.DEBUG || this.get_config('debug');
7451
7663
 
7452
- if ('autocapture' in config && this.autocapture) {
7664
+ if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
7453
7665
  this.autocapture.init();
7454
7666
  }
7455
7667
  }