mixpanel-browser 2.63.0 → 2.65.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 +12 -0
- package/README.md +1 -1
- package/dist/mixpanel-core.cjs.js +276 -54
- package/dist/mixpanel-recorder.js +6 -2
- 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 +276 -54
- package/dist/mixpanel-with-recorder.js +297 -75
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.js +297 -75
- package/dist/mixpanel.cjs.js +297 -75
- package/dist/mixpanel.globals.js +276 -54
- package/dist/mixpanel.min.js +151 -144
- package/dist/mixpanel.module.js +297 -75
- package/dist/mixpanel.umd.js +297 -75
- package/package.json +1 -1
- package/src/autocapture/index.js +4 -3
- package/src/autocapture/utils.js +7 -1
- package/src/config.js +1 -1
- package/src/flags/index.js +200 -0
- package/src/mixpanel-core.js +29 -3
- package/src/mixpanel-people.js +2 -12
- package/src/utils.js +5 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var Config = {
|
|
4
4
|
DEBUG: false,
|
|
5
|
-
LIB_VERSION: '2.
|
|
5
|
+
LIB_VERSION: '2.65.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
|
|
@@ -1870,6 +1870,9 @@ _.info = {
|
|
|
1870
1870
|
return 'Microsoft Edge';
|
|
1871
1871
|
} else if (_.includes(user_agent, 'FBIOS')) {
|
|
1872
1872
|
return 'Facebook Mobile';
|
|
1873
|
+
} else if (_.includes(user_agent, 'Whale/')) {
|
|
1874
|
+
// https://user-agents.net/browsers/whale-browser
|
|
1875
|
+
return 'Whale Browser';
|
|
1873
1876
|
} else if (_.includes(user_agent, 'Chrome')) {
|
|
1874
1877
|
return 'Chrome';
|
|
1875
1878
|
} else if (_.includes(user_agent, 'CriOS')) {
|
|
@@ -1921,7 +1924,8 @@ _.info = {
|
|
|
1921
1924
|
'Android Mobile': /android\s(\d+(\.\d+)?)/,
|
|
1922
1925
|
'Samsung Internet': /SamsungBrowser\/(\d+(\.\d+)?)/,
|
|
1923
1926
|
'Internet Explorer': /(rv:|MSIE )(\d+(\.\d+)?)/,
|
|
1924
|
-
'Mozilla': /rv:(\d+(\.\d+)?)
|
|
1927
|
+
'Mozilla': /rv:(\d+(\.\d+)?)/,
|
|
1928
|
+
'Whale Browser': /Whale\/(\d+(\.\d+)?)/
|
|
1925
1929
|
};
|
|
1926
1930
|
var regex = versionRegexs[browser];
|
|
1927
1931
|
if (regex === undefined) {
|
|
@@ -2158,7 +2162,7 @@ var TRACKED_ATTRS = [
|
|
|
2158
2162
|
'href', 'name', 'role', 'title', 'type'
|
|
2159
2163
|
];
|
|
2160
2164
|
|
|
2161
|
-
var logger$
|
|
2165
|
+
var logger$4 = console_with_prefix('autocapture');
|
|
2162
2166
|
|
|
2163
2167
|
|
|
2164
2168
|
function getClasses(el) {
|
|
@@ -2244,6 +2248,7 @@ function getPropsForDOMEvent(ev, config) {
|
|
|
2244
2248
|
var blockSelectors = config.blockSelectors || [];
|
|
2245
2249
|
var captureTextContent = config.captureTextContent || false;
|
|
2246
2250
|
var captureExtraAttrs = config.captureExtraAttrs || [];
|
|
2251
|
+
var capturedForHeatMap = config.capturedForHeatMap || false;
|
|
2247
2252
|
|
|
2248
2253
|
// convert array to set every time, as the config may have changed
|
|
2249
2254
|
var blockAttrsSet = {};
|
|
@@ -2298,7 +2303,9 @@ function getPropsForDOMEvent(ev, config) {
|
|
|
2298
2303
|
'$elements': elementsJson,
|
|
2299
2304
|
'$el_attr__href': href,
|
|
2300
2305
|
'$viewportHeight': Math.max(docElement['clientHeight'], win['innerHeight'] || 0),
|
|
2301
|
-
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0)
|
|
2306
|
+
'$viewportWidth': Math.max(docElement['clientWidth'], win['innerWidth'] || 0),
|
|
2307
|
+
'$pageHeight': document$1['body']['offsetHeight'] || 0,
|
|
2308
|
+
'$pageWidth': document$1['body']['offsetWidth'] || 0,
|
|
2302
2309
|
};
|
|
2303
2310
|
_.each(captureExtraAttrs, function(attr) {
|
|
2304
2311
|
if (!blockAttrsSet[attr] && target.hasAttribute(attr)) {
|
|
@@ -2322,6 +2329,9 @@ function getPropsForDOMEvent(ev, config) {
|
|
|
2322
2329
|
props['$' + prop] = ev[prop];
|
|
2323
2330
|
}
|
|
2324
2331
|
});
|
|
2332
|
+
if (capturedForHeatMap) {
|
|
2333
|
+
props['$captured_for_heatmap'] = true;
|
|
2334
|
+
}
|
|
2325
2335
|
target = guessRealClickTarget(ev);
|
|
2326
2336
|
}
|
|
2327
2337
|
// prioritize text content from "real" click target if different from original target
|
|
@@ -2416,7 +2426,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
2416
2426
|
return false;
|
|
2417
2427
|
}
|
|
2418
2428
|
} catch (err) {
|
|
2419
|
-
logger$
|
|
2429
|
+
logger$4.critical('Error while checking element in allowElementCallback', err);
|
|
2420
2430
|
return false;
|
|
2421
2431
|
}
|
|
2422
2432
|
}
|
|
@@ -2433,7 +2443,7 @@ function isElementAllowed(el, ev, allowElementCallback, allowSelectors) {
|
|
|
2433
2443
|
return true;
|
|
2434
2444
|
}
|
|
2435
2445
|
} catch (err) {
|
|
2436
|
-
logger$
|
|
2446
|
+
logger$4.critical('Error while checking selector: ' + sel, err);
|
|
2437
2447
|
}
|
|
2438
2448
|
}
|
|
2439
2449
|
return false;
|
|
@@ -2448,7 +2458,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
2448
2458
|
return true;
|
|
2449
2459
|
}
|
|
2450
2460
|
} catch (err) {
|
|
2451
|
-
logger$
|
|
2461
|
+
logger$4.critical('Error while checking element in blockElementCallback', err);
|
|
2452
2462
|
return true;
|
|
2453
2463
|
}
|
|
2454
2464
|
}
|
|
@@ -2462,7 +2472,7 @@ function isElementBlocked(el, ev, blockElementCallback, blockSelectors) {
|
|
|
2462
2472
|
return true;
|
|
2463
2473
|
}
|
|
2464
2474
|
} catch (err) {
|
|
2465
|
-
logger$
|
|
2475
|
+
logger$4.critical('Error while checking selector: ' + sel, err);
|
|
2466
2476
|
}
|
|
2467
2477
|
}
|
|
2468
2478
|
}
|
|
@@ -2668,22 +2678,22 @@ var CONFIG_TRACK_PAGEVIEW = 'pageview';
|
|
|
2668
2678
|
var CONFIG_TRACK_SCROLL = 'scroll';
|
|
2669
2679
|
var CONFIG_TRACK_SUBMIT = 'submit';
|
|
2670
2680
|
|
|
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;
|
|
2681
|
+
var CONFIG_DEFAULTS$1 = {};
|
|
2682
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_SELECTORS] = [];
|
|
2683
|
+
CONFIG_DEFAULTS$1[CONFIG_ALLOW_URL_REGEXES] = [];
|
|
2684
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ATTRS] = [];
|
|
2685
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_ELEMENT_CALLBACK] = null;
|
|
2686
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_SELECTORS] = [];
|
|
2687
|
+
CONFIG_DEFAULTS$1[CONFIG_BLOCK_URL_REGEXES] = [];
|
|
2688
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_EXTRA_ATTRS] = [];
|
|
2689
|
+
CONFIG_DEFAULTS$1[CONFIG_CAPTURE_TEXT_CONTENT] = false;
|
|
2690
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CAPTURE_ALL] = false;
|
|
2691
|
+
CONFIG_DEFAULTS$1[CONFIG_SCROLL_CHECKPOINTS] = [25, 50, 75, 100];
|
|
2692
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_CLICK] = true;
|
|
2693
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_INPUT] = true;
|
|
2694
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_PAGEVIEW] = PAGEVIEW_OPTION_FULL_URL;
|
|
2695
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SCROLL] = true;
|
|
2696
|
+
CONFIG_DEFAULTS$1[CONFIG_TRACK_SUBMIT] = true;
|
|
2687
2697
|
|
|
2688
2698
|
var DEFAULT_PROPS = {
|
|
2689
2699
|
'$mp_autocapture': true
|
|
@@ -2704,7 +2714,7 @@ var Autocapture = function(mp) {
|
|
|
2704
2714
|
|
|
2705
2715
|
Autocapture.prototype.init = function() {
|
|
2706
2716
|
if (!minDOMApisSupported()) {
|
|
2707
|
-
logger$
|
|
2717
|
+
logger$4.critical('Autocapture unavailable: missing required DOM APIs');
|
|
2708
2718
|
return;
|
|
2709
2719
|
}
|
|
2710
2720
|
|
|
@@ -2721,10 +2731,10 @@ Autocapture.prototype.getFullConfig = function() {
|
|
|
2721
2731
|
// Autocapture is completely off
|
|
2722
2732
|
return {};
|
|
2723
2733
|
} else if (_.isObject(autocaptureConfig)) {
|
|
2724
|
-
return _.extend({}, CONFIG_DEFAULTS, autocaptureConfig);
|
|
2734
|
+
return _.extend({}, CONFIG_DEFAULTS$1, autocaptureConfig);
|
|
2725
2735
|
} else {
|
|
2726
2736
|
// Autocapture config is non-object truthy value, return default
|
|
2727
|
-
return CONFIG_DEFAULTS;
|
|
2737
|
+
return CONFIG_DEFAULTS$1;
|
|
2728
2738
|
}
|
|
2729
2739
|
};
|
|
2730
2740
|
|
|
@@ -2748,7 +2758,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
2748
2758
|
break;
|
|
2749
2759
|
}
|
|
2750
2760
|
} catch (err) {
|
|
2751
|
-
logger$
|
|
2761
|
+
logger$4.critical('Error while checking block URL regex: ' + allowRegex, err);
|
|
2752
2762
|
return true;
|
|
2753
2763
|
}
|
|
2754
2764
|
}
|
|
@@ -2769,7 +2779,7 @@ Autocapture.prototype.currentUrlBlocked = function() {
|
|
|
2769
2779
|
return true;
|
|
2770
2780
|
}
|
|
2771
2781
|
} catch (err) {
|
|
2772
|
-
logger$
|
|
2782
|
+
logger$4.critical('Error while checking block URL regex: ' + blockUrlRegexes[i], err);
|
|
2773
2783
|
return true;
|
|
2774
2784
|
}
|
|
2775
2785
|
}
|
|
@@ -2798,7 +2808,8 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
|
|
|
2798
2808
|
blockElementCallback: this.getConfig(CONFIG_BLOCK_ELEMENT_CALLBACK),
|
|
2799
2809
|
blockSelectors: this.getConfig(CONFIG_BLOCK_SELECTORS),
|
|
2800
2810
|
captureExtraAttrs: this.getConfig(CONFIG_CAPTURE_EXTRA_ATTRS),
|
|
2801
|
-
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT)
|
|
2811
|
+
captureTextContent: this.getConfig(CONFIG_CAPTURE_TEXT_CONTENT),
|
|
2812
|
+
capturedForHeatMap: mpEventName === MP_EV_CLICK && !this.getConfig(CONFIG_TRACK_CLICK) && this.mp.is_recording_heatmap_data(),
|
|
2802
2813
|
});
|
|
2803
2814
|
if (props) {
|
|
2804
2815
|
_.extend(props, DEFAULT_PROPS);
|
|
@@ -2809,13 +2820,13 @@ Autocapture.prototype.trackDomEvent = function(ev, mpEventName) {
|
|
|
2809
2820
|
Autocapture.prototype.initClickTracking = function() {
|
|
2810
2821
|
win.removeEventListener(EV_CLICK, this.listenerClick);
|
|
2811
2822
|
|
|
2812
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
2823
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.get_config('record_heatmap_data')) {
|
|
2813
2824
|
return;
|
|
2814
2825
|
}
|
|
2815
|
-
logger$
|
|
2826
|
+
logger$4.log('Initializing click tracking');
|
|
2816
2827
|
|
|
2817
2828
|
this.listenerClick = win.addEventListener(EV_CLICK, function(ev) {
|
|
2818
|
-
if (!this.getConfig(CONFIG_TRACK_CLICK)) {
|
|
2829
|
+
if (!this.getConfig(CONFIG_TRACK_CLICK) && !this.mp.is_recording_heatmap_data()) {
|
|
2819
2830
|
return;
|
|
2820
2831
|
}
|
|
2821
2832
|
this.trackDomEvent(ev, MP_EV_CLICK);
|
|
@@ -2828,7 +2839,7 @@ Autocapture.prototype.initInputTracking = function() {
|
|
|
2828
2839
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
2829
2840
|
return;
|
|
2830
2841
|
}
|
|
2831
|
-
logger$
|
|
2842
|
+
logger$4.log('Initializing input tracking');
|
|
2832
2843
|
|
|
2833
2844
|
this.listenerChange = win.addEventListener(EV_CHANGE, function(ev) {
|
|
2834
2845
|
if (!this.getConfig(CONFIG_TRACK_INPUT)) {
|
|
@@ -2846,7 +2857,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
2846
2857
|
if (!this.pageviewTrackingConfig()) {
|
|
2847
2858
|
return;
|
|
2848
2859
|
}
|
|
2849
|
-
logger$
|
|
2860
|
+
logger$4.log('Initializing pageview tracking');
|
|
2850
2861
|
|
|
2851
2862
|
var previousTrackedUrl = '';
|
|
2852
2863
|
var tracked = false;
|
|
@@ -2901,7 +2912,7 @@ Autocapture.prototype.initPageviewTracking = function() {
|
|
|
2901
2912
|
}
|
|
2902
2913
|
if (didPathChange) {
|
|
2903
2914
|
this.lastScrollCheckpoint = 0;
|
|
2904
|
-
logger$
|
|
2915
|
+
logger$4.log('Path change: re-initializing scroll depth checkpoints');
|
|
2905
2916
|
}
|
|
2906
2917
|
}
|
|
2907
2918
|
}.bind(this)));
|
|
@@ -2913,7 +2924,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
2913
2924
|
if (!this.getConfig(CONFIG_TRACK_SCROLL)) {
|
|
2914
2925
|
return;
|
|
2915
2926
|
}
|
|
2916
|
-
logger$
|
|
2927
|
+
logger$4.log('Initializing scroll tracking');
|
|
2917
2928
|
this.lastScrollCheckpoint = 0;
|
|
2918
2929
|
|
|
2919
2930
|
this.listenerScroll = win.addEventListener(EV_SCROLLEND, safewrap(function() {
|
|
@@ -2950,7 +2961,7 @@ Autocapture.prototype.initScrollTracking = function() {
|
|
|
2950
2961
|
}
|
|
2951
2962
|
}
|
|
2952
2963
|
} catch (err) {
|
|
2953
|
-
logger$
|
|
2964
|
+
logger$4.critical('Error while calculating scroll percentage', err);
|
|
2954
2965
|
}
|
|
2955
2966
|
if (shouldTrack) {
|
|
2956
2967
|
this.mp.track(MP_EV_SCROLL, props);
|
|
@@ -2964,7 +2975,7 @@ Autocapture.prototype.initSubmitTracking = function() {
|
|
|
2964
2975
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
2965
2976
|
return;
|
|
2966
2977
|
}
|
|
2967
|
-
logger$
|
|
2978
|
+
logger$4.log('Initializing submit tracking');
|
|
2968
2979
|
|
|
2969
2980
|
this.listenerSubmit = win.addEventListener(EV_SUBMIT, function(ev) {
|
|
2970
2981
|
if (!this.getConfig(CONFIG_TRACK_SUBMIT)) {
|
|
@@ -2977,6 +2988,202 @@ Autocapture.prototype.initSubmitTracking = function() {
|
|
|
2977
2988
|
// TODO integrate error_reporter from mixpanel instance
|
|
2978
2989
|
safewrapClass(Autocapture);
|
|
2979
2990
|
|
|
2991
|
+
var fetch = win['fetch'];
|
|
2992
|
+
var logger$3 = console_with_prefix('flags');
|
|
2993
|
+
|
|
2994
|
+
var FLAGS_CONFIG_KEY = 'flags';
|
|
2995
|
+
|
|
2996
|
+
var CONFIG_CONTEXT = 'context';
|
|
2997
|
+
var CONFIG_DEFAULTS = {};
|
|
2998
|
+
CONFIG_DEFAULTS[CONFIG_CONTEXT] = {};
|
|
2999
|
+
|
|
3000
|
+
/**
|
|
3001
|
+
* FeatureFlagManager: support for Mixpanel's feature flagging product
|
|
3002
|
+
* @constructor
|
|
3003
|
+
*/
|
|
3004
|
+
var FeatureFlagManager = function(initOptions) {
|
|
3005
|
+
this.getMpConfig = initOptions.getConfigFunc;
|
|
3006
|
+
this.getDistinctId = initOptions.getDistinctIdFunc;
|
|
3007
|
+
this.track = initOptions.trackingFunc;
|
|
3008
|
+
};
|
|
3009
|
+
|
|
3010
|
+
FeatureFlagManager.prototype.init = function() {
|
|
3011
|
+
if (!minApisSupported()) {
|
|
3012
|
+
logger$3.critical('Feature Flags unavailable: missing minimum required APIs');
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
this.flags = null;
|
|
3017
|
+
this.fetchFlags();
|
|
3018
|
+
|
|
3019
|
+
this.trackedFeatures = new Set();
|
|
3020
|
+
};
|
|
3021
|
+
|
|
3022
|
+
FeatureFlagManager.prototype.getFullConfig = function() {
|
|
3023
|
+
var ffConfig = this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
3024
|
+
if (!ffConfig) {
|
|
3025
|
+
// flags are completely off
|
|
3026
|
+
return {};
|
|
3027
|
+
} else if (_.isObject(ffConfig)) {
|
|
3028
|
+
return _.extend({}, CONFIG_DEFAULTS, ffConfig);
|
|
3029
|
+
} else {
|
|
3030
|
+
// config is non-object truthy value, return default
|
|
3031
|
+
return CONFIG_DEFAULTS;
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
|
|
3035
|
+
FeatureFlagManager.prototype.getConfig = function(key) {
|
|
3036
|
+
return this.getFullConfig()[key];
|
|
3037
|
+
};
|
|
3038
|
+
|
|
3039
|
+
FeatureFlagManager.prototype.isSystemEnabled = function() {
|
|
3040
|
+
return !!this.getMpConfig(FLAGS_CONFIG_KEY);
|
|
3041
|
+
};
|
|
3042
|
+
|
|
3043
|
+
FeatureFlagManager.prototype.areFlagsReady = function() {
|
|
3044
|
+
if (!this.isSystemEnabled()) {
|
|
3045
|
+
logger$3.error('Feature Flags not enabled');
|
|
3046
|
+
}
|
|
3047
|
+
return !!this.flags;
|
|
3048
|
+
};
|
|
3049
|
+
|
|
3050
|
+
FeatureFlagManager.prototype.fetchFlags = function() {
|
|
3051
|
+
if (!this.isSystemEnabled()) {
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
var distinctId = this.getDistinctId();
|
|
3056
|
+
logger$3.log('Fetching flags for distinct ID: ' + distinctId);
|
|
3057
|
+
var reqParams = {
|
|
3058
|
+
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT))
|
|
3059
|
+
};
|
|
3060
|
+
this.fetchPromise = win['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], {
|
|
3061
|
+
'method': 'POST',
|
|
3062
|
+
'headers': {
|
|
3063
|
+
'Authorization': 'Basic ' + btoa(this.getMpConfig('token') + ':'),
|
|
3064
|
+
'Content-Type': 'application/octet-stream'
|
|
3065
|
+
},
|
|
3066
|
+
'body': JSON.stringify(reqParams)
|
|
3067
|
+
}).then(function(response) {
|
|
3068
|
+
return response.json().then(function(responseBody) {
|
|
3069
|
+
var responseFlags = responseBody['flags'];
|
|
3070
|
+
if (!responseFlags) {
|
|
3071
|
+
throw new Error('No flags in API response');
|
|
3072
|
+
}
|
|
3073
|
+
var flags = new Map();
|
|
3074
|
+
_.each(responseFlags, function(data, key) {
|
|
3075
|
+
flags.set(key, {
|
|
3076
|
+
'key': data['variant_key'],
|
|
3077
|
+
'value': data['variant_value']
|
|
3078
|
+
});
|
|
3079
|
+
});
|
|
3080
|
+
this.flags = flags;
|
|
3081
|
+
}.bind(this)).catch(function(error) {
|
|
3082
|
+
logger$3.error(error);
|
|
3083
|
+
});
|
|
3084
|
+
}.bind(this)).catch(function() {});
|
|
3085
|
+
};
|
|
3086
|
+
|
|
3087
|
+
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) {
|
|
3088
|
+
if (!this.fetchPromise) {
|
|
3089
|
+
return new Promise(function(resolve) {
|
|
3090
|
+
logger$3.critical('Feature Flags not initialized');
|
|
3091
|
+
resolve(fallback);
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
return this.fetchPromise.then(function() {
|
|
3096
|
+
return this.getVariantSync(featureName, fallback);
|
|
3097
|
+
}.bind(this)).catch(function(error) {
|
|
3098
|
+
logger$3.error(error);
|
|
3099
|
+
return fallback;
|
|
3100
|
+
});
|
|
3101
|
+
};
|
|
3102
|
+
|
|
3103
|
+
FeatureFlagManager.prototype.getVariantSync = function(featureName, fallback) {
|
|
3104
|
+
if (!this.areFlagsReady()) {
|
|
3105
|
+
logger$3.log('Flags not loaded yet');
|
|
3106
|
+
return fallback;
|
|
3107
|
+
}
|
|
3108
|
+
var feature = this.flags.get(featureName);
|
|
3109
|
+
if (!feature) {
|
|
3110
|
+
logger$3.log('No flag found: "' + featureName + '"');
|
|
3111
|
+
return fallback;
|
|
3112
|
+
}
|
|
3113
|
+
this.trackFeatureCheck(featureName, feature);
|
|
3114
|
+
return feature;
|
|
3115
|
+
};
|
|
3116
|
+
|
|
3117
|
+
FeatureFlagManager.prototype.getVariantValue = function(featureName, fallbackValue) {
|
|
3118
|
+
return this.getVariant(featureName, {'value': fallbackValue}).then(function(feature) {
|
|
3119
|
+
return feature['value'];
|
|
3120
|
+
}).catch(function(error) {
|
|
3121
|
+
logger$3.error(error);
|
|
3122
|
+
return fallbackValue;
|
|
3123
|
+
});
|
|
3124
|
+
};
|
|
3125
|
+
|
|
3126
|
+
// TODO remove deprecated method
|
|
3127
|
+
FeatureFlagManager.prototype.getFeatureData = function(featureName, fallbackValue) {
|
|
3128
|
+
logger$3.critical('mixpanel.flags.get_feature_data() is deprecated and will be removed in a future release. Use mixpanel.flags.get_variant_value() instead.');
|
|
3129
|
+
return this.getVariantValue(featureName, fallbackValue);
|
|
3130
|
+
};
|
|
3131
|
+
|
|
3132
|
+
FeatureFlagManager.prototype.getVariantValueSync = function(featureName, fallbackValue) {
|
|
3133
|
+
return this.getVariantSync(featureName, {'value': fallbackValue})['value'];
|
|
3134
|
+
};
|
|
3135
|
+
|
|
3136
|
+
FeatureFlagManager.prototype.isEnabled = function(featureName, fallbackValue) {
|
|
3137
|
+
return this.getVariantValue(featureName).then(function() {
|
|
3138
|
+
return this.isEnabledSync(featureName, fallbackValue);
|
|
3139
|
+
}.bind(this)).catch(function(error) {
|
|
3140
|
+
logger$3.error(error);
|
|
3141
|
+
return fallbackValue;
|
|
3142
|
+
});
|
|
3143
|
+
};
|
|
3144
|
+
|
|
3145
|
+
FeatureFlagManager.prototype.isEnabledSync = function(featureName, fallbackValue) {
|
|
3146
|
+
fallbackValue = fallbackValue || false;
|
|
3147
|
+
var val = this.getVariantValueSync(featureName, fallbackValue);
|
|
3148
|
+
if (val !== true && val !== false) {
|
|
3149
|
+
logger$3.error('Feature flag "' + featureName + '" value: ' + val + ' is not a boolean; returning fallback value: ' + fallbackValue);
|
|
3150
|
+
val = fallbackValue;
|
|
3151
|
+
}
|
|
3152
|
+
return val;
|
|
3153
|
+
};
|
|
3154
|
+
|
|
3155
|
+
FeatureFlagManager.prototype.trackFeatureCheck = function(featureName, feature) {
|
|
3156
|
+
if (this.trackedFeatures.has(featureName)) {
|
|
3157
|
+
return;
|
|
3158
|
+
}
|
|
3159
|
+
this.trackedFeatures.add(featureName);
|
|
3160
|
+
this.track('$experiment_started', {
|
|
3161
|
+
'Experiment name': featureName,
|
|
3162
|
+
'Variant name': feature['key'],
|
|
3163
|
+
'$experiment_type': 'feature_flag'
|
|
3164
|
+
});
|
|
3165
|
+
};
|
|
3166
|
+
|
|
3167
|
+
function minApisSupported() {
|
|
3168
|
+
return !!fetch &&
|
|
3169
|
+
typeof Promise !== 'undefined' &&
|
|
3170
|
+
typeof Map !== 'undefined' &&
|
|
3171
|
+
typeof Set !== 'undefined';
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
safewrapClass(FeatureFlagManager);
|
|
3175
|
+
|
|
3176
|
+
FeatureFlagManager.prototype['are_flags_ready'] = FeatureFlagManager.prototype.areFlagsReady;
|
|
3177
|
+
FeatureFlagManager.prototype['get_variant'] = FeatureFlagManager.prototype.getVariant;
|
|
3178
|
+
FeatureFlagManager.prototype['get_variant_sync'] = FeatureFlagManager.prototype.getVariantSync;
|
|
3179
|
+
FeatureFlagManager.prototype['get_variant_value'] = FeatureFlagManager.prototype.getVariantValue;
|
|
3180
|
+
FeatureFlagManager.prototype['get_variant_value_sync'] = FeatureFlagManager.prototype.getVariantValueSync;
|
|
3181
|
+
FeatureFlagManager.prototype['is_enabled'] = FeatureFlagManager.prototype.isEnabled;
|
|
3182
|
+
FeatureFlagManager.prototype['is_enabled_sync'] = FeatureFlagManager.prototype.isEnabledSync;
|
|
3183
|
+
|
|
3184
|
+
// Deprecated method
|
|
3185
|
+
FeatureFlagManager.prototype['get_feature_data'] = FeatureFlagManager.prototype.getFeatureData;
|
|
3186
|
+
|
|
2980
3187
|
/* eslint camelcase: "off" */
|
|
2981
3188
|
|
|
2982
3189
|
|
|
@@ -4859,18 +5066,8 @@ MixpanelPeople.prototype.union = addOptOutCheckMixpanelPeople(function(list_name
|
|
|
4859
5066
|
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
4860
5067
|
* @deprecated
|
|
4861
5068
|
*/
|
|
4862
|
-
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(
|
|
4863
|
-
|
|
4864
|
-
amount = parseFloat(amount);
|
|
4865
|
-
if (isNaN(amount)) {
|
|
4866
|
-
console.error('Invalid value passed to mixpanel.people.track_charge - must be a number');
|
|
4867
|
-
return;
|
|
4868
|
-
}
|
|
4869
|
-
}
|
|
4870
|
-
|
|
4871
|
-
return this.append('$transactions', _.extend({
|
|
4872
|
-
'$amount': amount
|
|
4873
|
-
}, properties), callback);
|
|
5069
|
+
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function() {
|
|
5070
|
+
console.error('mixpanel.people.track_charge() is deprecated and no longer has any effect.');
|
|
4874
5071
|
});
|
|
4875
5072
|
|
|
4876
5073
|
/*
|
|
@@ -5692,10 +5889,11 @@ if (navigator['sendBeacon']) {
|
|
|
5692
5889
|
}
|
|
5693
5890
|
|
|
5694
5891
|
var DEFAULT_API_ROUTES = {
|
|
5695
|
-
'track':
|
|
5892
|
+
'track': 'track/',
|
|
5696
5893
|
'engage': 'engage/',
|
|
5697
5894
|
'groups': 'groups/',
|
|
5698
|
-
'record': 'record/'
|
|
5895
|
+
'record': 'record/',
|
|
5896
|
+
'flags': 'flags/'
|
|
5699
5897
|
};
|
|
5700
5898
|
|
|
5701
5899
|
/*
|
|
@@ -5704,6 +5902,7 @@ var DEFAULT_API_ROUTES = {
|
|
|
5704
5902
|
var DEFAULT_CONFIG = {
|
|
5705
5903
|
'api_host': 'https://api-js.mixpanel.com',
|
|
5706
5904
|
'api_routes': DEFAULT_API_ROUTES,
|
|
5905
|
+
'api_extra_query_params': {},
|
|
5707
5906
|
'api_method': 'POST',
|
|
5708
5907
|
'api_transport': 'XHR',
|
|
5709
5908
|
'api_payload_format': PAYLOAD_TYPE_BASE64,
|
|
@@ -5713,6 +5912,7 @@ var DEFAULT_CONFIG = {
|
|
|
5713
5912
|
'cross_site_cookie': false,
|
|
5714
5913
|
'cross_subdomain_cookie': true,
|
|
5715
5914
|
'error_reporter': NOOP_FUNC,
|
|
5915
|
+
'flags': false,
|
|
5716
5916
|
'persistence': 'cookie',
|
|
5717
5917
|
'persistence_name': '',
|
|
5718
5918
|
'cookie_domain': '',
|
|
@@ -5753,6 +5953,7 @@ var DEFAULT_CONFIG = {
|
|
|
5753
5953
|
'record_block_selector': 'img, video',
|
|
5754
5954
|
'record_canvas': false,
|
|
5755
5955
|
'record_collect_fonts': false,
|
|
5956
|
+
'record_heatmap_data': false,
|
|
5756
5957
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
5757
5958
|
'record_mask_text_class': new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$'),
|
|
5758
5959
|
'record_mask_text_selector': '*',
|
|
@@ -5968,6 +6169,14 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
5968
6169
|
}, '');
|
|
5969
6170
|
}
|
|
5970
6171
|
|
|
6172
|
+
this.flags = new FeatureFlagManager({
|
|
6173
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
6174
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
6175
|
+
trackingFunc: _.bind(this.track, this)
|
|
6176
|
+
});
|
|
6177
|
+
this.flags.init();
|
|
6178
|
+
this['flags'] = this.flags;
|
|
6179
|
+
|
|
5971
6180
|
this.autocapture = new Autocapture(this);
|
|
5972
6181
|
this.autocapture.init();
|
|
5973
6182
|
|
|
@@ -6093,6 +6302,10 @@ MixpanelLib.prototype.resume_session_recording = function () {
|
|
|
6093
6302
|
}
|
|
6094
6303
|
};
|
|
6095
6304
|
|
|
6305
|
+
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
6306
|
+
return this._get_session_replay_id() && this.get_config('record_heatmap_data');
|
|
6307
|
+
};
|
|
6308
|
+
|
|
6096
6309
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
6097
6310
|
var props = {};
|
|
6098
6311
|
var replay_id = this._get_session_replay_id();
|
|
@@ -6277,6 +6490,8 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) {
|
|
|
6277
6490
|
delete data['data'];
|
|
6278
6491
|
}
|
|
6279
6492
|
|
|
6493
|
+
_.extend(data, this.get_config('api_extra_query_params'));
|
|
6494
|
+
|
|
6280
6495
|
url += '?' + _.HTTPBuildQuery(data);
|
|
6281
6496
|
|
|
6282
6497
|
var lib = this;
|
|
@@ -7174,6 +7389,11 @@ MixpanelLib.prototype.identify = function(
|
|
|
7174
7389
|
'$anon_distinct_id': previous_distinct_id
|
|
7175
7390
|
}, {skip_hooks: true});
|
|
7176
7391
|
}
|
|
7392
|
+
|
|
7393
|
+
// check feature flags again if distinct id has changed
|
|
7394
|
+
if (new_distinct_id !== previous_distinct_id) {
|
|
7395
|
+
this.flags.fetchFlags();
|
|
7396
|
+
}
|
|
7177
7397
|
};
|
|
7178
7398
|
|
|
7179
7399
|
/**
|
|
@@ -7188,6 +7408,8 @@ MixpanelLib.prototype.reset = function() {
|
|
|
7188
7408
|
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
7189
7409
|
'$device_id': uuid
|
|
7190
7410
|
}, '');
|
|
7411
|
+
this.stop_session_recording();
|
|
7412
|
+
this._check_and_start_session_recording();
|
|
7191
7413
|
};
|
|
7192
7414
|
|
|
7193
7415
|
/**
|
|
@@ -7448,7 +7670,7 @@ MixpanelLib.prototype.set_config = function(config) {
|
|
|
7448
7670
|
}
|
|
7449
7671
|
Config.DEBUG = Config.DEBUG || this.get_config('debug');
|
|
7450
7672
|
|
|
7451
|
-
if ('autocapture' in config && this.autocapture) {
|
|
7673
|
+
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
7452
7674
|
this.autocapture.init();
|
|
7453
7675
|
}
|
|
7454
7676
|
}
|