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.
- package/CHANGELOG.md +4 -0
- package/dist/mixpanel-core.cjs.js +252 -40
- package/dist/mixpanel-recorder.js +1 -1
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +252 -40
- package/dist/mixpanel-with-recorder.js +273 -61
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +273 -61
- package/dist/mixpanel.cjs.js +273 -61
- package/dist/mixpanel.globals.js +252 -40
- package/dist/mixpanel.min.js +149 -143
- package/dist/mixpanel.module.js +273 -61
- package/dist/mixpanel.umd.js +273 -61
- package/package.json +1 -1
- package/src/autocapture/index.js +4 -3
- package/src/autocapture/utils.js +4 -0
- package/src/config.js +1 -1
- package/src/flags/index.js +191 -0
- package/src/mixpanel-core.js +24 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
**2.64.0** (15 Apr 2025)
|
|
2
|
+
- Add `record_heatmap_data` init option for Session Recording to ensure click events are captured for Heat Maps
|
|
3
|
+
- Initial support for feature flagging
|
|
4
|
+
|
|
1
5
|
**2.63.0** (1 Apr 2025)
|
|
2
6
|
- Update rrweb to latest alpha version
|
|
3
7
|
- Refactor SDK build process to rely mainly on Rollup
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var Config = {
|
|
4
4
|
DEBUG: false,
|
|
5
|
-
LIB_VERSION: '2.
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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':
|
|
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
|
}
|
|
@@ -13944,7 +13944,7 @@
|
|
|
13944
13944
|
}
|
|
13945
13945
|
|
|
13946
13946
|
var Config = {
|
|
13947
|
-
LIB_VERSION: '2.
|
|
13947
|
+
LIB_VERSION: '2.64.0'
|
|
13948
13948
|
};
|
|
13949
13949
|
|
|
13950
13950
|
/* eslint camelcase: "off", eqeqeq: "off" */
|