@aranova/tracking-react 0.24.1 → 0.26.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.
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { a as ConversionConfigStore, c as TrackingConfigRuntime } from './tracking-config-runtime-BnUlS_Ae.js';
2
3
  import { CountryCode } from 'libphonenumber-js';
3
4
 
4
5
  /** Raw identifiers a caller may hand us (normalized before use). */
@@ -11,195 +12,6 @@ declare function stashUserData(data: ConversionUserData, country?: CountryCode):
11
12
  /** Drop everything (consent denial, tests). */
12
13
  declare function clearStashedUserData(): void;
13
14
 
14
- interface ServiceFiring {
15
- send_to: string;
16
- /** Action's configured default value (cents); the SDK fires it only when a sale has no amount. */
17
- value_cents?: number | null;
18
- currency?: string | null;
19
- }
20
- /** Serializable on-page trigger (owned by tracking-core/src/events/trigger-spec.ts). The shape
21
- * varies by `event_type`; only the parameter for that type is set. */
22
- interface ConfigTriggerSpec {
23
- event_type: string;
24
- threshold_percent?: number;
25
- threshold_seconds?: number;
26
- page_threshold?: number;
27
- page_name?: string;
28
- }
29
- /** One unified conversion goal: a revenue `sale` or an on-page `event`. */
30
- interface ConversionGoal {
31
- key: string;
32
- label?: string;
33
- kind: "sale" | "event";
34
- /** Structured fire-when for event-goals; null for sales. */
35
- trigger: ConfigTriggerSpec | null;
36
- firing: ServiceFiring | null;
37
- }
38
- interface ConversionConfig {
39
- schema_version: number;
40
- config_version: number;
41
- business_id?: string;
42
- customer_id?: string | null;
43
- environment?: string;
44
- google_tracking_state: "active" | "disabled";
45
- gtag_ids: Record<string, string>;
46
- meta_pixel_ids: Record<string, string>;
47
- /** LEGACY: sale-goals only (for pre-unified-goal readers). */
48
- services: Array<{
49
- key: string;
50
- label?: string;
51
- firing: ServiceFiring | null;
52
- }>;
53
- /** Unified goal list (sales + on-page events). Superset of `services`. */
54
- goals: ConversionGoal[];
55
- }
56
- interface ConversionConfigStore {
57
- /** Firing config for a goal/service key, or null when it doesn't fire on-site. */
58
- getFiring(key: string): ServiceFiring | null;
59
- /** The full goal for a key, or null when unknown. */
60
- getGoal(key: string): ConversionGoal | null;
61
- /** Every adopted goal (sales + events). */
62
- listGoals(): ConversionGoal[];
63
- /** The currently adopted config (baked / cached fallback until the fetch lands). */
64
- current(): ConversionConfig | null;
65
- /** True once a config is adopted (seeded synchronously from cache/baked, or fetched). */
66
- isReady(): boolean;
67
- /**
68
- * Run `listener` when a config first becomes available — immediately if already
69
- * ready, otherwise on the first adopt. Lets auto-fire replay automatic events that
70
- * occurred before the async CDN fetch resolved. Returns an unsubscribe fn.
71
- */
72
- onResolve(listener: () => void): () => void;
73
- /** Force a background revalidate against the CDN object. */
74
- revalidate(): Promise<void>;
75
- }
76
- interface ResolveConversionConfigOptions {
77
- /** Full URL of the per-business CDN object. */
78
- cdnUrl: string;
79
- /** Offline-correct fallback (e.g. the CLI-baked snapshot). */
80
- baked?: ConversionConfig | null;
81
- /** Injectable for tests / non-global-fetch runtimes. */
82
- fetchImpl?: typeof fetch;
83
- }
84
- /**
85
- * Resolve the config with stale-while-revalidate: seed synchronously from the
86
- * sessionStorage cache (or the baked fallback), then conditionally re-fetch the CDN object
87
- * with `If-None-Match`. A fetched object is adopted only if its `config_version` is strictly
88
- * greater than what's cached, so a reordered edge copy can't downgrade fresher state.
89
- * Non-blocking and browser-only; a failed fetch leaves the seed in place.
90
- */
91
- declare function resolveConversionConfig(options: ResolveConversionConfigOptions): ConversionConfigStore;
92
-
93
- /**
94
- * Where a business's published tracking config lives.
95
- *
96
- * `businessId` + `environment` are the stable identity; the ORIGIN it is fetched
97
- * from is deployment-specific (production CDN vs. a local object store), which is
98
- * why `cdnBaseUrl` exists. Codegen bakes only the identity, so one committed
99
- * generated file works in every environment and only an env var changes.
100
- *
101
- * `cdnUrl` remains supported and WINS when present — every client repo generated
102
- * before `cdnBaseUrl` passes one, and those must keep working untouched.
103
- */
104
- interface TrackingConfigReference {
105
- /**
106
- * Fully-resolved object URL. Optional: omit it and pass `cdnBaseUrl` (or rely
107
- * on the production default) to have it composed from the identity below.
108
- */
109
- cdnUrl?: string;
110
- /**
111
- * Origin (optionally with a path prefix) the config object is served from, e.g.
112
- * `https://demos.aranova.io` in production or
113
- * `http://localhost:9100/aranova-demos` against a local MinIO. Ignored when
114
- * `cdnUrl` is set; blank or omitted falls back to {@link DEFAULT_CDN_BASE_URL}.
115
- * `tracking-cli gen` wires this to an env var so retargeting is config, not code.
116
- */
117
- cdnBaseUrl?: string;
118
- businessId: string;
119
- environment: "production" | "test";
120
- }
121
- /**
122
- * The URL a reference resolves to. An explicit `cdnUrl` wins (back-compat);
123
- * otherwise compose from `cdnBaseUrl` (or the production default).
124
- *
125
- * A blank/whitespace `cdnBaseUrl` is treated as UNSET rather than composed: the
126
- * generated module reads it from an env var, and a var that is present-but-empty
127
- * (a stray `NEXT_PUBLIC_ARANOVA_CDN_BASE_URL=` line) would otherwise produce
128
- * `/tracking-config/...` — a same-origin request to the client's own site.
129
- */
130
- declare function resolveTrackingConfigUrl(ref: TrackingConfigReference): string;
131
- type RuntimeState = "unconfirmed" | "active" | "tombstone";
132
- interface QueuedConversion {
133
- key: string;
134
- value?: number | null;
135
- currency?: string | null;
136
- transactionId?: string | null;
137
- }
138
- type TrackingConfigConversionOptions = Omit<QueuedConversion, "key">;
139
- interface QueuedPageView {
140
- href: string;
141
- title: string | null;
142
- referrer: string | null;
143
- }
144
- declare class TrackingConfigRuntime {
145
- readonly ref: TrackingConfigReference;
146
- private readonly fetchImpl;
147
- /** Resolved config URL — see the constructor for why it is computed once. */
148
- private readonly url;
149
- private current;
150
- private etag;
151
- private stateValue;
152
- private confirmedAt;
153
- private authorityGeneration;
154
- private inFlight;
155
- private flushInFlight;
156
- private flushRequested;
157
- private retryTimer;
158
- private started;
159
- /** Consecutive failed authority attempts — drives the revalidate backoff. */
160
- private authorityFailures;
161
- /** Epoch ms before which `ensureAuthority` must not issue another request. */
162
- private nextAuthorityAttemptAt;
163
- private readonly conversionQueue;
164
- private readonly automaticQueue;
165
- private readonly pageQueue;
166
- private readonly listeners;
167
- constructor(ref: TrackingConfigReference, fetchImpl?: typeof fetch);
168
- /** The URL this runtime actually fetches (composed or explicit). */
169
- configUrl(): string;
170
- /**
171
- * Explicitly start authority resolution and Google-tag bootstrap.
172
- *
173
- * Idempotent so framework effects can call it after hydration without
174
- * depending on constructor timing.
175
- */
176
- start(): void;
177
- state(): RuntimeState;
178
- config(): ConversionConfig | null;
179
- __unsafeExpireAuthorityForTests(): void;
180
- /** Queue depths — asserted by tests to pin the bound. */
181
- __queueDepthsForTests(): {
182
- conversions: number;
183
- automatic: number;
184
- pages: number;
185
- };
186
- subscribe(listener: () => void): () => void;
187
- ensureAuthority(): Promise<boolean>;
188
- revalidate(): Promise<void>;
189
- private revalidateAuthority;
190
- queuePageView(snapshot?: QueuedPageView | null): void;
191
- fireConversion(key: string, options?: TrackingConfigConversionOptions): void;
192
- queueAutomaticEvent(eventType: string, metadata: Record<string, unknown>, transactionPath: string, transactionScope: string): void;
193
- listGoals(): ConversionGoal[];
194
- private revalidateNow;
195
- private expireAuthority;
196
- private confirm;
197
- private flush;
198
- private scheduleRetry;
199
- private flushNow;
200
- }
201
- declare function getTrackingConfigRuntime(ref: TrackingConfigReference, fetchImpl?: typeof fetch): TrackingConfigRuntime;
202
-
203
15
  /**
204
16
  * Sales / Conversions wire schemas — the client-side source of truth.
205
17
  *
@@ -582,6 +394,12 @@ interface Sale {
582
394
  updated_at: string;
583
395
  items: SaleItem[];
584
396
  }
397
+ /**
398
+ * The offset page shape returned by the internal admin list, which this client
399
+ * never calls (`list()` is keyset and returns {@link SaleCursorPage}).
400
+ *
401
+ * @deprecated Unused by this client — no verb returns or accepts it. Kept for one release; removed in the next major.
402
+ */
585
403
  interface SaleListPage {
586
404
  items: Sale[];
587
405
  total: number;
@@ -594,9 +412,10 @@ interface SaleCursorPage {
594
412
  has_more?: boolean;
595
413
  }
596
414
  /**
597
- * Sortable columns on the secret-key (keyset) and admin (offset) list endpoints.
598
- * `business_name` only applies to the cross-business admin list — it sorts the
599
- * joined `businesses.name` column.
415
+ * Sortable columns on the internal admin (offset) list. `list()` is typed to
416
+ * {@link SaleKeysetSortField}, which omits `customer_name` and `business_name`.
417
+ *
418
+ * @deprecated Unused by this client — no verb returns or accepts it. Kept for one release; removed in the next major.
600
419
  */
601
420
  type SaleSortField = "occurred_at" | "created_at" | "amount_total_cents" | "customer_name" | "business_name";
602
421
  type SaleSortOrder = "asc" | "desc";
@@ -628,10 +447,13 @@ interface SaleFilters {
628
447
  * Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
629
448
  * passed back as `cursor` on the next. `null` / undefined cursor = first page.
630
449
  *
631
- * Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** the
632
- * cursor encodes a position in that index, so a different sort would
633
- * invalidate cursors mid-pagination. For ad-hoc sorted reads use the
634
- * dashboard admin endpoint, which is offset-paginated.
450
+ * Ordering is selectable via `sort`/`order` on {@link SaleListQueryV2}. A cursor
451
+ * encodes a position under the sort it was minted with, so replaying it under a
452
+ * different sort is rejected (422) page with the sort you started with.
453
+ */
454
+ /**
455
+ * @deprecated Superseded by {@link SaleListQueryV2}, which is what `list()` accepts.
456
+ * Its ordering note was also stale — `sort`/`order` are supported. Removed in the next major.
635
457
  */
636
458
  interface SaleListQuery extends SaleFilters {
637
459
  limit?: number;
@@ -649,6 +471,10 @@ interface SaleListQueryV2 extends SaleListQuery {
649
471
  declare const TRACKING_RANGES: readonly ["24h", "7d", "30d"];
650
472
  type TrackingOverviewRange = (typeof TRACKING_RANGES)[number];
651
473
  /** Query input for `SalesClient.summary()` — filters + range + options. */
474
+ /**
475
+ * @deprecated The v1 summary query. `summary()` accepts {@link SaleSummaryQueryV2};
476
+ * the v1 endpoint no longer exists. Removed in the next major.
477
+ */
652
478
  interface SaleSummaryQuery extends SaleFilters {
653
479
  range: TrackingOverviewRange;
654
480
  /** Include the per-category line-item breakdown (extra join; default false). */
@@ -688,6 +514,10 @@ interface SalesTrendPoint {
688
514
  sale_count: number;
689
515
  revenue_cents: number;
690
516
  }
517
+ /**
518
+ * @deprecated The v1 summary response. `summary()` returns {@link SaleSummaryV2};
519
+ * the v1 endpoint no longer exists. Removed in the next major.
520
+ */
691
521
  interface SaleSummary {
692
522
  range: TrackingOverviewRange;
693
523
  business_id: string | null;
@@ -860,6 +690,23 @@ interface BusinessConfigFeatures {
860
690
  comparisons: boolean;
861
691
  retention: boolean;
862
692
  }
693
+ /** A built-in customer field a business can require on every sale. */
694
+ type SaleBuiltinRequirableField = "customer_name" | "customer_phone" | "customer_email" | "description";
695
+ /** v1 value types. `enum` is single-select over the property's `options`. */
696
+ type SalePropertyType = "string" | "number" | "boolean" | "enum" | "date";
697
+ interface SalePropertyOption {
698
+ key: string;
699
+ label: string;
700
+ }
701
+ /** One custom sale property as the sale form sees it: overrides applied, options
702
+ * already filtered to the business's enabled subset. */
703
+ interface EffectiveSaleProperty {
704
+ key: string;
705
+ label: string;
706
+ type: SalePropertyType;
707
+ required: boolean;
708
+ options?: SalePropertyOption[] | null;
709
+ }
863
710
  interface BusinessConfig {
864
711
  business_id: string;
865
712
  display_name: string;
@@ -869,6 +716,11 @@ interface BusinessConfig {
869
716
  default_phone_country: string | null;
870
717
  services: BusinessConfigService[];
871
718
  features: BusinessConfigFeatures;
719
+ builtin_required: SaleBuiltinRequirableField[];
720
+ properties: EffectiveSaleProperty[];
721
+ /** Whether the form should pre-tick the SMS consent box. A form default only —
722
+ * the per-sale `sms_consent` attestation is what every send path gates on. */
723
+ sms_consent_default_opt_in: boolean;
872
724
  }
873
725
 
874
726
  /** Shared config for every awaited (non fire-and-forget) API helper. */
@@ -937,10 +789,10 @@ interface SalesClient<TService extends string = string, TConversion extends stri
937
789
  occurred_at?: string;
938
790
  }): Promise<Sale>;
939
791
  /**
940
- * Record a revenue sale — the intent-revealing alias of {@link record} in the unified-goal
941
- * API. POSTs `/sales` and ALSO fires the on-site conversion when the sale-goal is
942
- * WEBPAGE-mapped. Use this for anything with real revenue; use {@link trackConversion} for a
943
- * non-revenue on-page event.
792
+ * Record a revenue sale — the intent-revealing alias of {@link record}. Identical
793
+ * behavior (same function reference): POSTs `/sales` and fires the on-site conversion
794
+ * when the sale-goal is WEBPAGE-mapped. Use either for real revenue; use
795
+ * {@link trackConversion} for a non-revenue on-page event.
944
796
  */
945
797
  recordSale(input: Omit<SaleInput, "currency" | "occurred_at" | "service" | "services"> & {
946
798
  service?: TService | null;
@@ -1046,4 +898,4 @@ interface PublicServiceItem {
1046
898
  */
1047
899
  declare function fetchServices(config: SalesTransportConfig): Promise<PublicServiceItem[]>;
1048
900
 
1049
- export { type SalesClient as $, AranovaApiError as A, type BusinessConfig as B, type ConversionConfig as C, type DistinctCustomersByCurrency as D, type SaleItem as E, type SaleItemInput as F, type Granularity as G, type SaleKeysetSortField as H, type SaleListPage as I, type SaleListQuery as J, type SaleListQueryV2 as K, type SaleService as L, type SaleServiceInput as M, NAMED_RANGES as N, type SaleSortField as O, type PublicServiceItem as P, type SaleSortOrder as Q, type SaleSummary as R, SUPPORTED_CURRENCIES as S, type TrackingConfigReference as T, type SaleSummaryPrevious as U, type SaleSummaryQuery as V, type SaleSummaryQueryV2 as W, type SaleSummaryV2 as X, type SaleUpdateInput as Y, type SalesBusinessClient as Z, type SalesCategoryBreakdown as _, type BusinessConfigFeatures as a, type SalesClientConfig as a0, type SalesCustomersClient as a1, type SalesServiceBreakdown as a2, type SalesTransportConfig as a3, type SalesTrendPoint as a4, type SummaryCurrencyDelta as a5, type SummaryDeltas as a6, type SummaryWindow as a7, type SupportedCurrency as a8, TRACKING_RANGES as a9, type TrackingOverviewRange as aa, clearStashedUserData as ab, createSalesClient as ac, fetchServices as ad, formatDateInTz as ae, formatMoney as af, fromMinor as ag, getTrackingConfigRuntime as ah, resolveConversionConfig as ai, resolveTrackingConfigUrl as aj, saleCreateSchema as ak, saleItemSchema as al, saleServiceSchema as am, saleUpdateSchema as an, salesRequest as ao, stashUserData as ap, toMinor as aq, type BusinessConfigService as b, type CompareTo as c, type ConversionConfigStore as d, type ConversionUserData as e, type CurrencyRevenue as f, type CustomerCurrencyDelta as g, type CustomerCurrencyTotal as h, type CustomerGetOptions as i, type CustomerGetResult as j, type CustomerKpis as k, type CustomerKpisDeltas as l, type CustomerKpisPrevious as m, type CustomerListPage as n, type CustomerListQuery as o, type CustomerProfile as p, type CustomerSegment as q, type CustomerSegmentCount as r, type CustomerSortField as s, type CustomerSummary as t, type CustomerSummaryQuery as u, type NamedRange as v, type Sale as w, type SaleCursorPage as x, type SaleFilters as y, type SaleInput as z };
901
+ export { type SalesCategoryBreakdown as $, AranovaApiError as A, type BusinessConfig as B, type CompareTo as C, type DistinctCustomersByCurrency as D, type EffectiveSaleProperty as E, type SaleItemInput as F, type Granularity as G, type SaleKeysetSortField as H, type SaleListPage as I, type SaleListQuery as J, type SaleListQueryV2 as K, type SalePropertyOption as L, type SalePropertyType as M, NAMED_RANGES as N, type SaleService as O, type PublicServiceItem as P, type SaleServiceInput as Q, type SaleSortField as R, SUPPORTED_CURRENCIES as S, type SaleSortOrder as T, type SaleSummary as U, type SaleSummaryPrevious as V, type SaleSummaryQuery as W, type SaleSummaryQueryV2 as X, type SaleSummaryV2 as Y, type SaleUpdateInput as Z, type SalesBusinessClient as _, type BusinessConfigFeatures as a, type SalesClient as a0, type SalesClientConfig as a1, type SalesCustomersClient as a2, type SalesServiceBreakdown as a3, type SalesTransportConfig as a4, type SalesTrendPoint as a5, type SummaryCurrencyDelta as a6, type SummaryDeltas as a7, type SummaryWindow as a8, type SupportedCurrency as a9, TRACKING_RANGES as aa, type TrackingOverviewRange as ab, clearStashedUserData as ac, createSalesClient as ad, fetchServices as ae, formatDateInTz as af, formatMoney as ag, fromMinor as ah, saleCreateSchema as ai, saleItemSchema as aj, saleServiceSchema as ak, saleUpdateSchema as al, salesRequest as am, stashUserData as an, toMinor as ao, type BusinessConfigService as b, type ConversionUserData as c, type CurrencyRevenue as d, type CustomerCurrencyDelta as e, type CustomerCurrencyTotal as f, type CustomerGetOptions as g, type CustomerGetResult as h, type CustomerKpis as i, type CustomerKpisDeltas as j, type CustomerKpisPrevious as k, type CustomerListPage as l, type CustomerListQuery as m, type CustomerProfile as n, type CustomerSegment as o, type CustomerSegmentCount as p, type CustomerSortField as q, type CustomerSummary as r, type CustomerSummaryQuery as s, type NamedRange as t, type Sale as u, type SaleBuiltinRequirableField as v, type SaleCursorPage as w, type SaleFilters as x, type SaleInput as y, type SaleItem as z };
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { a as ConversionConfigStore, c as TrackingConfigRuntime } from './tracking-config-runtime-BnUlS_Ae.mjs';
2
3
  import { CountryCode } from 'libphonenumber-js';
3
4
 
4
5
  /** Raw identifiers a caller may hand us (normalized before use). */
@@ -11,195 +12,6 @@ declare function stashUserData(data: ConversionUserData, country?: CountryCode):
11
12
  /** Drop everything (consent denial, tests). */
12
13
  declare function clearStashedUserData(): void;
13
14
 
14
- interface ServiceFiring {
15
- send_to: string;
16
- /** Action's configured default value (cents); the SDK fires it only when a sale has no amount. */
17
- value_cents?: number | null;
18
- currency?: string | null;
19
- }
20
- /** Serializable on-page trigger (owned by tracking-core/src/events/trigger-spec.ts). The shape
21
- * varies by `event_type`; only the parameter for that type is set. */
22
- interface ConfigTriggerSpec {
23
- event_type: string;
24
- threshold_percent?: number;
25
- threshold_seconds?: number;
26
- page_threshold?: number;
27
- page_name?: string;
28
- }
29
- /** One unified conversion goal: a revenue `sale` or an on-page `event`. */
30
- interface ConversionGoal {
31
- key: string;
32
- label?: string;
33
- kind: "sale" | "event";
34
- /** Structured fire-when for event-goals; null for sales. */
35
- trigger: ConfigTriggerSpec | null;
36
- firing: ServiceFiring | null;
37
- }
38
- interface ConversionConfig {
39
- schema_version: number;
40
- config_version: number;
41
- business_id?: string;
42
- customer_id?: string | null;
43
- environment?: string;
44
- google_tracking_state: "active" | "disabled";
45
- gtag_ids: Record<string, string>;
46
- meta_pixel_ids: Record<string, string>;
47
- /** LEGACY: sale-goals only (for pre-unified-goal readers). */
48
- services: Array<{
49
- key: string;
50
- label?: string;
51
- firing: ServiceFiring | null;
52
- }>;
53
- /** Unified goal list (sales + on-page events). Superset of `services`. */
54
- goals: ConversionGoal[];
55
- }
56
- interface ConversionConfigStore {
57
- /** Firing config for a goal/service key, or null when it doesn't fire on-site. */
58
- getFiring(key: string): ServiceFiring | null;
59
- /** The full goal for a key, or null when unknown. */
60
- getGoal(key: string): ConversionGoal | null;
61
- /** Every adopted goal (sales + events). */
62
- listGoals(): ConversionGoal[];
63
- /** The currently adopted config (baked / cached fallback until the fetch lands). */
64
- current(): ConversionConfig | null;
65
- /** True once a config is adopted (seeded synchronously from cache/baked, or fetched). */
66
- isReady(): boolean;
67
- /**
68
- * Run `listener` when a config first becomes available — immediately if already
69
- * ready, otherwise on the first adopt. Lets auto-fire replay automatic events that
70
- * occurred before the async CDN fetch resolved. Returns an unsubscribe fn.
71
- */
72
- onResolve(listener: () => void): () => void;
73
- /** Force a background revalidate against the CDN object. */
74
- revalidate(): Promise<void>;
75
- }
76
- interface ResolveConversionConfigOptions {
77
- /** Full URL of the per-business CDN object. */
78
- cdnUrl: string;
79
- /** Offline-correct fallback (e.g. the CLI-baked snapshot). */
80
- baked?: ConversionConfig | null;
81
- /** Injectable for tests / non-global-fetch runtimes. */
82
- fetchImpl?: typeof fetch;
83
- }
84
- /**
85
- * Resolve the config with stale-while-revalidate: seed synchronously from the
86
- * sessionStorage cache (or the baked fallback), then conditionally re-fetch the CDN object
87
- * with `If-None-Match`. A fetched object is adopted only if its `config_version` is strictly
88
- * greater than what's cached, so a reordered edge copy can't downgrade fresher state.
89
- * Non-blocking and browser-only; a failed fetch leaves the seed in place.
90
- */
91
- declare function resolveConversionConfig(options: ResolveConversionConfigOptions): ConversionConfigStore;
92
-
93
- /**
94
- * Where a business's published tracking config lives.
95
- *
96
- * `businessId` + `environment` are the stable identity; the ORIGIN it is fetched
97
- * from is deployment-specific (production CDN vs. a local object store), which is
98
- * why `cdnBaseUrl` exists. Codegen bakes only the identity, so one committed
99
- * generated file works in every environment and only an env var changes.
100
- *
101
- * `cdnUrl` remains supported and WINS when present — every client repo generated
102
- * before `cdnBaseUrl` passes one, and those must keep working untouched.
103
- */
104
- interface TrackingConfigReference {
105
- /**
106
- * Fully-resolved object URL. Optional: omit it and pass `cdnBaseUrl` (or rely
107
- * on the production default) to have it composed from the identity below.
108
- */
109
- cdnUrl?: string;
110
- /**
111
- * Origin (optionally with a path prefix) the config object is served from, e.g.
112
- * `https://demos.aranova.io` in production or
113
- * `http://localhost:9100/aranova-demos` against a local MinIO. Ignored when
114
- * `cdnUrl` is set; blank or omitted falls back to {@link DEFAULT_CDN_BASE_URL}.
115
- * `tracking-cli gen` wires this to an env var so retargeting is config, not code.
116
- */
117
- cdnBaseUrl?: string;
118
- businessId: string;
119
- environment: "production" | "test";
120
- }
121
- /**
122
- * The URL a reference resolves to. An explicit `cdnUrl` wins (back-compat);
123
- * otherwise compose from `cdnBaseUrl` (or the production default).
124
- *
125
- * A blank/whitespace `cdnBaseUrl` is treated as UNSET rather than composed: the
126
- * generated module reads it from an env var, and a var that is present-but-empty
127
- * (a stray `NEXT_PUBLIC_ARANOVA_CDN_BASE_URL=` line) would otherwise produce
128
- * `/tracking-config/...` — a same-origin request to the client's own site.
129
- */
130
- declare function resolveTrackingConfigUrl(ref: TrackingConfigReference): string;
131
- type RuntimeState = "unconfirmed" | "active" | "tombstone";
132
- interface QueuedConversion {
133
- key: string;
134
- value?: number | null;
135
- currency?: string | null;
136
- transactionId?: string | null;
137
- }
138
- type TrackingConfigConversionOptions = Omit<QueuedConversion, "key">;
139
- interface QueuedPageView {
140
- href: string;
141
- title: string | null;
142
- referrer: string | null;
143
- }
144
- declare class TrackingConfigRuntime {
145
- readonly ref: TrackingConfigReference;
146
- private readonly fetchImpl;
147
- /** Resolved config URL — see the constructor for why it is computed once. */
148
- private readonly url;
149
- private current;
150
- private etag;
151
- private stateValue;
152
- private confirmedAt;
153
- private authorityGeneration;
154
- private inFlight;
155
- private flushInFlight;
156
- private flushRequested;
157
- private retryTimer;
158
- private started;
159
- /** Consecutive failed authority attempts — drives the revalidate backoff. */
160
- private authorityFailures;
161
- /** Epoch ms before which `ensureAuthority` must not issue another request. */
162
- private nextAuthorityAttemptAt;
163
- private readonly conversionQueue;
164
- private readonly automaticQueue;
165
- private readonly pageQueue;
166
- private readonly listeners;
167
- constructor(ref: TrackingConfigReference, fetchImpl?: typeof fetch);
168
- /** The URL this runtime actually fetches (composed or explicit). */
169
- configUrl(): string;
170
- /**
171
- * Explicitly start authority resolution and Google-tag bootstrap.
172
- *
173
- * Idempotent so framework effects can call it after hydration without
174
- * depending on constructor timing.
175
- */
176
- start(): void;
177
- state(): RuntimeState;
178
- config(): ConversionConfig | null;
179
- __unsafeExpireAuthorityForTests(): void;
180
- /** Queue depths — asserted by tests to pin the bound. */
181
- __queueDepthsForTests(): {
182
- conversions: number;
183
- automatic: number;
184
- pages: number;
185
- };
186
- subscribe(listener: () => void): () => void;
187
- ensureAuthority(): Promise<boolean>;
188
- revalidate(): Promise<void>;
189
- private revalidateAuthority;
190
- queuePageView(snapshot?: QueuedPageView | null): void;
191
- fireConversion(key: string, options?: TrackingConfigConversionOptions): void;
192
- queueAutomaticEvent(eventType: string, metadata: Record<string, unknown>, transactionPath: string, transactionScope: string): void;
193
- listGoals(): ConversionGoal[];
194
- private revalidateNow;
195
- private expireAuthority;
196
- private confirm;
197
- private flush;
198
- private scheduleRetry;
199
- private flushNow;
200
- }
201
- declare function getTrackingConfigRuntime(ref: TrackingConfigReference, fetchImpl?: typeof fetch): TrackingConfigRuntime;
202
-
203
15
  /**
204
16
  * Sales / Conversions wire schemas — the client-side source of truth.
205
17
  *
@@ -582,6 +394,12 @@ interface Sale {
582
394
  updated_at: string;
583
395
  items: SaleItem[];
584
396
  }
397
+ /**
398
+ * The offset page shape returned by the internal admin list, which this client
399
+ * never calls (`list()` is keyset and returns {@link SaleCursorPage}).
400
+ *
401
+ * @deprecated Unused by this client — no verb returns or accepts it. Kept for one release; removed in the next major.
402
+ */
585
403
  interface SaleListPage {
586
404
  items: Sale[];
587
405
  total: number;
@@ -594,9 +412,10 @@ interface SaleCursorPage {
594
412
  has_more?: boolean;
595
413
  }
596
414
  /**
597
- * Sortable columns on the secret-key (keyset) and admin (offset) list endpoints.
598
- * `business_name` only applies to the cross-business admin list — it sorts the
599
- * joined `businesses.name` column.
415
+ * Sortable columns on the internal admin (offset) list. `list()` is typed to
416
+ * {@link SaleKeysetSortField}, which omits `customer_name` and `business_name`.
417
+ *
418
+ * @deprecated Unused by this client — no verb returns or accepts it. Kept for one release; removed in the next major.
600
419
  */
601
420
  type SaleSortField = "occurred_at" | "created_at" | "amount_total_cents" | "customer_name" | "business_name";
602
421
  type SaleSortOrder = "asc" | "desc";
@@ -628,10 +447,13 @@ interface SaleFilters {
628
447
  * Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
629
448
  * passed back as `cursor` on the next. `null` / undefined cursor = first page.
630
449
  *
631
- * Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** the
632
- * cursor encodes a position in that index, so a different sort would
633
- * invalidate cursors mid-pagination. For ad-hoc sorted reads use the
634
- * dashboard admin endpoint, which is offset-paginated.
450
+ * Ordering is selectable via `sort`/`order` on {@link SaleListQueryV2}. A cursor
451
+ * encodes a position under the sort it was minted with, so replaying it under a
452
+ * different sort is rejected (422) page with the sort you started with.
453
+ */
454
+ /**
455
+ * @deprecated Superseded by {@link SaleListQueryV2}, which is what `list()` accepts.
456
+ * Its ordering note was also stale — `sort`/`order` are supported. Removed in the next major.
635
457
  */
636
458
  interface SaleListQuery extends SaleFilters {
637
459
  limit?: number;
@@ -649,6 +471,10 @@ interface SaleListQueryV2 extends SaleListQuery {
649
471
  declare const TRACKING_RANGES: readonly ["24h", "7d", "30d"];
650
472
  type TrackingOverviewRange = (typeof TRACKING_RANGES)[number];
651
473
  /** Query input for `SalesClient.summary()` — filters + range + options. */
474
+ /**
475
+ * @deprecated The v1 summary query. `summary()` accepts {@link SaleSummaryQueryV2};
476
+ * the v1 endpoint no longer exists. Removed in the next major.
477
+ */
652
478
  interface SaleSummaryQuery extends SaleFilters {
653
479
  range: TrackingOverviewRange;
654
480
  /** Include the per-category line-item breakdown (extra join; default false). */
@@ -688,6 +514,10 @@ interface SalesTrendPoint {
688
514
  sale_count: number;
689
515
  revenue_cents: number;
690
516
  }
517
+ /**
518
+ * @deprecated The v1 summary response. `summary()` returns {@link SaleSummaryV2};
519
+ * the v1 endpoint no longer exists. Removed in the next major.
520
+ */
691
521
  interface SaleSummary {
692
522
  range: TrackingOverviewRange;
693
523
  business_id: string | null;
@@ -860,6 +690,23 @@ interface BusinessConfigFeatures {
860
690
  comparisons: boolean;
861
691
  retention: boolean;
862
692
  }
693
+ /** A built-in customer field a business can require on every sale. */
694
+ type SaleBuiltinRequirableField = "customer_name" | "customer_phone" | "customer_email" | "description";
695
+ /** v1 value types. `enum` is single-select over the property's `options`. */
696
+ type SalePropertyType = "string" | "number" | "boolean" | "enum" | "date";
697
+ interface SalePropertyOption {
698
+ key: string;
699
+ label: string;
700
+ }
701
+ /** One custom sale property as the sale form sees it: overrides applied, options
702
+ * already filtered to the business's enabled subset. */
703
+ interface EffectiveSaleProperty {
704
+ key: string;
705
+ label: string;
706
+ type: SalePropertyType;
707
+ required: boolean;
708
+ options?: SalePropertyOption[] | null;
709
+ }
863
710
  interface BusinessConfig {
864
711
  business_id: string;
865
712
  display_name: string;
@@ -869,6 +716,11 @@ interface BusinessConfig {
869
716
  default_phone_country: string | null;
870
717
  services: BusinessConfigService[];
871
718
  features: BusinessConfigFeatures;
719
+ builtin_required: SaleBuiltinRequirableField[];
720
+ properties: EffectiveSaleProperty[];
721
+ /** Whether the form should pre-tick the SMS consent box. A form default only —
722
+ * the per-sale `sms_consent` attestation is what every send path gates on. */
723
+ sms_consent_default_opt_in: boolean;
872
724
  }
873
725
 
874
726
  /** Shared config for every awaited (non fire-and-forget) API helper. */
@@ -937,10 +789,10 @@ interface SalesClient<TService extends string = string, TConversion extends stri
937
789
  occurred_at?: string;
938
790
  }): Promise<Sale>;
939
791
  /**
940
- * Record a revenue sale — the intent-revealing alias of {@link record} in the unified-goal
941
- * API. POSTs `/sales` and ALSO fires the on-site conversion when the sale-goal is
942
- * WEBPAGE-mapped. Use this for anything with real revenue; use {@link trackConversion} for a
943
- * non-revenue on-page event.
792
+ * Record a revenue sale — the intent-revealing alias of {@link record}. Identical
793
+ * behavior (same function reference): POSTs `/sales` and fires the on-site conversion
794
+ * when the sale-goal is WEBPAGE-mapped. Use either for real revenue; use
795
+ * {@link trackConversion} for a non-revenue on-page event.
944
796
  */
945
797
  recordSale(input: Omit<SaleInput, "currency" | "occurred_at" | "service" | "services"> & {
946
798
  service?: TService | null;
@@ -1046,4 +898,4 @@ interface PublicServiceItem {
1046
898
  */
1047
899
  declare function fetchServices(config: SalesTransportConfig): Promise<PublicServiceItem[]>;
1048
900
 
1049
- export { type SalesClient as $, AranovaApiError as A, type BusinessConfig as B, type ConversionConfig as C, type DistinctCustomersByCurrency as D, type SaleItem as E, type SaleItemInput as F, type Granularity as G, type SaleKeysetSortField as H, type SaleListPage as I, type SaleListQuery as J, type SaleListQueryV2 as K, type SaleService as L, type SaleServiceInput as M, NAMED_RANGES as N, type SaleSortField as O, type PublicServiceItem as P, type SaleSortOrder as Q, type SaleSummary as R, SUPPORTED_CURRENCIES as S, type TrackingConfigReference as T, type SaleSummaryPrevious as U, type SaleSummaryQuery as V, type SaleSummaryQueryV2 as W, type SaleSummaryV2 as X, type SaleUpdateInput as Y, type SalesBusinessClient as Z, type SalesCategoryBreakdown as _, type BusinessConfigFeatures as a, type SalesClientConfig as a0, type SalesCustomersClient as a1, type SalesServiceBreakdown as a2, type SalesTransportConfig as a3, type SalesTrendPoint as a4, type SummaryCurrencyDelta as a5, type SummaryDeltas as a6, type SummaryWindow as a7, type SupportedCurrency as a8, TRACKING_RANGES as a9, type TrackingOverviewRange as aa, clearStashedUserData as ab, createSalesClient as ac, fetchServices as ad, formatDateInTz as ae, formatMoney as af, fromMinor as ag, getTrackingConfigRuntime as ah, resolveConversionConfig as ai, resolveTrackingConfigUrl as aj, saleCreateSchema as ak, saleItemSchema as al, saleServiceSchema as am, saleUpdateSchema as an, salesRequest as ao, stashUserData as ap, toMinor as aq, type BusinessConfigService as b, type CompareTo as c, type ConversionConfigStore as d, type ConversionUserData as e, type CurrencyRevenue as f, type CustomerCurrencyDelta as g, type CustomerCurrencyTotal as h, type CustomerGetOptions as i, type CustomerGetResult as j, type CustomerKpis as k, type CustomerKpisDeltas as l, type CustomerKpisPrevious as m, type CustomerListPage as n, type CustomerListQuery as o, type CustomerProfile as p, type CustomerSegment as q, type CustomerSegmentCount as r, type CustomerSortField as s, type CustomerSummary as t, type CustomerSummaryQuery as u, type NamedRange as v, type Sale as w, type SaleCursorPage as x, type SaleFilters as y, type SaleInput as z };
901
+ export { type SalesCategoryBreakdown as $, AranovaApiError as A, type BusinessConfig as B, type CompareTo as C, type DistinctCustomersByCurrency as D, type EffectiveSaleProperty as E, type SaleItemInput as F, type Granularity as G, type SaleKeysetSortField as H, type SaleListPage as I, type SaleListQuery as J, type SaleListQueryV2 as K, type SalePropertyOption as L, type SalePropertyType as M, NAMED_RANGES as N, type SaleService as O, type PublicServiceItem as P, type SaleServiceInput as Q, type SaleSortField as R, SUPPORTED_CURRENCIES as S, type SaleSortOrder as T, type SaleSummary as U, type SaleSummaryPrevious as V, type SaleSummaryQuery as W, type SaleSummaryQueryV2 as X, type SaleSummaryV2 as Y, type SaleUpdateInput as Z, type SalesBusinessClient as _, type BusinessConfigFeatures as a, type SalesClient as a0, type SalesClientConfig as a1, type SalesCustomersClient as a2, type SalesServiceBreakdown as a3, type SalesTransportConfig as a4, type SalesTrendPoint as a5, type SummaryCurrencyDelta as a6, type SummaryDeltas as a7, type SummaryWindow as a8, type SupportedCurrency as a9, TRACKING_RANGES as aa, type TrackingOverviewRange as ab, clearStashedUserData as ac, createSalesClient as ad, fetchServices as ae, formatDateInTz as af, formatMoney as ag, fromMinor as ah, saleCreateSchema as ai, saleItemSchema as aj, saleServiceSchema as ak, saleUpdateSchema as al, salesRequest as am, stashUserData as an, toMinor as ao, type BusinessConfigService as b, type ConversionUserData as c, type CurrencyRevenue as d, type CustomerCurrencyDelta as e, type CustomerCurrencyTotal as f, type CustomerGetOptions as g, type CustomerGetResult as h, type CustomerKpis as i, type CustomerKpisDeltas as j, type CustomerKpisPrevious as k, type CustomerListPage as l, type CustomerListQuery as m, type CustomerProfile as n, type CustomerSegment as o, type CustomerSegmentCount as p, type CustomerSortField as q, type CustomerSummary as r, type CustomerSummaryQuery as s, type NamedRange as t, type Sale as u, type SaleBuiltinRequirableField as v, type SaleCursorPage as w, type SaleFilters as x, type SaleInput as y, type SaleItem as z };