@aranova/tracking-react 1.17.0 → 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
@@ -2030,6 +2030,13 @@ var EVENT_SEMANTICS = {
2030
2030
  outcomeRole: "engagement",
2031
2031
  clientVisibility: "detailed"
2032
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
+ },
2033
2040
  form_submit: {
2034
2041
  label: "Form submitted",
2035
2042
  category: "lead",
@@ -2646,7 +2653,7 @@ function createTrackingClient(config) {
2646
2653
  metadata: input.metadata ?? null,
2647
2654
  occurred_at: occurredAt
2648
2655
  });
2649
- if (queue.length >= maxQueueSize || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2656
+ if (queue.length >= maxQueueSize || input.eventType === "form_details" || getEventSemantics(input.eventType)?.outcomeRole === "lead") {
2650
2657
  void flush();
2651
2658
  } else {
2652
2659
  scheduleFlush();
@@ -2750,110 +2757,133 @@ var formStartConfigSchema = z5.strictObject({
2750
2757
  selector: z5.optional(z5.string())
2751
2758
  });
2752
2759
 
2753
- // ../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
2754
2764
  var z6 = __toESM(require("zod/mini"));
2755
- 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({
2756
2811
  form: z6.strictObject({
2757
2812
  id: z6.string(),
2758
- 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()))
2759
2822
  }),
2760
- step: z6.strictObject({
2761
- id: z6.string().check(z6.minLength(1), z6.maxLength(64), z6.regex(/^[A-Za-z0-9_-]+$/)),
2762
- // 1-based position in the flow the visitor is on right now.
2763
- index: z6.int().check(z6.gte(1), z6.lte(50)),
2764
- // Null when the number of steps depends on earlier answers.
2765
- total: z6.nullable(z6.int().check(z6.gte(1), z6.lte(50)))
2766
- }),
2767
- direction: z6.enum(["forward", "back"]),
2768
2823
  page: z6.strictObject({
2769
2824
  path: z6.string()
2770
2825
  })
2771
2826
  });
2772
- var formStepConfigSchema = z6.strictObject({});
2827
+ var formSubmitConfigSchema = z6.strictObject({});
2773
2828
 
2774
- // ../tracking-core/src/events/form-submit.ts
2775
- var z7 = __toESM(require("zod/mini"));
2776
- var jsonValueSchema = z7.lazy(
2777
- () => z7.union([
2778
- z7.string(),
2779
- z7.number(),
2780
- z7.boolean(),
2781
- z7.null(),
2782
- z7.array(jsonValueSchema),
2783
- z7.record(z7.string(), jsonValueSchema)
2784
- ])
2785
- ).register(z7.globalRegistry, { id: "JsonSerializableValue" });
2786
- var contractNameSchema = z7.string().check(z7.regex(/^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/));
2787
- var contractName = contractNameSchema;
2788
- var violationRole = z7.string().check(
2789
- z7.maxLength(200),
2790
- z7.regex(
2791
- /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?(\|[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?)*$/
2792
- )
2793
- );
2794
- var MAX_CONTRACT_VIOLATIONS = 50;
2795
- var contractViolationSchema = z7.strictObject({
2796
- role: z7.nullable(violationRole),
2797
- rule: z7.string().check(z7.regex(/^[a-z][a-z_]{0,47}$/))
2798
- });
2799
- var formSubmitMetadataSchema = z7.strictObject({
2829
+ // ../tracking-core/src/events/form-details.ts
2830
+ var formDetailsMetadataSchema = z7.strictObject({
2800
2831
  form: z7.strictObject({
2801
2832
  id: z7.string(),
2802
- action: z7.nullable(z7.string()),
2803
- fields: z7.optional(
2804
- z7.array(
2805
- z7.strictObject({
2806
- name: z7.string(),
2807
- type: z7.string(),
2808
- label: z7.nullable(z7.string()),
2809
- value: jsonValueSchema,
2810
- role: z7.optional(z7.nullable(contractName))
2811
- })
2812
- )
2813
- ),
2814
- kind: z7.optional(z7.nullable(contractName)),
2815
- contract_version: z7.optional(z7.nullable(z7.int().check(z7.gte(1)))),
2816
- contract_hash: z7.optional(z7.nullable(z7.string().check(z7.maxLength(64)))),
2817
- extra: z7.optional(
2818
- z7.nullable(
2819
- z7.array(
2820
- z7.strictObject({
2821
- key: z7.string().check(z7.maxLength(64)),
2822
- label: z7.string().check(z7.maxLength(200)),
2823
- value: jsonValueSchema
2824
- })
2825
- ).check(z7.maxLength(20))
2826
- )
2827
- ),
2828
- contract_violations: z7.optional(
2829
- z7.nullable(z7.array(contractViolationSchema).check(z7.maxLength(MAX_CONTRACT_VIOLATIONS)))
2830
- )
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
2831
2840
  }),
2832
2841
  page: z7.strictObject({
2833
2842
  path: z7.string()
2834
2843
  })
2835
2844
  });
2836
- var formSubmitConfigSchema = z7.strictObject({});
2845
+ var formDetailsConfigSchema = z7.strictObject({});
2837
2846
 
2838
- // ../tracking-core/src/events/multi-page-session.ts
2847
+ // ../tracking-core/src/events/form-step.ts
2839
2848
  var z8 = __toESM(require("zod/mini"));
2840
- var multiPageSessionMetadataSchema = z8.strictObject({
2841
- 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"]),
2842
2862
  page: z8.strictObject({
2843
2863
  path: z8.string()
2844
2864
  })
2845
2865
  });
2846
- var multiPageSessionConfigSchema = z8.strictObject({
2847
- 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))
2848
2878
  });
2849
2879
 
2850
2880
  // ../tracking-core/src/events/page-exit.ts
2851
- var z9 = __toESM(require("zod/mini"));
2852
- var pageExitMetadataSchema = z9.strictObject({
2853
- 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)),
2854
2884
  // null = left without any scroll signal; floor is 0 so a valid 0% is never
2855
2885
  // rejected (a single bad field 422s the whole keepalive beacon batch).
2856
- 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))),
2857
2887
  // The gating baseline: the fraction of the page visible at load with
2858
2888
  // zero scrolling — or, for pages that grew after the post-paint snapshot
2859
2889
  // (skeleton/streaming renders), the first-scroll position that
@@ -2861,104 +2891,104 @@ var pageExitMetadataSchema = z9.strictObject({
2861
2891
  // ended before the snapshot. Optionality is load-bearing: SDK builds
2862
2892
  // predating this field keep POSTing page_exit without the key —
2863
2893
  // requiring it would 422 whole keepalive beacon batches.
2864
- scroll_baseline_percent: z9.optional(z9.nullable(z9.int().check(z9.gte(0), z9.lte(100)))),
2865
- page: z9.strictObject({
2866
- 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()
2867
2897
  })
2868
2898
  });
2869
- var pageExitConfigSchema = z9.strictObject({});
2899
+ var pageExitConfigSchema = z10.strictObject({});
2870
2900
 
2871
2901
  // ../tracking-core/src/events/phone-click.ts
2872
- var z10 = __toESM(require("zod/mini"));
2873
- var phoneClickMetadataSchema = z10.strictObject({
2874
- phone_number: z10.string(),
2875
- page: z10.strictObject({
2876
- 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()
2877
2907
  }),
2878
- section: z10.optional(z10.nullable(z10.string()))
2908
+ section: z11.optional(z11.nullable(z11.string()))
2879
2909
  });
2880
- var phoneClickConfigSchema = z10.strictObject({
2881
- autoCapture: z10.optional(
2882
- z10.strictObject({
2883
- selector: z10.optional(z10.string())
2910
+ var phoneClickConfigSchema = z11.strictObject({
2911
+ autoCapture: z11.optional(
2912
+ z11.strictObject({
2913
+ selector: z11.optional(z11.string())
2884
2914
  })
2885
2915
  )
2886
2916
  });
2887
2917
 
2888
2918
  // ../tracking-core/src/events/scroll-depth.ts
2889
- var z11 = __toESM(require("zod/mini"));
2890
- var scrollDepthMetadataSchema = z11.strictObject({
2891
- depth_percent: z11.int().check(z11.gte(1), z11.lte(100)),
2892
- page: z11.strictObject({
2893
- 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()
2894
2924
  })
2895
2925
  });
2896
- var scrollDepthConfigSchema = z11.strictObject({
2897
- 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))
2898
2928
  });
2899
2929
 
2900
2930
  // ../tracking-core/src/events/specific-page-visit.ts
2901
- var z12 = __toESM(require("zod/mini"));
2931
+ var z13 = __toESM(require("zod/mini"));
2902
2932
  var PAGE_IDENTITY_MAX_LENGTH = 64;
2903
2933
  var PAGE_IDENTITY_PATTERN = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
2904
- var pageIdentitySchema = z12.string().check(
2905
- z12.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2906
- z12.regex(PAGE_IDENTITY_PATTERN, {
2934
+ var pageIdentitySchema = z13.string().check(
2935
+ z13.maxLength(PAGE_IDENTITY_MAX_LENGTH),
2936
+ z13.regex(PAGE_IDENTITY_PATTERN, {
2907
2937
  message: "page identity must be lowercase snake_case, start with a letter, and contain at most 64 characters"
2908
2938
  })
2909
2939
  );
2910
2940
  var specificPageNameSchema = pageIdentitySchema;
2911
- var specificPageVisitMetadataSchema = z12.strictObject({
2941
+ var specificPageVisitMetadataSchema = z13.strictObject({
2912
2942
  page_name: specificPageNameSchema,
2913
- page: z12.strictObject({
2914
- path: z12.string()
2943
+ page: z13.strictObject({
2944
+ path: z13.string()
2915
2945
  })
2916
2946
  });
2917
- var specificPageVisitConfigSchema = z12.strictObject({
2918
- pages: z12.array(
2919
- z12.strictObject({
2947
+ var specificPageVisitConfigSchema = z13.strictObject({
2948
+ pages: z13.array(
2949
+ z13.strictObject({
2920
2950
  name: specificPageNameSchema,
2921
- pathPattern: z12.custom((value) => value instanceof RegExp, {
2951
+ pathPattern: z13.custom((value) => value instanceof RegExp, {
2922
2952
  message: "pathPattern must be a RegExp"
2923
2953
  })
2924
2954
  })
2925
- ).check(z12.minLength(1))
2955
+ ).check(z13.minLength(1))
2926
2956
  });
2927
2957
 
2928
2958
  // ../tracking-core/src/events/site-link.ts
2929
- var z13 = __toESM(require("zod/mini"));
2930
- var siteLinkClickMetadataSchema = z13.strictObject({
2931
- destination_host: z13.string(),
2932
- destination_url: z13.string(),
2933
- page: z13.strictObject({
2934
- 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()
2935
2965
  })
2936
2966
  });
2937
- var siteLinkClickConfigSchema = z13.strictObject({});
2938
- var siteLinkArrivalMetadataSchema = z13.strictObject({
2939
- outcome: z13.enum(["linked", "stale", "invalid"]),
2940
- origin_session_id: z13.optional(z13.nullable(z13.string())),
2941
- 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())),
2942
2972
  // Milliseconds between the origin click and this page load.
2943
- transit_ms: z13.optional(z13.nullable(z13.number())),
2973
+ transit_ms: z14.optional(z14.nullable(z14.number())),
2944
2974
  // True when this browser had no visitor id and took the origin's.
2945
- adopted_visitor: z13.boolean(),
2946
- page: z13.strictObject({
2947
- path: z13.string()
2975
+ adopted_visitor: z14.boolean(),
2976
+ page: z14.strictObject({
2977
+ path: z14.string()
2948
2978
  })
2949
2979
  });
2950
- var siteLinkArrivalConfigSchema = z13.strictObject({});
2980
+ var siteLinkArrivalConfigSchema = z14.strictObject({});
2951
2981
 
2952
2982
  // ../tracking-core/src/events/time-on-site.ts
2953
- var z14 = __toESM(require("zod/mini"));
2954
- var timeOnSiteMetadataSchema = z14.strictObject({
2955
- duration_ms: z14.int().check(z14.nonnegative()),
2956
- page: z14.strictObject({
2957
- 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()
2958
2988
  })
2959
2989
  });
2960
- var timeOnSiteConfigSchema = z14.strictObject({
2961
- thresholdSeconds: z14.int().check(z14.positive())
2990
+ var timeOnSiteConfigSchema = z15.strictObject({
2991
+ thresholdSeconds: z15.int().check(z15.positive())
2962
2992
  });
2963
2993
 
2964
2994
  // ../tracking-core/src/events/registry.ts
@@ -3040,6 +3070,12 @@ var EVENT_REGISTRY = {
3040
3070
  metadataSchema: formStepMetadataSchema,
3041
3071
  configSchema: formStepConfigSchema
3042
3072
  },
3073
+ form_details: {
3074
+ kind: "manual",
3075
+ semantics: EVENT_SEMANTICS.form_details,
3076
+ metadataSchema: formDetailsMetadataSchema,
3077
+ configSchema: formDetailsConfigSchema
3078
+ },
3043
3079
  phone_click: {
3044
3080
  kind: "manual",
3045
3081
  semantics: EVENT_SEMANTICS.phone_click,
@@ -3078,6 +3114,7 @@ function salvageFormSubmit(metadata) {
3078
3114
  ...valid("contract_version", form.contract_version),
3079
3115
  ...valid("contract_hash", form.contract_hash),
3080
3116
  ...valid("extra", form.extra),
3117
+ ...valid("submission_id", form.submission_id),
3081
3118
  contract_violations: [...reported, INVALID_SHAPE].slice(-MAX_CONTRACT_VIOLATIONS)
3082
3119
  },
3083
3120
  page: { path: typeof page.path === "string" ? page.path : currentPath2() }
@@ -3358,7 +3395,7 @@ function attachScrollDepth(client, config) {
3358
3395
  }
3359
3396
  const thresholds = new Set(config.thresholds);
3360
3397
  let firedForPath = /* @__PURE__ */ new Set();
3361
- let currentPath3 = window.location.pathname;
3398
+ let currentPath4 = window.location.pathname;
3362
3399
  let rafId = null;
3363
3400
  const gate = createBaselineGate();
3364
3401
  function checkThresholds() {
@@ -3374,7 +3411,7 @@ function attachScrollDepth(client, config) {
3374
3411
  eventType: "scroll_depth",
3375
3412
  metadata: {
3376
3413
  depth_percent: threshold,
3377
- page: { path: currentPath3 }
3414
+ page: { path: currentPath4 }
3378
3415
  },
3379
3416
  pageUrl: window.location.href,
3380
3417
  occurredAt: null
@@ -3391,8 +3428,8 @@ function attachScrollDepth(client, config) {
3391
3428
  }
3392
3429
  function resetIfPathChanged() {
3393
3430
  const newPath = window.location.pathname;
3394
- if (newPath === currentPath3) return;
3395
- currentPath3 = newPath;
3431
+ if (newPath === currentPath4) return;
3432
+ currentPath4 = newPath;
3396
3433
  firedForPath = /* @__PURE__ */ new Set();
3397
3434
  gate.rebaseline();
3398
3435
  }
@@ -3455,13 +3492,13 @@ function attachMultiPageSession(client, config) {
3455
3492
  return storage.getItem(FIRED_KEY) === "1";
3456
3493
  }
3457
3494
  function check2() {
3458
- const currentPath3 = window.location.pathname;
3459
- if (currentPath3 === lastCheckedPath) return;
3460
- lastCheckedPath = currentPath3;
3495
+ const currentPath4 = window.location.pathname;
3496
+ if (currentPath4 === lastCheckedPath) return;
3497
+ lastCheckedPath = currentPath4;
3461
3498
  resetIfSessionChanged();
3462
3499
  if (hasFired()) return;
3463
3500
  const paths = getDistinctPaths();
3464
- paths.add(currentPath3);
3501
+ paths.add(currentPath4);
3465
3502
  saveDistinctPaths(paths);
3466
3503
  if (paths.size >= pageThreshold) {
3467
3504
  storage.setItem(FIRED_KEY, "1");
@@ -3506,7 +3543,7 @@ function attachFormStart(client, config) {
3506
3543
  }
3507
3544
  const selector = config.selector ?? "form";
3508
3545
  let firedForms = /* @__PURE__ */ new Set();
3509
- let currentPath3 = window.location.pathname;
3546
+ let currentPath4 = window.location.pathname;
3510
3547
  let pendingTap = null;
3511
3548
  function getFormKey(form) {
3512
3549
  if (form.id) return `id:${form.id}`;
@@ -3557,8 +3594,8 @@ function attachFormStart(client, config) {
3557
3594
  }
3558
3595
  function resetIfPathChanged() {
3559
3596
  const newPath = window.location.pathname;
3560
- if (newPath === currentPath3) return;
3561
- currentPath3 = newPath;
3597
+ if (newPath === currentPath4) return;
3598
+ currentPath4 = newPath;
3562
3599
  firedForms = /* @__PURE__ */ new Set();
3563
3600
  }
3564
3601
  const originalPushState = history.pushState.bind(history);
@@ -3599,7 +3636,7 @@ function attachPageExit(client) {
3599
3636
  return () => {
3600
3637
  };
3601
3638
  }
3602
- let currentPath3 = window.location.pathname;
3639
+ let currentPath4 = window.location.pathname;
3603
3640
  let activeSince = document.visibilityState === "visible" ? Date.now() : null;
3604
3641
  let accumulatedMs = 0;
3605
3642
  let maxScrollPercent = null;
@@ -3649,9 +3686,9 @@ function attachPageExit(client) {
3649
3686
  }
3650
3687
  function onNavigate() {
3651
3688
  const newPath = window.location.pathname;
3652
- if (newPath === currentPath3) return;
3653
- emitSegment(currentPath3, false);
3654
- currentPath3 = newPath;
3689
+ if (newPath === currentPath4) return;
3690
+ emitSegment(currentPath4, false);
3691
+ currentPath4 = newPath;
3655
3692
  maxScrollPercent = null;
3656
3693
  gate.rebaseline();
3657
3694
  accumulatedMs = 0;
@@ -3659,13 +3696,13 @@ function attachPageExit(client) {
3659
3696
  }
3660
3697
  function onVisibilityChange() {
3661
3698
  if (document.visibilityState === "hidden") {
3662
- emitSegment(currentPath3, true);
3699
+ emitSegment(currentPath4, true);
3663
3700
  } else {
3664
3701
  activeSince = Date.now();
3665
3702
  }
3666
3703
  }
3667
3704
  function onPageHide() {
3668
- emitSegment(currentPath3, true);
3705
+ emitSegment(currentPath4, true);
3669
3706
  }
3670
3707
  const unsubscribeNav = onHistoryChange(onNavigate);
3671
3708
  window.addEventListener("scroll", onScroll, { passive: true });
@@ -3845,7 +3882,7 @@ function attachPhoneClickCapture(client, config) {
3845
3882
  }
3846
3883
 
3847
3884
  // ../tracking-core/src/lead-forms/lead-forms.gen.ts
3848
- var z15 = __toESM(require("zod/mini"));
3885
+ var z16 = __toESM(require("zod/mini"));
3849
3886
  var LEAD_FORM_REGISTRY_VERSION = 2;
3850
3887
  var LEAD_FORM_ROLES = [
3851
3888
  "given_name",
@@ -3871,28 +3908,28 @@ var LEAD_FORM_ROLES = [
3871
3908
  "attribution"
3872
3909
  ];
3873
3910
  var leadFormPrimitiveSchemas = /* @__PURE__ */ (() => ({
3874
- string: z15.string().check(z15.maxLength(120)),
3875
- text: z15.string().check(z15.maxLength(2e3)),
3876
- enum: z15.string().check(z15.regex(/^[a-z0-9-]{1,48}$/)),
3877
- multi_enum: z15.array(z15.string().check(z15.regex(/^[a-z0-9-]{1,48}$/))).check(z15.maxLength(10)),
3878
- bool: z15.boolean(),
3879
- date: z15.string().check(z15.regex(/^\d{4}-\d{2}-\d{2}$/)),
3880
- time_window: z15.strictObject({
3881
- start: z15.string().check(z15.regex(/^([01]\d|2[0-3]):[0-5]\d$/)),
3882
- end: z15.nullable(z15.string().check(z15.regex(/^([01]\d|2[0-3]):[0-5]\d$/))),
3883
- 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)))
3884
3921
  }),
3885
- phone: z15.string().check(z15.regex(/^\+[1-9]\d{6,14}$/)),
3886
- email: z15.string().check(z15.maxLength(320), z15.regex(/^[^\s@]+@[^\s@]+$/)),
3887
- address: z15.strictObject({
3888
- line1: z15.string().check(z15.maxLength(120)),
3889
- line2: z15.optional(z15.string().check(z15.maxLength(120))),
3890
- city: z15.optional(z15.string().check(z15.maxLength(120))),
3891
- region: z15.optional(z15.string().check(z15.maxLength(120))),
3892
- postal_code: z15.optional(z15.string().check(z15.maxLength(120))),
3893
- 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)))
3894
3931
  }),
3895
- number: z15.number()
3932
+ number: z16.number()
3896
3933
  }))();
3897
3934
  var LEAD_FORM_ROLE_SPECS = {
3898
3935
  given_name: { primitive: "string", smsLabel: "", contactIdentity: true },
@@ -3974,34 +4011,70 @@ function createLeadFormSubmit(tracking, contracts, options = {}) {
3974
4011
  contracts,
3975
4012
  settings
3976
4013
  );
4014
+ const submission = { submissionId: uuidV4(), formId: input.formId, kind: input.kind };
3977
4015
  const metadata = {
3978
4016
  form: {
3979
4017
  id: input.formId,
3980
4018
  action: input.action ?? null,
3981
- fields: fields.map(([role, value]) => ({
3982
- name: role,
3983
- type: INPUT_TYPES[primitiveOf(role) ?? "string"],
3984
- label: labelOf(role),
3985
- value,
3986
- role
3987
- })),
4019
+ fields: fields.map(fieldEntry),
3988
4020
  kind: input.kind,
3989
4021
  contract_version: LEAD_FORM_REGISTRY_VERSION,
3990
4022
  ...hash ? { contract_hash: hash } : {},
3991
4023
  ...input.extra?.length ? { extra: input.extra } : {},
3992
- ...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
3993
4026
  },
3994
- page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
4027
+ page: { path: currentPath3() }
3995
4028
  };
3996
4029
  tracking.trackEvent("form_submit", metadata);
3997
- 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 };
3998
4059
  }
3999
4060
  };
4000
4061
  }
4001
- 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 } = {}) {
4002
4075
  const generated = contracts?.contracts[kind];
4003
4076
  const live = liveContract(settings.trackingConfig, kind);
4004
- const violations = check(live === void 0 ? generated : fromLive(live), fields);
4077
+ const violations = check(live === void 0 ? generated : fromLive(live), fields, partial);
4005
4078
  const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
4006
4079
  if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
4007
4080
  violations.push({ role: null, rule: "contract_behind" });
@@ -4047,7 +4120,7 @@ function normalize(role, value) {
4047
4120
  function isBlank(value) {
4048
4121
  return value === void 0 || value === null || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0;
4049
4122
  }
4050
- function check(contract, fields) {
4123
+ function check(contract, fields, partial) {
4051
4124
  const answered = new Map(fields);
4052
4125
  const violations = [];
4053
4126
  for (const [role, value] of fields) {
@@ -4065,6 +4138,7 @@ function check(contract, fields) {
4065
4138
  violations.push({ role, rule: "unknown_option" });
4066
4139
  }
4067
4140
  }
4141
+ if (partial) return violations;
4068
4142
  for (const { role, requiredWhen } of contract?.requires ?? []) {
4069
4143
  const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
4070
4144
  if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
@@ -4427,7 +4501,7 @@ function GoogleAdsTracking(props) {
4427
4501
  var import_react6 = require("react");
4428
4502
 
4429
4503
  // package.json
4430
- var version = "1.17.0";
4504
+ var version = "1.18.0";
4431
4505
 
4432
4506
  // ../tracking-core/src/phone-react.tsx
4433
4507
  var import_react5 = require("react");