@aranova/tracking-next 0.16.2 → 0.17.1

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/README.md CHANGED
@@ -169,6 +169,41 @@ export function LeadForm() {
169
169
 
170
170
  `fields[].value` can be any JSON value: string, number, boolean, null, array, or object. Only send reviewed, allowlisted, non-sensitive values; do not send names, emails, phone numbers entered by the visitor, addresses, payment data, medical details, passwords, file contents, or free-text messages.
171
171
 
172
+ ### Phone clicks (`tel:` taps) — manual or auto-capture
173
+
174
+ Opt into **auto-capture** and every `tel:` link is tracked with no per-link code. Add
175
+ `autoCapture` to the `phone_click` registration — a single delegated click listener does the rest:
176
+
177
+ ```tsx
178
+ manual: {
179
+ phone_click: { autoCapture: {} }, // default selector: a[href^="tel:"]
180
+ // or narrow it: { autoCapture: { selector: "a.call" } }
181
+ },
182
+ ```
183
+
184
+ ```tsx
185
+ <a href="tel:+14165550199" data-aranova-section="header">
186
+ (416) 555-0199
187
+ </a>
188
+ ```
189
+
190
+ The number is read from the `href` (normalized to E.164); `section` comes from an optional
191
+ `data-aranova-section`. **Unlike `cta_click`, a `phone_click` also fires the Google Ads
192
+ conversion** for a linked phone-call goal (a `CLICK_TO_CALL` action) — auto-fired the moment the
193
+ tap is captured, so you never call `trackConversion` (firing needs the sales client wired with the
194
+ same config; see below).
195
+
196
+ Prefer to instrument links yourself? Fire it from a click handler — this fires the conversion the
197
+ same way:
198
+
199
+ ```tsx
200
+ tracking.trackEvent("phone_click", {
201
+ phone_number: "+14165550199",
202
+ page: { path: window.location.pathname },
203
+ section: "header",
204
+ });
205
+ ```
206
+
172
207
  ### CTA clicks — manual or auto-capture
173
208
 
174
209
  Fire `cta_click` yourself for full control over the name:
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as TrackingParams, a as TrackingInstallSurface, b as TrackingEnvironment, c as TrackingClientContext, d as TrackingEventCreatePayload, e as TrackingSessionUpsertPayload, F as FormSubmitConfig, f as FormSubmitMetadata, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-DlAQK-gU.mjs';
2
2
  export { k as ConsentChoice, D as DEFAULT_DECLINE_TTL_DAYS, l as DEFAULT_PHONE_COUNTRY, J as JsonValue, S as SetConsentOptions, m as TrackedField, n as TrackingInitConfig, o as formSubmitConfigSchema, p as formSubmitMetadataSchema, q as formatPhone, r as formatPhoneAsTyped, s as getConsentChoice, t as getConsentState, u as jsonValueSchema, v as onConsentChange, w as optIn, x as optOut, y as parsePhone, z as phoneField, A as resetConsent, B as setConsentState, E as toE164 } from './phone-utils-DlAQK-gU.mjs';
3
- import { C as ConversionConfig } from './sales-Bq7H-Vym.mjs';
4
- export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as CurrencyRevenue, f as CustomerCurrencyDelta, g as CustomerCurrencyTotal, h as CustomerGetOptions, i as CustomerGetResult, j as CustomerKpis, k as CustomerKpisDeltas, l as CustomerKpisPrevious, m as CustomerListPage, n as CustomerListQuery, o as CustomerProfile, p as CustomerSegment, q as CustomerSegmentCount, r as CustomerSortField, s as CustomerSummary, t as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, u as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, v as Sale, w as SaleCursorPage, x as SaleFilters, y as SaleInput, z as SaleItem, E as SaleItemInput, F as SaleKeysetSortField, H as SaleListPage, I as SaleListQuery, J as SaleListQueryV2, K as SaleService, L as SaleServiceInput, M as SaleSortField, O as SaleSortOrder, Q as SaleSummary, R as SaleSummaryPrevious, T as SaleSummaryQuery, U as SaleSummaryQueryV2, V as SaleSummaryV2, W as SaleUpdateInput, X as SalesBusinessClient, Y as SalesCategoryBreakdown, Z as SalesClient, _ as SalesClientConfig, $ as SalesCustomersClient, a0 as SalesServiceBreakdown, a1 as SalesTransportConfig, a2 as SalesTrendPoint, a3 as SummaryCurrencyDelta, a4 as SummaryDeltas, a5 as SummaryWindow, a6 as SupportedCurrency, a7 as TRACKING_RANGES, a8 as TrackingOverviewRange, a9 as createSalesClient, aa as fetchServices, ab as formatDateInTz, ac as formatMoney, ad as fromMinor, ae as resolveConversionConfig, af as saleCreateSchema, ag as saleItemSchema, ah as saleServiceSchema, ai as saleUpdateSchema, aj as salesRequest, ak as toMinor } from './sales-Bq7H-Vym.mjs';
3
+ import { C as ConversionConfig } from './sales-C3jFBx08.mjs';
4
+ export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as CurrencyRevenue, f as CustomerCurrencyDelta, g as CustomerCurrencyTotal, h as CustomerGetOptions, i as CustomerGetResult, j as CustomerKpis, k as CustomerKpisDeltas, l as CustomerKpisPrevious, m as CustomerListPage, n as CustomerListQuery, o as CustomerProfile, p as CustomerSegment, q as CustomerSegmentCount, r as CustomerSortField, s as CustomerSummary, t as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, u as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, v as Sale, w as SaleCursorPage, x as SaleFilters, y as SaleInput, z as SaleItem, E as SaleItemInput, F as SaleKeysetSortField, H as SaleListPage, I as SaleListQuery, J as SaleListQueryV2, K as SaleService, L as SaleServiceInput, M as SaleSortField, O as SaleSortOrder, Q as SaleSummary, R as SaleSummaryPrevious, T as SaleSummaryQuery, U as SaleSummaryQueryV2, V as SaleSummaryV2, W as SaleUpdateInput, X as SalesBusinessClient, Y as SalesCategoryBreakdown, Z as SalesClient, _ as SalesClientConfig, $ as SalesCustomersClient, a0 as SalesServiceBreakdown, a1 as SalesTransportConfig, a2 as SalesTrendPoint, a3 as SummaryCurrencyDelta, a4 as SummaryDeltas, a5 as SummaryWindow, a6 as SupportedCurrency, a7 as TRACKING_RANGES, a8 as TrackingOverviewRange, a9 as createSalesClient, aa as fetchServices, ab as formatDateInTz, ac as formatMoney, ad as fromMinor, ae as resolveConversionConfig, af as saleCreateSchema, ag as saleItemSchema, ah as saleServiceSchema, ai as saleUpdateSchema, aj as salesRequest, ak as toMinor } from './sales-C3jFBx08.mjs';
5
5
  import { z } from 'zod';
6
6
  import * as src from 'src';
7
7
  import * as react from 'react';
@@ -436,9 +436,28 @@ type PhoneClickMetadata = z.infer<typeof phoneClickMetadataSchema>;
436
436
  /**
437
437
  * Registration config for `phone_click`.
438
438
  *
439
- * This event is manual-only and currently has no registration options.
439
+ * The event stays manually fireable; `autoCapture` additionally attaches a
440
+ * delegated click listener that fires it for any `tel:` link matching
441
+ * `selector` (default `a[href^="tel:"]`) — link your phone number, get the
442
+ * analytics event (and, for a linked phone-click goal, the conversion) for free.
440
443
  */
441
- declare const phoneClickConfigSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
444
+ declare const phoneClickConfigSchema: z.ZodObject<{
445
+ autoCapture: z.ZodOptional<z.ZodObject<{
446
+ selector: z.ZodOptional<z.ZodString>;
447
+ }, "strict", z.ZodTypeAny, {
448
+ selector?: string | undefined;
449
+ }, {
450
+ selector?: string | undefined;
451
+ }>>;
452
+ }, "strict", z.ZodTypeAny, {
453
+ autoCapture?: {
454
+ selector?: string | undefined;
455
+ } | undefined;
456
+ }, {
457
+ autoCapture?: {
458
+ selector?: string | undefined;
459
+ } | undefined;
460
+ }>;
442
461
  type PhoneClickConfig = z.infer<typeof phoneClickConfigSchema>;
443
462
 
444
463
  /**
@@ -994,7 +1013,23 @@ declare const EVENT_REGISTRY: {
994
1013
  phone_number: string;
995
1014
  section?: string | null | undefined;
996
1015
  }>;
997
- readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
1016
+ readonly configSchema: z.ZodObject<{
1017
+ autoCapture: z.ZodOptional<z.ZodObject<{
1018
+ selector: z.ZodOptional<z.ZodString>;
1019
+ }, "strict", z.ZodTypeAny, {
1020
+ selector?: string | undefined;
1021
+ }, {
1022
+ selector?: string | undefined;
1023
+ }>>;
1024
+ }, "strict", z.ZodTypeAny, {
1025
+ autoCapture?: {
1026
+ selector?: string | undefined;
1027
+ } | undefined;
1028
+ }, {
1029
+ autoCapture?: {
1030
+ selector?: string | undefined;
1031
+ } | undefined;
1032
+ }>;
998
1033
  };
999
1034
  readonly cta_click: {
1000
1035
  readonly kind: "manual";
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as TrackingParams, a as TrackingInstallSurface, b as TrackingEnvironment, c as TrackingClientContext, d as TrackingEventCreatePayload, e as TrackingSessionUpsertPayload, F as FormSubmitConfig, f as FormSubmitMetadata, C as ConsentState, g as ConsentChoiceState, h as ConsentSource, G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, P as PhoneConfig, i as ParsedPhone, j as PhoneDisplayFormat } from './phone-utils-DlAQK-gU.js';
2
2
  export { k as ConsentChoice, D as DEFAULT_DECLINE_TTL_DAYS, l as DEFAULT_PHONE_COUNTRY, J as JsonValue, S as SetConsentOptions, m as TrackedField, n as TrackingInitConfig, o as formSubmitConfigSchema, p as formSubmitMetadataSchema, q as formatPhone, r as formatPhoneAsTyped, s as getConsentChoice, t as getConsentState, u as jsonValueSchema, v as onConsentChange, w as optIn, x as optOut, y as parsePhone, z as phoneField, A as resetConsent, B as setConsentState, E as toE164 } from './phone-utils-DlAQK-gU.js';
3
- import { C as ConversionConfig } from './sales-Bq7H-Vym.js';
4
- export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as CurrencyRevenue, f as CustomerCurrencyDelta, g as CustomerCurrencyTotal, h as CustomerGetOptions, i as CustomerGetResult, j as CustomerKpis, k as CustomerKpisDeltas, l as CustomerKpisPrevious, m as CustomerListPage, n as CustomerListQuery, o as CustomerProfile, p as CustomerSegment, q as CustomerSegmentCount, r as CustomerSortField, s as CustomerSummary, t as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, u as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, v as Sale, w as SaleCursorPage, x as SaleFilters, y as SaleInput, z as SaleItem, E as SaleItemInput, F as SaleKeysetSortField, H as SaleListPage, I as SaleListQuery, J as SaleListQueryV2, K as SaleService, L as SaleServiceInput, M as SaleSortField, O as SaleSortOrder, Q as SaleSummary, R as SaleSummaryPrevious, T as SaleSummaryQuery, U as SaleSummaryQueryV2, V as SaleSummaryV2, W as SaleUpdateInput, X as SalesBusinessClient, Y as SalesCategoryBreakdown, Z as SalesClient, _ as SalesClientConfig, $ as SalesCustomersClient, a0 as SalesServiceBreakdown, a1 as SalesTransportConfig, a2 as SalesTrendPoint, a3 as SummaryCurrencyDelta, a4 as SummaryDeltas, a5 as SummaryWindow, a6 as SupportedCurrency, a7 as TRACKING_RANGES, a8 as TrackingOverviewRange, a9 as createSalesClient, aa as fetchServices, ab as formatDateInTz, ac as formatMoney, ad as fromMinor, ae as resolveConversionConfig, af as saleCreateSchema, ag as saleItemSchema, ah as saleServiceSchema, ai as saleUpdateSchema, aj as salesRequest, ak as toMinor } from './sales-Bq7H-Vym.js';
3
+ import { C as ConversionConfig } from './sales-C3jFBx08.js';
4
+ export { A as AranovaApiError, B as BusinessConfig, a as BusinessConfigFeatures, b as BusinessConfigService, c as CompareTo, d as ConversionConfigStore, e as CurrencyRevenue, f as CustomerCurrencyDelta, g as CustomerCurrencyTotal, h as CustomerGetOptions, i as CustomerGetResult, j as CustomerKpis, k as CustomerKpisDeltas, l as CustomerKpisPrevious, m as CustomerListPage, n as CustomerListQuery, o as CustomerProfile, p as CustomerSegment, q as CustomerSegmentCount, r as CustomerSortField, s as CustomerSummary, t as CustomerSummaryQuery, D as DistinctCustomersByCurrency, G as Granularity, N as NAMED_RANGES, u as NamedRange, P as PublicServiceItem, S as SUPPORTED_CURRENCIES, v as Sale, w as SaleCursorPage, x as SaleFilters, y as SaleInput, z as SaleItem, E as SaleItemInput, F as SaleKeysetSortField, H as SaleListPage, I as SaleListQuery, J as SaleListQueryV2, K as SaleService, L as SaleServiceInput, M as SaleSortField, O as SaleSortOrder, Q as SaleSummary, R as SaleSummaryPrevious, T as SaleSummaryQuery, U as SaleSummaryQueryV2, V as SaleSummaryV2, W as SaleUpdateInput, X as SalesBusinessClient, Y as SalesCategoryBreakdown, Z as SalesClient, _ as SalesClientConfig, $ as SalesCustomersClient, a0 as SalesServiceBreakdown, a1 as SalesTransportConfig, a2 as SalesTrendPoint, a3 as SummaryCurrencyDelta, a4 as SummaryDeltas, a5 as SummaryWindow, a6 as SupportedCurrency, a7 as TRACKING_RANGES, a8 as TrackingOverviewRange, a9 as createSalesClient, aa as fetchServices, ab as formatDateInTz, ac as formatMoney, ad as fromMinor, ae as resolveConversionConfig, af as saleCreateSchema, ag as saleItemSchema, ah as saleServiceSchema, ai as saleUpdateSchema, aj as salesRequest, ak as toMinor } from './sales-C3jFBx08.js';
5
5
  import { z } from 'zod';
6
6
  import * as src from 'src';
7
7
  import * as react from 'react';
@@ -436,9 +436,28 @@ type PhoneClickMetadata = z.infer<typeof phoneClickMetadataSchema>;
436
436
  /**
437
437
  * Registration config for `phone_click`.
438
438
  *
439
- * This event is manual-only and currently has no registration options.
439
+ * The event stays manually fireable; `autoCapture` additionally attaches a
440
+ * delegated click listener that fires it for any `tel:` link matching
441
+ * `selector` (default `a[href^="tel:"]`) — link your phone number, get the
442
+ * analytics event (and, for a linked phone-click goal, the conversion) for free.
440
443
  */
441
- declare const phoneClickConfigSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
444
+ declare const phoneClickConfigSchema: z.ZodObject<{
445
+ autoCapture: z.ZodOptional<z.ZodObject<{
446
+ selector: z.ZodOptional<z.ZodString>;
447
+ }, "strict", z.ZodTypeAny, {
448
+ selector?: string | undefined;
449
+ }, {
450
+ selector?: string | undefined;
451
+ }>>;
452
+ }, "strict", z.ZodTypeAny, {
453
+ autoCapture?: {
454
+ selector?: string | undefined;
455
+ } | undefined;
456
+ }, {
457
+ autoCapture?: {
458
+ selector?: string | undefined;
459
+ } | undefined;
460
+ }>;
442
461
  type PhoneClickConfig = z.infer<typeof phoneClickConfigSchema>;
443
462
 
444
463
  /**
@@ -994,7 +1013,23 @@ declare const EVENT_REGISTRY: {
994
1013
  phone_number: string;
995
1014
  section?: string | null | undefined;
996
1015
  }>;
997
- readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
1016
+ readonly configSchema: z.ZodObject<{
1017
+ autoCapture: z.ZodOptional<z.ZodObject<{
1018
+ selector: z.ZodOptional<z.ZodString>;
1019
+ }, "strict", z.ZodTypeAny, {
1020
+ selector?: string | undefined;
1021
+ }, {
1022
+ selector?: string | undefined;
1023
+ }>>;
1024
+ }, "strict", z.ZodTypeAny, {
1025
+ autoCapture?: {
1026
+ selector?: string | undefined;
1027
+ } | undefined;
1028
+ }, {
1029
+ autoCapture?: {
1030
+ selector?: string | undefined;
1031
+ } | undefined;
1032
+ }>;
998
1033
  };
999
1034
  readonly cta_click: {
1000
1035
  readonly kind: "manual";
package/dist/index.js CHANGED
@@ -784,8 +784,8 @@ function thresholdMet(goal, eventType, metadata) {
784
784
  return typeof metadata.page_name === "string" && metadata.page_name === t.page_name;
785
785
  case "page_view":
786
786
  case "form_start":
787
+ case "phone_click":
787
788
  return true;
788
- // no threshold — fire whenever the detector emits
789
789
  default:
790
790
  return false;
791
791
  }
@@ -1406,7 +1406,11 @@ var phoneClickMetadataSchema = import_zod8.z.object({
1406
1406
  }).strict(),
1407
1407
  section: import_zod8.z.string().nullable().optional()
1408
1408
  }).strict();
1409
- var phoneClickConfigSchema = import_zod8.z.object({}).strict();
1409
+ var phoneClickConfigSchema = import_zod8.z.object({
1410
+ autoCapture: import_zod8.z.object({
1411
+ selector: import_zod8.z.string().optional()
1412
+ }).strict().optional()
1413
+ }).strict();
1410
1414
 
1411
1415
  // ../tracking-core/src/events/scroll-depth.ts
1412
1416
  var import_zod9 = require("zod");
@@ -1907,6 +1911,99 @@ function attachCtaClickCapture(client, config) {
1907
1911
  };
1908
1912
  }
1909
1913
 
1914
+ // ../tracking-core/src/phone.ts
1915
+ var import_libphonenumber_js = require("libphonenumber-js");
1916
+ var DEFAULT_PHONE_COUNTRY = "CA";
1917
+ function parsePhone(raw, country) {
1918
+ const region = country ?? DEFAULT_PHONE_COUNTRY;
1919
+ const parsed = (0, import_libphonenumber_js.parsePhoneNumberFromString)(raw ?? "", region);
1920
+ if (!parsed) {
1921
+ return { e164: null, national: "", international: "", country: region, isValid: false };
1922
+ }
1923
+ const isValid = parsed.isValid();
1924
+ return {
1925
+ // E.164 is only surfaced for a *valid* number — a possible-but-invalid input
1926
+ // (e.g. too few digits) still parses but must not be transmitted.
1927
+ e164: isValid ? parsed.number : null,
1928
+ national: parsed.formatNational(),
1929
+ international: parsed.formatInternational(),
1930
+ country: parsed.country ?? region,
1931
+ isValid
1932
+ };
1933
+ }
1934
+ function toE164(raw, country) {
1935
+ return parsePhone(raw, country).e164;
1936
+ }
1937
+ function formatPhone(value, format = "national", country) {
1938
+ const parsed = parsePhone(value, country);
1939
+ if (typeof format === "function") return format(parsed);
1940
+ switch (format) {
1941
+ case "international":
1942
+ return parsed.international || value;
1943
+ case "e164":
1944
+ return parsed.e164 ?? value;
1945
+ case "national":
1946
+ default:
1947
+ return parsed.national || value;
1948
+ }
1949
+ }
1950
+ function formatPhoneAsTyped(raw, country) {
1951
+ return new import_libphonenumber_js.AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
1952
+ }
1953
+
1954
+ // ../tracking-core/src/triggers/phone-click-capture.ts
1955
+ var DEFAULT_TEL_SELECTOR = 'a[href^="tel:"]';
1956
+ function safeDecodeURIComponent(value) {
1957
+ try {
1958
+ return decodeURIComponent(value);
1959
+ } catch {
1960
+ return value;
1961
+ }
1962
+ }
1963
+ function resolvePhoneNumber(el) {
1964
+ const href = el instanceof HTMLAnchorElement ? el.href : el.getAttribute("href") ?? "";
1965
+ const raw = safeDecodeURIComponent(href.replace(/^tel:/i, "").split(";")[0]).trim();
1966
+ return toE164(raw) ?? raw;
1967
+ }
1968
+ function attachPhoneClickCapture(client, config) {
1969
+ if (typeof window === "undefined" || typeof document === "undefined") {
1970
+ return () => {
1971
+ };
1972
+ }
1973
+ const autoCapture = config.autoCapture;
1974
+ if (!autoCapture) {
1975
+ return () => {
1976
+ };
1977
+ }
1978
+ const selector = autoCapture.selector ?? DEFAULT_TEL_SELECTOR;
1979
+ function onClick(event) {
1980
+ const target = event.target;
1981
+ if (!(target instanceof Element)) return;
1982
+ let matched = null;
1983
+ try {
1984
+ matched = target.closest(selector);
1985
+ } catch {
1986
+ return;
1987
+ }
1988
+ if (matched === null) return;
1989
+ const metadata = {
1990
+ phone_number: resolvePhoneNumber(matched),
1991
+ page: { path: window.location.pathname },
1992
+ section: matched.getAttribute("data-aranova-section")
1993
+ };
1994
+ client.trackEvent({
1995
+ eventType: "phone_click",
1996
+ metadata,
1997
+ pageUrl: window.location.href,
1998
+ occurredAt: null
1999
+ });
2000
+ }
2001
+ document.addEventListener("click", onClick, true);
2002
+ return () => {
2003
+ document.removeEventListener("click", onClick, true);
2004
+ };
2005
+ }
2006
+
1910
2007
  // ../tracking-core/src/resources/sales/errors.ts
1911
2008
  var AranovaApiError = class extends Error {
1912
2009
  constructor(message, options) {
@@ -2194,7 +2291,10 @@ var saleCreateSchema = import_zod12.z.object({
2194
2291
  metadata: metadataSchema.nullable().optional(),
2195
2292
  customer_name: customerNameSchema.nullable().optional(),
2196
2293
  customer_phone: customerPhoneSchema.nullable().optional(),
2197
- customer_email: customerEmailSchema.nullable().optional()
2294
+ customer_email: customerEmailSchema.nullable().optional(),
2295
+ // CASL consent attestation: the customer agreed to receive SMS. Recorded
2296
+ // with a timestamp server-side; every SMS send path gates on it.
2297
+ sms_consent: import_zod12.z.boolean().default(false)
2198
2298
  }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: true }));
2199
2299
  var saleUpdateSchema = import_zod12.z.object({
2200
2300
  description: import_zod12.z.string().nullable().optional(),
@@ -2207,7 +2307,9 @@ var saleUpdateSchema = import_zod12.z.object({
2207
2307
  metadata: metadataSchema.nullable().optional(),
2208
2308
  customer_name: customerNameSchema.nullable().optional(),
2209
2309
  customer_phone: customerPhoneSchema.nullable().optional(),
2210
- customer_email: customerEmailSchema.nullable().optional()
2310
+ customer_email: customerEmailSchema.nullable().optional(),
2311
+ // NOT NULL server-side: omit to leave unchanged (explicit null is rejected).
2312
+ sms_consent: import_zod12.z.boolean().optional()
2211
2313
  }).strict().superRefine((val, ctx) => refineServiceXor(val, ctx, { requireAmount: false }));
2212
2314
  var TRACKING_RANGES = ["24h", "7d", "30d"];
2213
2315
  var NAMED_RANGES = [
@@ -2229,46 +2331,6 @@ async function fetchServices(config) {
2229
2331
  return salesRequest(config, "GET", "/services");
2230
2332
  }
2231
2333
 
2232
- // ../tracking-core/src/phone.ts
2233
- var import_libphonenumber_js = require("libphonenumber-js");
2234
- var DEFAULT_PHONE_COUNTRY = "CA";
2235
- function parsePhone(raw, country) {
2236
- const region = country ?? DEFAULT_PHONE_COUNTRY;
2237
- const parsed = (0, import_libphonenumber_js.parsePhoneNumberFromString)(raw ?? "", region);
2238
- if (!parsed) {
2239
- return { e164: null, national: "", international: "", country: region, isValid: false };
2240
- }
2241
- const isValid = parsed.isValid();
2242
- return {
2243
- // E.164 is only surfaced for a *valid* number — a possible-but-invalid input
2244
- // (e.g. too few digits) still parses but must not be transmitted.
2245
- e164: isValid ? parsed.number : null,
2246
- national: parsed.formatNational(),
2247
- international: parsed.formatInternational(),
2248
- country: parsed.country ?? region,
2249
- isValid
2250
- };
2251
- }
2252
- function toE164(raw, country) {
2253
- return parsePhone(raw, country).e164;
2254
- }
2255
- function formatPhone(value, format = "national", country) {
2256
- const parsed = parsePhone(value, country);
2257
- if (typeof format === "function") return format(parsed);
2258
- switch (format) {
2259
- case "international":
2260
- return parsed.international || value;
2261
- case "e164":
2262
- return parsed.e164 ?? value;
2263
- case "national":
2264
- default:
2265
- return parsed.national || value;
2266
- }
2267
- }
2268
- function formatPhoneAsTyped(raw, country) {
2269
- return new import_libphonenumber_js.AsYouType(country ?? DEFAULT_PHONE_COUNTRY).input(raw ?? "");
2270
- }
2271
-
2272
2334
  // ../tracking-core/src/phone-field.ts
2273
2335
  function phoneField(name, raw, country) {
2274
2336
  return { name, type: "phone", value: toE164(raw, country) };
@@ -2605,7 +2667,7 @@ function GoogleAdsTracking(props) {
2605
2667
  var import_navigation = require("next/navigation");
2606
2668
 
2607
2669
  // package.json
2608
- var version = "0.16.2";
2670
+ var version = "0.17.1";
2609
2671
 
2610
2672
  // src/factory.tsx
2611
2673
  var import_react4 = require("react");
@@ -2906,6 +2968,10 @@ function createTracking(options) {
2906
2968
  if (ctaClick) {
2907
2969
  detachers.push(attachCtaClickCapture(detectorClient, ctaClick));
2908
2970
  }
2971
+ const phoneClick = triggers.manual?.phone_click;
2972
+ if (phoneClick) {
2973
+ detachers.push(attachPhoneClickCapture(detectorClient, phoneClick));
2974
+ }
2909
2975
  return () => {
2910
2976
  for (let i = detachers.length - 1; i >= 0; i--) {
2911
2977
  detachers[i]();