@reservamos/browser-analytics 1.1.8-alpha.1 → 1.2.0-alpha.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.
@@ -158,6 +158,7 @@ declare const passengersCreatedSchema: z.ZodObject<{
158
158
  "Passenger Document Type": string;
159
159
  "Passenger Document Id": string;
160
160
  }>, "many">>;
161
+ Coupon: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
161
162
  }, "strict", z.ZodTypeAny, {
162
163
  product: "web" | "web-mobile" | "ios" | "android" | "app";
163
164
  Trips: {
@@ -198,6 +199,7 @@ declare const passengersCreatedSchema: z.ZodObject<{
198
199
  "Passenger Document Type": string;
199
200
  "Passenger Document Id": string;
200
201
  }[] | undefined;
202
+ Coupon?: string | undefined;
201
203
  }, {
202
204
  product: "web" | "web-mobile" | "ios" | "android" | "app";
203
205
  Trips: {
@@ -238,6 +240,7 @@ declare const passengersCreatedSchema: z.ZodObject<{
238
240
  "Passenger Document Type": string;
239
241
  "Passenger Document Id": string;
240
242
  }[] | undefined;
243
+ Coupon?: string | undefined;
241
244
  }>;
242
245
  export type PassengersCreatedProps = z.infer<typeof passengersCreatedSchema>;
243
246
  declare function trackPassengersCreated(eventProps: PassengersCreatedProps, meta?: EventMetadata): void;
@@ -366,9 +369,9 @@ declare const paymentAttemptSchema: z.ZodObject<{
366
369
  "Passenger Document Type": string;
367
370
  "Passenger Document Id": string;
368
371
  }[] | undefined;
372
+ Coupon?: string | undefined;
369
373
  "Operation Id"?: string | undefined;
370
374
  Insurance?: boolean | undefined;
371
- Coupon?: string | undefined;
372
375
  "User Status"?: string | undefined;
373
376
  }, {
374
377
  product: "web" | "web-mobile" | "ios" | "android" | "app";
@@ -411,9 +414,9 @@ declare const paymentAttemptSchema: z.ZodObject<{
411
414
  "Passenger Document Type": string;
412
415
  "Passenger Document Id": string;
413
416
  }[] | undefined;
417
+ Coupon?: string | undefined;
414
418
  "Operation Id"?: string | undefined;
415
419
  Insurance?: boolean | undefined;
416
- Coupon?: string | undefined;
417
420
  "User Status"?: string | undefined;
418
421
  }>;
419
422
  export type PaymentAttemptProps = z.infer<typeof paymentAttemptSchema>;
@@ -821,14 +824,23 @@ declare const purchaseConfirmationSchema: z.ZodObject<{
821
824
  ]>;
822
825
  "Payment Type": z.ZodOptional<z.ZodString>;
823
826
  Total: z.ZodOptional<z.ZodNumber>;
827
+ product: z.ZodOptional<z.ZodEffects<z.ZodEnum<[
828
+ "web",
829
+ "web-mobile",
830
+ "ios",
831
+ "android",
832
+ "app"
833
+ ]>, "web" | "web-mobile" | "ios" | "android" | "app", "web" | "web-mobile" | "ios" | "android" | "app">>;
824
834
  }, "strict", z.ZodTypeAny, {
825
835
  "Operation Id": string;
826
836
  "Payment Status": "confirmed" | "pending_pix";
837
+ product?: "web" | "web-mobile" | "ios" | "android" | "app" | undefined;
827
838
  Total?: number | undefined;
828
839
  "Payment Type"?: string | undefined;
829
840
  }, {
830
841
  "Operation Id": string;
831
842
  "Payment Status": "confirmed" | "pending_pix";
843
+ product?: "web" | "web-mobile" | "ios" | "android" | "app" | undefined;
832
844
  Total?: number | undefined;
833
845
  "Payment Type"?: string | undefined;
834
846
  }>;
@@ -1300,6 +1312,7 @@ declare const analytics: {
1300
1312
  identify: typeof identify;
1301
1313
  identifiers: {
1302
1314
  getFingerprintId: () => string | null;
1315
+ waitForFingerprintId: (timeoutMs?: number) => Promise<string | null>;
1303
1316
  getDistinctId: () => string | null;
1304
1317
  };
1305
1318
  profiles: {
@@ -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,
@@ -13471,7 +13473,7 @@ function observeIdentifyResult(stage, report, onTimeout) {
13471
13473
  }, 5e3);
13472
13474
  return { complete };
13473
13475
  }
13474
- const version = "1.1.8-alpha.1";
13476
+ const version = "1.2.0-alpha.0";
13475
13477
  const MIXPANEL_DISTINCT_ID_CACHE_KEY = "mp_distinct_id";
13476
13478
  const readinessSubscribers$1 = /* @__PURE__ */ new Set();
13477
13479
  let initializing = false;
@@ -13528,6 +13530,21 @@ function identify$1(userId2, properties, report) {
13528
13530
  trackingLifecycle.identify(userId2);
13529
13531
  mixpanel.identify(userId2);
13530
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) {
13531
13548
  if (!report) {
13532
13549
  mixpanel.people.set(properties);
13533
13550
  return;
@@ -13544,18 +13561,6 @@ function identify$1(userId2, properties, report) {
13544
13561
  observer.complete("failed");
13545
13562
  }
13546
13563
  }
13547
- function attachProperty(key, value) {
13548
- if (!isReady()) {
13549
- return;
13550
- }
13551
- mixpanel.people.union(key, [value]);
13552
- }
13553
- function setPeopleProperties(properties) {
13554
- if (!isReady()) {
13555
- return;
13556
- }
13557
- mixpanel.people.set(properties);
13558
- }
13559
13564
  function isReady() {
13560
13565
  return !initializing && window.mixpanel !== void 0;
13561
13566
  }
@@ -13566,8 +13571,7 @@ function track(eventName, properties) {
13566
13571
  mixpanel.track(eventName, { ...properties, "Reservamos Version": version });
13567
13572
  }
13568
13573
  const getMixpanelDistinctId = () => {
13569
- var _a;
13570
- 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;
13571
13575
  if (distinctId) {
13572
13576
  updateCachedDistinctId(distinctId);
13573
13577
  return distinctId;
@@ -13602,7 +13606,10 @@ const DEFAULT_CACHE_TIME_IN_DAYS = 7;
13602
13606
  const PROXY_QUERY_PARAM = "apiKey=<apiKey>&version=<version>&loaderVersion=<loaderVersion>";
13603
13607
  let fingerprintAgentReady = false;
13604
13608
  let initialization$1 = 0;
13609
+ let startedInitialization = -1;
13605
13610
  const readinessSubscribers = /* @__PURE__ */ new Set();
13611
+ const waitingConsumers = /* @__PURE__ */ new Set();
13612
+ let pendingIdentification;
13606
13613
  function onReady(notify) {
13607
13614
  readinessSubscribers.add(notify);
13608
13615
  return () => {
@@ -13612,6 +13619,8 @@ function onReady(notify) {
13612
13619
  function invalidate() {
13613
13620
  initialization$1++;
13614
13621
  fingerprintAgentReady = false;
13622
+ pendingIdentification = void 0;
13623
+ waitingConsumers.forEach((cancel) => cancel());
13615
13624
  }
13616
13625
  const getExpirationDate = (cacheTimeInDays) => {
13617
13626
  const currentDate = /* @__PURE__ */ new Date();
@@ -13658,7 +13667,8 @@ async function initFingerprint(apiKey, proxyUrl) {
13658
13667
  customEndpointArray.unshift(proxyUrl);
13659
13668
  customScriptEndpointArray.unshift(buildProxyUrl(proxyUrl));
13660
13669
  }
13661
- invalidate();
13670
+ if (startedInitialization === initialization$1) invalidate();
13671
+ startedInitialization = initialization$1;
13662
13672
  const attempt = initialization$1;
13663
13673
  window.fingerprintConfig = {};
13664
13674
  const client = new FpjsClient({
@@ -13678,6 +13688,7 @@ async function initFingerprint(apiKey, proxyUrl) {
13678
13688
  } catch (error) {
13679
13689
  if (window.fpClient === client && attempt === initialization$1) {
13680
13690
  fingerprintAgentReady = false;
13691
+ waitingConsumers.forEach((cancel) => cancel());
13681
13692
  }
13682
13693
  console.error("Error initializing identification service:", error);
13683
13694
  throw error;
@@ -13704,12 +13715,51 @@ async function identifyVisitor(ignoreCache = false, context) {
13704
13715
  return requestIdentification(ignoreCache, context);
13705
13716
  }
13706
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) {
13707
13757
  if (!isFingerprintReady()) {
13708
13758
  throw new Error("Identification service is not initialized.");
13709
13759
  }
13710
13760
  try {
13711
13761
  const result = await window.fpClient.getVisitorData({}, ignoreCache);
13712
- if (!context || context.isActive()) {
13762
+ if (context.isActive()) {
13713
13763
  try {
13714
13764
  setCachedFingerprint(result.visitorId);
13715
13765
  } catch {
@@ -13721,8 +13771,9 @@ async function requestIdentification(ignoreCache, context) {
13721
13771
  "Visitor Found": result.visitorFound
13722
13772
  });
13723
13773
  } catch (error) {
13724
- if (context) context.report("fingerprint", "failed");
13725
- else console.error("Error updating Mixpanel visitor profile:", error);
13774
+ context.report("fingerprint", "failed");
13775
+ if (hasUnscopedConsumer())
13776
+ console.error("Error updating Mixpanel visitor profile:", error);
13726
13777
  }
13727
13778
  }
13728
13779
  }
@@ -13734,10 +13785,46 @@ async function requestIdentification(ignoreCache, context) {
13734
13785
  cacheHit: result.cacheHit
13735
13786
  };
13736
13787
  } catch (error) {
13737
- if (!context) console.error("Error retrieving fingerprint:", error);
13788
+ if (hasUnscopedConsumer())
13789
+ console.error("Error retrieving fingerprint:", error);
13738
13790
  throw error;
13739
13791
  }
13740
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
+ }
13741
13828
  function isFingerprintReady() {
13742
13829
  return window.fpClient !== void 0 && fingerprintAgentReady;
13743
13830
  }
@@ -13748,7 +13835,8 @@ const fingerprintService = {
13748
13835
  isFingerprintReady,
13749
13836
  onReady,
13750
13837
  invalidate,
13751
- getCachedFingerprint
13838
+ getCachedFingerprint,
13839
+ waitForFingerprintId
13752
13840
  };
13753
13841
  trackingLifecycle.onInitialization(invalidate);
13754
13842
  function createPendingWorkQueue(options) {
@@ -14073,7 +14161,8 @@ const passengersCreatedSchema = z.object({
14073
14161
  "Trip Count": intField("Trip Count").optional(),
14074
14162
  "Total": numberField("Total"),
14075
14163
  "product": productValidation,
14076
- "Passengers": arrayField(passengerSchema, "Passengers", 1).optional()
14164
+ "Passengers": arrayField(passengerSchema, "Passengers", 1).optional(),
14165
+ "Coupon": stringField("Coupon").optional()
14077
14166
  }).strict();
14078
14167
  const EVENT_NAME$8 = "Passengers Created";
14079
14168
  function trackPassengersCreated(eventProps, meta = {}) {
@@ -14141,7 +14230,8 @@ const purchaseConfirmationSchema = z.object({
14141
14230
  "Operation Id": z.string().min(1, "Operation Id is required"),
14142
14231
  "Payment Status": z.enum(["confirmed", "pending_pix"]),
14143
14232
  "Payment Type": z.string().optional(),
14144
- "Total": z.number().optional()
14233
+ "Total": z.number().optional(),
14234
+ "product": productValidation.optional()
14145
14235
  }).strict();
14146
14236
  const EVENT_NAME$4 = "Purchase Confirmation Viewed";
14147
14237
  function trackPurchaseConfirmation(eventData, meta = {}) {
@@ -14957,6 +15047,7 @@ async function requestAnonymousProfile(payload, report) {
14957
15047
  }
14958
15048
  const KNOWN_PROPERTIES = ["firstName", "lastName", "email", "phone"];
14959
15049
  const FINGERPRINT_PROPERTY = "Known Fingerprints";
15050
+ let latestAttempt = 0;
14960
15051
  function mapProperties(properties) {
14961
15052
  const parsedProperties = {
14962
15053
  $first_name: properties == null ? void 0 : properties.firstName,
@@ -15026,12 +15117,58 @@ const identifyWithLocation = async (userId2, properties, report) => {
15026
15117
  else report("datalake", "failed");
15027
15118
  }
15028
15119
  };
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
+ }
15029
15161
  async function identify(userId2, properties = {}) {
15162
+ const attempt = ++latestAttempt;
15163
+ const input = { ...properties };
15030
15164
  const report = createIdentifyReporter();
15031
- if (!await waitForIdentifyReady(report)) return;
15165
+ const initialLifecycle = trackingLifecycle.capture();
15166
+ if (!await waitForIdentifyReady(report) || attempt !== latestAttempt || !initialLifecycle())
15167
+ return;
15168
+ let submitted = false;
15032
15169
  try {
15033
15170
  try {
15034
- validatorService.parseIdentifyProps(properties);
15171
+ validatorService.parseIdentifyProps(input);
15035
15172
  if (!userId2) {
15036
15173
  report("validation", "invalid_input");
15037
15174
  return;
@@ -15040,38 +15177,22 @@ async function identify(userId2, properties = {}) {
15040
15177
  report("validation", "invalid_input");
15041
15178
  return;
15042
15179
  }
15043
- const anonymousProfile = await waitForIdentifyStage(
15044
- "profile",
15045
- 3e3,
15046
- (context) => createAnonymousProfileForIdentify({ ...properties }, context.report),
15047
- report
15048
- );
15049
- if (anonymousProfile) {
15050
- properties.reservamos_one_id = anonymousProfile.id;
15051
- }
15052
- const mappedProps = mapProperties(properties);
15053
15180
  try {
15054
- mixpanelService.identify(userId2, mappedProps, report);
15181
+ mixpanelService.identify(userId2, mapProperties(input), report);
15055
15182
  } catch {
15056
15183
  report("mixpanel", "failed");
15184
+ return;
15057
15185
  }
15058
- const fingerprint = await waitForIdentifyStage(
15059
- "fingerprint",
15060
- 2e3,
15061
- getFingerprintForIdentify,
15062
- report
15063
- );
15064
- if (fingerprint) {
15065
- try {
15066
- mixpanelService.attachProperty(FINGERPRINT_PROPERTY, fingerprint);
15067
- } catch {
15068
- report("fingerprint", "failed");
15069
- }
15070
- }
15071
- } catch {
15072
- 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);
15073
15194
  } finally {
15074
- void identifyWithLocation(userId2, properties, report);
15195
+ if (!submitted) void identifyWithLocation(userId2, { ...input }, report);
15075
15196
  }
15076
15197
  }
15077
15198
  z.object({
@@ -15273,6 +15394,7 @@ const analytics = {
15273
15394
  identify,
15274
15395
  identifiers: {
15275
15396
  getFingerprintId: fingerprintService.getCachedFingerprint,
15397
+ waitForFingerprintId: fingerprintService.waitForFingerprintId,
15276
15398
  getDistinctId: mixpanelService.getMixpanelDistinctId
15277
15399
  },
15278
15400
  profiles: {