@reservamos/browser-analytics 1.1.8-alpha.0 → 1.1.8-alpha.2
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/CHANGELOG.md +21 -3
- package/README.md +33 -7
- package/dist/browser-analytics.cjs +2 -2
- package/dist/browser-analytics.cjs.map +1 -1
- package/dist/browser-analytics.d.ts +15 -2
- package/dist/browser-analytics.esm.js +590 -109
- package/dist/browser-analytics.esm.js.map +1 -1
- package/dist/browser-analytics.iife.js +2 -2
- package/dist/browser-analytics.iife.js.map +1 -1
- package/package.json +2 -2
- package/src/events/identify/identify.robustness.test.ts +112 -13
- package/src/events/identify/identify.ts +84 -34
- package/src/events/passengersCreated/passengersCreatedSchema.test.ts +142 -0
- package/src/events/passengersCreated/passengersCreatedSchema.ts +7 -1
- package/src/events/purchaseConfirmation/purchaseConfirmation.integration.test.ts +49 -0
- package/src/events/purchaseConfirmation/purchaseConfirmation.test.ts +17 -0
- package/src/events/purchaseConfirmation/purchaseConfirmationSchema.ts +2 -0
- package/src/events/sharedSchemas/tripSchema.ts +3 -8
- package/src/index.ts +1 -0
- package/src/init.botDetection.test.ts +187 -0
- package/src/init.test.ts +1 -0
- package/src/init.ts +15 -2
- package/src/services/botDetectionRelay.test.ts +3 -2
- package/src/services/deferredBotDetection.ts +60 -0
- package/src/services/fingerprint.test.ts +190 -0
- package/src/services/fingerprint.ts +141 -13
- package/src/services/fingerprint.wait.integration.test.ts +129 -0
- package/src/services/mixpanel.test.ts +119 -73
- package/src/services/mixpanel.ts +82 -23
- package/src/services/trackingLifecycle.ts +54 -0
- package/src/services/validator/validator.test.ts +79 -0
- package/src/track.readiness.test.ts +131 -0
- package/src/track.recovery.test.ts +339 -0
- package/src/track.storage.test.ts +142 -0
- package/src/track.test.ts +130 -5
- package/src/track.ts +110 -25
- package/src/util/pendingWork.test.ts +164 -0
- package/src/util/pendingWork.ts +148 -0
- package/src/util/snapshotEventData.ts +15 -0
|
@@ -4173,7 +4173,8 @@ function r$3({ apiName: r2, defaultApiVersion: i }) {
|
|
|
4173
4173
|
method: "POST",
|
|
4174
4174
|
body: JSON.stringify(p3),
|
|
4175
4175
|
headers: _2,
|
|
4176
|
-
...(f3 == null ? void 0 : f3.signal) && { signal: f3.signal }
|
|
4176
|
+
...(f3 == null ? void 0 : f3.signal) && { signal: f3.signal },
|
|
4177
|
+
...(f3 == null ? void 0 : f3.keepalive) !== void 0 && { keepalive: f3.keepalive }
|
|
4177
4178
|
});
|
|
4178
4179
|
return f3 ? y2 : await y2.json();
|
|
4179
4180
|
}
|
|
@@ -4269,7 +4270,8 @@ async function a$3({ requestId: a2, visitorId: o2, distinctId: s2, purchaseToken
|
|
|
4269
4270
|
responseType: "response",
|
|
4270
4271
|
apiPrefix: "api",
|
|
4271
4272
|
omitHeaders: ["Origin"],
|
|
4272
|
-
signal: u2.signal
|
|
4273
|
+
signal: u2.signal,
|
|
4274
|
+
keepalive: true
|
|
4273
4275
|
});
|
|
4274
4276
|
return l2 && r$2(l2, {
|
|
4275
4277
|
httpStatus: e3.status,
|
|
@@ -11260,9 +11262,9 @@ MixpanelRecorder.prototype._flushEvents = addOptOutCheckMixpanelLib(function(dat
|
|
|
11260
11262
|
if (deviceId) {
|
|
11261
11263
|
reqParams["$device_id"] = deviceId;
|
|
11262
11264
|
}
|
|
11263
|
-
var
|
|
11264
|
-
if (
|
|
11265
|
-
reqParams["$user_id"] =
|
|
11265
|
+
var userId2 = this._mixpanel.get_property("$user_id");
|
|
11266
|
+
if (userId2) {
|
|
11267
|
+
reqParams["$user_id"] = userId2;
|
|
11266
11268
|
}
|
|
11267
11269
|
if (CompressionStream) {
|
|
11268
11270
|
var jsonStream = new Blob([eventsJson], { type: "application/json" }).stream();
|
|
@@ -13339,6 +13341,50 @@ function loadNoop(_src, onload) {
|
|
|
13339
13341
|
onload();
|
|
13340
13342
|
}
|
|
13341
13343
|
var mixpanel = init_as_module(loadNoop);
|
|
13344
|
+
let generation = 0;
|
|
13345
|
+
let initialized = false;
|
|
13346
|
+
let userId;
|
|
13347
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
13348
|
+
const initializationSubscribers = /* @__PURE__ */ new Set();
|
|
13349
|
+
function invalidate$1() {
|
|
13350
|
+
generation++;
|
|
13351
|
+
subscribers.forEach((notify) => notify());
|
|
13352
|
+
}
|
|
13353
|
+
function beginInitialization() {
|
|
13354
|
+
if (initialized) invalidate$1();
|
|
13355
|
+
initialized = true;
|
|
13356
|
+
userId = void 0;
|
|
13357
|
+
initializationSubscribers.forEach((notify) => notify());
|
|
13358
|
+
}
|
|
13359
|
+
function identify$2(nextUserId) {
|
|
13360
|
+
if (userId !== nextUserId) {
|
|
13361
|
+
userId = nextUserId;
|
|
13362
|
+
invalidate$1();
|
|
13363
|
+
}
|
|
13364
|
+
}
|
|
13365
|
+
function capture() {
|
|
13366
|
+
const captured = generation;
|
|
13367
|
+
return () => captured === generation;
|
|
13368
|
+
}
|
|
13369
|
+
function onChange(notify) {
|
|
13370
|
+
subscribers.add(notify);
|
|
13371
|
+
return () => {
|
|
13372
|
+
subscribers.delete(notify);
|
|
13373
|
+
};
|
|
13374
|
+
}
|
|
13375
|
+
function onInitialization(notify) {
|
|
13376
|
+
initializationSubscribers.add(notify);
|
|
13377
|
+
return () => {
|
|
13378
|
+
initializationSubscribers.delete(notify);
|
|
13379
|
+
};
|
|
13380
|
+
}
|
|
13381
|
+
const trackingLifecycle = {
|
|
13382
|
+
beginInitialization,
|
|
13383
|
+
identify: identify$2,
|
|
13384
|
+
capture,
|
|
13385
|
+
onChange,
|
|
13386
|
+
onInitialization
|
|
13387
|
+
};
|
|
13342
13388
|
function createIdentifyReporter() {
|
|
13343
13389
|
const reported = /* @__PURE__ */ new Set();
|
|
13344
13390
|
return (stage, reason, httpStatus) => {
|
|
@@ -13373,16 +13419,16 @@ function waitForIdentifyReady(report) {
|
|
|
13373
13419
|
if (!active) return;
|
|
13374
13420
|
active = false;
|
|
13375
13421
|
clearTimeout(timer);
|
|
13376
|
-
window.removeEventListener("Tracker Ready",
|
|
13422
|
+
window.removeEventListener("Tracker Ready", onReady2);
|
|
13377
13423
|
if (!ready) report("readiness", "timeout");
|
|
13378
13424
|
resolve(ready);
|
|
13379
13425
|
};
|
|
13380
|
-
const
|
|
13426
|
+
const onReady2 = () => {
|
|
13381
13427
|
if (mixpanelService.isReady()) finish(true);
|
|
13382
13428
|
};
|
|
13383
13429
|
const timer = setTimeout(() => finish(false), 5e3);
|
|
13384
|
-
window.addEventListener("Tracker Ready",
|
|
13385
|
-
|
|
13430
|
+
window.addEventListener("Tracker Ready", onReady2);
|
|
13431
|
+
onReady2();
|
|
13386
13432
|
});
|
|
13387
13433
|
}
|
|
13388
13434
|
function waitForIdentifyStage(stage, timeout, run, report) {
|
|
@@ -13427,28 +13473,78 @@ function observeIdentifyResult(stage, report, onTimeout) {
|
|
|
13427
13473
|
}, 5e3);
|
|
13428
13474
|
return { complete };
|
|
13429
13475
|
}
|
|
13430
|
-
const version = "1.1.8-alpha.
|
|
13476
|
+
const version = "1.1.8-alpha.2";
|
|
13431
13477
|
const MIXPANEL_DISTINCT_ID_CACHE_KEY = "mp_distinct_id";
|
|
13478
|
+
const readinessSubscribers$1 = /* @__PURE__ */ new Set();
|
|
13479
|
+
let initializing = false;
|
|
13480
|
+
let initialization$2 = 0;
|
|
13481
|
+
let initializedConfig;
|
|
13482
|
+
function onReady$1(callback) {
|
|
13483
|
+
readinessSubscribers$1.add(callback);
|
|
13484
|
+
return () => {
|
|
13485
|
+
readinessSubscribers$1.delete(callback);
|
|
13486
|
+
};
|
|
13487
|
+
}
|
|
13432
13488
|
const SDK_SUPER_PROPERTIES = {
|
|
13433
13489
|
"Event Source": "sdk",
|
|
13434
13490
|
"Reservamos Version": version
|
|
13435
13491
|
};
|
|
13436
13492
|
function init$2(mixpanelToken, debug = false, proxyUrl) {
|
|
13493
|
+
validateConfiguration(mixpanelToken, proxyUrl);
|
|
13494
|
+
const attempt = ++initialization$2;
|
|
13495
|
+
initializing = true;
|
|
13496
|
+
trackingLifecycle.beginInitialization();
|
|
13497
|
+
if (initializedConfig && window.mixpanel === mixpanel) {
|
|
13498
|
+
mixpanel.set_config({ debug });
|
|
13499
|
+
initializing = false;
|
|
13500
|
+
readinessSubscribers$1.forEach((notify) => notify());
|
|
13501
|
+
return Promise.resolve();
|
|
13502
|
+
}
|
|
13437
13503
|
return new Promise((resolve) => {
|
|
13438
13504
|
mixpanel.init(mixpanelToken, {
|
|
13439
13505
|
debug,
|
|
13440
13506
|
loaded: () => {
|
|
13507
|
+
if (attempt !== initialization$2) {
|
|
13508
|
+
resolve();
|
|
13509
|
+
return;
|
|
13510
|
+
}
|
|
13441
13511
|
window.mixpanel = mixpanel;
|
|
13442
13512
|
mixpanel.register({ ...SDK_SUPER_PROPERTIES });
|
|
13513
|
+
initializedConfig = { token: mixpanelToken, proxyUrl };
|
|
13514
|
+
initializing = false;
|
|
13515
|
+
readinessSubscribers$1.forEach((notify) => notify());
|
|
13443
13516
|
resolve();
|
|
13444
13517
|
},
|
|
13445
13518
|
...proxyUrl && { api_host: proxyUrl }
|
|
13446
13519
|
});
|
|
13447
13520
|
});
|
|
13448
13521
|
}
|
|
13449
|
-
function
|
|
13450
|
-
mixpanel.
|
|
13451
|
-
|
|
13522
|
+
function validateConfiguration(token, proxyUrl) {
|
|
13523
|
+
if (initializedConfig && window.mixpanel === mixpanel && (initializedConfig.token !== token || initializedConfig.proxyUrl !== proxyUrl)) {
|
|
13524
|
+
throw new Error(
|
|
13525
|
+
"Changing the Mixpanel project or proxy requires a new page session."
|
|
13526
|
+
);
|
|
13527
|
+
}
|
|
13528
|
+
}
|
|
13529
|
+
function identify$1(userId2, properties, report) {
|
|
13530
|
+
trackingLifecycle.identify(userId2);
|
|
13531
|
+
mixpanel.identify(userId2);
|
|
13532
|
+
if (!updateCachedDistinctId(userId2)) report == null ? void 0 : report("cache", "unavailable");
|
|
13533
|
+
writePeopleProperties(properties, report);
|
|
13534
|
+
}
|
|
13535
|
+
function attachProperty(key, value) {
|
|
13536
|
+
if (!isReady()) {
|
|
13537
|
+
return;
|
|
13538
|
+
}
|
|
13539
|
+
mixpanel.people.union(key, [value]);
|
|
13540
|
+
}
|
|
13541
|
+
function setPeopleProperties(properties, report) {
|
|
13542
|
+
if (!isReady()) {
|
|
13543
|
+
return;
|
|
13544
|
+
}
|
|
13545
|
+
writePeopleProperties(properties, report);
|
|
13546
|
+
}
|
|
13547
|
+
function writePeopleProperties(properties, report) {
|
|
13452
13548
|
if (!report) {
|
|
13453
13549
|
mixpanel.people.set(properties);
|
|
13454
13550
|
return;
|
|
@@ -13465,20 +13561,8 @@ function identify$1(userId, properties, report) {
|
|
|
13465
13561
|
observer.complete("failed");
|
|
13466
13562
|
}
|
|
13467
13563
|
}
|
|
13468
|
-
function attachProperty(key, value) {
|
|
13469
|
-
if (!isReady()) {
|
|
13470
|
-
return;
|
|
13471
|
-
}
|
|
13472
|
-
mixpanel.people.union(key, [value]);
|
|
13473
|
-
}
|
|
13474
|
-
function setPeopleProperties(properties) {
|
|
13475
|
-
if (!isReady()) {
|
|
13476
|
-
return;
|
|
13477
|
-
}
|
|
13478
|
-
mixpanel.people.set(properties);
|
|
13479
|
-
}
|
|
13480
13564
|
function isReady() {
|
|
13481
|
-
return window.mixpanel !== void 0;
|
|
13565
|
+
return !initializing && window.mixpanel !== void 0;
|
|
13482
13566
|
}
|
|
13483
13567
|
function track(eventName, properties) {
|
|
13484
13568
|
if (!isReady()) {
|
|
@@ -13487,8 +13571,7 @@ function track(eventName, properties) {
|
|
|
13487
13571
|
mixpanel.track(eventName, { ...properties, "Reservamos Version": version });
|
|
13488
13572
|
}
|
|
13489
13573
|
const getMixpanelDistinctId = () => {
|
|
13490
|
-
|
|
13491
|
-
const distinctId = (_a = mixpanel == null ? void 0 : mixpanel.get_distinct_id) == null ? void 0 : _a.call(mixpanel);
|
|
13574
|
+
const distinctId = isReady() ? mixpanel.get_distinct_id() : null;
|
|
13492
13575
|
if (distinctId) {
|
|
13493
13576
|
updateCachedDistinctId(distinctId);
|
|
13494
13577
|
return distinctId;
|
|
@@ -13509,7 +13592,9 @@ function updateCachedDistinctId(distinctId) {
|
|
|
13509
13592
|
}
|
|
13510
13593
|
const mixpanelService = {
|
|
13511
13594
|
init: init$2,
|
|
13595
|
+
validateConfiguration,
|
|
13512
13596
|
isReady,
|
|
13597
|
+
onReady: onReady$1,
|
|
13513
13598
|
track,
|
|
13514
13599
|
identify: identify$1,
|
|
13515
13600
|
attachProperty,
|
|
@@ -13520,6 +13605,23 @@ const DEFAULT_CACHE_NAME = "default_fingerprint_cache";
|
|
|
13520
13605
|
const DEFAULT_CACHE_TIME_IN_DAYS = 7;
|
|
13521
13606
|
const PROXY_QUERY_PARAM = "apiKey=<apiKey>&version=<version>&loaderVersion=<loaderVersion>";
|
|
13522
13607
|
let fingerprintAgentReady = false;
|
|
13608
|
+
let initialization$1 = 0;
|
|
13609
|
+
let startedInitialization = -1;
|
|
13610
|
+
const readinessSubscribers = /* @__PURE__ */ new Set();
|
|
13611
|
+
const waitingConsumers = /* @__PURE__ */ new Set();
|
|
13612
|
+
let pendingIdentification;
|
|
13613
|
+
function onReady(notify) {
|
|
13614
|
+
readinessSubscribers.add(notify);
|
|
13615
|
+
return () => {
|
|
13616
|
+
readinessSubscribers.delete(notify);
|
|
13617
|
+
};
|
|
13618
|
+
}
|
|
13619
|
+
function invalidate() {
|
|
13620
|
+
initialization$1++;
|
|
13621
|
+
fingerprintAgentReady = false;
|
|
13622
|
+
pendingIdentification = void 0;
|
|
13623
|
+
waitingConsumers.forEach((cancel) => cancel());
|
|
13624
|
+
}
|
|
13523
13625
|
const getExpirationDate = (cacheTimeInDays) => {
|
|
13524
13626
|
const currentDate = /* @__PURE__ */ new Date();
|
|
13525
13627
|
const futureDate = new Date(
|
|
@@ -13565,7 +13667,9 @@ async function initFingerprint(apiKey, proxyUrl) {
|
|
|
13565
13667
|
customEndpointArray.unshift(proxyUrl);
|
|
13566
13668
|
customScriptEndpointArray.unshift(buildProxyUrl(proxyUrl));
|
|
13567
13669
|
}
|
|
13568
|
-
|
|
13670
|
+
if (startedInitialization === initialization$1) invalidate();
|
|
13671
|
+
startedInitialization = initialization$1;
|
|
13672
|
+
const attempt = initialization$1;
|
|
13569
13673
|
window.fingerprintConfig = {};
|
|
13570
13674
|
const client = new FpjsClient({
|
|
13571
13675
|
loadOptions: {
|
|
@@ -13577,19 +13681,21 @@ async function initFingerprint(apiKey, proxyUrl) {
|
|
|
13577
13681
|
window.fpClient = client;
|
|
13578
13682
|
try {
|
|
13579
13683
|
await client.init();
|
|
13580
|
-
if (window.fpClient === client) {
|
|
13684
|
+
if (window.fpClient === client && attempt === initialization$1) {
|
|
13581
13685
|
fingerprintAgentReady = true;
|
|
13686
|
+
readinessSubscribers.forEach((notify) => notify());
|
|
13582
13687
|
}
|
|
13583
13688
|
} catch (error) {
|
|
13584
|
-
if (window.fpClient === client) {
|
|
13689
|
+
if (window.fpClient === client && attempt === initialization$1) {
|
|
13585
13690
|
fingerprintAgentReady = false;
|
|
13691
|
+
waitingConsumers.forEach((cancel) => cancel());
|
|
13586
13692
|
}
|
|
13587
13693
|
console.error("Error initializing identification service:", error);
|
|
13588
13694
|
throw error;
|
|
13589
13695
|
}
|
|
13590
13696
|
}
|
|
13591
|
-
async function getFingerprint(cacheOnly = false) {
|
|
13592
|
-
return readFingerprint(cacheOnly);
|
|
13697
|
+
async function getFingerprint(cacheOnly = false, context) {
|
|
13698
|
+
return readFingerprint(cacheOnly, context);
|
|
13593
13699
|
}
|
|
13594
13700
|
function getFingerprintForIdentify(context) {
|
|
13595
13701
|
return readFingerprint(false, context);
|
|
@@ -13605,21 +13711,59 @@ async function readFingerprint(cacheOnly, context) {
|
|
|
13605
13711
|
const { visitorId } = await requestIdentification(false, context);
|
|
13606
13712
|
return visitorId;
|
|
13607
13713
|
}
|
|
13608
|
-
async function identifyVisitor(ignoreCache = false) {
|
|
13609
|
-
return requestIdentification(ignoreCache);
|
|
13714
|
+
async function identifyVisitor(ignoreCache = false, context) {
|
|
13715
|
+
return requestIdentification(ignoreCache, context);
|
|
13610
13716
|
}
|
|
13611
13717
|
async function requestIdentification(ignoreCache, context) {
|
|
13718
|
+
if (!ignoreCache && (pendingIdentification == null ? void 0 : pendingIdentification.isCurrent())) {
|
|
13719
|
+
for (const participant of pendingIdentification.contexts) {
|
|
13720
|
+
if (participant && !participant.isActive())
|
|
13721
|
+
pendingIdentification.contexts.delete(participant);
|
|
13722
|
+
}
|
|
13723
|
+
pendingIdentification.contexts.add(context);
|
|
13724
|
+
return pendingIdentification.promise;
|
|
13725
|
+
}
|
|
13726
|
+
const contexts = /* @__PURE__ */ new Set([context]);
|
|
13727
|
+
const attempt = initialization$1;
|
|
13728
|
+
const currentLifecycle = trackingLifecycle.capture();
|
|
13729
|
+
const isCurrent = () => attempt === initialization$1 && currentLifecycle();
|
|
13730
|
+
const sharedContext = {
|
|
13731
|
+
isActive: () => isCurrent() && [...contexts].some(
|
|
13732
|
+
(participant) => !participant || participant.isActive()
|
|
13733
|
+
),
|
|
13734
|
+
report: (...args) => {
|
|
13735
|
+
for (const participant of contexts) {
|
|
13736
|
+
if (participant == null ? void 0 : participant.isActive()) participant.report(...args);
|
|
13737
|
+
}
|
|
13738
|
+
}
|
|
13739
|
+
};
|
|
13740
|
+
const request = {
|
|
13741
|
+
contexts,
|
|
13742
|
+
isCurrent,
|
|
13743
|
+
promise: performIdentification(
|
|
13744
|
+
ignoreCache,
|
|
13745
|
+
sharedContext,
|
|
13746
|
+
() => contexts.has(void 0)
|
|
13747
|
+
)
|
|
13748
|
+
};
|
|
13749
|
+
pendingIdentification = request;
|
|
13750
|
+
const clear = () => {
|
|
13751
|
+
if (pendingIdentification === request) pendingIdentification = void 0;
|
|
13752
|
+
};
|
|
13753
|
+
void request.promise.then(clear, clear);
|
|
13754
|
+
return request.promise;
|
|
13755
|
+
}
|
|
13756
|
+
async function performIdentification(ignoreCache, context, hasUnscopedConsumer) {
|
|
13612
13757
|
if (!isFingerprintReady()) {
|
|
13613
13758
|
throw new Error("Identification service is not initialized.");
|
|
13614
13759
|
}
|
|
13615
13760
|
try {
|
|
13616
13761
|
const result = await window.fpClient.getVisitorData({}, ignoreCache);
|
|
13617
|
-
if (
|
|
13762
|
+
if (context.isActive()) {
|
|
13618
13763
|
try {
|
|
13619
13764
|
setCachedFingerprint(result.visitorId);
|
|
13620
|
-
} catch
|
|
13621
|
-
|
|
13622
|
-
context.report("cache", "unavailable");
|
|
13765
|
+
} catch {
|
|
13766
|
+
context == null ? void 0 : context.report("cache", "unavailable");
|
|
13623
13767
|
}
|
|
13624
13768
|
if (typeof result.visitorFound === "boolean") {
|
|
13625
13769
|
try {
|
|
@@ -13627,8 +13771,9 @@ async function requestIdentification(ignoreCache, context) {
|
|
|
13627
13771
|
"Visitor Found": result.visitorFound
|
|
13628
13772
|
});
|
|
13629
13773
|
} catch (error) {
|
|
13630
|
-
|
|
13631
|
-
|
|
13774
|
+
context.report("fingerprint", "failed");
|
|
13775
|
+
if (hasUnscopedConsumer())
|
|
13776
|
+
console.error("Error updating Mixpanel visitor profile:", error);
|
|
13632
13777
|
}
|
|
13633
13778
|
}
|
|
13634
13779
|
}
|
|
@@ -13640,10 +13785,46 @@ async function requestIdentification(ignoreCache, context) {
|
|
|
13640
13785
|
cacheHit: result.cacheHit
|
|
13641
13786
|
};
|
|
13642
13787
|
} catch (error) {
|
|
13643
|
-
if (
|
|
13788
|
+
if (hasUnscopedConsumer())
|
|
13789
|
+
console.error("Error retrieving fingerprint:", error);
|
|
13644
13790
|
throw error;
|
|
13645
13791
|
}
|
|
13646
13792
|
}
|
|
13793
|
+
function waitForFingerprintId(timeoutMs = 2e3) {
|
|
13794
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0 || timeoutMs > 2147483647)
|
|
13795
|
+
return Promise.resolve(null);
|
|
13796
|
+
const cached = getCachedFingerprint();
|
|
13797
|
+
if (cached) return Promise.resolve(cached);
|
|
13798
|
+
return new Promise((resolve) => {
|
|
13799
|
+
let active = true;
|
|
13800
|
+
let started = false;
|
|
13801
|
+
const finish = (visitorId) => {
|
|
13802
|
+
if (!active) return;
|
|
13803
|
+
active = false;
|
|
13804
|
+
clearTimeout(timer);
|
|
13805
|
+
stopReady();
|
|
13806
|
+
stopLifecycle();
|
|
13807
|
+
waitingConsumers.delete(cancel);
|
|
13808
|
+
resolve(visitorId);
|
|
13809
|
+
};
|
|
13810
|
+
const cancel = () => finish(null);
|
|
13811
|
+
const start = () => {
|
|
13812
|
+
if (!active || started || !isFingerprintReady()) return;
|
|
13813
|
+
started = true;
|
|
13814
|
+
const identity = getFingerprint(false, {
|
|
13815
|
+
// Caller timeout ends waiting; the shared request still checks its lifecycle.
|
|
13816
|
+
isActive: () => true,
|
|
13817
|
+
report: () => void 0
|
|
13818
|
+
});
|
|
13819
|
+
void identity.then((visitorId) => finish(visitorId || null), cancel);
|
|
13820
|
+
};
|
|
13821
|
+
const timer = setTimeout(cancel, timeoutMs);
|
|
13822
|
+
const stopReady = onReady(start);
|
|
13823
|
+
const stopLifecycle = trackingLifecycle.onChange(cancel);
|
|
13824
|
+
waitingConsumers.add(cancel);
|
|
13825
|
+
start();
|
|
13826
|
+
});
|
|
13827
|
+
}
|
|
13647
13828
|
function isFingerprintReady() {
|
|
13648
13829
|
return window.fpClient !== void 0 && fingerprintAgentReady;
|
|
13649
13830
|
}
|
|
@@ -13652,8 +13833,169 @@ const fingerprintService = {
|
|
|
13652
13833
|
getFingerprint,
|
|
13653
13834
|
identifyVisitor,
|
|
13654
13835
|
isFingerprintReady,
|
|
13655
|
-
|
|
13656
|
-
|
|
13836
|
+
onReady,
|
|
13837
|
+
invalidate,
|
|
13838
|
+
getCachedFingerprint,
|
|
13839
|
+
waitForFingerprintId
|
|
13840
|
+
};
|
|
13841
|
+
trackingLifecycle.onInitialization(invalidate);
|
|
13842
|
+
function createPendingWorkQueue(options) {
|
|
13843
|
+
const entries = /* @__PURE__ */ new Set();
|
|
13844
|
+
let bytes = 0;
|
|
13845
|
+
let active = 0;
|
|
13846
|
+
let draining = false;
|
|
13847
|
+
let unsubscribe;
|
|
13848
|
+
let timer;
|
|
13849
|
+
function diagnostic(entry, reason) {
|
|
13850
|
+
console.error("Tracking recovery diagnostic", {
|
|
13851
|
+
eventName: entry.eventName,
|
|
13852
|
+
stage: options.stage,
|
|
13853
|
+
reason
|
|
13854
|
+
});
|
|
13855
|
+
}
|
|
13856
|
+
function resolveForeground(entry) {
|
|
13857
|
+
var _a;
|
|
13858
|
+
(_a = entry.resolve) == null ? void 0 : _a.call(entry);
|
|
13859
|
+
entry.resolve = void 0;
|
|
13860
|
+
}
|
|
13861
|
+
function close(entry, reason) {
|
|
13862
|
+
if (entry.state === "closed") return;
|
|
13863
|
+
entry.state = "closed";
|
|
13864
|
+
entries.delete(entry);
|
|
13865
|
+
bytes -= entry.bytes;
|
|
13866
|
+
resolveForeground(entry);
|
|
13867
|
+
if (reason) diagnostic(entry, reason);
|
|
13868
|
+
}
|
|
13869
|
+
function schedule() {
|
|
13870
|
+
clearTimeout(timer);
|
|
13871
|
+
timer = void 0;
|
|
13872
|
+
if (entries.size === 0) {
|
|
13873
|
+
unsubscribe == null ? void 0 : unsubscribe();
|
|
13874
|
+
unsubscribe = void 0;
|
|
13875
|
+
return;
|
|
13876
|
+
}
|
|
13877
|
+
let next = Infinity;
|
|
13878
|
+
for (const entry of entries) {
|
|
13879
|
+
next = Math.min(next, entry.deadline);
|
|
13880
|
+
if (entry.resolve) next = Math.min(next, entry.foregroundDeadline);
|
|
13881
|
+
}
|
|
13882
|
+
timer = setTimeout(drain, Math.max(0, next - Date.now()));
|
|
13883
|
+
}
|
|
13884
|
+
function drain() {
|
|
13885
|
+
if (draining) return;
|
|
13886
|
+
draining = true;
|
|
13887
|
+
try {
|
|
13888
|
+
for (const entry of entries) {
|
|
13889
|
+
if (!entry.isCurrent()) close(entry, "identity_changed");
|
|
13890
|
+
else if (Date.now() >= entry.deadline) close(entry, "timeout");
|
|
13891
|
+
else if (entry.resolve && Date.now() >= entry.foregroundDeadline) {
|
|
13892
|
+
resolveForeground(entry);
|
|
13893
|
+
}
|
|
13894
|
+
}
|
|
13895
|
+
for (const entry of entries) {
|
|
13896
|
+
if (active >= options.maxActive || !options.isReady()) break;
|
|
13897
|
+
if (entry.state !== "waiting") continue;
|
|
13898
|
+
entry.state = "active";
|
|
13899
|
+
active++;
|
|
13900
|
+
const isActive = () => entry.state === "active" && Date.now() < entry.deadline && entry.isCurrent();
|
|
13901
|
+
const finish = (failed = false) => {
|
|
13902
|
+
if (failed && isActive()) diagnostic(entry, "failed");
|
|
13903
|
+
close(entry);
|
|
13904
|
+
active--;
|
|
13905
|
+
drain();
|
|
13906
|
+
};
|
|
13907
|
+
try {
|
|
13908
|
+
void Promise.resolve(entry.run(isActive)).then(
|
|
13909
|
+
() => finish(),
|
|
13910
|
+
() => finish(true)
|
|
13911
|
+
);
|
|
13912
|
+
} catch {
|
|
13913
|
+
finish(true);
|
|
13914
|
+
}
|
|
13915
|
+
}
|
|
13916
|
+
} finally {
|
|
13917
|
+
draining = false;
|
|
13918
|
+
schedule();
|
|
13919
|
+
}
|
|
13920
|
+
}
|
|
13921
|
+
function enqueue(work) {
|
|
13922
|
+
if (work.bytes > options.maxBytes) {
|
|
13923
|
+
diagnostic(work, "capacity");
|
|
13924
|
+
return Promise.resolve();
|
|
13925
|
+
}
|
|
13926
|
+
while (entries.size >= options.maxEntries || bytes + work.bytes > options.maxBytes) {
|
|
13927
|
+
const oldest = [...entries].find((entry) => entry.state === "waiting");
|
|
13928
|
+
if (!oldest) {
|
|
13929
|
+
diagnostic(work, "capacity");
|
|
13930
|
+
return Promise.resolve();
|
|
13931
|
+
}
|
|
13932
|
+
close(oldest, "capacity");
|
|
13933
|
+
}
|
|
13934
|
+
return new Promise((resolve) => {
|
|
13935
|
+
const entry = {
|
|
13936
|
+
...work,
|
|
13937
|
+
state: "waiting",
|
|
13938
|
+
deadline: Date.now() + options.lifetime,
|
|
13939
|
+
foregroundDeadline: Date.now() + options.wait,
|
|
13940
|
+
resolve
|
|
13941
|
+
};
|
|
13942
|
+
entries.add(entry);
|
|
13943
|
+
bytes += entry.bytes;
|
|
13944
|
+
unsubscribe ?? (unsubscribe = options.subscribe(drain));
|
|
13945
|
+
drain();
|
|
13946
|
+
});
|
|
13947
|
+
}
|
|
13948
|
+
return { enqueue };
|
|
13949
|
+
}
|
|
13950
|
+
const observations = createPendingWorkQueue({
|
|
13951
|
+
isReady: () => fingerprintService.isFingerprintReady(),
|
|
13952
|
+
subscribe(notify) {
|
|
13953
|
+
const stopReady = fingerprintService.onReady(notify);
|
|
13954
|
+
const stopIdentity = trackingLifecycle.onChange(notify);
|
|
13955
|
+
return () => {
|
|
13956
|
+
stopReady();
|
|
13957
|
+
stopIdentity();
|
|
13958
|
+
};
|
|
13959
|
+
},
|
|
13960
|
+
maxEntries: 100,
|
|
13961
|
+
maxBytes: 1024 * 1024,
|
|
13962
|
+
maxActive: 3,
|
|
13963
|
+
lifetime: 1e4,
|
|
13964
|
+
wait: 0,
|
|
13965
|
+
stage: "fingerprint"
|
|
13966
|
+
});
|
|
13967
|
+
function deferBotDetection(eventName, distinctId, isCurrent) {
|
|
13968
|
+
void observations.enqueue({
|
|
13969
|
+
eventName,
|
|
13970
|
+
bytes: new Blob([eventName, distinctId ?? ""]).size,
|
|
13971
|
+
isCurrent,
|
|
13972
|
+
async run(isActive) {
|
|
13973
|
+
let stage = "fingerprint";
|
|
13974
|
+
try {
|
|
13975
|
+
const identification = await fingerprintService.identifyVisitor(true, {
|
|
13976
|
+
isActive,
|
|
13977
|
+
report: () => void 0
|
|
13978
|
+
});
|
|
13979
|
+
if (!isActive() || !identification.requestId) return;
|
|
13980
|
+
stage = "relay";
|
|
13981
|
+
await botDetectionRelayService.relay({
|
|
13982
|
+
requestId: identification.requestId,
|
|
13983
|
+
visitorId: identification.visitorId,
|
|
13984
|
+
...distinctId && { distinctId },
|
|
13985
|
+
eventName
|
|
13986
|
+
});
|
|
13987
|
+
} catch {
|
|
13988
|
+
if (isActive()) {
|
|
13989
|
+
console.error("Bot Detection diagnostic", {
|
|
13990
|
+
eventName,
|
|
13991
|
+
stage,
|
|
13992
|
+
reason: "failed"
|
|
13993
|
+
});
|
|
13994
|
+
}
|
|
13995
|
+
}
|
|
13996
|
+
}
|
|
13997
|
+
});
|
|
13998
|
+
}
|
|
13657
13999
|
let environment;
|
|
13658
14000
|
let appName;
|
|
13659
14001
|
const origin = window.location.origin;
|
|
@@ -13792,7 +14134,7 @@ const tripSchema = z.object({
|
|
|
13792
14134
|
"Departure Origin Terminal": stringField("Departure Origin Terminal"),
|
|
13793
14135
|
"Departure Price": numberField("Departure Price"),
|
|
13794
14136
|
"Departure Route": stringField("Departure Route"),
|
|
13795
|
-
"Departure Stops":
|
|
14137
|
+
"Departure Stops": z.number().int(),
|
|
13796
14138
|
"Departure Time": dateField("Departure Time"),
|
|
13797
14139
|
"Departure Transport Type": stringField("Departure Transport Type"),
|
|
13798
14140
|
"Departure Transporter": stringField("Departure Transporter"),
|
|
@@ -13806,7 +14148,7 @@ const tripSchema = z.object({
|
|
|
13806
14148
|
"Return Origin Terminal": stringField("Return Origin Terminal").optional(),
|
|
13807
14149
|
"Return Price": numberField("Return Price").optional(),
|
|
13808
14150
|
"Return Route": stringField("Return Route").optional(),
|
|
13809
|
-
"Return Stops":
|
|
14151
|
+
"Return Stops": z.number().int().optional(),
|
|
13810
14152
|
"Return Time": dateField("Return Time").optional(),
|
|
13811
14153
|
"Return Transport Type": stringField("Return Transport Type").optional(),
|
|
13812
14154
|
"Return Transporter": stringField("Return Transporter").optional(),
|
|
@@ -13819,7 +14161,8 @@ const passengersCreatedSchema = z.object({
|
|
|
13819
14161
|
"Trip Count": intField("Trip Count").optional(),
|
|
13820
14162
|
"Total": numberField("Total"),
|
|
13821
14163
|
"product": productValidation,
|
|
13822
|
-
"Passengers": arrayField(passengerSchema, "Passengers", 1).optional()
|
|
14164
|
+
"Passengers": arrayField(passengerSchema, "Passengers", 1).optional(),
|
|
14165
|
+
"Coupon": stringField("Coupon").optional()
|
|
13823
14166
|
}).strict();
|
|
13824
14167
|
const EVENT_NAME$8 = "Passengers Created";
|
|
13825
14168
|
function trackPassengersCreated(eventProps, meta = {}) {
|
|
@@ -13887,7 +14230,8 @@ const purchaseConfirmationSchema = z.object({
|
|
|
13887
14230
|
"Operation Id": z.string().min(1, "Operation Id is required"),
|
|
13888
14231
|
"Payment Status": z.enum(["confirmed", "pending_pix"]),
|
|
13889
14232
|
"Payment Type": z.string().optional(),
|
|
13890
|
-
"Total": z.number().optional()
|
|
14233
|
+
"Total": z.number().optional(),
|
|
14234
|
+
"product": productValidation.optional()
|
|
13891
14235
|
}).strict();
|
|
13892
14236
|
const EVENT_NAME$4 = "Purchase Confirmation Viewed";
|
|
13893
14237
|
function trackPurchaseConfirmation(eventData, meta = {}) {
|
|
@@ -14071,6 +14415,7 @@ const validatorService = {
|
|
|
14071
14415
|
parseIdentifyProps,
|
|
14072
14416
|
validateProps
|
|
14073
14417
|
};
|
|
14418
|
+
let initialization = 0;
|
|
14074
14419
|
function onLoaded() {
|
|
14075
14420
|
window.dispatchEvent(new CustomEvent("Tracker Ready"));
|
|
14076
14421
|
}
|
|
@@ -14085,19 +14430,30 @@ async function init$1(config) {
|
|
|
14085
14430
|
identifyProxyUrl,
|
|
14086
14431
|
appName: appName2
|
|
14087
14432
|
} = config;
|
|
14433
|
+
mixpanelService.validateConfiguration(mixpanelToken, mixpanelProxyUrl);
|
|
14434
|
+
const attempt = ++initialization;
|
|
14435
|
+
const isCurrent = () => attempt === initialization;
|
|
14088
14436
|
await mixpanelService.init(mixpanelToken, debug, mixpanelProxyUrl);
|
|
14437
|
+
if (!isCurrent()) return;
|
|
14089
14438
|
configService.setEnvironment(isSandbox ? "sandbox" : "prod");
|
|
14090
14439
|
if (appName2) {
|
|
14091
14440
|
configService.setAppName(appName2);
|
|
14092
14441
|
}
|
|
14093
14442
|
a$1.setConfig(configService.getCoreAPIConfig());
|
|
14094
14443
|
onLoaded();
|
|
14444
|
+
if (!isCurrent()) return;
|
|
14095
14445
|
await Promise.all([
|
|
14096
14446
|
initializeOptionalStage(
|
|
14097
14447
|
"fingerprint",
|
|
14098
|
-
() => fingerprintService.initFingerprint(
|
|
14448
|
+
() => isCurrent() ? fingerprintService.initFingerprint(
|
|
14449
|
+
identificationKey,
|
|
14450
|
+
identifyProxyUrl
|
|
14451
|
+
) : Promise.resolve()
|
|
14099
14452
|
),
|
|
14100
|
-
initializeOptionalStage(
|
|
14453
|
+
initializeOptionalStage(
|
|
14454
|
+
"geolocation",
|
|
14455
|
+
() => isCurrent() ? geolocationService.init() : Promise.resolve()
|
|
14456
|
+
)
|
|
14101
14457
|
]);
|
|
14102
14458
|
}
|
|
14103
14459
|
function initializeOptionalStage(stage, initialize) {
|
|
@@ -14323,6 +14679,20 @@ const geolocationService = {
|
|
|
14323
14679
|
getCoordinates,
|
|
14324
14680
|
getGeolocationSource
|
|
14325
14681
|
};
|
|
14682
|
+
function snapshotEventData(value) {
|
|
14683
|
+
if (Array.isArray(value))
|
|
14684
|
+
return value.map((item) => snapshotEventData(item));
|
|
14685
|
+
if (value instanceof Date) return new Date(value.getTime());
|
|
14686
|
+
if (value !== null && typeof value === "object") {
|
|
14687
|
+
return Object.fromEntries(
|
|
14688
|
+
Object.entries(value).map(([key, item]) => [
|
|
14689
|
+
key,
|
|
14690
|
+
snapshotEventData(item)
|
|
14691
|
+
])
|
|
14692
|
+
);
|
|
14693
|
+
}
|
|
14694
|
+
return value;
|
|
14695
|
+
}
|
|
14326
14696
|
const FP_TRIGGER_EVENTS = ["Search", "View Results"];
|
|
14327
14697
|
const EXTRA_UTM_FIELDS = {
|
|
14328
14698
|
utm_brand: "UTM Brand",
|
|
@@ -14377,15 +14747,17 @@ async function tryTrackEvent(trackEventCallback, eventName = "Track Event Error"
|
|
|
14377
14747
|
const ready = await new Promise((resolve) => {
|
|
14378
14748
|
const finish = (isReady2) => {
|
|
14379
14749
|
clearTimeout(timer);
|
|
14380
|
-
window.removeEventListener("Tracker Ready",
|
|
14750
|
+
window.removeEventListener("Tracker Ready", onReady2);
|
|
14751
|
+
unsubscribe();
|
|
14381
14752
|
resolve(isReady2);
|
|
14382
14753
|
};
|
|
14383
|
-
const
|
|
14754
|
+
const onReady2 = () => {
|
|
14384
14755
|
if (mixpanelService.isReady()) finish(true);
|
|
14385
14756
|
};
|
|
14386
14757
|
const timer = setTimeout(() => finish(mixpanelService.isReady()), 5e3);
|
|
14387
|
-
|
|
14388
|
-
|
|
14758
|
+
const unsubscribe = mixpanelService.onReady(onReady2);
|
|
14759
|
+
window.addEventListener("Tracker Ready", onReady2);
|
|
14760
|
+
onReady2();
|
|
14389
14761
|
});
|
|
14390
14762
|
if (!ready) {
|
|
14391
14763
|
console.error("Tracking diagnostic", {
|
|
@@ -14406,28 +14778,94 @@ async function tryTrackEvent(trackEventCallback, eventName = "Track Event Error"
|
|
|
14406
14778
|
});
|
|
14407
14779
|
}
|
|
14408
14780
|
}
|
|
14781
|
+
const pendingEvents = createPendingWorkQueue({
|
|
14782
|
+
isReady: () => mixpanelService.isReady(),
|
|
14783
|
+
subscribe(notify) {
|
|
14784
|
+
const stopReady = mixpanelService.onReady(notify);
|
|
14785
|
+
const stopIdentity = trackingLifecycle.onChange(notify);
|
|
14786
|
+
window.addEventListener("Tracker Ready", notify);
|
|
14787
|
+
return () => {
|
|
14788
|
+
stopReady();
|
|
14789
|
+
stopIdentity();
|
|
14790
|
+
window.removeEventListener("Tracker Ready", notify);
|
|
14791
|
+
};
|
|
14792
|
+
},
|
|
14793
|
+
maxEntries: 100,
|
|
14794
|
+
maxBytes: 1024 * 1024,
|
|
14795
|
+
maxActive: 100,
|
|
14796
|
+
lifetime: 6e4,
|
|
14797
|
+
wait: 5e3,
|
|
14798
|
+
stage: "readiness"
|
|
14799
|
+
});
|
|
14409
14800
|
function trackEvent(eventName, eventProperties, meta = {}) {
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14801
|
+
const isCurrent = trackingLifecycle.capture();
|
|
14802
|
+
const trackingParams = extractTrackingParams();
|
|
14803
|
+
if (mixpanelService.isReady()) {
|
|
14804
|
+
return submitEvent(
|
|
14805
|
+
eventName,
|
|
14806
|
+
eventProperties,
|
|
14807
|
+
meta,
|
|
14808
|
+
isCurrent,
|
|
14809
|
+
trackingParams
|
|
14810
|
+
);
|
|
14811
|
+
}
|
|
14812
|
+
try {
|
|
14813
|
+
validatorService.parseEventProps(eventName, eventProperties);
|
|
14814
|
+
} catch (error) {
|
|
14815
|
+
trackEventError(eventName, error, eventProperties);
|
|
14816
|
+
return Promise.resolve();
|
|
14817
|
+
}
|
|
14818
|
+
let snapshot2;
|
|
14819
|
+
let bytes;
|
|
14820
|
+
try {
|
|
14821
|
+
const serialized = JSON.stringify(
|
|
14822
|
+
{ eventName, eventProperties, meta, trackingParams },
|
|
14823
|
+
(_key, value) => {
|
|
14824
|
+
if (typeof value === "function" || typeof value === "symbol")
|
|
14825
|
+
throw new Error();
|
|
14826
|
+
return value === void 0 ? null : value;
|
|
14827
|
+
}
|
|
14828
|
+
);
|
|
14829
|
+
bytes = new Blob([serialized]).size;
|
|
14830
|
+
if (bytes > 1024 * 1024) throw new Error();
|
|
14831
|
+
snapshot2 = snapshotEventData({ eventProperties, meta });
|
|
14832
|
+
} catch {
|
|
14833
|
+
console.error("Tracking recovery diagnostic", {
|
|
14834
|
+
eventName,
|
|
14835
|
+
stage: "readiness",
|
|
14836
|
+
reason: "snapshot_unavailable"
|
|
14837
|
+
});
|
|
14838
|
+
return Promise.resolve();
|
|
14839
|
+
}
|
|
14840
|
+
return pendingEvents.enqueue({
|
|
14841
|
+
eventName,
|
|
14842
|
+
bytes,
|
|
14843
|
+
isCurrent,
|
|
14844
|
+
run: (isActive) => submitEvent(
|
|
14845
|
+
eventName,
|
|
14846
|
+
snapshot2.eventProperties,
|
|
14847
|
+
snapshot2.meta,
|
|
14848
|
+
isActive,
|
|
14849
|
+
trackingParams
|
|
14850
|
+
)
|
|
14851
|
+
});
|
|
14414
14852
|
}
|
|
14415
|
-
async function submitEvent(eventName, eventProperties, meta) {
|
|
14853
|
+
async function submitEvent(eventName, eventProperties, meta, isCurrent, trackingParams) {
|
|
14854
|
+
const observationContext = trackingLifecycle.capture();
|
|
14416
14855
|
try {
|
|
14417
14856
|
validatorService.parseEventProps(eventName, eventProperties);
|
|
14418
14857
|
const distinctId = mixpanelService.getMixpanelDistinctId();
|
|
14419
14858
|
const botDetectionEnabled = botDetectionRelayService.isEnabledFor(eventName);
|
|
14420
14859
|
let fingerprint = "";
|
|
14421
|
-
if (botDetectionEnabled) {
|
|
14860
|
+
if (botDetectionEnabled || FP_TRIGGER_EVENTS.includes(eventName)) {
|
|
14422
14861
|
try {
|
|
14423
14862
|
fingerprint = fingerprintService.getCachedFingerprint() ?? "";
|
|
14424
14863
|
} catch (error) {
|
|
14425
14864
|
console.error("Error reading cached fingerprint:", error);
|
|
14426
14865
|
}
|
|
14427
14866
|
} else {
|
|
14428
|
-
const cacheOnly = !FP_TRIGGER_EVENTS.includes(eventName);
|
|
14429
14867
|
try {
|
|
14430
|
-
fingerprint = await fingerprintService.getFingerprint(
|
|
14868
|
+
fingerprint = await fingerprintService.getFingerprint(true);
|
|
14431
14869
|
} catch {
|
|
14432
14870
|
console.error("Tracking diagnostic", {
|
|
14433
14871
|
eventName,
|
|
@@ -14449,7 +14887,6 @@ async function submitEvent(eventName, eventProperties, meta) {
|
|
|
14449
14887
|
const defaultProperties = {
|
|
14450
14888
|
"User Fingerprint": fingerprint
|
|
14451
14889
|
};
|
|
14452
|
-
const trackingParams = extractTrackingParams();
|
|
14453
14890
|
const simplifiedData = flattenEventData(eventProperties);
|
|
14454
14891
|
const properties = {
|
|
14455
14892
|
...defaultProperties,
|
|
@@ -14458,28 +14895,40 @@ async function submitEvent(eventName, eventProperties, meta) {
|
|
|
14458
14895
|
...defaultCoordinates,
|
|
14459
14896
|
...meta
|
|
14460
14897
|
};
|
|
14461
|
-
|
|
14898
|
+
if (!isCurrent()) return;
|
|
14899
|
+
try {
|
|
14900
|
+
mixpanelService.track(eventName, properties);
|
|
14901
|
+
} catch {
|
|
14902
|
+
console.error("Tracking diagnostic", {
|
|
14903
|
+
eventName,
|
|
14904
|
+
stage: "submission",
|
|
14905
|
+
reason: "uncertain"
|
|
14906
|
+
});
|
|
14907
|
+
return;
|
|
14908
|
+
}
|
|
14462
14909
|
if (botDetectionEnabled) {
|
|
14463
|
-
|
|
14910
|
+
deferBotDetection(eventName, distinctId, observationContext);
|
|
14911
|
+
} else if (FP_TRIGGER_EVENTS.includes(eventName)) {
|
|
14912
|
+
void refreshFingerprint(eventName, observationContext);
|
|
14464
14913
|
}
|
|
14465
14914
|
} catch (error) {
|
|
14466
14915
|
console.error(`Error tracking event '${eventName}':`, error);
|
|
14467
14916
|
trackEventError(eventName, error, eventProperties);
|
|
14468
14917
|
}
|
|
14469
14918
|
}
|
|
14470
|
-
async function
|
|
14919
|
+
async function refreshFingerprint(eventName, isCurrent) {
|
|
14920
|
+
const deadline = Date.now() + 1e4;
|
|
14471
14921
|
try {
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
|
|
14478
|
-
|
|
14479
|
-
|
|
14922
|
+
await fingerprintService.getFingerprint(false, {
|
|
14923
|
+
isActive: () => isCurrent() && Date.now() < deadline,
|
|
14924
|
+
report: () => void 0
|
|
14925
|
+
});
|
|
14926
|
+
} catch {
|
|
14927
|
+
console.error("Tracking diagnostic", {
|
|
14928
|
+
eventName,
|
|
14929
|
+
stage: "fingerprint",
|
|
14930
|
+
reason: "failed"
|
|
14480
14931
|
});
|
|
14481
|
-
} catch (error) {
|
|
14482
|
-
console.error(`Error running Bot Detection for '${eventName}':`, error);
|
|
14483
14932
|
}
|
|
14484
14933
|
}
|
|
14485
14934
|
function extractTrackingParams() {
|
|
@@ -14598,6 +15047,7 @@ async function requestAnonymousProfile(payload, report) {
|
|
|
14598
15047
|
}
|
|
14599
15048
|
const KNOWN_PROPERTIES = ["firstName", "lastName", "email", "phone"];
|
|
14600
15049
|
const FINGERPRINT_PROPERTY = "Known Fingerprints";
|
|
15050
|
+
let latestAttempt = 0;
|
|
14601
15051
|
function mapProperties(properties) {
|
|
14602
15052
|
const parsedProperties = {
|
|
14603
15053
|
$first_name: properties == null ? void 0 : properties.firstName,
|
|
@@ -14616,7 +15066,7 @@ function mapProperties(properties) {
|
|
|
14616
15066
|
);
|
|
14617
15067
|
return { ...parsedProperties, ...additionalProperties };
|
|
14618
15068
|
}
|
|
14619
|
-
const identifyWithLocation = async (
|
|
15069
|
+
const identifyWithLocation = async (userId2, properties, report) => {
|
|
14620
15070
|
var _a, _b, _c;
|
|
14621
15071
|
let observer;
|
|
14622
15072
|
try {
|
|
@@ -14653,7 +15103,7 @@ const identifyWithLocation = async (userId, properties, report) => {
|
|
|
14653
15103
|
body: JSON.stringify({
|
|
14654
15104
|
profile_params: {
|
|
14655
15105
|
...properties,
|
|
14656
|
-
distinct_id:
|
|
15106
|
+
distinct_id: userId2
|
|
14657
15107
|
}
|
|
14658
15108
|
})
|
|
14659
15109
|
}
|
|
@@ -14667,13 +15117,59 @@ const identifyWithLocation = async (userId, properties, report) => {
|
|
|
14667
15117
|
else report("datalake", "failed");
|
|
14668
15118
|
}
|
|
14669
15119
|
};
|
|
14670
|
-
async function
|
|
15120
|
+
async function enrichProfileAndLocation(userId2, properties, isActive, report) {
|
|
15121
|
+
const profile = await waitForIdentifyStage(
|
|
15122
|
+
"profile",
|
|
15123
|
+
3e3,
|
|
15124
|
+
(context) => isActive() ? createAnonymousProfileForIdentify({ ...properties }, context.report) : Promise.resolve(void 0),
|
|
15125
|
+
report
|
|
15126
|
+
);
|
|
15127
|
+
if (!isActive()) return;
|
|
15128
|
+
const enriched = {
|
|
15129
|
+
...properties,
|
|
15130
|
+
...profile && { reservamos_one_id: profile.id }
|
|
15131
|
+
};
|
|
15132
|
+
if (profile) {
|
|
15133
|
+
try {
|
|
15134
|
+
mixpanelService.setPeopleProperties(
|
|
15135
|
+
{ reservamos_one_id: profile.id },
|
|
15136
|
+
report
|
|
15137
|
+
);
|
|
15138
|
+
} catch {
|
|
15139
|
+
report("profile", "failed");
|
|
15140
|
+
}
|
|
15141
|
+
}
|
|
15142
|
+
void identifyWithLocation(userId2, enriched, report);
|
|
15143
|
+
}
|
|
15144
|
+
async function enrichFingerprint(isActive, report) {
|
|
15145
|
+
const fingerprint = await waitForIdentifyStage(
|
|
15146
|
+
"fingerprint",
|
|
15147
|
+
2e3,
|
|
15148
|
+
(context) => !isActive() ? Promise.resolve("") : getFingerprintForIdentify({
|
|
15149
|
+
isActive: () => context.isActive() && isActive(),
|
|
15150
|
+
report: context.report
|
|
15151
|
+
}),
|
|
15152
|
+
report
|
|
15153
|
+
);
|
|
15154
|
+
if (!fingerprint || !isActive()) return;
|
|
15155
|
+
try {
|
|
15156
|
+
mixpanelService.attachProperty(FINGERPRINT_PROPERTY, fingerprint);
|
|
15157
|
+
} catch {
|
|
15158
|
+
report("fingerprint", "failed");
|
|
15159
|
+
}
|
|
15160
|
+
}
|
|
15161
|
+
async function identify(userId2, properties = {}) {
|
|
15162
|
+
const attempt = ++latestAttempt;
|
|
15163
|
+
const input = { ...properties };
|
|
14671
15164
|
const report = createIdentifyReporter();
|
|
14672
|
-
|
|
15165
|
+
const initialLifecycle = trackingLifecycle.capture();
|
|
15166
|
+
if (!await waitForIdentifyReady(report) || attempt !== latestAttempt || !initialLifecycle())
|
|
15167
|
+
return;
|
|
15168
|
+
let submitted = false;
|
|
14673
15169
|
try {
|
|
14674
15170
|
try {
|
|
14675
|
-
validatorService.parseIdentifyProps(
|
|
14676
|
-
if (!
|
|
15171
|
+
validatorService.parseIdentifyProps(input);
|
|
15172
|
+
if (!userId2) {
|
|
14677
15173
|
report("validation", "invalid_input");
|
|
14678
15174
|
return;
|
|
14679
15175
|
}
|
|
@@ -14681,38 +15177,22 @@ async function identify(userId, properties = {}) {
|
|
|
14681
15177
|
report("validation", "invalid_input");
|
|
14682
15178
|
return;
|
|
14683
15179
|
}
|
|
14684
|
-
const anonymousProfile = await waitForIdentifyStage(
|
|
14685
|
-
"profile",
|
|
14686
|
-
3e3,
|
|
14687
|
-
(context) => createAnonymousProfileForIdentify({ ...properties }, context.report),
|
|
14688
|
-
report
|
|
14689
|
-
);
|
|
14690
|
-
if (anonymousProfile) {
|
|
14691
|
-
properties.reservamos_one_id = anonymousProfile.id;
|
|
14692
|
-
}
|
|
14693
|
-
const mappedProps = mapProperties(properties);
|
|
14694
15180
|
try {
|
|
14695
|
-
mixpanelService.identify(
|
|
15181
|
+
mixpanelService.identify(userId2, mapProperties(input), report);
|
|
14696
15182
|
} catch {
|
|
14697
15183
|
report("mixpanel", "failed");
|
|
15184
|
+
return;
|
|
14698
15185
|
}
|
|
14699
|
-
const
|
|
14700
|
-
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14704
|
-
|
|
14705
|
-
|
|
14706
|
-
|
|
14707
|
-
mixpanelService.attachProperty(FINGERPRINT_PROPERTY, fingerprint);
|
|
14708
|
-
} catch {
|
|
14709
|
-
report("fingerprint", "failed");
|
|
14710
|
-
}
|
|
14711
|
-
}
|
|
14712
|
-
} catch {
|
|
14713
|
-
report("mixpanel", "failed");
|
|
15186
|
+
const currentLifecycle = trackingLifecycle.capture();
|
|
15187
|
+
const isActive = () => attempt === latestAttempt && currentLifecycle();
|
|
15188
|
+
const scopedReport = (...args) => {
|
|
15189
|
+
if (isActive()) report(...args);
|
|
15190
|
+
};
|
|
15191
|
+
submitted = true;
|
|
15192
|
+
void enrichProfileAndLocation(userId2, input, isActive, scopedReport);
|
|
15193
|
+
void enrichFingerprint(isActive, scopedReport);
|
|
14714
15194
|
} finally {
|
|
14715
|
-
void identifyWithLocation(
|
|
15195
|
+
if (!submitted) void identifyWithLocation(userId2, { ...input }, report);
|
|
14716
15196
|
}
|
|
14717
15197
|
}
|
|
14718
15198
|
z.object({
|
|
@@ -14914,6 +15394,7 @@ const analytics = {
|
|
|
14914
15394
|
identify,
|
|
14915
15395
|
identifiers: {
|
|
14916
15396
|
getFingerprintId: fingerprintService.getCachedFingerprint,
|
|
15397
|
+
waitForFingerprintId: fingerprintService.waitForFingerprintId,
|
|
14917
15398
|
getDistinctId: mixpanelService.getMixpanelDistinctId
|
|
14918
15399
|
},
|
|
14919
15400
|
profiles: {
|