mixpanel-browser 2.73.0 → 2.74.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/.claude/settings.local.json +12 -0
- package/.eslintrc.json +7 -4
- package/.github/workflows/integration-tests.yml +52 -0
- package/.github/workflows/unit-tests.yml +40 -0
- package/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/build.sh +1 -5
- package/dist/mixpanel-core.cjs.d.ts +12 -1
- package/dist/mixpanel-core.cjs.js +115 -15
- package/dist/mixpanel-recorder.js +5255 -687
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +12 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +115 -15
- package/dist/mixpanel-with-recorder.d.ts +12 -1
- package/dist/mixpanel-with-recorder.js +6720 -2079
- package/dist/mixpanel-with-recorder.min.d.ts +12 -1
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +12 -1
- package/dist/mixpanel.amd.js +6720 -2079
- package/dist/mixpanel.cjs.d.ts +12 -1
- package/dist/mixpanel.cjs.js +6720 -2079
- package/dist/mixpanel.globals.js +115 -15
- package/dist/mixpanel.min.js +174 -172
- package/dist/mixpanel.module.d.ts +12 -1
- package/dist/mixpanel.module.js +6720 -2079
- package/dist/mixpanel.umd.d.ts +12 -1
- package/dist/mixpanel.umd.js +6720 -2079
- package/dist/rrweb-bundled.js +4315 -591
- package/dist/rrweb-compiled.js +4962 -641
- package/package.json +30 -5
- package/rollup.config.mjs +254 -224
- package/src/autocapture/utils.js +15 -7
- package/src/config.js +1 -1
- package/src/index.d.ts +12 -1
- package/src/mixpanel-core.js +89 -5
- package/src/recorder/masking.js +197 -0
- package/src/recorder/rrweb-entrypoint.js +2 -1
- package/src/recorder/session-recording.js +43 -4
- package/src/recorder/utils.js +5 -1
- package/src/utils.js +11 -2
- package/testServer.js +51 -7
- package/.github/workflows/tests.yml +0 -25
package/dist/mixpanel.globals.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var Config = {
|
|
5
5
|
DEBUG: false,
|
|
6
|
-
LIB_VERSION: '2.
|
|
6
|
+
LIB_VERSION: '2.74.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
|
|
@@ -1505,8 +1505,17 @@
|
|
|
1505
1505
|
};
|
|
1506
1506
|
}
|
|
1507
1507
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1508
|
+
// Safari errors out accessing localStorage/sessionStorage when cookies are disabled,
|
|
1509
|
+
// so create dummy storage wrappers that silently fail as a fallback.
|
|
1510
|
+
var windowLocalStorage = null, windowSessionStorage = null;
|
|
1511
|
+
try {
|
|
1512
|
+
windowLocalStorage = win.localStorage;
|
|
1513
|
+
windowSessionStorage = win.sessionStorage;
|
|
1514
|
+
// eslint-disable-next-line no-empty
|
|
1515
|
+
} catch (_err) {}
|
|
1516
|
+
|
|
1517
|
+
_.localStorage = _storageWrapper(windowLocalStorage, 'localStorage', localStorageSupported);
|
|
1518
|
+
_.sessionStorage = _storageWrapper(windowSessionStorage, 'sessionStorage', sessionStorageSupported);
|
|
1510
1519
|
|
|
1511
1520
|
_.register_event = (function() {
|
|
1512
1521
|
// written by Dean Edwards, 2005
|
|
@@ -2656,6 +2665,18 @@
|
|
|
2656
2665
|
}
|
|
2657
2666
|
}
|
|
2658
2667
|
|
|
2668
|
+
function elementLooksSensitive(el) {
|
|
2669
|
+
var name = (el.name || el.id || '').toString().toLowerCase();
|
|
2670
|
+
if (typeof name === 'string') { // it's possible for el.name or el.id to be a DOM element if el is a form with a child input[name="name"]
|
|
2671
|
+
var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
|
|
2672
|
+
if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
|
|
2673
|
+
return true;
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2677
|
+
return false;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2659
2680
|
/*
|
|
2660
2681
|
* Check whether a DOM element should be "tracked" or if it may contain sensitive data
|
|
2661
2682
|
* using a variety of heuristics.
|
|
@@ -2708,13 +2729,8 @@
|
|
|
2708
2729
|
}
|
|
2709
2730
|
}
|
|
2710
2731
|
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
if (typeof name === 'string') { // it's possible for el.name or el.id to be a DOM element if el is a form with a child input[name="name"]
|
|
2714
|
-
var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
|
|
2715
|
-
if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
|
|
2716
|
-
return false;
|
|
2717
|
-
}
|
|
2732
|
+
if (elementLooksSensitive(el)) {
|
|
2733
|
+
return false;
|
|
2718
2734
|
}
|
|
2719
2735
|
|
|
2720
2736
|
return true;
|
|
@@ -6842,6 +6858,9 @@
|
|
|
6842
6858
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
6843
6859
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
6844
6860
|
/** @const */ var DEVICE_ID_PREFIX = '$device:';
|
|
6861
|
+
/** @const */ var SETTING_STRICT = 'strict';
|
|
6862
|
+
/** @const */ var SETTING_FALLBACK = 'fallback';
|
|
6863
|
+
/** @const */ var SETTING_DISABLED = 'disabled';
|
|
6845
6864
|
|
|
6846
6865
|
|
|
6847
6866
|
/*
|
|
@@ -6870,7 +6889,8 @@
|
|
|
6870
6889
|
'engage': 'engage/',
|
|
6871
6890
|
'groups': 'groups/',
|
|
6872
6891
|
'record': 'record/',
|
|
6873
|
-
'flags': 'flags/'
|
|
6892
|
+
'flags': 'flags/',
|
|
6893
|
+
'settings': 'settings/'
|
|
6874
6894
|
};
|
|
6875
6895
|
|
|
6876
6896
|
/*
|
|
@@ -6934,12 +6954,12 @@
|
|
|
6934
6954
|
'record_console': true,
|
|
6935
6955
|
'record_heatmap_data': false,
|
|
6936
6956
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
6937
|
-
'
|
|
6938
|
-
'record_mask_text_selector': '*',
|
|
6957
|
+
'record_mask_inputs': true,
|
|
6939
6958
|
'record_max_ms': MAX_RECORDING_MS,
|
|
6940
6959
|
'record_min_ms': 0,
|
|
6941
6960
|
'record_sessions_percent': 0,
|
|
6942
|
-
'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
|
|
6961
|
+
'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js',
|
|
6962
|
+
'remote_settings_mode': SETTING_DISABLED // 'strict', 'fallback', 'disabled'
|
|
6943
6963
|
};
|
|
6944
6964
|
|
|
6945
6965
|
var DOM_LOADED = false;
|
|
@@ -7177,7 +7197,16 @@
|
|
|
7177
7197
|
this.autocapture.init();
|
|
7178
7198
|
|
|
7179
7199
|
this._init_tab_id();
|
|
7180
|
-
|
|
7200
|
+
|
|
7201
|
+
// Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
|
|
7202
|
+
var mode = this.get_config('remote_settings_mode');
|
|
7203
|
+
if (mode === SETTING_STRICT || mode === SETTING_FALLBACK) {
|
|
7204
|
+
this._fetch_remote_settings(mode).then(_.bind(function() {
|
|
7205
|
+
this._check_and_start_session_recording();
|
|
7206
|
+
}, this));
|
|
7207
|
+
} else {
|
|
7208
|
+
this._check_and_start_session_recording();
|
|
7209
|
+
}
|
|
7181
7210
|
};
|
|
7182
7211
|
|
|
7183
7212
|
/**
|
|
@@ -7602,6 +7631,77 @@
|
|
|
7602
7631
|
return succeeded;
|
|
7603
7632
|
};
|
|
7604
7633
|
|
|
7634
|
+
MixpanelLib.prototype._fetch_remote_settings = function(mode) {
|
|
7635
|
+
var disableRecordingIfStrict = function() {
|
|
7636
|
+
if (mode === 'strict') {
|
|
7637
|
+
self.set_config({'record_sessions_percent': 0});
|
|
7638
|
+
}
|
|
7639
|
+
};
|
|
7640
|
+
|
|
7641
|
+
if (!win['AbortController']) {
|
|
7642
|
+
console.critical('Remote settings unavailable: missing minimum required APIs');
|
|
7643
|
+
disableRecordingIfStrict();
|
|
7644
|
+
return Promise.resolve();
|
|
7645
|
+
}
|
|
7646
|
+
|
|
7647
|
+
var settings_endpoint = this.get_api_host('settings') + '/' + this.get_config('api_routes')['settings'];
|
|
7648
|
+
var request_params = {
|
|
7649
|
+
'$lib_version': Config.LIB_VERSION,
|
|
7650
|
+
'mp_lib': 'web',
|
|
7651
|
+
'sdk_config': '1',
|
|
7652
|
+
};
|
|
7653
|
+
var query_string = _.HTTPBuildQuery(request_params);
|
|
7654
|
+
var full_url = settings_endpoint + '?' + query_string;
|
|
7655
|
+
var self = this;
|
|
7656
|
+
|
|
7657
|
+
var abortController = new AbortController();
|
|
7658
|
+
var timeout_id = setTimeout(function() {
|
|
7659
|
+
abortController.abort();
|
|
7660
|
+
}, 500);
|
|
7661
|
+
var fetchOptions = {
|
|
7662
|
+
'method': 'GET',
|
|
7663
|
+
'headers': {
|
|
7664
|
+
'Authorization': 'Basic ' + btoa(self.get_config('token') + ':'),
|
|
7665
|
+
},
|
|
7666
|
+
'signal': abortController.signal
|
|
7667
|
+
};
|
|
7668
|
+
|
|
7669
|
+
return win['fetch'](full_url, fetchOptions).then(function(response) {
|
|
7670
|
+
clearTimeout(timeout_id);
|
|
7671
|
+
if (!response['ok']) {
|
|
7672
|
+
console.critical('Network response was not ok');
|
|
7673
|
+
disableRecordingIfStrict();
|
|
7674
|
+
return;
|
|
7675
|
+
}
|
|
7676
|
+
return response.json();
|
|
7677
|
+
}).then(function(result) {
|
|
7678
|
+
if (result && result['sdk_config'] && result['sdk_config']['config']) {
|
|
7679
|
+
var remote_config = result['sdk_config']['config'];
|
|
7680
|
+
|
|
7681
|
+
// Verify that remote config contains only valid keys from DEFAULT_CONFIG
|
|
7682
|
+
var valid_config = {};
|
|
7683
|
+
_.each(remote_config, function(value, key) {
|
|
7684
|
+
if (DEFAULT_CONFIG.hasOwnProperty(key)) {
|
|
7685
|
+
valid_config[key] = value;
|
|
7686
|
+
}
|
|
7687
|
+
});
|
|
7688
|
+
|
|
7689
|
+
if (_.isEmptyObject(valid_config)) {
|
|
7690
|
+
console.critical('No valid config keys found in remote settings.');
|
|
7691
|
+
disableRecordingIfStrict();
|
|
7692
|
+
} else {
|
|
7693
|
+
self.set_config(valid_config);
|
|
7694
|
+
}
|
|
7695
|
+
} else {
|
|
7696
|
+
disableRecordingIfStrict();
|
|
7697
|
+
}
|
|
7698
|
+
}).catch(function(err) {
|
|
7699
|
+
clearTimeout(timeout_id);
|
|
7700
|
+
console.critical('Failed to fetch remote settings', err);
|
|
7701
|
+
disableRecordingIfStrict();
|
|
7702
|
+
});
|
|
7703
|
+
};
|
|
7704
|
+
|
|
7605
7705
|
/**
|
|
7606
7706
|
* _execute_array() deals with processing any mixpanel function
|
|
7607
7707
|
* calls that were called before the Mixpanel library were loaded
|