@aranova/tracking-react 1.14.0 → 1.15.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/{bookings-Bw2ImtPd.d.ts → bookings-CkfA5XOM.d.ts} +283 -8
- package/dist/{bookings-CDGNZUaH.d.mts → bookings-DFz3BUiP.d.mts} +283 -8
- package/dist/client.d.mts +10 -9
- package/dist/client.d.ts +10 -9
- package/dist/client.js +157 -141
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +157 -141
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.js +365 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +365 -203
- package/dist/index.mjs.map +1 -1
- package/dist/{submit-DuvP5AGN.d.ts → ingest-typed-BO6Arbw-.d.mts} +2 -252
- package/dist/{submit-rqgXl-Wg.d.mts → ingest-typed-D7I4aQ7p.d.ts} +2 -252
- package/dist/{phone-utils-Cfdx474X.d.mts → phone-utils-CYr6AmEP.d.mts} +55 -2
- package/dist/{phone-utils-D2TGPCQW.d.ts → phone-utils-CYr6AmEP.d.ts} +55 -2
- package/dist/phone.d.mts +1 -2
- package/dist/phone.d.ts +1 -2
- package/dist/{sales-DkdrGIUS.d.ts → sales-C0FMkN4m.d.ts} +1 -1
- package/dist/{sales-D4aU73mR.d.mts → sales-KbTcowYa.d.mts} +1 -1
- package/dist/sales.d.mts +3 -3
- package/dist/sales.d.ts +3 -3
- package/dist/sales.js +1205 -170
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +1205 -170
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/form-submit-C_vJXCxh.d.mts +0 -57
- package/dist/form-submit-C_vJXCxh.d.ts +0 -57
package/dist/client.mjs
CHANGED
|
@@ -3879,6 +3879,157 @@ var LEAD_FORM_ROLE_SPECS = {
|
|
|
3879
3879
|
attribution: { primitive: "enum", smsLabel: "", uninteresting: true }
|
|
3880
3880
|
};
|
|
3881
3881
|
|
|
3882
|
+
// ../tracking-core/src/lead-forms/submit.ts
|
|
3883
|
+
import { safeParse as safeParse3 } from "zod/mini";
|
|
3884
|
+
var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
|
|
3885
|
+
var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
|
|
3886
|
+
var ADD_ON = /^add_on:[a-z0-9_-]{1,48}$/;
|
|
3887
|
+
var CONTRACT_NAME = /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/;
|
|
3888
|
+
var INPUT_TYPES = {
|
|
3889
|
+
string: "text",
|
|
3890
|
+
text: "textarea",
|
|
3891
|
+
enum: "select",
|
|
3892
|
+
multi_enum: "select",
|
|
3893
|
+
bool: "checkbox",
|
|
3894
|
+
date: "date",
|
|
3895
|
+
time_window: "time",
|
|
3896
|
+
phone: "tel",
|
|
3897
|
+
email: "email",
|
|
3898
|
+
address: "address",
|
|
3899
|
+
number: "number"
|
|
3900
|
+
};
|
|
3901
|
+
function createLeadFormSubmit(tracking, contracts, options = {}) {
|
|
3902
|
+
registerCapability("typed_form_submit");
|
|
3903
|
+
const settings = { ...typedClientSettings(tracking), ...options };
|
|
3904
|
+
return {
|
|
3905
|
+
submit(input) {
|
|
3906
|
+
const fields = presentFields(input.fields);
|
|
3907
|
+
const { violations, hash } = judgeLeadForm(
|
|
3908
|
+
input.kind,
|
|
3909
|
+
input.formId,
|
|
3910
|
+
fields,
|
|
3911
|
+
contracts,
|
|
3912
|
+
settings
|
|
3913
|
+
);
|
|
3914
|
+
const metadata = {
|
|
3915
|
+
form: {
|
|
3916
|
+
id: input.formId,
|
|
3917
|
+
action: input.action ?? null,
|
|
3918
|
+
fields: fields.map(([role, value]) => ({
|
|
3919
|
+
name: role,
|
|
3920
|
+
type: INPUT_TYPES[primitiveOf(role) ?? "string"],
|
|
3921
|
+
label: labelOf(role),
|
|
3922
|
+
value,
|
|
3923
|
+
role
|
|
3924
|
+
})),
|
|
3925
|
+
kind: input.kind,
|
|
3926
|
+
contract_version: LEAD_FORM_REGISTRY_VERSION,
|
|
3927
|
+
...hash ? { contract_hash: hash } : {},
|
|
3928
|
+
...input.extra?.length ? { extra: input.extra } : {},
|
|
3929
|
+
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
|
|
3930
|
+
},
|
|
3931
|
+
page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
|
|
3932
|
+
};
|
|
3933
|
+
tracking.trackEvent("form_submit", metadata);
|
|
3934
|
+
return metadata;
|
|
3935
|
+
}
|
|
3936
|
+
};
|
|
3937
|
+
}
|
|
3938
|
+
function judgeLeadForm(kind, formId, fields, contracts, settings) {
|
|
3939
|
+
const generated = contracts?.contracts[kind];
|
|
3940
|
+
const live = liveContract(settings.trackingConfig, kind);
|
|
3941
|
+
const violations = check(live === void 0 ? generated : fromLive(live), fields);
|
|
3942
|
+
const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
|
|
3943
|
+
if (contracts && (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION)) {
|
|
3944
|
+
violations.push({ role: null, rule: "contract_behind" });
|
|
3945
|
+
}
|
|
3946
|
+
if (violations.length > 0 && (settings.debug || settings.environment === "development")) {
|
|
3947
|
+
const message = `[AranovaTracking] lead form "${formId}" (${kind}) breaks its contract: ${violations.map((v) => `${v.rule}${v.role ? ` (${v.role})` : ""}`).join(", ")}`;
|
|
3948
|
+
console.error(message);
|
|
3949
|
+
if (settings.debug) throw new Error(message);
|
|
3950
|
+
}
|
|
3951
|
+
return {
|
|
3952
|
+
violations,
|
|
3953
|
+
hash: liveHash === void 0 ? generated?.hash ?? null : liveHash
|
|
3954
|
+
};
|
|
3955
|
+
}
|
|
3956
|
+
function liveContract(ref, kind) {
|
|
3957
|
+
const leadForms = ref ? getTrackingConfigRuntime(ref).leadForms() : null;
|
|
3958
|
+
if (!leadForms) return void 0;
|
|
3959
|
+
return leadForms.contracts.find((c) => c.form_kind === kind) ?? null;
|
|
3960
|
+
}
|
|
3961
|
+
function fromLive(live) {
|
|
3962
|
+
if (!live) return void 0;
|
|
3963
|
+
return {
|
|
3964
|
+
requires: live.requires.map((r) => ({
|
|
3965
|
+
role: r.role,
|
|
3966
|
+
requiredWhen: r.required_when ? { role: r.required_when.role, anyOf: r.required_when.any_of } : null
|
|
3967
|
+
})),
|
|
3968
|
+
requiresAny: live.requires_any.map((g) => g.roles),
|
|
3969
|
+
// Deprecated keys still resolve: a cached form may send them (ADR-0024 §7).
|
|
3970
|
+
options: Object.fromEntries(live.options.map((o) => [o.role, o.options.map((x) => x.key)]))
|
|
3971
|
+
};
|
|
3972
|
+
}
|
|
3973
|
+
function presentFields(fields) {
|
|
3974
|
+
return Object.entries(fields).map(([role, value]) => [role, normalize(role, value)]).filter((entry) => !isBlank(entry[1])).sort(([a], [b]) => (ROLE_ORDER.get(a) ?? 999) - (ROLE_ORDER.get(b) ?? 999));
|
|
3975
|
+
}
|
|
3976
|
+
function normalize(role, value) {
|
|
3977
|
+
if (typeof value !== "string") return value;
|
|
3978
|
+
const trimmed = value.trim();
|
|
3979
|
+
const primitive = primitiveOf(role);
|
|
3980
|
+
if (primitive === "phone") return toE164(trimmed) ?? trimmed;
|
|
3981
|
+
if (primitive === "email") return trimmed.toLowerCase();
|
|
3982
|
+
return primitive === "text" ? value : trimmed;
|
|
3983
|
+
}
|
|
3984
|
+
function isBlank(value) {
|
|
3985
|
+
return value === void 0 || value === null || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0;
|
|
3986
|
+
}
|
|
3987
|
+
function check(contract, fields) {
|
|
3988
|
+
const answered = new Map(fields);
|
|
3989
|
+
const violations = [];
|
|
3990
|
+
for (const [role, value] of fields) {
|
|
3991
|
+
const primitive = primitiveOf(role);
|
|
3992
|
+
if (!primitive) {
|
|
3993
|
+
violations.push({ role: CONTRACT_NAME.test(role) ? role : null, rule: "unknown_role" });
|
|
3994
|
+
continue;
|
|
3995
|
+
}
|
|
3996
|
+
if (!safeParse3(leadFormPrimitiveSchemas[primitive], value).success) {
|
|
3997
|
+
violations.push({ role, rule: "invalid_value" });
|
|
3998
|
+
continue;
|
|
3999
|
+
}
|
|
4000
|
+
const allowed = contract?.options[role] ?? registryOptions(role);
|
|
4001
|
+
if (allowed?.length && optionKeys(value).some((key) => !allowed.includes(key))) {
|
|
4002
|
+
violations.push({ role, rule: "unknown_option" });
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
for (const { role, requiredWhen } of contract?.requires ?? []) {
|
|
4006
|
+
const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
|
|
4007
|
+
if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
|
|
4008
|
+
}
|
|
4009
|
+
for (const group of contract?.requiresAny ?? []) {
|
|
4010
|
+
if (!group.some((role) => answered.has(role))) {
|
|
4011
|
+
violations.push({ role: group.join("|"), rule: "missing_any_of" });
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
return violations;
|
|
4015
|
+
}
|
|
4016
|
+
function primitiveOf(role) {
|
|
4017
|
+
if (ADD_ON.test(role)) return "bool";
|
|
4018
|
+
return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].primitive : null;
|
|
4019
|
+
}
|
|
4020
|
+
function labelOf(role) {
|
|
4021
|
+
if (ADD_ON.test(role)) return role.slice("add_on:".length).replaceAll(/[_-]+/g, " ");
|
|
4022
|
+
return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].smsLabel || null : null;
|
|
4023
|
+
}
|
|
4024
|
+
function registryOptions(role) {
|
|
4025
|
+
const spec = KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role] : void 0;
|
|
4026
|
+
return spec && "options" in spec ? spec.options.map((o) => o.key) : void 0;
|
|
4027
|
+
}
|
|
4028
|
+
function optionKeys(value) {
|
|
4029
|
+
if (typeof value === "string") return [value];
|
|
4030
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
4031
|
+
}
|
|
4032
|
+
|
|
3882
4033
|
// ../tracking-core/src/resources/sales/bookings.ts
|
|
3883
4034
|
var newBookingAttemptKey = uuidV4;
|
|
3884
4035
|
|
|
@@ -4213,7 +4364,7 @@ function GoogleAdsTracking(props) {
|
|
|
4213
4364
|
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect5, useMemo as useMemo4 } from "react";
|
|
4214
4365
|
|
|
4215
4366
|
// package.json
|
|
4216
|
-
var version = "1.
|
|
4367
|
+
var version = "1.15.0";
|
|
4217
4368
|
|
|
4218
4369
|
// ../tracking-core/src/phone-react.tsx
|
|
4219
4370
|
import {
|
|
@@ -4542,7 +4693,11 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4542
4693
|
const attemptKey = useRef(null);
|
|
4543
4694
|
const [booked, setBooked] = useState4(null);
|
|
4544
4695
|
const inFlight = useRef(null);
|
|
4545
|
-
const {
|
|
4696
|
+
const { simulate, contracts } = options;
|
|
4697
|
+
const formSubmit = useMemo5(
|
|
4698
|
+
() => options.formSubmit && contracts ? { ...options.formSubmit, contracts } : options.formSubmit,
|
|
4699
|
+
[options.formSubmit, contracts]
|
|
4700
|
+
);
|
|
4546
4701
|
const submit = useCallback3(
|
|
4547
4702
|
(input) => {
|
|
4548
4703
|
if (inFlight.current) return inFlight.current;
|
|
@@ -4594,145 +4749,6 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4594
4749
|
const status = submitting ? "submitting" : outcome?.status ?? "idle";
|
|
4595
4750
|
return { status, outcome, booked, submit, updateBooking, reset };
|
|
4596
4751
|
}
|
|
4597
|
-
|
|
4598
|
-
// ../tracking-core/src/lead-forms/submit.ts
|
|
4599
|
-
import { safeParse as safeParse3 } from "zod/mini";
|
|
4600
|
-
var KNOWN_ROLES = new Set(LEAD_FORM_ROLES);
|
|
4601
|
-
var ROLE_ORDER = new Map(LEAD_FORM_ROLES.map((role, index) => [role, index]));
|
|
4602
|
-
var ADD_ON = /^add_on:[a-z0-9_-]{1,48}$/;
|
|
4603
|
-
var CONTRACT_NAME = /^[a-z][a-z0-9_]{0,47}(:[a-z0-9_-]{1,48})?$/;
|
|
4604
|
-
var INPUT_TYPES = {
|
|
4605
|
-
string: "text",
|
|
4606
|
-
text: "textarea",
|
|
4607
|
-
enum: "select",
|
|
4608
|
-
multi_enum: "select",
|
|
4609
|
-
bool: "checkbox",
|
|
4610
|
-
date: "date",
|
|
4611
|
-
time_window: "time",
|
|
4612
|
-
phone: "tel",
|
|
4613
|
-
email: "email",
|
|
4614
|
-
address: "address",
|
|
4615
|
-
number: "number"
|
|
4616
|
-
};
|
|
4617
|
-
function createLeadFormSubmit(tracking, contracts, options = {}) {
|
|
4618
|
-
registerCapability("typed_form_submit");
|
|
4619
|
-
const settings = { ...typedClientSettings(tracking), ...options };
|
|
4620
|
-
return {
|
|
4621
|
-
submit(input) {
|
|
4622
|
-
const generated = contracts.contracts[input.kind];
|
|
4623
|
-
const live = liveContract(settings.trackingConfig, input.kind);
|
|
4624
|
-
const fields = presentFields(input.fields);
|
|
4625
|
-
const violations = check(live === void 0 ? generated : fromLive(live), fields);
|
|
4626
|
-
const liveHash = live === void 0 ? void 0 : live?.contract_hash ?? null;
|
|
4627
|
-
if (liveHash !== void 0 && (generated?.hash ?? null) !== liveHash || contracts.registryVersion !== LEAD_FORM_REGISTRY_VERSION) {
|
|
4628
|
-
violations.push({ role: null, rule: "contract_behind" });
|
|
4629
|
-
}
|
|
4630
|
-
const hash = liveHash === void 0 ? generated?.hash ?? null : liveHash;
|
|
4631
|
-
const metadata = {
|
|
4632
|
-
form: {
|
|
4633
|
-
id: input.formId,
|
|
4634
|
-
action: input.action ?? null,
|
|
4635
|
-
fields: fields.map(([role, value]) => ({
|
|
4636
|
-
name: role,
|
|
4637
|
-
type: INPUT_TYPES[primitiveOf(role) ?? "string"],
|
|
4638
|
-
label: labelOf(role),
|
|
4639
|
-
value,
|
|
4640
|
-
role
|
|
4641
|
-
})),
|
|
4642
|
-
kind: input.kind,
|
|
4643
|
-
contract_version: LEAD_FORM_REGISTRY_VERSION,
|
|
4644
|
-
...hash ? { contract_hash: hash } : {},
|
|
4645
|
-
...input.extra?.length ? { extra: input.extra } : {},
|
|
4646
|
-
...violations.length > 0 ? { contract_violations: violations.slice(0, MAX_CONTRACT_VIOLATIONS) } : {}
|
|
4647
|
-
},
|
|
4648
|
-
page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
|
|
4649
|
-
};
|
|
4650
|
-
if (violations.length > 0 && (settings.debug || settings.environment === "development")) {
|
|
4651
|
-
const message = `[AranovaTracking] lead form "${input.formId}" (${input.kind}) breaks its contract: ${violations.map((v) => `${v.rule}${v.role ? ` (${v.role})` : ""}`).join(", ")}`;
|
|
4652
|
-
console.error(message);
|
|
4653
|
-
if (settings.debug) throw new Error(message);
|
|
4654
|
-
}
|
|
4655
|
-
tracking.trackEvent("form_submit", metadata);
|
|
4656
|
-
return metadata;
|
|
4657
|
-
}
|
|
4658
|
-
};
|
|
4659
|
-
}
|
|
4660
|
-
function liveContract(ref, kind) {
|
|
4661
|
-
const leadForms = ref ? getTrackingConfigRuntime(ref).leadForms() : null;
|
|
4662
|
-
if (!leadForms) return void 0;
|
|
4663
|
-
return leadForms.contracts.find((c) => c.form_kind === kind) ?? null;
|
|
4664
|
-
}
|
|
4665
|
-
function fromLive(live) {
|
|
4666
|
-
if (!live) return void 0;
|
|
4667
|
-
return {
|
|
4668
|
-
requires: live.requires.map((r) => ({
|
|
4669
|
-
role: r.role,
|
|
4670
|
-
requiredWhen: r.required_when ? { role: r.required_when.role, anyOf: r.required_when.any_of } : null
|
|
4671
|
-
})),
|
|
4672
|
-
requiresAny: live.requires_any.map((g) => g.roles),
|
|
4673
|
-
// Deprecated keys still resolve: a cached form may send them (ADR-0024 §7).
|
|
4674
|
-
options: Object.fromEntries(live.options.map((o) => [o.role, o.options.map((x) => x.key)]))
|
|
4675
|
-
};
|
|
4676
|
-
}
|
|
4677
|
-
function presentFields(fields) {
|
|
4678
|
-
return Object.entries(fields).map(([role, value]) => [role, normalize(role, value)]).filter((entry) => !isBlank(entry[1])).sort(([a], [b]) => (ROLE_ORDER.get(a) ?? 999) - (ROLE_ORDER.get(b) ?? 999));
|
|
4679
|
-
}
|
|
4680
|
-
function normalize(role, value) {
|
|
4681
|
-
if (typeof value !== "string") return value;
|
|
4682
|
-
const trimmed = value.trim();
|
|
4683
|
-
const primitive = primitiveOf(role);
|
|
4684
|
-
if (primitive === "phone") return toE164(trimmed) ?? trimmed;
|
|
4685
|
-
if (primitive === "email") return trimmed.toLowerCase();
|
|
4686
|
-
return primitive === "text" ? value : trimmed;
|
|
4687
|
-
}
|
|
4688
|
-
function isBlank(value) {
|
|
4689
|
-
return value === void 0 || value === null || typeof value === "string" && value.trim() === "" || Array.isArray(value) && value.length === 0;
|
|
4690
|
-
}
|
|
4691
|
-
function check(contract, fields) {
|
|
4692
|
-
const answered = new Map(fields);
|
|
4693
|
-
const violations = [];
|
|
4694
|
-
for (const [role, value] of fields) {
|
|
4695
|
-
const primitive = primitiveOf(role);
|
|
4696
|
-
if (!primitive) {
|
|
4697
|
-
violations.push({ role: CONTRACT_NAME.test(role) ? role : null, rule: "unknown_role" });
|
|
4698
|
-
continue;
|
|
4699
|
-
}
|
|
4700
|
-
if (!safeParse3(leadFormPrimitiveSchemas[primitive], value).success) {
|
|
4701
|
-
violations.push({ role, rule: "invalid_value" });
|
|
4702
|
-
continue;
|
|
4703
|
-
}
|
|
4704
|
-
const allowed = contract?.options[role] ?? registryOptions(role);
|
|
4705
|
-
if (allowed?.length && optionKeys(value).some((key) => !allowed.includes(key))) {
|
|
4706
|
-
violations.push({ role, rule: "unknown_option" });
|
|
4707
|
-
}
|
|
4708
|
-
}
|
|
4709
|
-
for (const { role, requiredWhen } of contract?.requires ?? []) {
|
|
4710
|
-
const owing = requiredWhen === null || optionKeys(answered.get(requiredWhen.role)).some((key) => requiredWhen.anyOf.includes(key));
|
|
4711
|
-
if (owing && !answered.has(role)) violations.push({ role, rule: "missing_required" });
|
|
4712
|
-
}
|
|
4713
|
-
for (const group of contract?.requiresAny ?? []) {
|
|
4714
|
-
if (!group.some((role) => answered.has(role))) {
|
|
4715
|
-
violations.push({ role: group.join("|"), rule: "missing_any_of" });
|
|
4716
|
-
}
|
|
4717
|
-
}
|
|
4718
|
-
return violations;
|
|
4719
|
-
}
|
|
4720
|
-
function primitiveOf(role) {
|
|
4721
|
-
if (ADD_ON.test(role)) return "bool";
|
|
4722
|
-
return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].primitive : null;
|
|
4723
|
-
}
|
|
4724
|
-
function labelOf(role) {
|
|
4725
|
-
if (ADD_ON.test(role)) return role.slice("add_on:".length).replaceAll(/[_-]+/g, " ");
|
|
4726
|
-
return KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role].smsLabel || null : null;
|
|
4727
|
-
}
|
|
4728
|
-
function registryOptions(role) {
|
|
4729
|
-
const spec = KNOWN_ROLES.has(role) ? LEAD_FORM_ROLE_SPECS[role] : void 0;
|
|
4730
|
-
return spec && "options" in spec ? spec.options.map((o) => o.key) : void 0;
|
|
4731
|
-
}
|
|
4732
|
-
function optionKeys(value) {
|
|
4733
|
-
if (typeof value === "string") return [value];
|
|
4734
|
-
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
4735
|
-
}
|
|
4736
4752
|
export {
|
|
4737
4753
|
AdPlatformTracking,
|
|
4738
4754
|
BookingHandoffLink,
|