@aranova/tracking-next 1.1.0 → 1.2.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/dist/index.mjs CHANGED
@@ -487,6 +487,35 @@ function buildLandingPayloadFields(sessionId, override) {
487
487
  };
488
488
  }
489
489
 
490
+ // ../tracking-core/src/session.ts
491
+ var VISITOR_STORAGE_KEY = "aranova_tracking_visitor";
492
+ var SESSION_STORAGE_KEY = "aranova_tracking_session";
493
+ var SESSION_IDLE_MS = 30 * 60 * 1e3;
494
+ function readLocalStorage(key) {
495
+ try {
496
+ return window.localStorage.getItem(key);
497
+ } catch {
498
+ return null;
499
+ }
500
+ }
501
+ function peekVisitorId() {
502
+ if (typeof window === "undefined") return null;
503
+ const existing = readLocalStorage(VISITOR_STORAGE_KEY);
504
+ return existing && existing.length > 0 ? existing : null;
505
+ }
506
+ function peekSessionId(now = Date.now()) {
507
+ if (typeof window === "undefined") return null;
508
+ const raw = readLocalStorage(SESSION_STORAGE_KEY);
509
+ if (!raw) return null;
510
+ try {
511
+ const parsed = JSON.parse(raw);
512
+ if (typeof parsed.id !== "string" || typeof parsed.last_event_at !== "number") return null;
513
+ return now - parsed.last_event_at <= SESSION_IDLE_MS ? parsed.id : null;
514
+ } catch {
515
+ return null;
516
+ }
517
+ }
518
+
490
519
  // ../tracking-core/src/cross-site-link.ts
491
520
  var LINK_PARAM = "_arv";
492
521
  var LINK_TOKEN_TTL_MS = 5 * 60 * 1e3;
@@ -1649,9 +1678,19 @@ var zErrorCode = z2.enum([
1649
1678
  "bad_request",
1650
1679
  "not_found",
1651
1680
  "conflict",
1681
+ "gone",
1652
1682
  "incompatible_payload",
1653
1683
  "repeat_confirmation_required",
1654
1684
  "idempotency_conflict",
1685
+ "slot_unavailable",
1686
+ "calendar_not_connected",
1687
+ "calendar_disconnected",
1688
+ "booking_not_found",
1689
+ "booking_not_cancellable",
1690
+ "booking_not_reschedulable",
1691
+ "manage_token_invalid",
1692
+ "google_error",
1693
+ "calendar_not_owned",
1655
1694
  "validation_error",
1656
1695
  "unknown_service",
1657
1696
  "invalid_sale_properties",
@@ -1715,6 +1754,7 @@ var zSmsWithheldReason = z2.enum([
1715
1754
  "no_handler",
1716
1755
  "dispatch_already_recorded",
1717
1756
  "text_back_disabled",
1757
+ "number_text_back_disabled",
1718
1758
  "number_not_active",
1719
1759
  "a2p_registration_required",
1720
1760
  "alert_recipient_cannot_receive_sms",
@@ -1931,6 +1971,40 @@ import {
1931
1971
  useTrackingParams
1932
1972
  } from "@aranova/tracking-next/client";
1933
1973
 
1974
+ // ../tracking-core/src/resources/calendar/attribution.ts
1975
+ var LIMITS = {
1976
+ session_id: 64,
1977
+ visitor_id: 64,
1978
+ gclid: 256,
1979
+ fbclid: 256,
1980
+ utm_source: 128,
1981
+ utm_medium: 128,
1982
+ utm_campaign: 128,
1983
+ utm_term: 128,
1984
+ utm_content: 128
1985
+ };
1986
+ function getBookingAttribution() {
1987
+ if (typeof window === "undefined") return {};
1988
+ const params = getTrackingParamsFromCookieReader(getCookieValueFromDocument);
1989
+ const values = {
1990
+ session_id: peekSessionId(),
1991
+ visitor_id: peekVisitorId(),
1992
+ gclid: params.gclid,
1993
+ fbclid: params.fbclid,
1994
+ utm_source: params.utm_source,
1995
+ utm_medium: params.utm_medium,
1996
+ utm_campaign: params.utm_campaign,
1997
+ utm_term: params.utm_term,
1998
+ utm_content: params.utm_content
1999
+ };
2000
+ const attribution = {};
2001
+ for (const key of Object.keys(LIMITS)) {
2002
+ const value = values[key];
2003
+ if (value) attribution[key] = value.slice(0, LIMITS[key]);
2004
+ }
2005
+ return attribution;
2006
+ }
2007
+
1934
2008
  // ../tracking-core/src/resources/calendar/transport.ts
1935
2009
  async function calendarRequest(config, method, path, body) {
1936
2010
  return apiRequest(config, method, `/calendar${path}`, body);
@@ -2063,22 +2137,27 @@ var zBookingRescheduleSchema = z4.strictObject({
2063
2137
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/))
2064
2138
  });
2065
2139
  var zBookingResponse = z4.strictObject({
2140
+ all_day: z4.boolean(),
2066
2141
  appointment_type: z4.nullable(z4.string()),
2067
2142
  calendar_key: z4.string(),
2143
+ created_at: z4.iso.datetime({ offset: true }),
2068
2144
  customer: zBookingCustomerOutput,
2069
2145
  end_at: z4.iso.datetime({ offset: true }),
2146
+ google_event_id: z4.nullable(z4.string()),
2070
2147
  google_html_link: z4.nullable(z4.string()),
2071
- google_sync_state: z4.string(),
2148
+ google_sync_state: z4.enum(["queued", "synced", "uncertain", "failed", "drifted"]),
2149
+ ical_uid: z4.nullable(z4.string()),
2072
2150
  id: z4.string(),
2073
2151
  manage_token: z4.nullable(z4.string()),
2074
2152
  meet_url: z4.nullable(z4.string()),
2153
+ organizer_email: z4.nullable(z4.string()),
2075
2154
  start_at: z4.iso.datetime({ offset: true }),
2076
- status: z4.string(),
2155
+ status: z4.enum(["pending", "confirmed", "cancelled", "no_show"]),
2077
2156
  time_zone: z4.string(),
2078
2157
  title: z4.string()
2079
2158
  });
2080
2159
  var zBookingSource = z4.enum(["website", "phone", "walk_in", "import", "operator"]);
2081
- var zBookingMetadata = z4.strictObject({
2160
+ var zBookingMetadataInput = z4.strictObject({
2082
2161
  custom: z4.nullish(
2083
2162
  z4.record(z4.string(), z4.nullable(z4.union([z4.string(), z4.int(), z4.number(), z4.boolean()])))
2084
2163
  ),
@@ -2098,6 +2177,40 @@ var zBookingMetadata = z4.strictObject({
2098
2177
  utm_term: z4.nullish(z4.string().check(z4.maxLength(128))),
2099
2178
  visitor_id: z4.nullish(z4.string().check(z4.maxLength(64)))
2100
2179
  });
2180
+ var zBusySource = z4.enum(["google", "booking"]);
2181
+ var zBusyInterval = z4.strictObject({
2182
+ end_at: z4.iso.datetime({ offset: true }),
2183
+ source: zBusySource,
2184
+ start_at: z4.iso.datetime({ offset: true })
2185
+ });
2186
+ var zBusyWindow = z4.strictObject({
2187
+ since: z4.iso.datetime({ offset: true }),
2188
+ until: z4.iso.datetime({ offset: true })
2189
+ });
2190
+ var zBusyResponse = z4.strictObject({
2191
+ busy: z4.array(zBusyInterval),
2192
+ calendar_key: z4.string(),
2193
+ generated_at: z4.iso.datetime({ offset: true }),
2194
+ time_zone: z4.string(),
2195
+ window: zBusyWindow
2196
+ });
2197
+ var zCalendarSummary = z4.strictObject({
2198
+ allow_overlaps: z4.boolean(),
2199
+ calendar_key: z4.string(),
2200
+ connected_at: z4.nullable(z4.iso.datetime({ offset: true })),
2201
+ google_account_email: z4.nullable(z4.string()),
2202
+ granted_scopes: z4.nullable(z4.array(z4.string())),
2203
+ label: z4.string(),
2204
+ status: z4.enum([
2205
+ "pending_invite",
2206
+ "awaiting_calendar_selection",
2207
+ "connected",
2208
+ "needs_reconnect",
2209
+ "revoked",
2210
+ "disabled"
2211
+ ]),
2212
+ time_zone: z4.string()
2213
+ });
2101
2214
  var zCustomLocation = z4.strictObject({
2102
2215
  kind: z4.literal("custom"),
2103
2216
  text: z4.string().check(z4.maxLength(1024))
@@ -2117,9 +2230,19 @@ var zErrorCode2 = z4.enum([
2117
2230
  "bad_request",
2118
2231
  "not_found",
2119
2232
  "conflict",
2233
+ "gone",
2120
2234
  "incompatible_payload",
2121
2235
  "repeat_confirmation_required",
2122
2236
  "idempotency_conflict",
2237
+ "slot_unavailable",
2238
+ "calendar_not_connected",
2239
+ "calendar_disconnected",
2240
+ "booking_not_found",
2241
+ "booking_not_cancellable",
2242
+ "booking_not_reschedulable",
2243
+ "manage_token_invalid",
2244
+ "google_error",
2245
+ "calendar_not_owned",
2123
2246
  "validation_error",
2124
2247
  "unknown_service",
2125
2248
  "invalid_sale_properties",
@@ -2154,15 +2277,16 @@ var zBookingCreateSchema = z4.strictObject({
2154
2277
  buffer_before_minutes: z4._default(z4.optional(z4.int().check(z4.gte(0), z4.lte(1440))), 0),
2155
2278
  calendar_key: z4.string().check(z4.minLength(1), z4.maxLength(64)),
2156
2279
  customer: zBookingCustomerInput,
2280
+ date: z4.nullish(z4.iso.date()),
2157
2281
  description: z4.nullish(z4.string().check(z4.maxLength(8e3))),
2158
2282
  duration_minutes: z4.nullish(z4.int().check(z4.gt(0), z4.lte(1440))),
2159
2283
  end_at: z4.nullish(z4.iso.datetime({ offset: true })),
2160
2284
  idempotency_key: z4.nullish(z4.string().check(z4.maxLength(128))),
2161
2285
  location: z4.nullish(z4.union([zMeetLocation, zPhysicalLocation, zPhoneLocation, zCustomLocation])),
2162
- metadata: z4.nullish(zBookingMetadata),
2286
+ metadata: z4.nullish(zBookingMetadataInput),
2163
2287
  reminders: z4.nullish(zBookingReminders),
2164
2288
  send_invites: z4._default(z4.optional(z4.boolean()), true),
2165
- start_at: z4.iso.datetime({ offset: true }),
2289
+ start_at: z4.nullish(z4.iso.datetime({ offset: true })),
2166
2290
  time_zone: z4.string().check(z4.minLength(1), z4.maxLength(64), z4.regex(/^[A-Za-z0-9_+\-\/]+$/)),
2167
2291
  title: z4.nullish(z4.string().check(z4.maxLength(300)))
2168
2292
  });
@@ -2196,22 +2320,17 @@ var MAX_REMINDER_OVERRIDES = 5;
2196
2320
  var MAX_REMINDER_MINUTES = 40320;
2197
2321
  var MAX_BOOKING_MINUTES = 1440;
2198
2322
  var BOOKING_SOURCES = ["website", "phone", "walk_in", "import", "operator"];
2199
- var BOOKING_STATUSES = ["pending", "confirmed", "cancelled", "no_show"];
2200
- var GOOGLE_SYNC_STATES = ["queued", "synced", "uncertain", "failed", "drifted"];
2201
- var CALENDAR_SYNC_STATUSES = [
2202
- "pending_invite",
2203
- "awaiting_calendar_selection",
2204
- "connected",
2205
- "needs_reconnect",
2206
- "revoked",
2207
- "disabled"
2208
- ];
2323
+ var BOOKING_STATUSES = zBookingResponse.shape.status.options;
2324
+ var GOOGLE_SYNC_STATES = zBookingResponse.shape.google_sync_state.options;
2325
+ var CALENDAR_SYNC_STATUSES = zCalendarSummary.shape.status.options;
2209
2326
  var CALENDAR_ERROR_CODES = [
2210
2327
  "slot_unavailable",
2211
2328
  "calendar_not_connected",
2212
2329
  "calendar_disconnected",
2213
2330
  "booking_not_found",
2214
- "outside_booking_window",
2331
+ "booking_not_cancellable",
2332
+ "booking_not_reschedulable",
2333
+ "manage_token_invalid",
2215
2334
  "rate_limited",
2216
2335
  "google_error"
2217
2336
  ];
@@ -2232,7 +2351,7 @@ var ianaTz = z5.string().check(
2232
2351
  var bookingAttendeeSchema = zBookingAttendee;
2233
2352
  var bookingReminderSchema = zBookingReminder;
2234
2353
  var bookingCustomerSchema = zBookingCustomerInput;
2235
- var bookingMetadataSchema = z5.extend(zBookingMetadata, {
2354
+ var bookingMetadataSchema = z5.extend(zBookingMetadataInput, {
2236
2355
  custom: z5.nullish(
2237
2356
  z5.record(z5.string(), z5.union([z5.string(), z5.int(), z5.number(), z5.boolean(), z5.null()]))
2238
2357
  )
@@ -2261,6 +2380,24 @@ function refineEndXor(value, ctx) {
2261
2380
  addIssue2(ctx, ["end_at"], "end_at must be after start_at");
2262
2381
  }
2263
2382
  }
2383
+ function refineStartXor(value, ctx) {
2384
+ const hasStart = value.start_at !== void 0 && value.start_at !== null;
2385
+ const hasDate = value.date !== void 0 && value.date !== null;
2386
+ if (hasStart === hasDate) {
2387
+ addIssue2(ctx, ["start_at"], "provide exactly one of start_at or date");
2388
+ return;
2389
+ }
2390
+ if (hasStart) {
2391
+ refineEndXor(value, ctx);
2392
+ return;
2393
+ }
2394
+ if (value.end_at != null || value.duration_minutes != null) {
2395
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no end_at or duration_minutes");
2396
+ }
2397
+ if (value.buffer_before_minutes || value.buffer_after_minutes) {
2398
+ addIssue2(ctx, ["date"], "an all-day booking (date) takes no buffers");
2399
+ }
2400
+ }
2264
2401
  var bookingRemindersSchema = z5.extend(zBookingReminders, {
2265
2402
  overrides: z5._default(
2266
2403
  z5.array(bookingReminderSchema).check(z5.maxLength(MAX_REMINDER_OVERRIDES)),
@@ -2279,7 +2416,7 @@ var bookingCreateSchema = z5.extend(zBookingCreateSchema, {
2279
2416
  // our compositions into its own output.
2280
2417
  reminders: z5.nullish(bookingRemindersSchema),
2281
2418
  metadata: z5.nullish(bookingMetadataSchema)
2282
- }).check((ctx) => refineEndXor(ctx.value, ctx));
2419
+ }).check((ctx) => refineStartXor(ctx.value, ctx));
2283
2420
  var bookingRescheduleSchema = z5.extend(zBookingRescheduleSchema, { time_zone: ianaTz }).check((ctx) => refineEndXor(ctx.value, ctx));
2284
2421
  var bookingCancelSchema = zBookingCancelSchema;
2285
2422
 
@@ -2438,7 +2575,10 @@ function useBookingForm(options = {}) {
2438
2575
  const response = await fetch(endpoint, {
2439
2576
  method: "POST",
2440
2577
  headers: { "Content-Type": "application/json" },
2441
- body: JSON.stringify(input)
2578
+ body: JSON.stringify({
2579
+ ...input,
2580
+ metadata: { ...getBookingAttribution(), ...input.metadata }
2581
+ })
2442
2582
  });
2443
2583
  const body = await response.json().catch(() => null);
2444
2584
  if (!response.ok) {
@@ -2522,6 +2662,7 @@ export {
2522
2662
  formatPhoneAsTyped,
2523
2663
  formatSlotRange,
2524
2664
  fromMinor,
2665
+ getBookingAttribution,
2525
2666
  getConsentChoice,
2526
2667
  getConsentState,
2527
2668
  getEventSemantics,