mixpanel-browser
Advanced tools
Comparing version
@@ -0,1 +1,8 @@ | ||
**2.67.0** (17 Jul 2025) | ||
- Use `get_api_host()` consistently across the SDK | ||
- Include `device_id` in default Feature Flag context | ||
- Track latency props in `$experiment_started` event | ||
- Fix async behavior in `mixpanel.reset()` when a session recording is active | ||
- Fix recorder integration test race conditions | ||
**2.66.0** (8 Jul 2025) | ||
@@ -2,0 +9,0 @@ - Add `api_host` configuration option to support different hosts/proxies for different endpoints (thanks @chrisknu) |
{ | ||
"name": "mixpanel-browser", | ||
"version": "2.66.0", | ||
"version": "2.67.0", | ||
"description": "The official Mixpanel JavaScript browser client library", | ||
@@ -5,0 +5,0 @@ "main": "dist/mixpanel.cjs.js", |
var Config = { | ||
DEBUG: false, | ||
LIB_VERSION: '2.66.0' | ||
LIB_VERSION: '2.67.0' | ||
}; | ||
export default Config; |
@@ -18,4 +18,5 @@ import { _, console_with_prefix, safewrapClass } from '../utils'; // eslint-disable-line camelcase | ||
var FeatureFlagManager = function(initOptions) { | ||
this.getFullApiRoute = initOptions.getFullApiRoute; | ||
this.getMpConfig = initOptions.getConfigFunc; | ||
this.getDistinctId = initOptions.getDistinctIdFunc; | ||
this.getMpProperty = initOptions.getPropertyFunc; | ||
this.track = initOptions.trackingFunc; | ||
@@ -69,8 +70,10 @@ }; | ||
var distinctId = this.getDistinctId(); | ||
var distinctId = this.getMpProperty('distinct_id'); | ||
var deviceId = this.getMpProperty('$device_id'); | ||
logger.log('Fetching flags for distinct ID: ' + distinctId); | ||
var reqParams = { | ||
'context': _.extend({'distinct_id': distinctId}, this.getConfig(CONFIG_CONTEXT)) | ||
'context': _.extend({'distinct_id': distinctId, 'device_id': deviceId}, this.getConfig(CONFIG_CONTEXT)) | ||
}; | ||
this.fetchPromise = window['fetch'](this.getMpConfig('api_host') + '/' + this.getMpConfig('api_routes')['flags'], { | ||
this._fetchInProgressStartTime = Date.now(); | ||
this.fetchPromise = window['fetch'](this.getFullApiRoute(), { | ||
'method': 'POST', | ||
@@ -83,2 +86,3 @@ 'headers': { | ||
}).then(function(response) { | ||
this.markFetchComplete(); | ||
return response.json().then(function(responseBody) { | ||
@@ -98,7 +102,22 @@ var responseFlags = responseBody['flags']; | ||
}.bind(this)).catch(function(error) { | ||
this.markFetchComplete(); | ||
logger.error(error); | ||
}); | ||
}.bind(this)).catch(function() {}); | ||
}.bind(this)); | ||
}.bind(this)).catch(function(error) { | ||
this.markFetchComplete(); | ||
logger.error(error); | ||
}.bind(this)); | ||
}; | ||
FeatureFlagManager.prototype.markFetchComplete = function() { | ||
if (!this._fetchInProgressStartTime) { | ||
logger.error('Fetch in progress started time not set, cannot mark fetch complete'); | ||
return; | ||
} | ||
this._fetchStartTime = this._fetchInProgressStartTime; | ||
this._fetchCompleteTime = Date.now(); | ||
this._fetchLatency = this._fetchCompleteTime - this._fetchStartTime; | ||
this._fetchInProgressStartTime = null; | ||
}; | ||
FeatureFlagManager.prototype.getVariant = function(featureName, fallback) { | ||
@@ -180,3 +199,6 @@ if (!this.fetchPromise) { | ||
'Variant name': feature['key'], | ||
'$experiment_type': 'feature_flag' | ||
'$experiment_type': 'feature_flag', | ||
'Variant fetch start time': new Date(this._fetchStartTime).toISOString(), | ||
'Variant fetch complete time': new Date(this._fetchCompleteTime).toISOString(), | ||
'Variant fetch latency (ms)': this._fetchLatency | ||
}); | ||
@@ -183,0 +205,0 @@ }; |
@@ -66,3 +66,10 @@ import { window } from '../window'; | ||
/** | ||
* @typedef {Object} UserIdInfo | ||
* @property {string} distinct_id | ||
* @property {string} user_id | ||
* @property {string} device_id | ||
*/ | ||
/** | ||
@@ -122,2 +129,26 @@ * This class encapsulates a single session recording and its lifecycle. | ||
/** | ||
* @returns {UserIdInfo} | ||
*/ | ||
SessionRecording.prototype.getUserIdInfo = function () { | ||
if (this.finalFlushUserIdInfo) { | ||
return this.finalFlushUserIdInfo; | ||
} | ||
var userIdInfo = { | ||
'distinct_id': String(this._mixpanel.get_distinct_id()), | ||
}; | ||
// send ID management props if they exist | ||
var deviceId = this._mixpanel.get_property('$device_id'); | ||
if (deviceId) { | ||
userIdInfo['$device_id'] = deviceId; | ||
} | ||
var userId = this._mixpanel.get_property('$user_id'); | ||
if (userId) { | ||
userIdInfo['$user_id'] = userId; | ||
} | ||
return userIdInfo; | ||
}; | ||
SessionRecording.prototype.unloadPersistedData = function () { | ||
@@ -247,2 +278,5 @@ this.batcher.stop(); | ||
SessionRecording.prototype.stopRecording = function (skipFlush) { | ||
// store the user ID info in case this is getting called in mixpanel.reset() | ||
this.finalFlushUserIdInfo = this.getUserIdInfo(); | ||
if (!this.isRrwebStopped()) { | ||
@@ -413,3 +447,2 @@ try { | ||
'batch_start_time': batchStartTime / 1000, | ||
'distinct_id': String(this._mixpanel.get_distinct_id()), | ||
'mp_lib': 'web', | ||
@@ -423,13 +456,4 @@ 'replay_id': replayId, | ||
var eventsJson = JSON.stringify(data); | ||
Object.assign(reqParams, this.getUserIdInfo()); | ||
// send ID management props if they exist | ||
var deviceId = this._mixpanel.get_property('$device_id'); | ||
if (deviceId) { | ||
reqParams['$device_id'] = deviceId; | ||
} | ||
var userId = this._mixpanel.get_property('$user_id'); | ||
if (userId) { | ||
reqParams['$user_id'] = userId; | ||
} | ||
if (CompressionStream) { | ||
@@ -436,0 +460,0 @@ var jsonStream = new Blob([eventsJson], {type: 'application/json'}).stream(); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
9249396
0.14%71
1.43%178303
0.13%