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/.eslintrc.json
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
"sourceType": "module"
|
|
9
9
|
},
|
|
10
10
|
"rules": {
|
|
11
|
-
"camelcase": "error",
|
|
11
|
+
"camelcase": ["error", {
|
|
12
|
+
"properties": "never"
|
|
13
|
+
}],
|
|
12
14
|
"eol-last": "error",
|
|
13
15
|
"eqeqeq": "error",
|
|
14
16
|
"indent":
|
|
@@ -29,13 +31,14 @@
|
|
|
29
31
|
]
|
|
30
32
|
},
|
|
31
33
|
"overrides": [{
|
|
32
|
-
"files": ["tests/unit/**/*.js"],
|
|
34
|
+
"files": ["tests/unit/**/*.js", "tests/browser/**/*.js", "*.mjs"],
|
|
33
35
|
"parserOptions": {
|
|
34
|
-
"ecmaVersion":
|
|
36
|
+
"ecmaVersion": 9,
|
|
35
37
|
"sourceType": "module"
|
|
36
38
|
},
|
|
37
39
|
"env": {
|
|
38
|
-
"mocha": true
|
|
40
|
+
"mocha": true,
|
|
41
|
+
"node": true
|
|
39
42
|
},
|
|
40
43
|
"rules": {
|
|
41
44
|
"camelcase": "error",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Integration Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
checks: write # for dorny/test-reporter to post results
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
browser: [chrome-latest, edge-latest, safari-latest, firefox-latest, ios-safari-sim, android-chrome-sim]
|
|
21
|
+
|
|
22
|
+
env:
|
|
23
|
+
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
|
|
24
|
+
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
|
25
|
+
SAUCE_TUNNEL_NAME: ci-js-sdk-test-${{ matrix.browser }}-${{ github.run_id }}
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- name: Use Node.js 22.x
|
|
30
|
+
uses: actions/setup-node@v4
|
|
31
|
+
with:
|
|
32
|
+
node-version: 22.x
|
|
33
|
+
|
|
34
|
+
- name: Install Dependencies
|
|
35
|
+
run: npm ci
|
|
36
|
+
|
|
37
|
+
- name: Build
|
|
38
|
+
run: npm run build-full
|
|
39
|
+
|
|
40
|
+
- name: Sauce test
|
|
41
|
+
# for some reason, android emulator tests don't work with localhost so we need an IP to give to the runner...
|
|
42
|
+
run: BROWSER=${{ matrix.browser }} ROOT_DIR=$(pwd) SAUCE_HOST=$(hostname -I | awk '{print $1; exit}') npm run integration-test:sauce
|
|
43
|
+
|
|
44
|
+
- name: Test Report
|
|
45
|
+
uses: dorny/test-reporter@7b7927aa7da8b82e81e755810cb51f39941a2cc7 # v2
|
|
46
|
+
if: success() || failure() # run this step even if previous step failed
|
|
47
|
+
with:
|
|
48
|
+
name: Browser Tests # Name of the check run which will be created
|
|
49
|
+
reporter: mocha-json # Format of test results
|
|
50
|
+
path: 'tests/browser/results/*.json' # Path to test results
|
|
51
|
+
list-tests: 'failed'
|
|
52
|
+
fail-on-error: 'false'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Unit Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
checks: write # for dorny/test-reporter to post results
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
node-version: [20.x, 22.x]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
24
|
+
uses: actions/setup-node@v4
|
|
25
|
+
with:
|
|
26
|
+
node-version: ${{ matrix.node-version }}
|
|
27
|
+
- run: npm ci
|
|
28
|
+
- run: npm run test:ci
|
|
29
|
+
- run: npm run build-dist
|
|
30
|
+
|
|
31
|
+
- name: Test Report
|
|
32
|
+
uses: dorny/test-reporter@7b7927aa7da8b82e81e755810cb51f39941a2cc7 # v2
|
|
33
|
+
if: success() || failure()
|
|
34
|
+
with:
|
|
35
|
+
name: Unit Tests
|
|
36
|
+
reporter: mocha-json
|
|
37
|
+
path: 'tests/unit/results/*.json'
|
|
38
|
+
list-tests: 'failed'
|
|
39
|
+
fail-on-error: 'false'
|
|
40
|
+
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
**2.74.0** (27 Jan 2026)
|
|
2
|
+
- New session recording masking configuration options, including the ability to unmask inputs and allowlist-based selector masking.
|
|
3
|
+
- Adds initial support for the remote settings API, allowing remote configuration of SDK config options.
|
|
4
|
+
- Adds new automated browser test suite that runs in CI and locally in chrome headless. See tests/browser/README.html for more information.
|
|
5
|
+
- Fixes type definitions for api_routes
|
|
6
|
+
- Removes outdated examples in the examples/ dir
|
|
7
|
+
|
|
1
8
|
**2.73.0** (23 Dec 2025)
|
|
2
9
|
- Adds several new hooks: `before_identify`, `before_register`, `before_register_once`, `before_track`, `before_unregister`
|
|
3
10
|
- Adds instance-initialization notification to allow Data Inspector browser extension to hook into SDK actions
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ mixpanel.init('YOUR_TOKEN', {autocapture: true, debug: true, persistence: 'local
|
|
|
67
67
|
- Install development dependencies: `npm install`
|
|
68
68
|
- Run unit tests: `npm test`
|
|
69
69
|
- Start test server for browser tests: `npm run integration_test`
|
|
70
|
-
- Browse to [http://localhost:
|
|
70
|
+
- Browse to [http://localhost:3001/tests/](http://localhost:3001/tests/) and choose a scenario to run
|
|
71
71
|
|
|
72
72
|
In the future we plan to automate the last step with a headless browser to streamline development (although
|
|
73
73
|
Mixpanel production releases are tested against a large matrix of browsers and operating systems).
|
package/build.sh
CHANGED
|
@@ -19,15 +19,11 @@ if [ ! -z "$FULL" ]; then
|
|
|
19
19
|
npx webpack tests/module-cjs.js tests/module-cjs.bundle.js
|
|
20
20
|
npx browserify tests/module-es2015.js -t [ babelify --compact false ] --outfile tests/module-es2015.bundle.js
|
|
21
21
|
|
|
22
|
-
echo 'Bundling module-loader examples'
|
|
23
|
-
pushd examples/commonjs-browserify; npm install && npm run build; popd
|
|
24
|
-
pushd examples/es2015-babelify; npm install && npm run build; popd
|
|
25
|
-
pushd examples/umd-webpack; npm install && npm run build; popd
|
|
26
22
|
pushd examples/typescript; npm install && npm run build; popd
|
|
27
23
|
fi
|
|
28
24
|
|
|
29
25
|
if [ ! -z "$DIST" ]; then
|
|
30
26
|
echo 'Copying to dist/'
|
|
31
27
|
rm -r dist
|
|
32
|
-
|
|
28
|
+
rsync -av --exclude='test' build/ dist/
|
|
33
29
|
fi
|
|
@@ -6,6 +6,8 @@ export type PushItem = Array<string | Dict | ((this: Mixpanel) => void)>;
|
|
|
6
6
|
|
|
7
7
|
export type Query = string | Element | Element[];
|
|
8
8
|
|
|
9
|
+
export type RemoteSettingType = "disabled" | "fallback" | "strict";
|
|
10
|
+
|
|
9
11
|
export interface Dict {
|
|
10
12
|
[key: string]: any;
|
|
11
13
|
}
|
|
@@ -166,6 +168,8 @@ export interface Config {
|
|
|
166
168
|
track?: string;
|
|
167
169
|
engage?: string;
|
|
168
170
|
groups?: string;
|
|
171
|
+
record?: string;
|
|
172
|
+
flags?: string;
|
|
169
173
|
};
|
|
170
174
|
api_method: string;
|
|
171
175
|
api_transport: string;
|
|
@@ -225,12 +229,18 @@ export interface Config {
|
|
|
225
229
|
record_idle_timeout_ms: number;
|
|
226
230
|
record_inline_images: boolean;
|
|
227
231
|
record_mask_text_class: string | RegExp;
|
|
228
|
-
record_mask_text_selector: string;
|
|
232
|
+
record_mask_text_selector: string | string[];
|
|
233
|
+
record_unmask_text_selector: string | string[];
|
|
234
|
+
record_mask_all_text: boolean;
|
|
235
|
+
record_mask_input_selector: string | string[];
|
|
236
|
+
record_unmask_input_selector: string | string[];
|
|
237
|
+
record_mask_all_inputs: boolean;
|
|
229
238
|
record_min_ms: number;
|
|
230
239
|
record_max_ms: number;
|
|
231
240
|
record_sessions_percent: number;
|
|
232
241
|
record_canvas: boolean;
|
|
233
242
|
record_heatmap_data: boolean;
|
|
243
|
+
remote_settings_mode: RemoteSettingType;
|
|
234
244
|
hooks: {
|
|
235
245
|
before_identify?: (new_distinct_id: string) => string | null;
|
|
236
246
|
before_register?: (
|
|
@@ -256,6 +266,7 @@ export interface Config {
|
|
|
256
266
|
};
|
|
257
267
|
}
|
|
258
268
|
|
|
269
|
+
|
|
259
270
|
export type VerboseResponse =
|
|
260
271
|
| {
|
|
261
272
|
status: 1;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var Config = {
|
|
4
4
|
DEBUG: false,
|
|
5
|
-
LIB_VERSION: '2.
|
|
5
|
+
LIB_VERSION: '2.74.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
|
|
@@ -1504,8 +1504,17 @@ function _storageWrapper(storage, name, is_supported_fn) {
|
|
|
1504
1504
|
};
|
|
1505
1505
|
}
|
|
1506
1506
|
|
|
1507
|
-
|
|
1508
|
-
|
|
1507
|
+
// Safari errors out accessing localStorage/sessionStorage when cookies are disabled,
|
|
1508
|
+
// so create dummy storage wrappers that silently fail as a fallback.
|
|
1509
|
+
var windowLocalStorage = null, windowSessionStorage = null;
|
|
1510
|
+
try {
|
|
1511
|
+
windowLocalStorage = win.localStorage;
|
|
1512
|
+
windowSessionStorage = win.sessionStorage;
|
|
1513
|
+
// eslint-disable-next-line no-empty
|
|
1514
|
+
} catch (_err) {}
|
|
1515
|
+
|
|
1516
|
+
_.localStorage = _storageWrapper(windowLocalStorage, 'localStorage', localStorageSupported);
|
|
1517
|
+
_.sessionStorage = _storageWrapper(windowSessionStorage, 'sessionStorage', sessionStorageSupported);
|
|
1509
1518
|
|
|
1510
1519
|
_.register_event = (function() {
|
|
1511
1520
|
// written by Dean Edwards, 2005
|
|
@@ -2655,6 +2664,18 @@ function shouldTrackDomEvent(el, ev) {
|
|
|
2655
2664
|
}
|
|
2656
2665
|
}
|
|
2657
2666
|
|
|
2667
|
+
function elementLooksSensitive(el) {
|
|
2668
|
+
var name = (el.name || el.id || '').toString().toLowerCase();
|
|
2669
|
+
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"]
|
|
2670
|
+
var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
|
|
2671
|
+
if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
|
|
2672
|
+
return true;
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
return false;
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2658
2679
|
/*
|
|
2659
2680
|
* Check whether a DOM element should be "tracked" or if it may contain sensitive data
|
|
2660
2681
|
* using a variety of heuristics.
|
|
@@ -2707,13 +2728,8 @@ function shouldTrackElementDetails(el, ev, allowElementCallback, allowSelectors)
|
|
|
2707
2728
|
}
|
|
2708
2729
|
}
|
|
2709
2730
|
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
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"]
|
|
2713
|
-
var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
|
|
2714
|
-
if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
|
|
2715
|
-
return false;
|
|
2716
|
-
}
|
|
2731
|
+
if (elementLooksSensitive(el)) {
|
|
2732
|
+
return false;
|
|
2717
2733
|
}
|
|
2718
2734
|
|
|
2719
2735
|
return true;
|
|
@@ -6841,6 +6857,9 @@ var INIT_SNIPPET = 1;
|
|
|
6841
6857
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
6842
6858
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
6843
6859
|
/** @const */ var DEVICE_ID_PREFIX = '$device:';
|
|
6860
|
+
/** @const */ var SETTING_STRICT = 'strict';
|
|
6861
|
+
/** @const */ var SETTING_FALLBACK = 'fallback';
|
|
6862
|
+
/** @const */ var SETTING_DISABLED = 'disabled';
|
|
6844
6863
|
|
|
6845
6864
|
|
|
6846
6865
|
/*
|
|
@@ -6869,7 +6888,8 @@ var DEFAULT_API_ROUTES = {
|
|
|
6869
6888
|
'engage': 'engage/',
|
|
6870
6889
|
'groups': 'groups/',
|
|
6871
6890
|
'record': 'record/',
|
|
6872
|
-
'flags': 'flags/'
|
|
6891
|
+
'flags': 'flags/',
|
|
6892
|
+
'settings': 'settings/'
|
|
6873
6893
|
};
|
|
6874
6894
|
|
|
6875
6895
|
/*
|
|
@@ -6933,12 +6953,12 @@ var DEFAULT_CONFIG = {
|
|
|
6933
6953
|
'record_console': true,
|
|
6934
6954
|
'record_heatmap_data': false,
|
|
6935
6955
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
6936
|
-
'
|
|
6937
|
-
'record_mask_text_selector': '*',
|
|
6956
|
+
'record_mask_inputs': true,
|
|
6938
6957
|
'record_max_ms': MAX_RECORDING_MS,
|
|
6939
6958
|
'record_min_ms': 0,
|
|
6940
6959
|
'record_sessions_percent': 0,
|
|
6941
|
-
'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
|
|
6960
|
+
'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js',
|
|
6961
|
+
'remote_settings_mode': SETTING_DISABLED // 'strict', 'fallback', 'disabled'
|
|
6942
6962
|
};
|
|
6943
6963
|
|
|
6944
6964
|
var DOM_LOADED = false;
|
|
@@ -7176,7 +7196,16 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
7176
7196
|
this.autocapture.init();
|
|
7177
7197
|
|
|
7178
7198
|
this._init_tab_id();
|
|
7179
|
-
|
|
7199
|
+
|
|
7200
|
+
// Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
|
|
7201
|
+
var mode = this.get_config('remote_settings_mode');
|
|
7202
|
+
if (mode === SETTING_STRICT || mode === SETTING_FALLBACK) {
|
|
7203
|
+
this._fetch_remote_settings(mode).then(_.bind(function() {
|
|
7204
|
+
this._check_and_start_session_recording();
|
|
7205
|
+
}, this));
|
|
7206
|
+
} else {
|
|
7207
|
+
this._check_and_start_session_recording();
|
|
7208
|
+
}
|
|
7180
7209
|
};
|
|
7181
7210
|
|
|
7182
7211
|
/**
|
|
@@ -7601,6 +7630,77 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) {
|
|
|
7601
7630
|
return succeeded;
|
|
7602
7631
|
};
|
|
7603
7632
|
|
|
7633
|
+
MixpanelLib.prototype._fetch_remote_settings = function(mode) {
|
|
7634
|
+
var disableRecordingIfStrict = function() {
|
|
7635
|
+
if (mode === 'strict') {
|
|
7636
|
+
self.set_config({'record_sessions_percent': 0});
|
|
7637
|
+
}
|
|
7638
|
+
};
|
|
7639
|
+
|
|
7640
|
+
if (!win['AbortController']) {
|
|
7641
|
+
console.critical('Remote settings unavailable: missing minimum required APIs');
|
|
7642
|
+
disableRecordingIfStrict();
|
|
7643
|
+
return Promise.resolve();
|
|
7644
|
+
}
|
|
7645
|
+
|
|
7646
|
+
var settings_endpoint = this.get_api_host('settings') + '/' + this.get_config('api_routes')['settings'];
|
|
7647
|
+
var request_params = {
|
|
7648
|
+
'$lib_version': Config.LIB_VERSION,
|
|
7649
|
+
'mp_lib': 'web',
|
|
7650
|
+
'sdk_config': '1',
|
|
7651
|
+
};
|
|
7652
|
+
var query_string = _.HTTPBuildQuery(request_params);
|
|
7653
|
+
var full_url = settings_endpoint + '?' + query_string;
|
|
7654
|
+
var self = this;
|
|
7655
|
+
|
|
7656
|
+
var abortController = new AbortController();
|
|
7657
|
+
var timeout_id = setTimeout(function() {
|
|
7658
|
+
abortController.abort();
|
|
7659
|
+
}, 500);
|
|
7660
|
+
var fetchOptions = {
|
|
7661
|
+
'method': 'GET',
|
|
7662
|
+
'headers': {
|
|
7663
|
+
'Authorization': 'Basic ' + btoa(self.get_config('token') + ':'),
|
|
7664
|
+
},
|
|
7665
|
+
'signal': abortController.signal
|
|
7666
|
+
};
|
|
7667
|
+
|
|
7668
|
+
return win['fetch'](full_url, fetchOptions).then(function(response) {
|
|
7669
|
+
clearTimeout(timeout_id);
|
|
7670
|
+
if (!response['ok']) {
|
|
7671
|
+
console.critical('Network response was not ok');
|
|
7672
|
+
disableRecordingIfStrict();
|
|
7673
|
+
return;
|
|
7674
|
+
}
|
|
7675
|
+
return response.json();
|
|
7676
|
+
}).then(function(result) {
|
|
7677
|
+
if (result && result['sdk_config'] && result['sdk_config']['config']) {
|
|
7678
|
+
var remote_config = result['sdk_config']['config'];
|
|
7679
|
+
|
|
7680
|
+
// Verify that remote config contains only valid keys from DEFAULT_CONFIG
|
|
7681
|
+
var valid_config = {};
|
|
7682
|
+
_.each(remote_config, function(value, key) {
|
|
7683
|
+
if (DEFAULT_CONFIG.hasOwnProperty(key)) {
|
|
7684
|
+
valid_config[key] = value;
|
|
7685
|
+
}
|
|
7686
|
+
});
|
|
7687
|
+
|
|
7688
|
+
if (_.isEmptyObject(valid_config)) {
|
|
7689
|
+
console.critical('No valid config keys found in remote settings.');
|
|
7690
|
+
disableRecordingIfStrict();
|
|
7691
|
+
} else {
|
|
7692
|
+
self.set_config(valid_config);
|
|
7693
|
+
}
|
|
7694
|
+
} else {
|
|
7695
|
+
disableRecordingIfStrict();
|
|
7696
|
+
}
|
|
7697
|
+
}).catch(function(err) {
|
|
7698
|
+
clearTimeout(timeout_id);
|
|
7699
|
+
console.critical('Failed to fetch remote settings', err);
|
|
7700
|
+
disableRecordingIfStrict();
|
|
7701
|
+
});
|
|
7702
|
+
};
|
|
7703
|
+
|
|
7604
7704
|
/**
|
|
7605
7705
|
* _execute_array() deals with processing any mixpanel function
|
|
7606
7706
|
* calls that were called before the Mixpanel library were loaded
|