@aranova/tracking-react 0.8.0 → 0.9.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 +59 -2
- package/dist/index.d.mts +163 -7
- package/dist/index.d.ts +163 -7
- package/dist/index.js +244 -71
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +243 -72
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -176,13 +176,70 @@ npx @aranova/tracking-cli gen # reads ARANOVA_TRACKING_SECRET_KEY from
|
|
|
176
176
|
See the full guide: [sales-tracking.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/sales-tracking.md)
|
|
177
177
|
and the CLI reference: [cli.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/cli.md).
|
|
178
178
|
|
|
179
|
+
## Consent UI
|
|
180
|
+
|
|
181
|
+
The bundled `<ConsentBanner />` renders a non-blocking bottom-docked banner while consent is `pending`, persists the visitor's choice to `localStorage`, and propagates it to Google Consent Mode v2 when gtag is loaded. **Inline-styled** — no Tailwind or CSS imports required at the consumer.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { ConsentBanner } from '@aranova/tracking-react';
|
|
185
|
+
|
|
186
|
+
// Drop-in, defaults work everywhere
|
|
187
|
+
<ConsentBanner />
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
All props are optional:
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
<ConsentBanner
|
|
194
|
+
title="Cookies"
|
|
195
|
+
message="We use cookies to track ad performance."
|
|
196
|
+
acceptLabel="Sure"
|
|
197
|
+
declineLabel="No thanks"
|
|
198
|
+
policyHref="/privacy"
|
|
199
|
+
policyLabel="Privacy policy" // default: "Learn more"
|
|
200
|
+
onAccept={() => track('consent_accepted')}
|
|
201
|
+
onDecline={() => track('consent_declined')}
|
|
202
|
+
position="bottom" // or "top"
|
|
203
|
+
theme="light" // "light" | "dark" | "auto"
|
|
204
|
+
className="my-extra-classes"
|
|
205
|
+
style={{ background: '#fafafa' }} // wins over the theme defaults
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Fully custom UI — `useConsent()`
|
|
210
|
+
|
|
211
|
+
For a bespoke banner, skip the component and drive your own UI with the headless hook:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { useConsent } from '@aranova/tracking-react';
|
|
215
|
+
|
|
216
|
+
function CookieBar() {
|
|
217
|
+
const { state, accept, decline, reset, isPending } = useConsent();
|
|
218
|
+
|
|
219
|
+
if (!isPending) {
|
|
220
|
+
// Footer link: re-open the banner if they change their mind.
|
|
221
|
+
return <button onClick={reset}>Cookie preferences</button>;
|
|
222
|
+
}
|
|
223
|
+
return (
|
|
224
|
+
<MyBespokeBanner>
|
|
225
|
+
<button onClick={decline}>No thanks</button>
|
|
226
|
+
<button onClick={accept}>Sure</button>
|
|
227
|
+
</MyBespokeBanner>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The hook handles localStorage persistence, gtag sync, and cross-tab propagation — same machinery the default banner uses. `resetConsent()` is also exported as a standalone for non-component contexts.
|
|
233
|
+
|
|
179
234
|
## Exports
|
|
180
235
|
|
|
181
236
|
- `createTracking()`
|
|
182
237
|
- `TrackingProvider` and scoped `useTracking`
|
|
183
238
|
- `GoogleAdsTracking`
|
|
184
|
-
- `ConsentBanner`
|
|
185
|
-
- `
|
|
239
|
+
- `ConsentBanner` + `ConsentBannerProps`
|
|
240
|
+
- Consent hooks: `useConsent()` + `UseConsentResult` (headless); `useConsentState()` (read-only alias)
|
|
241
|
+
- Standalone consent helpers: `getConsentState()`, `setConsentState()`, `resetConsent()`
|
|
242
|
+
- Attribution hooks: `useTrackingParams()`, `useGclid()`
|
|
186
243
|
- `createSalesClient()` (isomorphic sales client — public key writes, secret key reads/CRUD) + money helpers (`toMinor`/`fromMinor`/`formatMoney`)
|
|
187
244
|
- Codegen: [`@aranova/tracking-cli`](https://www.npmjs.com/package/@aranova/tracking-cli) — `gen` typed service unions (devDependency)
|
|
188
245
|
- Event metadata/config types such as `FormSubmitMetadata`, `PhoneClickMetadata`, and `JsonValue`
|
package/dist/index.d.mts
CHANGED
|
@@ -1,15 +1,71 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
3
2
|
import * as src from 'src';
|
|
4
3
|
import { z } from 'zod';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Default non-blocking consent banner.
|
|
8
7
|
*
|
|
9
|
-
* Renders only while consent is `pending
|
|
10
|
-
*
|
|
8
|
+
* Renders only while consent is `pending`; collapses to `null` once the
|
|
9
|
+
* visitor has chosen.
|
|
10
|
+
*
|
|
11
|
+
* **Styling is intentionally self-contained** — inline styles, zero CSS
|
|
12
|
+
* dependencies, no Tailwind required at the consumer. The Tailwind-based
|
|
13
|
+
* banner shipped before 0.9.1 rendered as transparent in any consumer that
|
|
14
|
+
* didn't configure their content array to scan
|
|
15
|
+
* `node_modules/@aranova/tracking-react/dist/**`; this version sidesteps that
|
|
16
|
+
* class of bug entirely.
|
|
17
|
+
*
|
|
18
|
+
* For a fully bespoke banner, skip this component and use {@link useConsent}
|
|
19
|
+
* directly to drive your own UI.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Drop-in default
|
|
23
|
+
* <ConsentBanner />
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Customized
|
|
27
|
+
* <ConsentBanner
|
|
28
|
+
* message="We use cookies to learn which ads drive bookings."
|
|
29
|
+
* acceptLabel="Sounds good"
|
|
30
|
+
* declineLabel="No thanks"
|
|
31
|
+
* policyHref="/privacy"
|
|
32
|
+
* policyLabel="Privacy policy"
|
|
33
|
+
* theme="dark"
|
|
34
|
+
* onAccept={() => track('consent_accepted')}
|
|
35
|
+
* onDecline={() => track('consent_declined')}
|
|
36
|
+
* />
|
|
11
37
|
*/
|
|
12
|
-
|
|
38
|
+
interface ConsentBannerProps {
|
|
39
|
+
/** Body text. Defaults to the standard cookies-for-ad-performance message. */
|
|
40
|
+
message?: ReactNode;
|
|
41
|
+
/** Optional bold title above the body text. */
|
|
42
|
+
title?: ReactNode;
|
|
43
|
+
/** Label for the accept button. Default: `"Accept"`. */
|
|
44
|
+
acceptLabel?: string;
|
|
45
|
+
/** Label for the decline button. Default: `"Decline"`. */
|
|
46
|
+
declineLabel?: string;
|
|
47
|
+
/** Optional link inline with the message (e.g. to a privacy policy). */
|
|
48
|
+
policyHref?: string;
|
|
49
|
+
/** Visible text for {@link policyHref}. Default: `"Learn more"`. */
|
|
50
|
+
policyLabel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Fires after the consent state is persisted + propagated to gtag. Useful
|
|
53
|
+
* for emitting your own analytics event on the choice.
|
|
54
|
+
*/
|
|
55
|
+
onAccept?: () => void;
|
|
56
|
+
onDecline?: () => void;
|
|
57
|
+
/** Where the banner docks. Default: `"bottom"`. */
|
|
58
|
+
position?: 'top' | 'bottom';
|
|
59
|
+
/**
|
|
60
|
+
* Visual theme. `"auto"` follows `prefers-color-scheme`. Default: `"light"`.
|
|
61
|
+
*/
|
|
62
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
63
|
+
/** Class added to the outer wrapper for additional styling hooks. */
|
|
64
|
+
className?: string;
|
|
65
|
+
/** Inline style overrides applied to the outer wrapper after the defaults. */
|
|
66
|
+
style?: CSSProperties;
|
|
67
|
+
}
|
|
68
|
+
declare function ConsentBanner({ message, title, acceptLabel, declineLabel, policyHref, policyLabel, onAccept, onDecline, position, theme, className, style, }?: ConsentBannerProps): ReactNode;
|
|
13
69
|
|
|
14
70
|
/**
|
|
15
71
|
* Visitor consent state stored by the SDK.
|
|
@@ -187,6 +243,22 @@ declare function getConsentState(): ConsentState;
|
|
|
187
243
|
* loaded.
|
|
188
244
|
*/
|
|
189
245
|
declare function setConsentState(state: GtagConsentValue): void;
|
|
246
|
+
/**
|
|
247
|
+
* Clear the stored consent choice so the banner re-appears on next render.
|
|
248
|
+
*
|
|
249
|
+
* Power a "Cookie preferences" link in a footer so visitors can change their
|
|
250
|
+
* mind without losing access to your site:
|
|
251
|
+
*
|
|
252
|
+
* ```tsx
|
|
253
|
+
* const { reset } = useConsent();
|
|
254
|
+
* <button onClick={reset}>Cookie preferences</button>
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* Does NOT push an `update` to gtag — there's nothing to update because the
|
|
258
|
+
* visitor hasn't chosen anything yet. The next `setConsentState()` call will
|
|
259
|
+
* sync gtag once they re-choose.
|
|
260
|
+
*/
|
|
261
|
+
declare function resetConsent(): void;
|
|
190
262
|
|
|
191
263
|
interface TrackingContextInput {
|
|
192
264
|
packageName?: string | null;
|
|
@@ -1464,6 +1536,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1464
1536
|
unit_cost_cents?: number | null | undefined;
|
|
1465
1537
|
}>, "many">>;
|
|
1466
1538
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1539
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1540
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1541
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1467
1542
|
}, "strict", z.ZodTypeAny, {
|
|
1468
1543
|
currency: "USD" | "CAD";
|
|
1469
1544
|
amount_total_cents: number;
|
|
@@ -1481,6 +1556,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1481
1556
|
external_id?: string | null | undefined;
|
|
1482
1557
|
description?: string | null | undefined;
|
|
1483
1558
|
service?: string | null | undefined;
|
|
1559
|
+
customer_name?: string | null | undefined;
|
|
1560
|
+
customer_phone?: string | null | undefined;
|
|
1561
|
+
customer_email?: string | null | undefined;
|
|
1484
1562
|
}, {
|
|
1485
1563
|
currency: "USD" | "CAD";
|
|
1486
1564
|
amount_total_cents: number;
|
|
@@ -1498,6 +1576,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1498
1576
|
category?: string | null | undefined;
|
|
1499
1577
|
unit_cost_cents?: number | null | undefined;
|
|
1500
1578
|
}[] | undefined;
|
|
1579
|
+
customer_name?: string | null | undefined;
|
|
1580
|
+
customer_phone?: string | null | undefined;
|
|
1581
|
+
customer_email?: string | null | undefined;
|
|
1501
1582
|
}>;
|
|
1502
1583
|
declare const saleUpdateSchema: z.ZodObject<{
|
|
1503
1584
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -1528,6 +1609,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1528
1609
|
unit_cost_cents?: number | null | undefined;
|
|
1529
1610
|
}>, "many">>;
|
|
1530
1611
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1612
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1613
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1614
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1531
1615
|
}, "strict", z.ZodTypeAny, {
|
|
1532
1616
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1533
1617
|
description?: string | null | undefined;
|
|
@@ -1543,6 +1627,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1543
1627
|
category?: string | null | undefined;
|
|
1544
1628
|
unit_cost_cents?: number | null | undefined;
|
|
1545
1629
|
}[] | undefined;
|
|
1630
|
+
customer_name?: string | null | undefined;
|
|
1631
|
+
customer_phone?: string | null | undefined;
|
|
1632
|
+
customer_email?: string | null | undefined;
|
|
1546
1633
|
}, {
|
|
1547
1634
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1548
1635
|
description?: string | null | undefined;
|
|
@@ -1558,6 +1645,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1558
1645
|
category?: string | null | undefined;
|
|
1559
1646
|
unit_cost_cents?: number | null | undefined;
|
|
1560
1647
|
}[] | undefined;
|
|
1648
|
+
customer_name?: string | null | undefined;
|
|
1649
|
+
customer_phone?: string | null | undefined;
|
|
1650
|
+
customer_email?: string | null | undefined;
|
|
1561
1651
|
}>;
|
|
1562
1652
|
type SaleItemInput = z.input<typeof saleItemSchema>;
|
|
1563
1653
|
type SaleInput = z.input<typeof saleCreateSchema>;
|
|
@@ -1585,6 +1675,9 @@ interface Sale {
|
|
|
1585
1675
|
occurred_at: string;
|
|
1586
1676
|
environment: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1587
1677
|
metadata: Record<string, unknown> | null;
|
|
1678
|
+
customer_name: string | null;
|
|
1679
|
+
customer_phone: string | null;
|
|
1680
|
+
customer_email: string | null;
|
|
1588
1681
|
created_at: string;
|
|
1589
1682
|
updated_at: string;
|
|
1590
1683
|
items: SaleItem[];
|
|
@@ -1597,13 +1690,38 @@ interface SaleCursorPage {
|
|
|
1597
1690
|
items: Sale[];
|
|
1598
1691
|
next_cursor: string | null;
|
|
1599
1692
|
}
|
|
1600
|
-
|
|
1693
|
+
/**
|
|
1694
|
+
* Comprehensive filter shape mirrored from the backend's `SaleQueryFilters`.
|
|
1695
|
+
*
|
|
1696
|
+
* `search` runs case-insensitively across `customer_name`, `customer_phone`,
|
|
1697
|
+
* `customer_email`, `description`, and `external_id` — the human-facing
|
|
1698
|
+
* columns. `service_id` is the resolved per-business service UUID (different
|
|
1699
|
+
* from the create-time `service` *key*).
|
|
1700
|
+
*/
|
|
1701
|
+
interface SaleFilters {
|
|
1601
1702
|
business_id?: string;
|
|
1602
1703
|
external_id?: string;
|
|
1704
|
+
service_id?: string;
|
|
1603
1705
|
currency?: SupportedCurrency;
|
|
1604
1706
|
environment?: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1605
1707
|
since?: string;
|
|
1606
1708
|
until?: string;
|
|
1709
|
+
min_amount_cents?: number;
|
|
1710
|
+
max_amount_cents?: number;
|
|
1711
|
+
search?: string;
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Full query input for `SalesClient.list()` — filters + pagination.
|
|
1715
|
+
*
|
|
1716
|
+
* Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
|
|
1717
|
+
* passed back as `cursor` on the next. `null` / undefined cursor = first page.
|
|
1718
|
+
*
|
|
1719
|
+
* Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** — the
|
|
1720
|
+
* cursor encodes a position in that index, so a different sort would
|
|
1721
|
+
* invalidate cursors mid-pagination. For ad-hoc sorted reads use the
|
|
1722
|
+
* dashboard admin endpoint, which is offset-paginated.
|
|
1723
|
+
*/
|
|
1724
|
+
interface SaleListQuery extends SaleFilters {
|
|
1607
1725
|
limit?: number;
|
|
1608
1726
|
cursor?: string | null;
|
|
1609
1727
|
}
|
|
@@ -1735,8 +1853,46 @@ declare function useTrackingParams(): TrackingParams;
|
|
|
1735
1853
|
/**
|
|
1736
1854
|
* Read the current visitor consent state and update when another tab changes
|
|
1737
1855
|
* the stored value.
|
|
1856
|
+
*
|
|
1857
|
+
* Prefer {@link useConsent} for new code — it returns the same state plus
|
|
1858
|
+
* the `accept` / `decline` / `reset` actions a custom consent UI needs.
|
|
1859
|
+
* `useConsentState` is kept as a convenience for callers that only need to
|
|
1860
|
+
* read.
|
|
1738
1861
|
*/
|
|
1739
1862
|
declare function useConsentState(): ConsentState;
|
|
1863
|
+
/**
|
|
1864
|
+
* The headless consent surface — state + actions in one hook.
|
|
1865
|
+
*
|
|
1866
|
+
* Build a fully-custom banner without losing the gtag-sync, localStorage
|
|
1867
|
+
* persistence, or cross-tab propagation:
|
|
1868
|
+
*
|
|
1869
|
+
* ```tsx
|
|
1870
|
+
* const { state, accept, decline, reset, isPending } = useConsent();
|
|
1871
|
+
*
|
|
1872
|
+
* if (!isPending) {
|
|
1873
|
+
* return <button onClick={reset}>Cookie preferences</button>;
|
|
1874
|
+
* }
|
|
1875
|
+
* return (
|
|
1876
|
+
* <MyBannerStyling>
|
|
1877
|
+
* <button onClick={decline}>No thanks</button>
|
|
1878
|
+
* <button onClick={accept}>Sure</button>
|
|
1879
|
+
* </MyBannerStyling>
|
|
1880
|
+
* );
|
|
1881
|
+
* ```
|
|
1882
|
+
*
|
|
1883
|
+
* The boolean helpers (`isPending` / `isGranted` / `isDenied`) are equivalent
|
|
1884
|
+
* to comparing `state` directly — they're there for readability at call sites.
|
|
1885
|
+
*/
|
|
1886
|
+
interface UseConsentResult {
|
|
1887
|
+
state: ConsentState;
|
|
1888
|
+
isPending: boolean;
|
|
1889
|
+
isGranted: boolean;
|
|
1890
|
+
isDenied: boolean;
|
|
1891
|
+
accept: () => void;
|
|
1892
|
+
decline: () => void;
|
|
1893
|
+
reset: () => void;
|
|
1894
|
+
}
|
|
1895
|
+
declare function useConsent(): UseConsentResult;
|
|
1740
1896
|
|
|
1741
1897
|
interface CreateTrackingOptions<TRegistry extends TriggerRegistryConfig> {
|
|
1742
1898
|
/**
|
|
@@ -1807,4 +1963,4 @@ interface CreateTrackingResult<TRegistry extends TriggerRegistryConfig> {
|
|
|
1807
1963
|
}
|
|
1808
1964
|
declare function createTracking<TRegistry extends TriggerRegistryConfig>(options: CreateTrackingOptions<TRegistry>): CreateTrackingResult<TRegistry>;
|
|
1809
1965
|
|
|
1810
|
-
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentState, type CreateTrackingOptions, type CreateTrackingResult, type CtaClickConfig, type CtaClickMetadata, type EventConfig, type EventMetadata, type EventName, type FormStartConfig, type FormStartMetadata, type FormSubmitConfig, type FormSubmitMetadata, GoogleAdsTracking, type GoogleAdsTrackingProps, type JsonValue, type ManualEventName, type MultiPageSessionConfig, type MultiPageSessionMetadata, type PageViewConfig, type PageViewMetadata, type PhoneClickConfig, type PhoneClickMetadata, type PublicServiceItem, type RegisteredAutomaticEvents, type RegisteredManualEvents, type Sale, type SaleCursorPage, type SaleInput, type SaleItem, type SaleItemInput, type SaleListPage, type SaleListQuery, type SaleUpdateInput, type SalesClient, type SalesClientConfig, type SalesTransportConfig, type ScrollDepthConfig, type ScrollDepthMetadata, type SpecificPageName, type SpecificPageVisitConfig, type SpecificPageVisitMetadata, type SupportedCurrency, TRACKING_PARAM_KEYS, type TimeOnSiteConfig, type TimeOnSiteMetadata, type TrackingClient, type TrackingClientContext, type TrackingEventCreatePayload, type TrackingInitConfig, type TrackingInstallSurface, type TrackingParams, type TrackingProviderProps, type TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, setConsentState, toMinor, useConsentState, useGclid, useTrackingParams };
|
|
1966
|
+
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentBannerProps, type ConsentState, type CreateTrackingOptions, type CreateTrackingResult, type CtaClickConfig, type CtaClickMetadata, type EventConfig, type EventMetadata, type EventName, type FormStartConfig, type FormStartMetadata, type FormSubmitConfig, type FormSubmitMetadata, GoogleAdsTracking, type GoogleAdsTrackingProps, type JsonValue, type ManualEventName, type MultiPageSessionConfig, type MultiPageSessionMetadata, type PageViewConfig, type PageViewMetadata, type PhoneClickConfig, type PhoneClickMetadata, type PublicServiceItem, type RegisteredAutomaticEvents, type RegisteredManualEvents, type Sale, type SaleCursorPage, type SaleInput, type SaleItem, type SaleItemInput, type SaleListPage, type SaleListQuery, type SaleUpdateInput, type SalesClient, type SalesClientConfig, type SalesTransportConfig, type ScrollDepthConfig, type ScrollDepthMetadata, type SpecificPageName, type SpecificPageVisitConfig, type SpecificPageVisitMetadata, type SupportedCurrency, TRACKING_PARAM_KEYS, type TimeOnSiteConfig, type TimeOnSiteMetadata, type TrackingClient, type TrackingClientContext, type TrackingEventCreatePayload, type TrackingInitConfig, type TrackingInstallSurface, type TrackingParams, type TrackingProviderProps, type TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, type UseConsentResult, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, resetConsent, setConsentState, toMinor, useConsent, useConsentState, useGclid, useTrackingParams };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,71 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
3
2
|
import * as src from 'src';
|
|
4
3
|
import { z } from 'zod';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Default non-blocking consent banner.
|
|
8
7
|
*
|
|
9
|
-
* Renders only while consent is `pending
|
|
10
|
-
*
|
|
8
|
+
* Renders only while consent is `pending`; collapses to `null` once the
|
|
9
|
+
* visitor has chosen.
|
|
10
|
+
*
|
|
11
|
+
* **Styling is intentionally self-contained** — inline styles, zero CSS
|
|
12
|
+
* dependencies, no Tailwind required at the consumer. The Tailwind-based
|
|
13
|
+
* banner shipped before 0.9.1 rendered as transparent in any consumer that
|
|
14
|
+
* didn't configure their content array to scan
|
|
15
|
+
* `node_modules/@aranova/tracking-react/dist/**`; this version sidesteps that
|
|
16
|
+
* class of bug entirely.
|
|
17
|
+
*
|
|
18
|
+
* For a fully bespoke banner, skip this component and use {@link useConsent}
|
|
19
|
+
* directly to drive your own UI.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Drop-in default
|
|
23
|
+
* <ConsentBanner />
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Customized
|
|
27
|
+
* <ConsentBanner
|
|
28
|
+
* message="We use cookies to learn which ads drive bookings."
|
|
29
|
+
* acceptLabel="Sounds good"
|
|
30
|
+
* declineLabel="No thanks"
|
|
31
|
+
* policyHref="/privacy"
|
|
32
|
+
* policyLabel="Privacy policy"
|
|
33
|
+
* theme="dark"
|
|
34
|
+
* onAccept={() => track('consent_accepted')}
|
|
35
|
+
* onDecline={() => track('consent_declined')}
|
|
36
|
+
* />
|
|
11
37
|
*/
|
|
12
|
-
|
|
38
|
+
interface ConsentBannerProps {
|
|
39
|
+
/** Body text. Defaults to the standard cookies-for-ad-performance message. */
|
|
40
|
+
message?: ReactNode;
|
|
41
|
+
/** Optional bold title above the body text. */
|
|
42
|
+
title?: ReactNode;
|
|
43
|
+
/** Label for the accept button. Default: `"Accept"`. */
|
|
44
|
+
acceptLabel?: string;
|
|
45
|
+
/** Label for the decline button. Default: `"Decline"`. */
|
|
46
|
+
declineLabel?: string;
|
|
47
|
+
/** Optional link inline with the message (e.g. to a privacy policy). */
|
|
48
|
+
policyHref?: string;
|
|
49
|
+
/** Visible text for {@link policyHref}. Default: `"Learn more"`. */
|
|
50
|
+
policyLabel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Fires after the consent state is persisted + propagated to gtag. Useful
|
|
53
|
+
* for emitting your own analytics event on the choice.
|
|
54
|
+
*/
|
|
55
|
+
onAccept?: () => void;
|
|
56
|
+
onDecline?: () => void;
|
|
57
|
+
/** Where the banner docks. Default: `"bottom"`. */
|
|
58
|
+
position?: 'top' | 'bottom';
|
|
59
|
+
/**
|
|
60
|
+
* Visual theme. `"auto"` follows `prefers-color-scheme`. Default: `"light"`.
|
|
61
|
+
*/
|
|
62
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
63
|
+
/** Class added to the outer wrapper for additional styling hooks. */
|
|
64
|
+
className?: string;
|
|
65
|
+
/** Inline style overrides applied to the outer wrapper after the defaults. */
|
|
66
|
+
style?: CSSProperties;
|
|
67
|
+
}
|
|
68
|
+
declare function ConsentBanner({ message, title, acceptLabel, declineLabel, policyHref, policyLabel, onAccept, onDecline, position, theme, className, style, }?: ConsentBannerProps): ReactNode;
|
|
13
69
|
|
|
14
70
|
/**
|
|
15
71
|
* Visitor consent state stored by the SDK.
|
|
@@ -187,6 +243,22 @@ declare function getConsentState(): ConsentState;
|
|
|
187
243
|
* loaded.
|
|
188
244
|
*/
|
|
189
245
|
declare function setConsentState(state: GtagConsentValue): void;
|
|
246
|
+
/**
|
|
247
|
+
* Clear the stored consent choice so the banner re-appears on next render.
|
|
248
|
+
*
|
|
249
|
+
* Power a "Cookie preferences" link in a footer so visitors can change their
|
|
250
|
+
* mind without losing access to your site:
|
|
251
|
+
*
|
|
252
|
+
* ```tsx
|
|
253
|
+
* const { reset } = useConsent();
|
|
254
|
+
* <button onClick={reset}>Cookie preferences</button>
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* Does NOT push an `update` to gtag — there's nothing to update because the
|
|
258
|
+
* visitor hasn't chosen anything yet. The next `setConsentState()` call will
|
|
259
|
+
* sync gtag once they re-choose.
|
|
260
|
+
*/
|
|
261
|
+
declare function resetConsent(): void;
|
|
190
262
|
|
|
191
263
|
interface TrackingContextInput {
|
|
192
264
|
packageName?: string | null;
|
|
@@ -1464,6 +1536,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1464
1536
|
unit_cost_cents?: number | null | undefined;
|
|
1465
1537
|
}>, "many">>;
|
|
1466
1538
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1539
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1540
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1541
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1467
1542
|
}, "strict", z.ZodTypeAny, {
|
|
1468
1543
|
currency: "USD" | "CAD";
|
|
1469
1544
|
amount_total_cents: number;
|
|
@@ -1481,6 +1556,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1481
1556
|
external_id?: string | null | undefined;
|
|
1482
1557
|
description?: string | null | undefined;
|
|
1483
1558
|
service?: string | null | undefined;
|
|
1559
|
+
customer_name?: string | null | undefined;
|
|
1560
|
+
customer_phone?: string | null | undefined;
|
|
1561
|
+
customer_email?: string | null | undefined;
|
|
1484
1562
|
}, {
|
|
1485
1563
|
currency: "USD" | "CAD";
|
|
1486
1564
|
amount_total_cents: number;
|
|
@@ -1498,6 +1576,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1498
1576
|
category?: string | null | undefined;
|
|
1499
1577
|
unit_cost_cents?: number | null | undefined;
|
|
1500
1578
|
}[] | undefined;
|
|
1579
|
+
customer_name?: string | null | undefined;
|
|
1580
|
+
customer_phone?: string | null | undefined;
|
|
1581
|
+
customer_email?: string | null | undefined;
|
|
1501
1582
|
}>;
|
|
1502
1583
|
declare const saleUpdateSchema: z.ZodObject<{
|
|
1503
1584
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -1528,6 +1609,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1528
1609
|
unit_cost_cents?: number | null | undefined;
|
|
1529
1610
|
}>, "many">>;
|
|
1530
1611
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1612
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1613
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1614
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1531
1615
|
}, "strict", z.ZodTypeAny, {
|
|
1532
1616
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1533
1617
|
description?: string | null | undefined;
|
|
@@ -1543,6 +1627,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1543
1627
|
category?: string | null | undefined;
|
|
1544
1628
|
unit_cost_cents?: number | null | undefined;
|
|
1545
1629
|
}[] | undefined;
|
|
1630
|
+
customer_name?: string | null | undefined;
|
|
1631
|
+
customer_phone?: string | null | undefined;
|
|
1632
|
+
customer_email?: string | null | undefined;
|
|
1546
1633
|
}, {
|
|
1547
1634
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1548
1635
|
description?: string | null | undefined;
|
|
@@ -1558,6 +1645,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1558
1645
|
category?: string | null | undefined;
|
|
1559
1646
|
unit_cost_cents?: number | null | undefined;
|
|
1560
1647
|
}[] | undefined;
|
|
1648
|
+
customer_name?: string | null | undefined;
|
|
1649
|
+
customer_phone?: string | null | undefined;
|
|
1650
|
+
customer_email?: string | null | undefined;
|
|
1561
1651
|
}>;
|
|
1562
1652
|
type SaleItemInput = z.input<typeof saleItemSchema>;
|
|
1563
1653
|
type SaleInput = z.input<typeof saleCreateSchema>;
|
|
@@ -1585,6 +1675,9 @@ interface Sale {
|
|
|
1585
1675
|
occurred_at: string;
|
|
1586
1676
|
environment: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1587
1677
|
metadata: Record<string, unknown> | null;
|
|
1678
|
+
customer_name: string | null;
|
|
1679
|
+
customer_phone: string | null;
|
|
1680
|
+
customer_email: string | null;
|
|
1588
1681
|
created_at: string;
|
|
1589
1682
|
updated_at: string;
|
|
1590
1683
|
items: SaleItem[];
|
|
@@ -1597,13 +1690,38 @@ interface SaleCursorPage {
|
|
|
1597
1690
|
items: Sale[];
|
|
1598
1691
|
next_cursor: string | null;
|
|
1599
1692
|
}
|
|
1600
|
-
|
|
1693
|
+
/**
|
|
1694
|
+
* Comprehensive filter shape mirrored from the backend's `SaleQueryFilters`.
|
|
1695
|
+
*
|
|
1696
|
+
* `search` runs case-insensitively across `customer_name`, `customer_phone`,
|
|
1697
|
+
* `customer_email`, `description`, and `external_id` — the human-facing
|
|
1698
|
+
* columns. `service_id` is the resolved per-business service UUID (different
|
|
1699
|
+
* from the create-time `service` *key*).
|
|
1700
|
+
*/
|
|
1701
|
+
interface SaleFilters {
|
|
1601
1702
|
business_id?: string;
|
|
1602
1703
|
external_id?: string;
|
|
1704
|
+
service_id?: string;
|
|
1603
1705
|
currency?: SupportedCurrency;
|
|
1604
1706
|
environment?: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1605
1707
|
since?: string;
|
|
1606
1708
|
until?: string;
|
|
1709
|
+
min_amount_cents?: number;
|
|
1710
|
+
max_amount_cents?: number;
|
|
1711
|
+
search?: string;
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Full query input for `SalesClient.list()` — filters + pagination.
|
|
1715
|
+
*
|
|
1716
|
+
* Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
|
|
1717
|
+
* passed back as `cursor` on the next. `null` / undefined cursor = first page.
|
|
1718
|
+
*
|
|
1719
|
+
* Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** — the
|
|
1720
|
+
* cursor encodes a position in that index, so a different sort would
|
|
1721
|
+
* invalidate cursors mid-pagination. For ad-hoc sorted reads use the
|
|
1722
|
+
* dashboard admin endpoint, which is offset-paginated.
|
|
1723
|
+
*/
|
|
1724
|
+
interface SaleListQuery extends SaleFilters {
|
|
1607
1725
|
limit?: number;
|
|
1608
1726
|
cursor?: string | null;
|
|
1609
1727
|
}
|
|
@@ -1735,8 +1853,46 @@ declare function useTrackingParams(): TrackingParams;
|
|
|
1735
1853
|
/**
|
|
1736
1854
|
* Read the current visitor consent state and update when another tab changes
|
|
1737
1855
|
* the stored value.
|
|
1856
|
+
*
|
|
1857
|
+
* Prefer {@link useConsent} for new code — it returns the same state plus
|
|
1858
|
+
* the `accept` / `decline` / `reset` actions a custom consent UI needs.
|
|
1859
|
+
* `useConsentState` is kept as a convenience for callers that only need to
|
|
1860
|
+
* read.
|
|
1738
1861
|
*/
|
|
1739
1862
|
declare function useConsentState(): ConsentState;
|
|
1863
|
+
/**
|
|
1864
|
+
* The headless consent surface — state + actions in one hook.
|
|
1865
|
+
*
|
|
1866
|
+
* Build a fully-custom banner without losing the gtag-sync, localStorage
|
|
1867
|
+
* persistence, or cross-tab propagation:
|
|
1868
|
+
*
|
|
1869
|
+
* ```tsx
|
|
1870
|
+
* const { state, accept, decline, reset, isPending } = useConsent();
|
|
1871
|
+
*
|
|
1872
|
+
* if (!isPending) {
|
|
1873
|
+
* return <button onClick={reset}>Cookie preferences</button>;
|
|
1874
|
+
* }
|
|
1875
|
+
* return (
|
|
1876
|
+
* <MyBannerStyling>
|
|
1877
|
+
* <button onClick={decline}>No thanks</button>
|
|
1878
|
+
* <button onClick={accept}>Sure</button>
|
|
1879
|
+
* </MyBannerStyling>
|
|
1880
|
+
* );
|
|
1881
|
+
* ```
|
|
1882
|
+
*
|
|
1883
|
+
* The boolean helpers (`isPending` / `isGranted` / `isDenied`) are equivalent
|
|
1884
|
+
* to comparing `state` directly — they're there for readability at call sites.
|
|
1885
|
+
*/
|
|
1886
|
+
interface UseConsentResult {
|
|
1887
|
+
state: ConsentState;
|
|
1888
|
+
isPending: boolean;
|
|
1889
|
+
isGranted: boolean;
|
|
1890
|
+
isDenied: boolean;
|
|
1891
|
+
accept: () => void;
|
|
1892
|
+
decline: () => void;
|
|
1893
|
+
reset: () => void;
|
|
1894
|
+
}
|
|
1895
|
+
declare function useConsent(): UseConsentResult;
|
|
1740
1896
|
|
|
1741
1897
|
interface CreateTrackingOptions<TRegistry extends TriggerRegistryConfig> {
|
|
1742
1898
|
/**
|
|
@@ -1807,4 +1963,4 @@ interface CreateTrackingResult<TRegistry extends TriggerRegistryConfig> {
|
|
|
1807
1963
|
}
|
|
1808
1964
|
declare function createTracking<TRegistry extends TriggerRegistryConfig>(options: CreateTrackingOptions<TRegistry>): CreateTrackingResult<TRegistry>;
|
|
1809
1965
|
|
|
1810
|
-
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentState, type CreateTrackingOptions, type CreateTrackingResult, type CtaClickConfig, type CtaClickMetadata, type EventConfig, type EventMetadata, type EventName, type FormStartConfig, type FormStartMetadata, type FormSubmitConfig, type FormSubmitMetadata, GoogleAdsTracking, type GoogleAdsTrackingProps, type JsonValue, type ManualEventName, type MultiPageSessionConfig, type MultiPageSessionMetadata, type PageViewConfig, type PageViewMetadata, type PhoneClickConfig, type PhoneClickMetadata, type PublicServiceItem, type RegisteredAutomaticEvents, type RegisteredManualEvents, type Sale, type SaleCursorPage, type SaleInput, type SaleItem, type SaleItemInput, type SaleListPage, type SaleListQuery, type SaleUpdateInput, type SalesClient, type SalesClientConfig, type SalesTransportConfig, type ScrollDepthConfig, type ScrollDepthMetadata, type SpecificPageName, type SpecificPageVisitConfig, type SpecificPageVisitMetadata, type SupportedCurrency, TRACKING_PARAM_KEYS, type TimeOnSiteConfig, type TimeOnSiteMetadata, type TrackingClient, type TrackingClientContext, type TrackingEventCreatePayload, type TrackingInitConfig, type TrackingInstallSurface, type TrackingParams, type TrackingProviderProps, type TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, setConsentState, toMinor, useConsentState, useGclid, useTrackingParams };
|
|
1966
|
+
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentBannerProps, type ConsentState, type CreateTrackingOptions, type CreateTrackingResult, type CtaClickConfig, type CtaClickMetadata, type EventConfig, type EventMetadata, type EventName, type FormStartConfig, type FormStartMetadata, type FormSubmitConfig, type FormSubmitMetadata, GoogleAdsTracking, type GoogleAdsTrackingProps, type JsonValue, type ManualEventName, type MultiPageSessionConfig, type MultiPageSessionMetadata, type PageViewConfig, type PageViewMetadata, type PhoneClickConfig, type PhoneClickMetadata, type PublicServiceItem, type RegisteredAutomaticEvents, type RegisteredManualEvents, type Sale, type SaleCursorPage, type SaleInput, type SaleItem, type SaleItemInput, type SaleListPage, type SaleListQuery, type SaleUpdateInput, type SalesClient, type SalesClientConfig, type SalesTransportConfig, type ScrollDepthConfig, type ScrollDepthMetadata, type SpecificPageName, type SpecificPageVisitConfig, type SpecificPageVisitMetadata, type SupportedCurrency, TRACKING_PARAM_KEYS, type TimeOnSiteConfig, type TimeOnSiteMetadata, type TrackingClient, type TrackingClientContext, type TrackingEventCreatePayload, type TrackingInitConfig, type TrackingInstallSurface, type TrackingParams, type TrackingProviderProps, type TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, type UseConsentResult, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, resetConsent, setConsentState, toMinor, useConsent, useConsentState, useGclid, useTrackingParams };
|