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.
@@ -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,