@aranova/tracking-react 1.16.1 → 1.18.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/client.js CHANGED
@@ -1031,9 +1031,18 @@ function parseBookingRules(value) {
1031
1031
  special_hours: parseWindowsMap(r.special_hours),
1032
1032
  vehicle_required: r.vehicle_required === true,
1033
1033
  vehicle_deferred: r.vehicle_deferred === true,
1034
- drop_off_options: isStringList(r.drop_off_options) ? r.drop_off_options : []
1034
+ drop_off_options: isStringList(r.drop_off_options) ? r.drop_off_options : [],
1035
+ booked_counts: parseCounts(r.booked_counts)
1035
1036
  };
1036
1037
  }
1038
+ function parseCounts(value) {
1039
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
1040
+ const counts = {};
1041
+ for (const [date, count] of Object.entries(value)) {
1042
+ if (typeof count === "number" && Number.isInteger(count) && count >= 0) counts[date] = count;
1043
+ }
1044
+ return counts;
1045
+ }
1037
1046
  function parseBookingOption(value) {
1038
1047
  if (!value || typeof value !== "object") return [];
1039
1048
  const o = value;
@@ -1826,7 +1835,8 @@ function camelRules(rules) {
1826
1835
  specialHours: rules.special_hours,
1827
1836
  vehicleRequired: rules.vehicle_required,
1828
1837
  vehicleDeferred: rules.vehicle_deferred,
1829
- dropOffOptions: rules.drop_off_options
1838
+ dropOffOptions: rules.drop_off_options,
1839
+ bookedCounts: rules.booked_counts ?? {}
1830
1840
  };
1831
1841
  }
1832
1842
  var WEEKDAYS = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
@@ -1859,7 +1869,8 @@ function bookableSlots(rules, { timeZone, now = /* @__PURE__ */ new Date() }) {
1859
1869
  date,
1860
1870
  weekday,
1861
1871
  morning: [...windows.morning],
1862
- afternoon: [...windows.afternoon]
1872
+ afternoon: [...windows.afternoon],
1873
+ booked: rules.bookedCounts?.[date] ?? 0
1863
1874
  });
1864
1875
  }
1865
1876
  return days;
@@ -2019,6 +2030,13 @@ var EVENT_SEMANTICS = {
2019
2030
  outcomeRole: "engagement",
2020
2031
  clientVisibility: "detailed"
2021
2032
  },
2033
+ // Adds to the submit it names; counting it as a lead would double every lead.
2034
+ form_details: {
2035
+ label: "Form details added",
2036
+ category: "lead",
2037
+ outcomeRole: "engagement",
2038
+ clientVisibility: "detailed"
2039
+ },
2022
2040
  form_submit: {
2023
2041
  label: "Form submitted",
2024
2042
  category: "lead",
@@ -2635,7 +2653,7 @@ function createTrackingClient(config) {
2635
2653
  metadata: input.metadata ?? null,
2636
2654
  occurred_at: occurredAt
2637
2655
  });
2638
- if (queue.length >= maxQueueSize || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2656
+ if (queue.length >= maxQueueSize || input.eventType === "form_details" || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2639
2657
  void flush();
2640
2658
  } else {
2641
2659
  scheduleFlush();
@@ -2739,110 +2757,133 @@ var formStartConfigSchema = z5.strictObject({
2739
2757
  selector: z5.optional(z5.string())
2740
2758
  });
2741
2759
 
2742
- // ../tracking-core/src/events/form-step.ts
2760
+ // ../tracking-core/src/events/form-details.ts
2761
+ var z7 = __toESM(require("zod/mini"));
2762
+
2763
+ // ../tracking-core/src/events/form-submit.ts
2743
2764
  var z6 = __toESM(require("zod/mini"));
2744
- var formStepMetadataSchema = z6.strictObject({
2765
+ var jsonValueSchema = z6.lazy(
2766
+ () => z6.union([
2767
+ z6.string(),
2768
+ z6.number(),
2769
+ z6.boolean(),
2770
+ z6.null(),
2771
+ z6.array(jsonValueSchema),
2772
+ z6.record(z6.string(), jsonValueSchema)
2773
+ ])
2774
+ ).register(z6.globalRegistry, { id: "JsonSerializableValue" });
2775
+ var contractNameSchema = z6.string().check(z6.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
2776
+ var violationRole = z6.string().check(
2777
+ z6.maxLength(200),
2778
+ z6.regex(
2779
+ /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
2780
+ )
2781
+ );
2782
+ var MAX_CONTRACT_VIOLATIONS = 50;
2783
+ var contractViolationSchema = z6.strictObject({
2784
+ role: z6.nullable(violationRole),
2785
+ rule: z6.string().check(z6.regex(/^[a-z][a-z_]{0,47}$/))
2786
+ });
2787
+ var formFieldSchema = z6.strictObject({
2788
+ name: z6.string(),
2789
+ type: z6.string(),
2790
+ label: z6.nullable(z6.string()),
2791
+ value: jsonValueSchema,
2792
+ role: z6.optional(z6.nullable(contractNameSchema))
2793
+ });
2794
+ var formExtraSchema = z6.optional(
2795
+ z6.nullable(
2796
+ z6.array(
2797
+ z6.strictObject({
2798
+ key: z6.string().check(z6.maxLength(64)),
2799
+ label: z6.string().check(z6.maxLength(200)),
2800
+ value: jsonValueSchema
2801
+ })
2802
+ ).check(z6.maxLength(20))
2803
+ )
2804
+ );
2805
+ var contractVersionSchema = z6.optional(z6.nullable(z6.int().check(z6.gte(1))));
2806
+ var contractHashSchema = z6.optional(z6.nullable(z6.string().check(z6.maxLength(64))));
2807
+ var formContractViolationsSchema = z6.optional(
2808
+ z6.nullable(z6.array(contractViolationSchema).check(z6.maxLength(MAX_CONTRACT_VIOLATIONS)))
2809
+ );
2810
+ var formSubmitMetadataSchema = z6.strictObject({
2745
2811
  form: z6.strictObject({
2746
2812
  id: z6.string(),
2747
- action: z6.nullable(z6.string())
2813
+ action: z6.nullable(z6.string()),
2814
+ fields: z6.optional(z6.array(formFieldSchema)),
2815
+ kind: z6.optional(z6.nullable(contractNameSchema)),
2816
+ contract_version: contractVersionSchema,
2817
+ contract_hash: contractHashSchema,
2818
+ extra: formExtraSchema,
2819
+ contract_violations: formContractViolationsSchema,
2820
+ // Minted per submit; a later `form_details` names it to add answers to this lead.
2821
+ submission_id: z6.optional(z6.nullable(z6.uuidv4()))
2748
2822
  }),
2749
- step: z6.strictObject({
2750
- id: z6.string().check(z6.minLength(1), z6.maxLength(64), z6.regex(/^[A-Za-z0-9_-]+$/)),
2751
- // 1-based position in the flow the visitor is on right now.
2752
- index: z6.int().check(z6.gte(1), z6.lte(50)),
2753
- // Null when the number of steps depends on earlier answers.
2754
- total: z6.nullable(z6.int().check(z6.gte(1), z6.lte(50)))
2755
- }),
2756
- direction: z6.enum(["forward", "back"]),
2757
2823
  page: z6.strictObject({
2758
2824
  path: z6.string()
2759
2825
  })
2760
2826
  });
2761
- var formStepConfigSchema = z6.strictObject({});
2827
+ var formSubmitConfigSchema = z6.strictObject({});
2762
2828
 
2763
- // ../tracking-core/src/events/form-submit.ts
2764
- var z7 = __toESM(require("zod/mini"));
2765
- var jsonValueSchema = z7.lazy(
2766
- () => z7.union([
2767
- z7.string(),
2768
- z7.number(),
2769
- z7.boolean(),
2770
- z7.null(),
2771
- z7.array(jsonValueSchema),
2772
- z7.record(z7.string(), jsonValueSchema)
2773
- ])
2774
- ).register(z7.globalRegistry, { id: "JsonSerializableValue" });
2775
- var contractNameSchema = z7.string().check(z7.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
2776
- var contractName = contractNameSchema;
2777
- var violationRole = z7.string().check(
2778
- z7.maxLength(200),
2779
- z7.regex(
2780
- /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
2781
- )
2782
- );
2783
- var MAX_CONTRACT_VIOLATIONS = 50;
2784
- var contractViolationSchema = z7.strictObject({
2785
- role: z7.nullable(violationRole),
2786
- rule: z7.string().check(z7.regex(/^[a-z][a-z_]{0,47}$/))
2787
- });
2788
- var formSubmitMetadataSchema = z7.strictObject({
2829
+ // ../tracking-core/src/events/form-details.ts
2830
+ var formDetailsMetadataSchema = z7.strictObject({
2789
2831
  form: z7.strictObject({
2790
2832
  id: z7.string(),
2791
- action: z7.nullable(z7.string()),
2792
- fields: z7.optional(
2793
- z7.array(
2794
- z7.strictObject({
2795
- name: z7.string(),
2796
- type: z7.string(),
2797
- label: z7.nullable(z7.string()),
2798
- value: jsonValueSchema,
2799
- role: z7.optional(z7.nullable(contractName))
2800
- })
2801
- )
2802
- ),
2803
- kind: z7.optional(z7.nullable(contractName)),
2804
- contract_version: z7.optional(z7.nullable(z7.int().check(z7.gte(1)))),
2805
- contract_hash: z7.optional(z7.nullable(z7.string().check(z7.maxLength(64)))),
2806
- extra: z7.optional(
2807
- z7.nullable(
2808
- z7.array(
2809
- z7.strictObject({
2810
- key: z7.string().check(z7.maxLength(64)),
2811
- label: z7.string().check(z7.maxLength(200)),
2812
- value: jsonValueSchema
2813
- })
2814
- ).check(z7.maxLength(20))
2815
- )
2816
- ),
2817
- contract_violations: z7.optional(
2818
- z7.nullable(z7.array(contractViolationSchema).check(z7.maxLength(MAX_CONTRACT_VIOLATIONS)))
2819
- )
2833
+ submission_id: z7.uuidv4(),
2834
+ kind: z7.optional(z7.nullable(contractNameSchema)),
2835
+ fields: z7.array(formFieldSchema),
2836
+ contract_version: contractVersionSchema,
2837
+ contract_hash: contractHashSchema,
2838
+ extra: formExtraSchema,
2839
+ contract_violations: formContractViolationsSchema
2820
2840
  }),
2821
2841
  page: z7.strictObject({
2822
2842
  path: z7.string()
2823
2843
  })
2824
2844
  });
2825
- var formSubmitConfigSchema = z7.strictObject({});
2845
+ var formDetailsConfigSchema = z7.strictObject({});
2826
2846
 
2827
- // ../tracking-core/src/events/multi-page-session.ts
2847
+ // ../tracking-core/src/events/form-step.ts
2828
2848
  var z8 = __toESM(require("zod/mini"));
2829
- var multiPageSessionMetadataSchema = z8.strictObject({
2830
- page_count: z8.int().check(z8.gte(2)),
2849
+ var formStepMetadataSchema = z8.strictObject({
2850
+ form: z8.strictObject({
2851
+ id: z8.string(),
2852
+ action: z8.nullable(z8.string())
2853
+ }),
2854
+ step: z8.strictObject({
2855
+ id: z8.string().check(z8.minLength(1), z8.maxLength(64), z8.regex(/^[A-Za-z0-9_-]+$/)),
2856
+ // 1-based position in the flow the visitor is on right now.
2857
+ index: z8.int().check(z8.gte(1), z8.lte(50)),
2858
+ // Null when the number of steps depends on earlier answers.
2859
+ total: z8.nullable(z8.int().check(z8.gte(1), z8.lte(50)))
2860
+ }),
2861
+ direction: z8.enum(["forward", "back"]),
2831
2862
  page: z8.strictObject({
2832
2863
  path: z8.string()
2833
2864
  })
2834
2865
  });
2835
- var multiPageSessionConfigSchema = z8.strictObject({
2836
- pageThreshold: z8.int().check(z8.gte(2))
2866
+ var formStepConfigSchema = z8.strictObject({});
2867
+
2868
+ // ../tracking-core/src/events/multi-page-session.ts
2869
+ var z9 = __toESM(require("zod/mini"));
2870
+ var multiPageSessionMetadataSchema = z9.strictObject({
2871
+ page_count: z9.int().check(z9.gte(2)),
2872
+ page: z9.strictObject({
2873
+ path: z9.string()
2874
+ })
2875
+ });
2876
+ var multiPageSessionConfigSchema = z9.strictObject({
2877
+ pageThreshold: z9.int().check(z9.gte(2))
2837
2878
  });
2838
2879
 
2839
2880
  // ../tracking-core/src/events/page-exit.ts
2840
- var z9 = __toESM(require("zod/mini"));
2841
- var pageExitMetadataSchema = z9.strictObject({
2842
- dwell_ms: z9.int().check(z9.gte(0)),
2881
+ var z10 = __toESM(require("zod/mini"));
2882
+ var pageExitMetadataSchema = z10.strictObject({
2883
+ dwell_ms: z10.int().check(z10.gte(0)),
2843
2884
  // null = left without any scroll signal; floor is 0 so a valid 0% is never
2844
2885
  // rejected (a single bad field 422s the whole keepalive beacon batch).
2845
- max_scroll_percent: z9.nullable(z9.int().check(z9.gte(0), z9.lte(100))),
2886
+ max_scroll_percent: z10.nullable(z10.int().check(z10.gte(0), z10.lte(100))),
2846
2887
  // The gating baseline: the fraction of the page visible at load with
2847
2888
  // zero scrolling — or, for pages that grew after the post-paint snapshot
2848
2889
  // (skeleton/streaming renders), the first-scroll position that
@@ -2850,104 +2891,104 @@ var pageExitMetadataSchema = z9.strictObject({
2850
2891
  // ended before the snapshot. Optionality is load-bearing: SDK builds
2851
2892
  // predating this field keep POSTing page_exit without the key —
2852
2893
  // requiring it would 422 whole keepalive beacon batches.
2853
- scroll_baseline_percent: z9.optional(z9.nullable(z9.int().check(z9.gte(0), z9.lte(100)))),
2854
- page: z9.strictObject({
2855
- path: z9.string()
2894
+ scroll_baseline_percent: z10.optional(z10.nullable(z10.int().check(z10.gte(0), z10.lte(100)))),
2895
+ page: z10.strictObject({
2896
+ path: z10.string()
2856
2897
  })
2857
2898
  });
2858
- var pageExitConfigSchema = z9.strictObject({});
2899
+ var pageExitConfigSchema = z10.strictObject({});
2859
2900
 
2860
2901
  // ../tracking-core/src/events/phone-click.ts
2861
- var z10 = __toESM(require("zod/mini"));
2862
- var phoneClickMetadataSchema = z10.strictObject({
2863
- phone_number: z10.string(),
2864
- page: z10.strictObject({
2865
- path: z10.string()
2902
+ var z11 = __toESM(require("zod/mini"));
2903
+ var phoneClickMetadataSchema = z11.strictObject({
2904
+ phone_number: z11.string(),
2905
+ page: z11.strictObject({
2906
+ path: z11.string()
2866
2907
  }),
2867
- section: z10.optional(z10.nullable(z10.string()))
2908
+ section: z11.optional(z11.nullable(z11.string()))
2868
2909
  });
2869
- var phoneClickConfigSchema = z10.strictObject({
2870
- autoCapture: z10.optional(
2871
- z10.strictObject({
2872
- selector: z10.optional(z10.string())
2910
+ var phoneClickConfigSchema = z11.strictObject({
2911
+ autoCapture: z11.optional(
2912
+ z11.strictObject({
2913
+ selector: z11.optional(z11.string())
2873
2914
  })
2874
2915
  )
2875
2916
  });
2876
2917
 
2877
2918
  // ../tracking-core/src/events/scroll-depth.ts
2878
- var z11 = __toESM(require("zod/mini"));
2879
- var scrollDepthMetadataSchema = z11.strictObject({
2880
- depth_percent: z11.int().check(z11.gte(1), z11.lte(100)),
2881
- page: z11.strictObject({
2882
- path: z11.string()
2919
+ var z12 = __toESM(require("zod/mini"));
2920
+ var scrollDepthMetadataSchema = z12.strictObject({
2921
+ depth_percent: z12.int().check(z12.gte(1), z12.lte(100)),
2922
+ page: z12.strictObject({
2923
+ path: z12.string()
2883
2924
  })
2884
2925
  });
2885
- var scrollDepthConfigSchema = z11.strictObject({
2886
- thresholds: z11.array(z11.int().check(z11.gte(1), z11.lte(100))).check(z11.minLength(1))
2926
+ var scrollDepthConfigSchema = z12.strictObject({
2927
+ thresholds: z12.array(z12.int().check(z12.gte(1), z12.lte(100))).check(z12.minLength(1))
2887
2928
  });
2888
2929
 
2889
2930
  // ../tracking-core/src/events/specific-page-visit.ts
2890
- var z12 = __toESM(require("zod/mini"));
2931
+ var z13 = __toESM(require("zod/mini"));
2891
2932
  var PAGE_IDENTITY_MAX_LENGTH = 64;
2892
2933
  var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
2893
- var pageIdentitySchema = z12.string().check(
2894
- z12.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2895
- z12.regex(PAGE_IDENTITY_PATTERN, {
2934
+ var pageIdentitySchema = z13.string().check(
2935
+ z13.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2936
+ z13.regex(PAGE_IDENTITY_PATTERN, {
2896
2937
  message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
2897
2938
  })
2898
2939
  );
2899
2940
  var specificPageNameSchema = pageIdentitySchema;
2900
- var specificPageVisitMetadataSchema = z12.strictObject({
2941
+ var specificPageVisitMetadataSchema = z13.strictObject({
2901
2942
  page_name: specificPageNameSchema,
2902
- page: z12.strictObject({
2903
- path: z12.string()
2943
+ page: z13.strictObject({
2944
+ path: z13.string()
2904
2945
  })
2905
2946
  });
2906
- var specificPageVisitConfigSchema = z12.strictObject({
2907
- pages: z12.array(
2908
- z12.strictObject({
2947
+ var specificPageVisitConfigSchema = z13.strictObject({
2948
+ pages: z13.array(
2949
+ z13.strictObject({
2909
2950
  name: specificPageNameSchema,
2910
- pathPattern: z12.custom((value) => value instanceof RegExp, {
2951
+ pathPattern: z13.custom((value) => value instanceof RegExp, {
2911
2952
  message: "pathPattern must be a RegExp"
2912
2953
  })
2913
2954
  })
2914
- ).check(z12.minLength(1))
2955
+ ).check(z13.minLength(1))
2915
2956
  });
2916
2957
 
2917
2958
  // ../tracking-core/src/events/site-link.ts
2918
- var z13 = __toESM(require("zod/mini"));
2919
- var siteLinkClickMetadataSchema = z13.strictObject({
2920
- destination_host: z13.string(),
2921
- destination_url: z13.string(),
2922
- page: z13.strictObject({
2923
- path: z13.string()
2959
+ var z14 = __toESM(require("zod/mini"));
2960
+ var siteLinkClickMetadataSchema = z14.strictObject({
2961
+ destination_host: z14.string(),
2962
+ destination_url: z14.string(),
2963
+ page: z14.strictObject({
2964
+ path: z14.string()
2924
2965
  })
2925
2966
  });
2926
- var siteLinkClickConfigSchema = z13.strictObject({});
2927
- var siteLinkArrivalMetadataSchema = z13.strictObject({
2928
- outcome: z13.enum(["linked", "stale", "invalid"]),
2929
- origin_session_id: z13.optional(z13.nullable(z13.string())),
2930
- origin_visitor_id: z13.optional(z13.nullable(z13.string())),
2967
+ var siteLinkClickConfigSchema = z14.strictObject({});
2968
+ var siteLinkArrivalMetadataSchema = z14.strictObject({
2969
+ outcome: z14.enum(["linked", "stale", "invalid"]),
2970
+ origin_session_id: z14.optional(z14.nullable(z14.string())),
2971
+ origin_visitor_id: z14.optional(z14.nullable(z14.string())),
2931
2972
  // Milliseconds between the origin click and this page load.
2932
- transit_ms: z13.optional(z13.nullable(z13.number())),
2973
+ transit_ms: z14.optional(z14.nullable(z14.number())),
2933
2974
  // True when this browser had no visitor id and took the origin's.
2934
- adopted_visitor: z13.boolean(),
2935
- page: z13.strictObject({
2936
- path: z13.string()
2975
+ adopted_visitor: z14.boolean(),
2976
+ page: z14.strictObject({
2977
+ path: z14.string()
2937
2978
  })
2938
2979
  });
2939
- var siteLinkArrivalConfigSchema = z13.strictObject({});
2980
+ var siteLinkArrivalConfigSchema = z14.strictObject({});
2940
2981
 
2941
2982
  // ../tracking-core/src/events/time-on-site.ts
2942
- var z14 = __toESM(require("zod/mini"));
2943
- var timeOnSiteMetadataSchema = z14.strictObject({
2944
- duration_ms: z14.int().check(z14.nonnegative()),
2945
- page: z14.strictObject({
2946
- path: z14.string()
2983
+ var z15 = __toESM(require("zod/mini"));
2984
+ var timeOnSiteMetadataSchema = z15.strictObject({
2985
+ duration_ms: z15.int().check(z15.nonnegative()),
2986
+ page: z15.strictObject({
2987
+ path: z15.string()
2947
2988
  })
2948
2989
  });
2949
- var timeOnSiteConfigSchema = z14.strictObject({
2950
- thresholdSeconds: z14.int().check(z14.positive())
2990
+ var timeOnSiteConfigSchema = z15.strictObject({
2991
+ thresholdSeconds: z15.int().check(z15.positive())
2951
2992
  });
2952
2993
 
2953
2994
  // ../tracking-core/src/events/registry.ts
@@ -3029,6 +3070,12 @@ var EVENT_REGISTRY = {
3029
3070
  metadataSchema: formStepMetadataSchema,
3030
3071
  configSchema: formStepConfigSchema
3031
3072
  },
3073
+ form_details: {
3074
+ kind: "manual",
3075
+ semantics: EVENT_SEMANTICS.form_details,
3076
+ metadataSchema: formDetailsMetadataSchema,
3077
+ configSchema: formDetailsConfigSchema
3078
+ },
3032
3079
  phone_click: {
3033
3080
  kind: "manual",
3034
3081
  semantics: EVENT_SEMANTICS.phone_click,
@@ -3067,6 +3114,7 @@ function salvageFormSubmit(metadata) {
3067
3114
  ...valid("contract_version", form.contract_version),
3068
3115
  ...valid("contract_hash", form.contract_hash),
3069
3116
  ...valid("extra", form.extra),
3117
+ ...valid("submission_id", form.submission_id),
3070
3118
  contract_violations: [...reported, INVALID_SHAPE].slice(-MAX_CONTRACT_VIOLATIONS)
3071
3119
  },
3072
3120
  page: { path: typeof page.path === "string" ? page.path : currentPath2() }
@@ -3347,7 +3395,7 @@ function attachScrollDepth(client, config) {
3347
3395
  }
3348
3396
  const thresholds = new Set(config.thresholds);
3349
3397
  let firedForPath = /* @__PURE__ */ new Set();
3350
- let currentPath3 = window.location.pathname;
3398
+ let currentPath4 = window.location.pathname;
3351
3399
  let rafId = null;
3352
3400
  const gate = createBaselineGate();
3353
3401
  function checkThresholds() {
@@ -3363,7 +3411,7 @@ function attachScrollDepth(client, config) {
3363
3411
  eventType: "scroll_depth",
3364
3412
  metadata: {
3365
3413
  depth_percent: threshold,
3366
- page: { path: currentPath3 }
3414
+ page: { path: currentPath4 }
3367
3415
  },
3368
3416
  pageUrl: window.location.href,
3369
3417
  occurredAt: null
@@ -3380,8 +3428,8 @@ function attachScrollDepth(client, config) {
3380
3428
  }
3381
3429
  function resetIfPathChanged() {
3382
3430
  const newPath = window.location.pathname;
3383
- if (newPath === currentPath3) return;
3384
- currentPath3 = newPath;
3431
+ if (newPath === currentPath4) return;
3432
+ currentPath4 = newPath;
3385
3433
  firedForPath = /* @__PURE__ */ new Set();
3386
3434
  gate.rebaseline();
3387
3435
  }
@@ -3444,13 +3492,13 @@ function attachMultiPageSession(client, config) {
3444
3492
  return storage.getItem(FIRED_KEY) === "1";
3445
3493
  }
3446
3494
  function check2() {
3447
- const currentPath3 = window.location.pathname;
3448
- if (currentPath3 === lastCheckedPath) return;
3449
- lastCheckedPath = currentPath3;
3495
+ const currentPath4 = window.location.pathname;
3496
+ if (currentPath4 === lastCheckedPath) return;
3497
+ lastCheckedPath = currentPath4;
3450
3498
  resetIfSessionChanged();
3451
3499
  if (hasFired()) return;
3452
3500
  const paths = getDistinctPaths();
3453
- paths.add(currentPath3);
3501
+ paths.add(currentPath4);
3454
3502
  saveDistinctPaths(paths);
3455
3503
  if (paths.size >= pageThreshold) {
3456
3504
  storage.setItem(FIRED_KEY, "1");
@@ -3495,7 +3543,7 @@ function attachFormStart(client, config) {
3495
3543
  }
3496
3544
  const selector = config.selector ?? "form";
3497
3545
  let firedForms = /* @__PURE__ */ new Set();
3498
- let currentPath3 = window.location.pathname;
3546
+ let currentPath4 = window.location.pathname;
3499
3547
  let pendingTap = null;
3500
3548
  function getFormKey(form) {
3501
3549
  if (form.id) return `id:${form.id}`;
@@ -3546,8 +3594,8 @@ function attachFormStart(client, config) {
3546
3594
  }
3547
3595
  function resetIfPathChanged() {
3548
3596
  const newPath = window.location.pathname;
3549
- if (newPath === currentPath3) return;
3550
- currentPath3 = newPath;
3597
+ if (newPath === currentPath4) return;
3598
+ currentPath4 = newPath;
3551
3599
  firedForms = /* @__PURE__ */ new Set();
3552
3600
  }
3553
3601
  const originalPushState = history.pushState.bind(history);
@@ -3588,7 +3636,7 @@ function attachPageExit(client) {
3588
3636
  return () => {
3589
3637
  };
3590
3638
  }
3591
- let currentPath3 = window.location.pathname;
3639
+ let currentPath4 = window.location.pathname;
3592
3640
  let activeSince = document.visibilityState === "visible" ? Date.now() : null;
3593
3641
  let accumulatedMs = 0;
3594
3642
  let maxScrollPercent = null;
@@ -3638,9 +3686,9 @@ function attachPageExit(client) {
3638
3686
  }
3639
3687
  function onNavigate() {
3640
3688
  const newPath = window.location.pathname;
3641
- if (newPath === currentPath3) return;
3642
- emitSegment(currentPath3, false);
3643
- currentPath3 = newPath;
3689
+ if (newPath === currentPath4) return;
3690
+ emitSegment(currentPath4, false);
3691
+ currentPath4 = newPath;
3644
3692
  maxScrollPercent = null;
3645
3693
  gate.rebaseline();
3646
3694
  accumulatedMs = 0;
@@ -3648,13 +3696,13 @@ function attachPageExit(client) {
3648
3696
  }
3649
3697
  function onVisibilityChange() {
3650
3698
  if (document.visibilityState === "hidden") {
3651
- emitSegment(currentPath3, true);
3699
+ emitSegment(currentPath4, true);
3652
3700
  } else {
3653
3701
  activeSince = Date.now();
3654
3702
  }
3655
3703
  }
3656
3704
  function onPageHide() {
3657
- emitSegment(currentPath3, true);
3705
+ emitSegment(currentPath4, true);
3658
3706
  }
3659
3707
  const unsubscribeNav = onHistoryChange(onNavigate);
3660
3708
  window.addEventListener("scroll", onScroll, { passive: true });
@@ -3834,7 +3882,7 @@ function attachPhoneClickCapture(client, config) {
3834
3882
  }
3835
3883
 
3836
3884
  // ../tracking-core/src/lead-forms/lead-forms.gen.ts
3837
- var z15 = __toESM(require("zod/mini"));
3885
+ var z16 = __toESM(require("zod/mini"));
3838
3886
  var LEAD_FORM_REGISTRY_VERSION = 2;
3839
3887
  var LEAD_FORM_ROLES = [
3840
3888
  "given_name",
@@ -3860,28 +3908,28 @@ var LEAD_FORM_ROLES = [
3860
3908
  "attribution"
3861
3909
  ];
3862
3910
  var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
3863
- string: z15.string().check(z15.maxLength(120)),
3864
- text: z15.string().check(z15.maxLength(2e3)),
3865
- enum: z15.string().check(z15.regex(/^[a-z0-9-]{1,48}$/)),
3866
- multi_enum: z15.array(z15.string().check(z15.regex(/^[a-z0-9-]{1,48}$/))).check(z15.maxLength(10)),
3867
- bool: z15.boolean(),
3868
- date: z15.string().check(z15.regex(/^\d{4}-\d{2}-\d{2}$/)),
3869
- time_window: z15.strictObject({
3870
- start: z15.string().check(z15.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
3871
- end: z15.nullable(z15.string().check(z15.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
3872
- label: z15.optional(z15.string().check(z15.maxLength(60)))
3911
+ string: z16.string().check(z16.maxLength(120)),
3912
+ text: z16.string().check(z16.maxLength(2e3)),
3913
+ enum: z16.string().check(z16.regex(/^[a-z0-9-]{1,48}$/)),
3914
+ multi_enum: z16.array(z16.string().check(z16.regex(/^[a-z0-9-]{1,48}$/))).check(z16.maxLength(10)),
3915
+ bool: z16.boolean(),
3916
+ date: z16.string().check(z16.regex(/^\d{4}-\d{2}-\d{2}$/)),
3917
+ time_window: z16.strictObject({
3918
+ start: z16.string().check(z16.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
3919
+ end: z16.nullable(z16.string().check(z16.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
3920
+ label: z16.optional(z16.string().check(z16.maxLength(60)))
3873
3921
  }),
3874
- phone: z15.string().check(z15.regex(/^\+[1-9]\d{6,14}$/)),
3875
- email: z15.string().check(z15.maxLength(320), z15.regex(/^[^\s@]+@[^\s@]+$/)),
3876
- address: z15.strictObject({
3877
- line1: z15.string().check(z15.maxLength(120)),
3878
- line2: z15.optional(z15.string().check(z15.maxLength(120))),
3879
- city: z15.optional(z15.string().check(z15.maxLength(120))),
3880
- region: z15.optional(z15.string().check(z15.maxLength(120))),
3881
- postal_code: z15.optional(z15.string().check(z15.maxLength(120))),
3882
- country: z15.optional(z15.string().check(z15.maxLength(120)))
3922
+ phone: z16.string().check(z16.regex(/^\+[1-9]\d{6,14}$/)),
3923
+ email: z16.string().check(z16.maxLength(320), z16.regex(/^[^\s@]+@[^\s@]+$/)),
3924
+ address: z16.strictObject({
3925
+ line1: z16.string().check(z16.maxLength(120)),
3926
+ line2: z16.optional(z16.string().check(z16.maxLength(120))),
3927
+ city: z16.optional(z16.string().check(z16.maxLength(120))),
3928
+ region: z16.optional(z16.string().check(z16.maxLength(120))),
3929
+ postal_code: z16.optional(z16.string().check(z16.maxLength(120))),
3930
+ country: z16.optional(z16.string().check(z16.maxLength(120)))
3883
3931
  }),
3884
- number: z15.number()
3932
+ number: z16.number()
3885
3933
  }))();
3886
3934
  var LEAD_FORM_ROLE_SPECS = {
3887
3935
  given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
@@ -3963,34 +4011,70 @@ function createLeadFormSubmit(tracking, contracts, options = {}) {
3963
4011
  contracts,
3964
4012
  settings
3965
4013
  );
4014
+ const submission = { submissionId: uuidV4(), formId: input.formId, kind: input.kind };
3966
4015
  const metadata = {
3967
4016
  form: {
3968
4017
  id: input.formId,
3969
4018
  action: input.action ?? null,
3970
- fields: fields.map(([role, value]) => ({
3971
- name: role,
3972
- type: INPUT_TYPES[primitiveOf(role) ?? "string"],
3973
- label: labelOf(role),
3974
- value,
3975
- role
3976
- })),
4019
+ fields: fields.map(fieldEntry),
3977
4020
  kind: input.kind,
3978
4021
  contract_version: LEAD_FORM_REGISTRY_VERSION,
3979
4022
  ...hash ? { contract_hash: hash } : {},
3980
4023
  ...input.extra?.length ? { extra: input.extra } : {},
3981
- ...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
4024
+ ...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {},
4025
+ submission_id: submission.submissionId
3982
4026
  },
3983
- page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
4027
+ page: { path: currentPath3() }
3984
4028
  };
3985
4029
  tracking.trackEvent("form_submit", metadata);
3986
- return metadata;
4030
+ return { ...metadata, submission };
4031
+ },
4032
+ addDetails(submission, input) {
4033
+ const fields = presentFields(input.fields);
4034
+ const extra = (input.extra ?? []).filter((item) => !isBlank(item.value));
4035
+ if (fields.length === 0 && extra.length === 0) return { sent: false, reason: "no_fields" };
4036
+ const { violations, hash } = judgeLeadForm(
4037
+ submission.kind,
4038
+ submission.formId,
4039
+ fields,
4040
+ contracts,
4041
+ settings,
4042
+ { partial: true }
4043
+ );
4044
+ const metadata = {
4045
+ form: {
4046
+ id: submission.formId,
4047
+ submission_id: submission.submissionId,
4048
+ kind: submission.kind,
4049
+ fields: fields.map(fieldEntry),
4050
+ contract_version: LEAD_FORM_REGISTRY_VERSION,
4051
+ ...hash ? { contract_hash: hash } : {},
4052
+ ...extra.length > 0 ? { extra } : {},
4053
+ ...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
4054
+ },
4055
+ page: { path: currentPath3() }
4056
+ };
4057
+ tracking.trackEvent("form_details", metadata);
4058
+ return { sent: true };
3987
4059
  }
3988
4060
  };
3989
4061
  }
3990
- function judgeLeadForm(kind, formId, fields, contracts, settings) {
4062
+ function fieldEntry([role, value]) {
4063
+ return {
4064
+ name: role,
4065
+ type: INPUT_TYPES[primitiveOf(role) ?? "string"],
4066
+ label: labelOf(role),
4067
+ value,
4068
+ role
4069
+ };
4070
+ }
4071
+ function currentPath3() {
4072
+ return typeof window === "undefined" ? "/" : window.location.pathname;
4073
+ }
4074
+ function judgeLeadForm(kind, formId, fields, contracts, settings, { partial = false } = {}) {
3991
4075
  const generated = contracts?.contracts[kind];
3992
4076
  const live = liveContract(settings.trackingConfig, kind);
3993
- const violations = check(live === void 0 ? generated : fromLive(live), fields);
4077
+ const violations = check(live === void 0 ? generated : fromLive(live), fields, partial);
3994
4078
  const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
3995
4079
  if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
3996
4080
  violations.push({ role: null, rule: "contract_behind" });
@@ -4036,7 +4120,7 @@ function normalize(role, value) {
4036
4120
  function isBlank(value) {
4037
4121
  return value === void 0 || value === null || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0;
4038
4122
  }
4039
- function check(contract, fields) {
4123
+ function check(contract, fields, partial) {
4040
4124
  const answered = new Map(fields);
4041
4125
  const violations = [];
4042
4126
  for (const [role, value] of fields) {
@@ -4054,6 +4138,7 @@ function check(contract, fields) {
4054
4138
  violations.push({ role, rule: "unknown_option" });
4055
4139
  }
4056
4140
  }
4141
+ if (partial) return violations;
4057
4142
  for (const { role, requiredWhen } of contract?.requires ?? []) {
4058
4143
  const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
4059
4144
  if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
@@ -4416,7 +4501,7 @@ function GoogleAdsTracking(props) {
4416
4501
  var import_react6 = require("react");
4417
4502
 
4418
4503
  // package.json
4419
- var version = "1.16.1";
4504
+ var version = "1.18.0";
4420
4505
 
4421
4506
  // ../tracking-core/src/phone-react.tsx
4422
4507
  var import_react5 = require("react");