mixpanel-browser 2.49.0 → 2.50.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/build.sh +2 -1
- package/dist/mixpanel-js-wrapper.js +2 -2
- package/dist/mixpanel-recorder.js +5940 -0
- package/dist/mixpanel-recorder.min.js +24 -0
- package/dist/mixpanel.amd.js +141 -64
- package/dist/mixpanel.cjs.js +140 -63
- package/dist/mixpanel.globals.js +141 -64
- package/dist/mixpanel.min.js +110 -108
- package/dist/mixpanel.umd.js +142 -65
- package/package.json +7 -2
- package/src/config.js +1 -1
- package/src/mixpanel-core.js +53 -3
- package/src/recorder/index.js +153 -0
- package/src/recorder/rollup.config.js +19 -0
- package/src/utils.js +4 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {default as record} from 'rrweb/es/rrweb/packages/rrweb/src/record/index.js';
|
|
2
|
+
|
|
3
|
+
import { MAX_RECORDING_MS, console_with_prefix, _ } from '../utils'; // eslint-disable-line camelcase
|
|
4
|
+
import { addOptOutCheckMixpanelLib } from '../gdpr-utils';
|
|
5
|
+
|
|
6
|
+
var logger = console_with_prefix('recorder');
|
|
7
|
+
|
|
8
|
+
var MixpanelRecorder = function(mixpanelInstance) {
|
|
9
|
+
this._mixpanel = mixpanelInstance;
|
|
10
|
+
|
|
11
|
+
// internal rrweb stopRecording function
|
|
12
|
+
this._stopRecording = null;
|
|
13
|
+
|
|
14
|
+
this.recEvents = [];
|
|
15
|
+
this.seqNo = 0;
|
|
16
|
+
this.replayId = null;
|
|
17
|
+
this.replayStartTime = null;
|
|
18
|
+
this.batchStartTime = null;
|
|
19
|
+
this.replayLengthMs = 0;
|
|
20
|
+
this.sendBatchId = null;
|
|
21
|
+
|
|
22
|
+
this.idleTimeoutId = null;
|
|
23
|
+
this.maxTimeoutId = null;
|
|
24
|
+
|
|
25
|
+
this.recordMaxMs = MAX_RECORDING_MS;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// eslint-disable-next-line camelcase
|
|
29
|
+
MixpanelRecorder.prototype.get_config = function(configVar) {
|
|
30
|
+
return this._mixpanel.get_config(configVar);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
MixpanelRecorder.prototype.startRecording = function () {
|
|
34
|
+
if (this._stopRecording !== null) {
|
|
35
|
+
logger.log('Recording already in progress, skipping startRecording.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.recordMaxMs = this.get_config('record_max_ms');
|
|
40
|
+
if (this.recordMaxMs > MAX_RECORDING_MS) {
|
|
41
|
+
this.recordMaxMs = MAX_RECORDING_MS;
|
|
42
|
+
logger.critical('record_max_ms cannot be greater than ' + MAX_RECORDING_MS + 'ms. Capping value.');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.recEvents = [];
|
|
46
|
+
this.seqNo = 0;
|
|
47
|
+
this.startDate = new Date();
|
|
48
|
+
this.replayStartTime = this.startDate.getTime();
|
|
49
|
+
this.batchStartTime = this.replayStartTime;
|
|
50
|
+
|
|
51
|
+
this.replayId = _.UUID();
|
|
52
|
+
this.replayLengthMs = 0;
|
|
53
|
+
|
|
54
|
+
var resetIdleTimeout = _.bind(function () {
|
|
55
|
+
clearTimeout(this.idleTimeoutId);
|
|
56
|
+
this.idleTimeoutId = setTimeout(_.bind(function () {
|
|
57
|
+
logger.log('Idle timeout reached, restarting recording.');
|
|
58
|
+
this.resetRecording();
|
|
59
|
+
}, this), this.get_config('record_idle_timeout_ms'));
|
|
60
|
+
}, this);
|
|
61
|
+
|
|
62
|
+
this._stopRecording = record({
|
|
63
|
+
'emit': _.bind(function (ev) {
|
|
64
|
+
this.recEvents.push(ev);
|
|
65
|
+
this.replayLengthMs = new Date().getTime() - this.replayStartTime;
|
|
66
|
+
resetIdleTimeout();
|
|
67
|
+
}, this),
|
|
68
|
+
'maskAllInputs': true,
|
|
69
|
+
'maskTextSelector': this.get_config('record_mask_text_selector')
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
resetIdleTimeout();
|
|
73
|
+
|
|
74
|
+
this.sendBatchId = setInterval(_.bind(this.flushEventsWithOptOut, this), 10000);
|
|
75
|
+
this.maxTimeoutId = setTimeout(_.bind(this.resetRecording, this), this.recordMaxMs);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
MixpanelRecorder.prototype.resetRecording = function () {
|
|
79
|
+
this.stopRecording();
|
|
80
|
+
this.startRecording();
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
MixpanelRecorder.prototype.stopRecording = function () {
|
|
84
|
+
if (this._stopRecording !== null) {
|
|
85
|
+
this._stopRecording();
|
|
86
|
+
this._stopRecording = null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this._flushEvents(); // flush any remaining events
|
|
90
|
+
this.replayId = null;
|
|
91
|
+
|
|
92
|
+
clearInterval(this.sendBatchId);
|
|
93
|
+
clearTimeout(this.idleTimeoutId);
|
|
94
|
+
clearTimeout(this.maxTimeoutId);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Flushes the current batch of events to the server, but passes an opt-out callback to make sure
|
|
99
|
+
* we stop recording and dump any queued events if the user has opted out.
|
|
100
|
+
*/
|
|
101
|
+
MixpanelRecorder.prototype.flushEventsWithOptOut = function () {
|
|
102
|
+
this._flushEvents(_.bind(this._onOptOut, this));
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
MixpanelRecorder.prototype._onOptOut = function (code) {
|
|
106
|
+
// addOptOutCheckMixpanelLib invokes this function with code=0 when the user has opted out
|
|
107
|
+
if (code === 0) {
|
|
108
|
+
this.recEvents = [];
|
|
109
|
+
this.stopRecording();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @api private
|
|
115
|
+
* Private method, flushes the current batch of events to the server.
|
|
116
|
+
*/
|
|
117
|
+
MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function() {
|
|
118
|
+
var numEvents = this.recEvents.length;
|
|
119
|
+
if (numEvents > 0) {
|
|
120
|
+
var reqBody = {
|
|
121
|
+
'distinct_id': String(this._mixpanel.get_distinct_id()),
|
|
122
|
+
'events': this.recEvents,
|
|
123
|
+
'seq': this.seqNo++,
|
|
124
|
+
'batch_start_time': this.batchStartTime / 1000,
|
|
125
|
+
'replay_id': this.replayId,
|
|
126
|
+
'replay_length_ms': this.replayLengthMs,
|
|
127
|
+
'replay_start_time': this.replayStartTime / 1000
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// send ID management props if they exist
|
|
131
|
+
var deviceId = this._mixpanel.get_property('$device_id');
|
|
132
|
+
if (deviceId) {
|
|
133
|
+
reqBody['$device_id'] = deviceId;
|
|
134
|
+
}
|
|
135
|
+
var userId = this._mixpanel.get_property('$user_id');
|
|
136
|
+
if (userId) {
|
|
137
|
+
reqBody['$user_id'] = userId;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
window['fetch'](this.get_config('api_host') + '/' + this.get_config('api_routes')['record'], {
|
|
141
|
+
'method': 'POST',
|
|
142
|
+
'headers': {
|
|
143
|
+
'Authorization': 'Basic ' + btoa(this.get_config('token') + ':'),
|
|
144
|
+
'Content-Type': 'application/json'
|
|
145
|
+
},
|
|
146
|
+
'body': _.JSONEncode(reqBody)
|
|
147
|
+
});
|
|
148
|
+
this.recEvents = this.recEvents.slice(numEvents);
|
|
149
|
+
this.batchStartTime = new Date().getTime();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
window['__mp_recorder'] = MixpanelRecorder;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import esbuild from 'rollup-plugin-esbuild';
|
|
2
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
input: 'index.js',
|
|
6
|
+
output: [
|
|
7
|
+
{
|
|
8
|
+
file: 'build/mixpanel-recorder.js',
|
|
9
|
+
format: 'esm'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
file: 'build/mixpanel-recorder.min.js',
|
|
13
|
+
format: 'esm',
|
|
14
|
+
name: 'version',
|
|
15
|
+
plugins: [esbuild({minify: true})]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
plugins: [nodeResolve({browser: true})],
|
|
19
|
+
};
|
package/src/utils.js
CHANGED
|
@@ -20,6 +20,9 @@ if (typeof(window) === 'undefined') {
|
|
|
20
20
|
win = window;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// Maximum allowed session recording length
|
|
24
|
+
var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
25
|
+
|
|
23
26
|
/*
|
|
24
27
|
* Saved references to long variable names, so that closure compiler can
|
|
25
28
|
* minimize file size.
|
|
@@ -1721,6 +1724,7 @@ _['info']['browserVersion'] = _.info.browserVersion;
|
|
|
1721
1724
|
_['info']['properties'] = _.info.properties;
|
|
1722
1725
|
|
|
1723
1726
|
export {
|
|
1727
|
+
MAX_RECORDING_MS,
|
|
1724
1728
|
_,
|
|
1725
1729
|
userAgent,
|
|
1726
1730
|
console,
|