mixpanel-browser 2.75.0 → 2.77.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 +14 -0
- package/.github/dependabot.yml +8 -0
- package/.github/workflows/integration-tests.yml +4 -4
- package/.github/workflows/unit-tests.yml +4 -4
- package/CHANGELOG.md +14 -0
- package/build.sh +10 -8
- package/dist/async-modules/mixpanel-recorder-DLKbUIEE.js +23669 -0
- package/dist/async-modules/mixpanel-recorder-wIWnMDLA.min.js +2 -0
- package/dist/async-modules/mixpanel-recorder-wIWnMDLA.min.js.map +1 -0
- package/dist/async-modules/mixpanel-targeting-CTcftSJC.min.js +2 -0
- package/dist/async-modules/mixpanel-targeting-CTcftSJC.min.js.map +1 -0
- package/dist/async-modules/mixpanel-targeting-CmVvUyFM.js +2520 -0
- package/dist/mixpanel-core.cjs.d.ts +70 -1
- package/dist/mixpanel-core.cjs.js +724 -426
- package/dist/mixpanel-recorder.js +791 -41
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-targeting.js +6 -62
- package/dist/mixpanel-targeting.min.js +1 -1
- package/dist/mixpanel-targeting.min.js.map +1 -1
- package/dist/mixpanel-with-async-modules.cjs.d.ts +70 -1
- package/dist/mixpanel-with-async-modules.cjs.js +724 -426
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +70 -1
- package/dist/mixpanel-with-async-recorder.cjs.js +724 -426
- package/dist/mixpanel-with-recorder.d.ts +70 -1
- package/dist/mixpanel-with-recorder.js +1471 -450
- package/dist/mixpanel-with-recorder.min.d.ts +70 -1
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +70 -1
- package/dist/mixpanel.amd.js +1473 -504
- package/dist/mixpanel.cjs.d.ts +70 -1
- package/dist/mixpanel.cjs.js +1473 -504
- package/dist/mixpanel.globals.js +724 -426
- package/dist/mixpanel.min.js +189 -182
- package/dist/mixpanel.module.d.ts +70 -1
- package/dist/mixpanel.module.js +1473 -504
- package/dist/mixpanel.umd.d.ts +70 -1
- package/dist/mixpanel.umd.js +1473 -504
- package/dist/rrweb-bundled.js +61 -9
- package/dist/rrweb-compiled.js +56 -9
- package/logo.svg +5 -0
- package/package.json +6 -4
- package/rollup.config.mjs +163 -46
- package/src/autocapture/index.js +10 -27
- package/src/config.js +9 -3
- package/src/flags/index.js +1 -2
- package/src/index.d.ts +70 -1
- package/src/mixpanel-core.js +77 -112
- package/src/recorder/index.js +1 -1
- package/src/recorder/recorder.js +5 -1
- package/src/recorder/rrweb-network-plugin.js +649 -0
- package/src/recorder/session-recording.js +36 -12
- package/src/recorder/utils.js +27 -1
- package/src/recorder-manager.js +324 -0
- package/src/request-batcher.js +1 -1
- package/src/targeting/event-matcher.js +2 -57
- package/src/targeting/index.js +1 -1
- package/src/targeting/loader.js +1 -1
- package/src/utils.js +13 -1
- package/testServer.js +69 -1
- package/src/globals.js +0 -14
- /package/src/loaders/{loader-module-with-async-recorder.d.ts → loader-module-with-async-modules.d.ts} +0 -0
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RulesLogic } from 'json-logic-js';
|
|
2
|
+
|
|
1
3
|
export type Persistence = "cookie" | "localStorage";
|
|
2
4
|
|
|
3
5
|
export type ApiPayloadFormat = "base64" | "json";
|
|
@@ -8,6 +10,16 @@ export type Query = string | Element | Element[];
|
|
|
8
10
|
|
|
9
11
|
export type RemoteSettingType = "disabled" | "fallback" | "strict";
|
|
10
12
|
|
|
13
|
+
|
|
14
|
+
export interface EventTriggerProps {
|
|
15
|
+
percentage: number;
|
|
16
|
+
property_filters?: RulesLogic;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface RecordingEventTriggers {
|
|
20
|
+
[eventName: string]: EventTriggerProps;
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
export interface Dict {
|
|
12
24
|
[key: string]: any;
|
|
13
25
|
}
|
|
@@ -225,6 +237,9 @@ export interface Config {
|
|
|
225
237
|
recorder_src: string;
|
|
226
238
|
record_block_class: string | RegExp;
|
|
227
239
|
record_block_selector: string;
|
|
240
|
+
record_console: boolean;
|
|
241
|
+
record_network: boolean;
|
|
242
|
+
record_network_options: NetworkRecordOptions;
|
|
228
243
|
record_collect_fonts: boolean;
|
|
229
244
|
record_idle_timeout_ms: number;
|
|
230
245
|
record_inline_images: boolean;
|
|
@@ -237,10 +252,12 @@ export interface Config {
|
|
|
237
252
|
record_mask_all_inputs: boolean;
|
|
238
253
|
record_min_ms: number;
|
|
239
254
|
record_max_ms: number;
|
|
240
|
-
|
|
255
|
+
record_allowed_iframe_origins: string[];
|
|
241
256
|
record_canvas: boolean;
|
|
257
|
+
recording_event_triggers: RecordingEventTriggers;
|
|
242
258
|
record_heatmap_data: boolean;
|
|
243
259
|
remote_settings_mode: RemoteSettingType;
|
|
260
|
+
record_sessions_percent: number;
|
|
244
261
|
hooks: {
|
|
245
262
|
before_identify?: (new_distinct_id: string) => string | null;
|
|
246
263
|
before_register?: (
|
|
@@ -518,5 +535,57 @@ export function get_session_recording_properties():
|
|
|
518
535
|
| { $mp_replay_id?: string }
|
|
519
536
|
| {};
|
|
520
537
|
|
|
538
|
+
// Network Recording Plugin Types
|
|
539
|
+
export type InitiatorType =
|
|
540
|
+
| 'audio'
|
|
541
|
+
| 'beacon'
|
|
542
|
+
| 'body'
|
|
543
|
+
| 'css'
|
|
544
|
+
| 'early-hint'
|
|
545
|
+
| 'embed'
|
|
546
|
+
| 'fetch'
|
|
547
|
+
| 'frame'
|
|
548
|
+
| 'iframe'
|
|
549
|
+
| 'icon'
|
|
550
|
+
| 'image'
|
|
551
|
+
| 'img'
|
|
552
|
+
| 'input'
|
|
553
|
+
| 'link'
|
|
554
|
+
| 'navigation'
|
|
555
|
+
| 'object'
|
|
556
|
+
| 'ping'
|
|
557
|
+
| 'script'
|
|
558
|
+
| 'track'
|
|
559
|
+
| 'video'
|
|
560
|
+
| 'xmlhttprequest';
|
|
561
|
+
|
|
562
|
+
export interface NetworkRequest {
|
|
563
|
+
url: string;
|
|
564
|
+
method?: string;
|
|
565
|
+
initiatorType: InitiatorType;
|
|
566
|
+
status?: number;
|
|
567
|
+
startTime: number;
|
|
568
|
+
endTime: number;
|
|
569
|
+
timeOrigin: number;
|
|
570
|
+
requestHeaders?: Record<string, string>;
|
|
571
|
+
requestBody?: string;
|
|
572
|
+
responseHeaders?: Record<string, string>;
|
|
573
|
+
responseBody?: string;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export interface NetworkRecordOptions {
|
|
577
|
+
initiatorTypes?: InitiatorType[];
|
|
578
|
+
ignoreRequestUrls?: string[];
|
|
579
|
+
ignoreRequestFn?: (data: NetworkRequest) => boolean;
|
|
580
|
+
recordHeaders?: { request: string[]; response: string[] };
|
|
581
|
+
recordBodyUrls?: { request: string[]; response: string[] };
|
|
582
|
+
recordInitialRequests?: boolean;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
export interface NetworkData {
|
|
586
|
+
requests: NetworkRequest[];
|
|
587
|
+
isInitial?: boolean;
|
|
588
|
+
}
|
|
589
|
+
|
|
521
590
|
declare const mixpanel: OverridedMixpanel;
|
|
522
591
|
export default mixpanel;
|
package/src/mixpanel-core.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/* eslint camelcase: "off" */
|
|
2
|
-
import Config from './config';
|
|
2
|
+
import {Config, TARGETING_FILENAME} from './config';
|
|
3
3
|
import { MAX_RECORDING_MS, _, console, userAgent, document, navigator, slice, NOOP_FUNC, JSONStringify } from './utils';
|
|
4
|
-
import { isRecordingExpired } from './recorder/utils';
|
|
5
4
|
import { window } from './window';
|
|
6
|
-
import { RECORDER_GLOBAL_NAME } from './globals';
|
|
7
5
|
import { Autocapture } from './autocapture';
|
|
8
6
|
import { FeatureFlagManager } from './flags';
|
|
7
|
+
import { RecorderManager } from './recorder-manager';
|
|
9
8
|
import { FormTracker, LinkTracker } from './dom-trackers';
|
|
10
9
|
import { RequestBatcher } from './request-batcher';
|
|
11
10
|
import { MixpanelGroup } from './mixpanel-group';
|
|
@@ -23,7 +22,6 @@ import {
|
|
|
23
22
|
clearOptInOut,
|
|
24
23
|
addOptOutCheckMixpanelLib
|
|
25
24
|
} from './gdpr-utils';
|
|
26
|
-
import { IDBStorageWrapper, RECORDING_REGISTRY_STORE_NAME } from './storage/indexed-db';
|
|
27
25
|
|
|
28
26
|
/*
|
|
29
27
|
* Mixpanel JS Library
|
|
@@ -66,7 +64,6 @@ var INIT_SNIPPET = 1;
|
|
|
66
64
|
/** @const */ var SETTING_FALLBACK = 'fallback';
|
|
67
65
|
/** @const */ var SETTING_DISABLED = 'disabled';
|
|
68
66
|
|
|
69
|
-
|
|
70
67
|
/*
|
|
71
68
|
* Dynamic... constants? Is that an oxymoron?
|
|
72
69
|
*/
|
|
@@ -151,19 +148,24 @@ var DEFAULT_CONFIG = {
|
|
|
151
148
|
'batch_request_timeout_ms': 90000,
|
|
152
149
|
'batch_autostart': true,
|
|
153
150
|
'hooks': {},
|
|
151
|
+
'record_allowed_iframe_origins': [],
|
|
154
152
|
'record_block_class': new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$'),
|
|
155
153
|
'record_block_selector': 'img, video, audio',
|
|
156
154
|
'record_canvas': false,
|
|
157
155
|
'record_collect_fonts': false,
|
|
158
156
|
'record_console': true,
|
|
159
157
|
'record_heatmap_data': false,
|
|
158
|
+
'recording_event_triggers': {},
|
|
160
159
|
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
161
160
|
'record_mask_inputs': true,
|
|
162
161
|
'record_max_ms': MAX_RECORDING_MS,
|
|
163
162
|
'record_min_ms': 0,
|
|
163
|
+
'record_network': false,
|
|
164
|
+
'record_network_options': {},
|
|
164
165
|
'record_sessions_percent': 0,
|
|
165
|
-
'recorder_src':
|
|
166
|
-
'targeting_src':
|
|
166
|
+
'recorder_src': null,
|
|
167
|
+
'targeting_src': null,
|
|
168
|
+
'lib_base_path': 'https://cdn.mxpnl.com/libs/',
|
|
167
169
|
'remote_settings_mode': SETTING_DISABLED // 'strict', 'fallback', 'disabled'
|
|
168
170
|
};
|
|
169
171
|
|
|
@@ -317,6 +319,19 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
317
319
|
'callback_fn': ((name === PRIMARY_INSTANCE_NAME) ? name : PRIMARY_INSTANCE_NAME + '.' + name) + '._jsc'
|
|
318
320
|
}));
|
|
319
321
|
|
|
322
|
+
this.recorderManager = new RecorderManager({
|
|
323
|
+
mixpanelInstance: this,
|
|
324
|
+
getConfigFunc: _.bind(this.get_config, this),
|
|
325
|
+
setConfigFunc: _.bind(this.set_config, this),
|
|
326
|
+
getTabIdFunc: _.bind(this.get_tab_id, this),
|
|
327
|
+
reportErrorFunc: _.bind(this.report_error, this),
|
|
328
|
+
getDistinctIdFunc: _.bind(this.get_distinct_id, this),
|
|
329
|
+
recorderSrc: this.get_config('recorder_src'),
|
|
330
|
+
targetingSrc: this.get_config('targeting_src'),
|
|
331
|
+
libBasePath: this.get_config('lib_base_path'),
|
|
332
|
+
loadExtraBundle: load_extra_bundle
|
|
333
|
+
});
|
|
334
|
+
|
|
320
335
|
this['_jsc'] = NOOP_FUNC;
|
|
321
336
|
|
|
322
337
|
this.__dom_loaded_queue = [];
|
|
@@ -395,7 +410,7 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
395
410
|
getPropertyFunc: _.bind(this.get_property, this),
|
|
396
411
|
trackingFunc: _.bind(this.track, this),
|
|
397
412
|
loadExtraBundle: load_extra_bundle,
|
|
398
|
-
targetingSrc: this.get_config('targeting_src')
|
|
413
|
+
targetingSrc: this.get_config('targeting_src') || (this.get_config('lib_base_path') + TARGETING_FILENAME)
|
|
399
414
|
});
|
|
400
415
|
this.flags.init();
|
|
401
416
|
this['flags'] = this.flags;
|
|
@@ -408,11 +423,11 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
408
423
|
// Based on remote_settings_mode, fetch remote settings and then start session recording if applicable
|
|
409
424
|
var mode = this.get_config('remote_settings_mode');
|
|
410
425
|
if (mode === SETTING_STRICT || mode === SETTING_FALLBACK) {
|
|
411
|
-
this._fetch_remote_settings(mode).then(_.bind(function() {
|
|
412
|
-
this._check_and_start_session_recording();
|
|
426
|
+
this.__session_recording_init_promise = this._fetch_remote_settings(mode).then(_.bind(function() {
|
|
427
|
+
return this._check_and_start_session_recording();
|
|
413
428
|
}, this));
|
|
414
429
|
} else {
|
|
415
|
-
this._check_and_start_session_recording();
|
|
430
|
+
this.__session_recording_init_promise = this._check_and_start_session_recording();
|
|
416
431
|
}
|
|
417
432
|
};
|
|
418
433
|
|
|
@@ -456,132 +471,50 @@ MixpanelLib.prototype.get_tab_id = function () {
|
|
|
456
471
|
return this.tab_id || null;
|
|
457
472
|
};
|
|
458
473
|
|
|
459
|
-
MixpanelLib.prototype._should_load_recorder = function () {
|
|
460
|
-
if (this.get_config('disable_persistence')) {
|
|
461
|
-
console.log('Load recorder check skipped due to disable_persistence config');
|
|
462
|
-
return Promise.resolve(false);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
var recording_registry_idb = new IDBStorageWrapper(RECORDING_REGISTRY_STORE_NAME);
|
|
466
|
-
var tab_id = this.get_tab_id();
|
|
467
|
-
return recording_registry_idb.init()
|
|
468
|
-
.then(function () {
|
|
469
|
-
return recording_registry_idb.getAll();
|
|
470
|
-
})
|
|
471
|
-
.then(function (recordings) {
|
|
472
|
-
for (var i = 0; i < recordings.length; i++) {
|
|
473
|
-
// if there are expired recordings in the registry, we should load the recorder to flush them
|
|
474
|
-
// if there's a recording for this tab id, we should load the recorder to continue the recording
|
|
475
|
-
if (isRecordingExpired(recordings[i]) || recordings[i]['tabId'] === tab_id) {
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
return false;
|
|
480
|
-
})
|
|
481
|
-
.catch(_.bind(function (err) {
|
|
482
|
-
this.report_error('Error checking recording registry', err);
|
|
483
|
-
}, this));
|
|
484
|
-
};
|
|
485
|
-
|
|
486
474
|
MixpanelLib.prototype._check_and_start_session_recording = addOptOutCheckMixpanelLib(function(force_start) {
|
|
487
|
-
|
|
488
|
-
console.critical('Browser does not support MutationObserver; skipping session recording');
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
var loadRecorder = _.bind(function(startNewIfInactive) {
|
|
493
|
-
var handleLoadedRecorder = _.bind(function() {
|
|
494
|
-
this._recorder = this._recorder || new window[RECORDER_GLOBAL_NAME](this);
|
|
495
|
-
this._recorder['resumeRecording'](startNewIfInactive);
|
|
496
|
-
}, this);
|
|
497
|
-
|
|
498
|
-
if (_.isUndefined(window[RECORDER_GLOBAL_NAME])) {
|
|
499
|
-
load_extra_bundle(this.get_config('recorder_src'), handleLoadedRecorder);
|
|
500
|
-
} else {
|
|
501
|
-
handleLoadedRecorder();
|
|
502
|
-
}
|
|
503
|
-
}, this);
|
|
504
|
-
|
|
505
|
-
/**
|
|
506
|
-
* If the user is sampled or start_session_recording is called, we always load the recorder since it's guaranteed a recording should start.
|
|
507
|
-
* Otherwise, if the recording registry has any records then it's likely there's a recording in progress or orphaned data that needs to be flushed.
|
|
508
|
-
*/
|
|
509
|
-
var is_sampled = this.get_config('record_sessions_percent') > 0 && Math.random() * 100 <= this.get_config('record_sessions_percent');
|
|
510
|
-
if (force_start || is_sampled) {
|
|
511
|
-
loadRecorder(true);
|
|
512
|
-
} else {
|
|
513
|
-
this._should_load_recorder()
|
|
514
|
-
.then(function (shouldLoad) {
|
|
515
|
-
if (shouldLoad) {
|
|
516
|
-
loadRecorder(false);
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
}
|
|
475
|
+
return this.recorderManager.checkAndStartSessionRecording(force_start);
|
|
520
476
|
});
|
|
521
477
|
|
|
478
|
+
MixpanelLib.prototype._start_recording_on_event = function(event_name, properties) {
|
|
479
|
+
return this.recorderManager.startRecordingOnEvent(event_name, properties);
|
|
480
|
+
};
|
|
481
|
+
|
|
522
482
|
MixpanelLib.prototype.start_session_recording = function () {
|
|
523
|
-
this._check_and_start_session_recording(true);
|
|
483
|
+
return this._check_and_start_session_recording(true);
|
|
524
484
|
};
|
|
525
485
|
|
|
526
486
|
MixpanelLib.prototype.stop_session_recording = function () {
|
|
527
|
-
|
|
528
|
-
return this._recorder['stopRecording']();
|
|
529
|
-
}
|
|
530
|
-
return Promise.resolve();
|
|
487
|
+
return this.recorderManager.stopSessionRecording();
|
|
531
488
|
};
|
|
532
489
|
|
|
533
490
|
MixpanelLib.prototype.pause_session_recording = function () {
|
|
534
|
-
|
|
535
|
-
return this._recorder['pauseRecording']();
|
|
536
|
-
}
|
|
537
|
-
return Promise.resolve();
|
|
491
|
+
return this.recorderManager.pauseSessionRecording();
|
|
538
492
|
};
|
|
539
493
|
|
|
540
494
|
MixpanelLib.prototype.resume_session_recording = function () {
|
|
541
|
-
|
|
542
|
-
return this._recorder['resumeRecording']();
|
|
543
|
-
}
|
|
544
|
-
return Promise.resolve();
|
|
495
|
+
return this.recorderManager.resumeSessionRecording();
|
|
545
496
|
};
|
|
546
497
|
|
|
547
498
|
MixpanelLib.prototype.is_recording_heatmap_data = function () {
|
|
548
|
-
return this.
|
|
499
|
+
return this.recorderManager.isRecordingHeatmapData();
|
|
549
500
|
};
|
|
550
501
|
|
|
551
502
|
MixpanelLib.prototype.get_session_recording_properties = function () {
|
|
552
|
-
|
|
553
|
-
var replay_id = this._get_session_replay_id();
|
|
554
|
-
if (replay_id) {
|
|
555
|
-
props['$mp_replay_id'] = replay_id;
|
|
556
|
-
}
|
|
557
|
-
return props;
|
|
503
|
+
return this.recorderManager.getSessionRecordingProperties();
|
|
558
504
|
};
|
|
559
505
|
|
|
560
506
|
MixpanelLib.prototype.get_session_replay_url = function () {
|
|
561
|
-
|
|
562
|
-
var replay_id = this._get_session_replay_id();
|
|
563
|
-
if (replay_id) {
|
|
564
|
-
var query_params = _.HTTPBuildQuery({
|
|
565
|
-
'replay_id': replay_id,
|
|
566
|
-
'distinct_id': this.get_distinct_id(),
|
|
567
|
-
'token': this.get_config('token')
|
|
568
|
-
});
|
|
569
|
-
replay_url = 'https://mixpanel.com/projects/replay-redirect?' + query_params;
|
|
570
|
-
}
|
|
571
|
-
return replay_url;
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
MixpanelLib.prototype._get_session_replay_id = function () {
|
|
575
|
-
var replay_id = null;
|
|
576
|
-
if (this._recorder) {
|
|
577
|
-
replay_id = this._recorder['replayId'];
|
|
578
|
-
}
|
|
579
|
-
return replay_id || null;
|
|
507
|
+
return this.recorderManager.getSessionReplayUrl();
|
|
580
508
|
};
|
|
581
509
|
|
|
582
510
|
// "private" public method to reach into the recorder in test cases
|
|
583
511
|
MixpanelLib.prototype.__get_recorder = function () {
|
|
584
|
-
return this.
|
|
512
|
+
return this.recorderManager.getRecorder();
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
// "private" public method to get session recording init promise in test cases
|
|
516
|
+
MixpanelLib.prototype.__get_recording_init_promise = function () {
|
|
517
|
+
return this.__session_recording_init_promise;
|
|
585
518
|
};
|
|
586
519
|
|
|
587
520
|
// Private methods
|
|
@@ -839,6 +772,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) {
|
|
|
839
772
|
};
|
|
840
773
|
|
|
841
774
|
MixpanelLib.prototype._fetch_remote_settings = function(mode) {
|
|
775
|
+
var self = this;
|
|
842
776
|
var disableRecordingIfStrict = function() {
|
|
843
777
|
if (mode === 'strict') {
|
|
844
778
|
self.set_config({'record_sessions_percent': 0});
|
|
@@ -859,7 +793,6 @@ MixpanelLib.prototype._fetch_remote_settings = function(mode) {
|
|
|
859
793
|
};
|
|
860
794
|
var query_string = _.HTTPBuildQuery(request_params);
|
|
861
795
|
var full_url = settings_endpoint + '?' + query_string;
|
|
862
|
-
var self = this;
|
|
863
796
|
|
|
864
797
|
var abortController = new AbortController();
|
|
865
798
|
var timeout_id = setTimeout(function() {
|
|
@@ -1051,6 +984,34 @@ MixpanelLib.prototype.push = function(item) {
|
|
|
1051
984
|
this._execute_array([item]);
|
|
1052
985
|
};
|
|
1053
986
|
|
|
987
|
+
/**
|
|
988
|
+
* Enables events on the Mixpanel object. If passed no arguments,
|
|
989
|
+
* this function enable tracking of all events. If passed an
|
|
990
|
+
* array of event names, those events will be enabled, but other
|
|
991
|
+
* existing disabled events will continue to be not tracked.
|
|
992
|
+
*
|
|
993
|
+
* @param {Array} [events] An array of event names to enable
|
|
994
|
+
*/
|
|
995
|
+
MixpanelLib.prototype.enable = function(events) {
|
|
996
|
+
var keys, new_disabled_events, i, j;
|
|
997
|
+
|
|
998
|
+
if (typeof(events) === 'undefined') {
|
|
999
|
+
this._flags.disable_all_events = false;
|
|
1000
|
+
} else {
|
|
1001
|
+
keys = {};
|
|
1002
|
+
new_disabled_events = [];
|
|
1003
|
+
for (i = 0; i < events.length; i++) {
|
|
1004
|
+
keys[events[i]] = true;
|
|
1005
|
+
}
|
|
1006
|
+
for (j = 0; j < this.__disabled_events.length; j++) {
|
|
1007
|
+
if (!keys[this.__disabled_events[j]]) {
|
|
1008
|
+
new_disabled_events.push(this.__disabled_events[j]);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
this.__disabled_events = new_disabled_events;
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1054
1015
|
/**
|
|
1055
1016
|
* Disable events on the Mixpanel object. If passed no arguments,
|
|
1056
1017
|
* this function disables tracking of any event. If passed an
|
|
@@ -1224,6 +1185,8 @@ MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, pro
|
|
|
1224
1185
|
this.report_error('Invalid value for property_blacklist config: ' + property_blacklist);
|
|
1225
1186
|
}
|
|
1226
1187
|
|
|
1188
|
+
this._start_recording_on_event(event_name, properties);
|
|
1189
|
+
|
|
1227
1190
|
var data = {
|
|
1228
1191
|
'event': event_name,
|
|
1229
1192
|
'properties': properties
|
|
@@ -2432,6 +2395,7 @@ MixpanelLib.prototype.remove_hook = function(hook_name, hook_fn) {
|
|
|
2432
2395
|
// MixpanelLib Exports
|
|
2433
2396
|
MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
|
|
2434
2397
|
MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
|
|
2398
|
+
MixpanelLib.prototype['enable'] = MixpanelLib.prototype.enable;
|
|
2435
2399
|
MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
|
|
2436
2400
|
MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
|
|
2437
2401
|
MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
|
|
@@ -2475,6 +2439,7 @@ MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES
|
|
|
2475
2439
|
|
|
2476
2440
|
// Exports intended only for testing
|
|
2477
2441
|
MixpanelLib.prototype['__get_recorder'] = MixpanelLib.prototype.__get_recorder;
|
|
2442
|
+
MixpanelLib.prototype['__get_recording_init_promise'] = MixpanelLib.prototype.__get_recording_init_promise;
|
|
2478
2443
|
|
|
2479
2444
|
// MixpanelPersistence Exports
|
|
2480
2445
|
MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
|
package/src/recorder/index.js
CHANGED
package/src/recorder/recorder.js
CHANGED
|
@@ -125,8 +125,12 @@ MixpanelRecorder.prototype.resetRecording = function () {
|
|
|
125
125
|
this.startRecording({shouldStopBatcher: true});
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
+
MixpanelRecorder.prototype.isRecording = function () {
|
|
129
|
+
return this.activeRecording && !this.activeRecording.isRrwebStopped();
|
|
130
|
+
};
|
|
131
|
+
|
|
128
132
|
MixpanelRecorder.prototype.getActiveReplayId = function () {
|
|
129
|
-
if (this.
|
|
133
|
+
if (this.isRecording()) {
|
|
130
134
|
return this.activeRecording.replayId;
|
|
131
135
|
} else {
|
|
132
136
|
return null;
|