@aranova/tracking-next 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 +57 -1
- package/dist/index.d.mts +164 -7
- package/dist/index.d.ts +164 -7
- package/dist/index.js +231 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +231 -60
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,9 +216,65 @@ npx @aranova/tracking-cli gen # reads ARANOVA_TRACKING_SECRET_KEY from
|
|
|
216
216
|
See the full guide: [sales-tracking.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/sales-tracking.md)
|
|
217
217
|
and the CLI reference: [cli.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/cli.md).
|
|
218
218
|
|
|
219
|
+
## Consent UI
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
import { ConsentBanner } from '@aranova/tracking-next';
|
|
225
|
+
|
|
226
|
+
// Drop-in (already wired in the root layout example above)
|
|
227
|
+
<ConsentBanner />
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
All props are optional:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
<ConsentBanner
|
|
234
|
+
title="Cookies"
|
|
235
|
+
message="We use cookies to track ad performance."
|
|
236
|
+
acceptLabel="Sure"
|
|
237
|
+
declineLabel="No thanks"
|
|
238
|
+
policyHref="/privacy"
|
|
239
|
+
policyLabel="Privacy policy" // default: "Learn more"
|
|
240
|
+
onAccept={() => track('consent_accepted')}
|
|
241
|
+
onDecline={() => track('consent_declined')}
|
|
242
|
+
position="bottom" // or "top"
|
|
243
|
+
theme="light" // "light" | "dark" | "auto"
|
|
244
|
+
className="my-extra-classes"
|
|
245
|
+
style={{ background: '#fafafa' }} // wins over the theme defaults
|
|
246
|
+
/>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Fully custom UI — `useConsent()`
|
|
250
|
+
|
|
251
|
+
For a bespoke banner, skip the component and drive your own UI with the headless hook:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
'use client';
|
|
255
|
+
import { useConsent } from '@aranova/tracking-next';
|
|
256
|
+
|
|
257
|
+
function CookieBar() {
|
|
258
|
+
const { state, accept, decline, reset, isPending } = useConsent();
|
|
259
|
+
|
|
260
|
+
if (!isPending) {
|
|
261
|
+
// Footer link: re-open the banner if they change their mind.
|
|
262
|
+
return <button onClick={reset}>Cookie preferences</button>;
|
|
263
|
+
}
|
|
264
|
+
return (
|
|
265
|
+
<MyBespokeBanner>
|
|
266
|
+
<button onClick={decline}>No thanks</button>
|
|
267
|
+
<button onClick={accept}>Sure</button>
|
|
268
|
+
</MyBespokeBanner>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
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 (server actions that revalidate after an account change, etc.).
|
|
274
|
+
|
|
219
275
|
## Exports
|
|
220
276
|
|
|
221
|
-
- Root package: `createTracking`, `TrackingProvider`, `useTracking`, `GoogleAdsTracking`, `ConsentBanner`,
|
|
277
|
+
- Root package: `createTracking`, `TrackingProvider`, `useTracking`, `GoogleAdsTracking`, `ConsentBanner` (+ `ConsentBannerProps`), `useConsent` (+ `UseConsentResult`), `useConsentState`, `useGclid`, `useTrackingParams`, standalone consent helpers (`getConsentState`, `setConsentState`, `resetConsent`), event types, and `createSalesClient()` (isomorphic sales client — public key writes, secret key reads/CRUD) + money helpers (`toMinor`/`fromMinor`/`formatMoney`)
|
|
222
278
|
- `@aranova/tracking-next/middleware`: `createTrackingMiddleware()`
|
|
223
279
|
- `@aranova/tracking-next/server`: `getTrackingParamsServer()`
|
|
224
280
|
- Codegen: [`@aranova/tracking-cli`](https://www.npmjs.com/package/@aranova/tracking-cli) — `gen` typed service unions (devDependency)
|
package/dist/index.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ import { C as ConsentState, T as TrackingInstallSurface, a as TrackingEnvironmen
|
|
|
2
2
|
export { f as TrackingInitConfig } from './types-BPJLgMsG.mjs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import * as src from 'src';
|
|
5
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
5
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
-
import { ReactNode } from 'react';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Google Consent Mode value sent to `gtag('consent', 'update', ...)`.
|
|
@@ -21,6 +21,22 @@ declare function getConsentState(): ConsentState;
|
|
|
21
21
|
* loaded.
|
|
22
22
|
*/
|
|
23
23
|
declare function setConsentState(state: GtagConsentValue): void;
|
|
24
|
+
/**
|
|
25
|
+
* Clear the stored consent choice so the banner re-appears on next render.
|
|
26
|
+
*
|
|
27
|
+
* Power a "Cookie preferences" link in a footer so visitors can change their
|
|
28
|
+
* mind without losing access to your site:
|
|
29
|
+
*
|
|
30
|
+
* ```tsx
|
|
31
|
+
* const { reset } = useConsent();
|
|
32
|
+
* <button onClick={reset}>Cookie preferences</button>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Does NOT push an `update` to gtag — there's nothing to update because the
|
|
36
|
+
* visitor hasn't chosen anything yet. The next `setConsentState()` call will
|
|
37
|
+
* sync gtag once they re-choose.
|
|
38
|
+
*/
|
|
39
|
+
declare function resetConsent(): void;
|
|
24
40
|
|
|
25
41
|
interface TrackingContextInput {
|
|
26
42
|
packageName?: string | null;
|
|
@@ -1298,6 +1314,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1298
1314
|
unit_cost_cents?: number | null | undefined;
|
|
1299
1315
|
}>, "many">>;
|
|
1300
1316
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1317
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1318
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1319
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1301
1320
|
}, "strict", z.ZodTypeAny, {
|
|
1302
1321
|
currency: "USD" | "CAD";
|
|
1303
1322
|
amount_total_cents: number;
|
|
@@ -1315,6 +1334,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1315
1334
|
external_id?: string | null | undefined;
|
|
1316
1335
|
description?: string | null | undefined;
|
|
1317
1336
|
service?: string | null | undefined;
|
|
1337
|
+
customer_name?: string | null | undefined;
|
|
1338
|
+
customer_phone?: string | null | undefined;
|
|
1339
|
+
customer_email?: string | null | undefined;
|
|
1318
1340
|
}, {
|
|
1319
1341
|
currency: "USD" | "CAD";
|
|
1320
1342
|
amount_total_cents: number;
|
|
@@ -1332,6 +1354,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1332
1354
|
category?: string | null | undefined;
|
|
1333
1355
|
unit_cost_cents?: number | null | undefined;
|
|
1334
1356
|
}[] | undefined;
|
|
1357
|
+
customer_name?: string | null | undefined;
|
|
1358
|
+
customer_phone?: string | null | undefined;
|
|
1359
|
+
customer_email?: string | null | undefined;
|
|
1335
1360
|
}>;
|
|
1336
1361
|
declare const saleUpdateSchema: z.ZodObject<{
|
|
1337
1362
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -1362,6 +1387,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1362
1387
|
unit_cost_cents?: number | null | undefined;
|
|
1363
1388
|
}>, "many">>;
|
|
1364
1389
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1390
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1391
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1392
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1365
1393
|
}, "strict", z.ZodTypeAny, {
|
|
1366
1394
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1367
1395
|
description?: string | null | undefined;
|
|
@@ -1377,6 +1405,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1377
1405
|
category?: string | null | undefined;
|
|
1378
1406
|
unit_cost_cents?: number | null | undefined;
|
|
1379
1407
|
}[] | undefined;
|
|
1408
|
+
customer_name?: string | null | undefined;
|
|
1409
|
+
customer_phone?: string | null | undefined;
|
|
1410
|
+
customer_email?: string | null | undefined;
|
|
1380
1411
|
}, {
|
|
1381
1412
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1382
1413
|
description?: string | null | undefined;
|
|
@@ -1392,6 +1423,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1392
1423
|
category?: string | null | undefined;
|
|
1393
1424
|
unit_cost_cents?: number | null | undefined;
|
|
1394
1425
|
}[] | undefined;
|
|
1426
|
+
customer_name?: string | null | undefined;
|
|
1427
|
+
customer_phone?: string | null | undefined;
|
|
1428
|
+
customer_email?: string | null | undefined;
|
|
1395
1429
|
}>;
|
|
1396
1430
|
type SaleItemInput = z.input<typeof saleItemSchema>;
|
|
1397
1431
|
type SaleInput = z.input<typeof saleCreateSchema>;
|
|
@@ -1419,6 +1453,9 @@ interface Sale {
|
|
|
1419
1453
|
occurred_at: string;
|
|
1420
1454
|
environment: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1421
1455
|
metadata: Record<string, unknown> | null;
|
|
1456
|
+
customer_name: string | null;
|
|
1457
|
+
customer_phone: string | null;
|
|
1458
|
+
customer_email: string | null;
|
|
1422
1459
|
created_at: string;
|
|
1423
1460
|
updated_at: string;
|
|
1424
1461
|
items: SaleItem[];
|
|
@@ -1431,13 +1468,38 @@ interface SaleCursorPage {
|
|
|
1431
1468
|
items: Sale[];
|
|
1432
1469
|
next_cursor: string | null;
|
|
1433
1470
|
}
|
|
1434
|
-
|
|
1471
|
+
/**
|
|
1472
|
+
* Comprehensive filter shape mirrored from the backend's `SaleQueryFilters`.
|
|
1473
|
+
*
|
|
1474
|
+
* `search` runs case-insensitively across `customer_name`, `customer_phone`,
|
|
1475
|
+
* `customer_email`, `description`, and `external_id` — the human-facing
|
|
1476
|
+
* columns. `service_id` is the resolved per-business service UUID (different
|
|
1477
|
+
* from the create-time `service` *key*).
|
|
1478
|
+
*/
|
|
1479
|
+
interface SaleFilters {
|
|
1435
1480
|
business_id?: string;
|
|
1436
1481
|
external_id?: string;
|
|
1482
|
+
service_id?: string;
|
|
1437
1483
|
currency?: SupportedCurrency;
|
|
1438
1484
|
environment?: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1439
1485
|
since?: string;
|
|
1440
1486
|
until?: string;
|
|
1487
|
+
min_amount_cents?: number;
|
|
1488
|
+
max_amount_cents?: number;
|
|
1489
|
+
search?: string;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Full query input for `SalesClient.list()` — filters + pagination.
|
|
1493
|
+
*
|
|
1494
|
+
* Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
|
|
1495
|
+
* passed back as `cursor` on the next. `null` / undefined cursor = first page.
|
|
1496
|
+
*
|
|
1497
|
+
* Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** — the
|
|
1498
|
+
* cursor encodes a position in that index, so a different sort would
|
|
1499
|
+
* invalidate cursors mid-pagination. For ad-hoc sorted reads use the
|
|
1500
|
+
* dashboard admin endpoint, which is offset-paginated.
|
|
1501
|
+
*/
|
|
1502
|
+
interface SaleListQuery extends SaleFilters {
|
|
1441
1503
|
limit?: number;
|
|
1442
1504
|
cursor?: string | null;
|
|
1443
1505
|
}
|
|
@@ -1534,12 +1596,69 @@ declare class AranovaApiError extends Error {
|
|
|
1534
1596
|
}
|
|
1535
1597
|
|
|
1536
1598
|
/**
|
|
1537
|
-
* Default non-blocking consent banner
|
|
1599
|
+
* Default non-blocking consent banner.
|
|
1600
|
+
*
|
|
1601
|
+
* Renders only while consent is `pending`; collapses to `null` once the
|
|
1602
|
+
* visitor has chosen.
|
|
1603
|
+
*
|
|
1604
|
+
* **Styling is intentionally self-contained** — inline styles, zero CSS
|
|
1605
|
+
* dependencies, no Tailwind required at the consumer. The Tailwind-based
|
|
1606
|
+
* banner shipped before 0.9.1 rendered as transparent in any consumer that
|
|
1607
|
+
* didn't configure their content array to scan
|
|
1608
|
+
* `node_modules/@aranova/tracking-next/dist/**`; this version sidesteps that
|
|
1609
|
+
* class of bug entirely.
|
|
1610
|
+
*
|
|
1611
|
+
* For a fully bespoke banner, skip this component and use {@link useConsent}
|
|
1612
|
+
* directly to drive your own UI.
|
|
1538
1613
|
*
|
|
1539
|
-
*
|
|
1540
|
-
* in
|
|
1614
|
+
* @example
|
|
1615
|
+
* // Drop-in default
|
|
1616
|
+
* <ConsentBanner />
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* // Customized
|
|
1620
|
+
* <ConsentBanner
|
|
1621
|
+
* message="We use cookies to learn which ads drive bookings."
|
|
1622
|
+
* acceptLabel="Sounds good"
|
|
1623
|
+
* declineLabel="No thanks"
|
|
1624
|
+
* policyHref="/privacy"
|
|
1625
|
+
* policyLabel="Privacy policy"
|
|
1626
|
+
* theme="dark"
|
|
1627
|
+
* onAccept={() => track('consent_accepted')}
|
|
1628
|
+
* onDecline={() => track('consent_declined')}
|
|
1629
|
+
* />
|
|
1541
1630
|
*/
|
|
1542
|
-
|
|
1631
|
+
interface ConsentBannerProps {
|
|
1632
|
+
/** Body text. Defaults to the standard cookies-for-ad-performance message. */
|
|
1633
|
+
message?: ReactNode;
|
|
1634
|
+
/** Optional bold title above the body text. */
|
|
1635
|
+
title?: ReactNode;
|
|
1636
|
+
/** Label for the accept button. Default: `"Accept"`. */
|
|
1637
|
+
acceptLabel?: string;
|
|
1638
|
+
/** Label for the decline button. Default: `"Decline"`. */
|
|
1639
|
+
declineLabel?: string;
|
|
1640
|
+
/** Optional link inline with the message (e.g. to a privacy policy). */
|
|
1641
|
+
policyHref?: string;
|
|
1642
|
+
/** Visible text for {@link policyHref}. Default: `"Learn more"`. */
|
|
1643
|
+
policyLabel?: string;
|
|
1644
|
+
/**
|
|
1645
|
+
* Fires after the consent state is persisted + propagated to gtag. Useful
|
|
1646
|
+
* for emitting your own analytics event on the choice.
|
|
1647
|
+
*/
|
|
1648
|
+
onAccept?: () => void;
|
|
1649
|
+
onDecline?: () => void;
|
|
1650
|
+
/** Where the banner docks. Default: `"bottom"`. */
|
|
1651
|
+
position?: 'top' | 'bottom';
|
|
1652
|
+
/**
|
|
1653
|
+
* Visual theme. `"auto"` follows `prefers-color-scheme`. Default: `"light"`.
|
|
1654
|
+
*/
|
|
1655
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
1656
|
+
/** Class added to the outer wrapper for additional styling hooks. */
|
|
1657
|
+
className?: string;
|
|
1658
|
+
/** Inline style overrides applied to the outer wrapper after the defaults. */
|
|
1659
|
+
style?: CSSProperties;
|
|
1660
|
+
}
|
|
1661
|
+
declare function ConsentBanner({ message, title, acceptLabel, declineLabel, policyHref, policyLabel, onAccept, onDecline, position, theme, className, style, }?: ConsentBannerProps): ReactNode;
|
|
1543
1662
|
|
|
1544
1663
|
/**
|
|
1545
1664
|
* Read the captured Google Ads click id from first-party cookies.
|
|
@@ -1556,8 +1675,46 @@ declare function useTrackingParams(): TrackingParams;
|
|
|
1556
1675
|
/**
|
|
1557
1676
|
* Read the current visitor consent state and update when another tab changes
|
|
1558
1677
|
* the stored value.
|
|
1678
|
+
*
|
|
1679
|
+
* Prefer {@link useConsent} for new code — it returns the same state plus
|
|
1680
|
+
* the `accept` / `decline` / `reset` actions a custom consent UI needs.
|
|
1681
|
+
* `useConsentState` is kept as a convenience for callers that only need to
|
|
1682
|
+
* read.
|
|
1559
1683
|
*/
|
|
1560
1684
|
declare function useConsentState(): ConsentState;
|
|
1685
|
+
/**
|
|
1686
|
+
* The headless consent surface — state + actions in one hook.
|
|
1687
|
+
*
|
|
1688
|
+
* Build a fully-custom banner without losing the gtag-sync, localStorage
|
|
1689
|
+
* persistence, or cross-tab propagation:
|
|
1690
|
+
*
|
|
1691
|
+
* ```tsx
|
|
1692
|
+
* const { state, accept, decline, reset, isPending } = useConsent();
|
|
1693
|
+
*
|
|
1694
|
+
* if (!isPending) {
|
|
1695
|
+
* return <button onClick={reset}>Cookie preferences</button>;
|
|
1696
|
+
* }
|
|
1697
|
+
* return (
|
|
1698
|
+
* <MyBannerStyling>
|
|
1699
|
+
* <button onClick={decline}>No thanks</button>
|
|
1700
|
+
* <button onClick={accept}>Sure</button>
|
|
1701
|
+
* </MyBannerStyling>
|
|
1702
|
+
* );
|
|
1703
|
+
* ```
|
|
1704
|
+
*
|
|
1705
|
+
* The boolean helpers (`isPending` / `isGranted` / `isDenied`) are equivalent
|
|
1706
|
+
* to comparing `state` directly — they're there for readability at call sites.
|
|
1707
|
+
*/
|
|
1708
|
+
interface UseConsentResult {
|
|
1709
|
+
state: ConsentState;
|
|
1710
|
+
isPending: boolean;
|
|
1711
|
+
isGranted: boolean;
|
|
1712
|
+
isDenied: boolean;
|
|
1713
|
+
accept: () => void;
|
|
1714
|
+
decline: () => void;
|
|
1715
|
+
reset: () => void;
|
|
1716
|
+
}
|
|
1717
|
+
declare function useConsent(): UseConsentResult;
|
|
1561
1718
|
|
|
1562
1719
|
/**
|
|
1563
1720
|
* Props for the Next.js Google Ads tracking component.
|
|
@@ -1646,4 +1803,4 @@ interface CreateTrackingResult<TRegistry extends TriggerRegistryConfig> {
|
|
|
1646
1803
|
*/
|
|
1647
1804
|
declare function createTracking<TRegistry extends TriggerRegistryConfig>(options: CreateTrackingOptions<TRegistry>): CreateTrackingResult<TRegistry>;
|
|
1648
1805
|
|
|
1649
|
-
export { AranovaApiError, type AutomaticEventName, ConsentBanner, 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, TrackingClientContext, TrackingEventCreatePayload, TrackingInstallSurface, TrackingParams, type TrackingProviderProps, TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, setConsentState, toMinor, useConsentState, useGclid, useTrackingParams };
|
|
1806
|
+
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentBannerProps, 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, TrackingClientContext, TrackingEventCreatePayload, TrackingInstallSurface, TrackingParams, type TrackingProviderProps, 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
|
@@ -2,8 +2,8 @@ import { C as ConsentState, T as TrackingInstallSurface, a as TrackingEnvironmen
|
|
|
2
2
|
export { f as TrackingInitConfig } from './types-BPJLgMsG.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import * as src from 'src';
|
|
5
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
5
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
-
import { ReactNode } from 'react';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Google Consent Mode value sent to `gtag('consent', 'update', ...)`.
|
|
@@ -21,6 +21,22 @@ declare function getConsentState(): ConsentState;
|
|
|
21
21
|
* loaded.
|
|
22
22
|
*/
|
|
23
23
|
declare function setConsentState(state: GtagConsentValue): void;
|
|
24
|
+
/**
|
|
25
|
+
* Clear the stored consent choice so the banner re-appears on next render.
|
|
26
|
+
*
|
|
27
|
+
* Power a "Cookie preferences" link in a footer so visitors can change their
|
|
28
|
+
* mind without losing access to your site:
|
|
29
|
+
*
|
|
30
|
+
* ```tsx
|
|
31
|
+
* const { reset } = useConsent();
|
|
32
|
+
* <button onClick={reset}>Cookie preferences</button>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Does NOT push an `update` to gtag — there's nothing to update because the
|
|
36
|
+
* visitor hasn't chosen anything yet. The next `setConsentState()` call will
|
|
37
|
+
* sync gtag once they re-choose.
|
|
38
|
+
*/
|
|
39
|
+
declare function resetConsent(): void;
|
|
24
40
|
|
|
25
41
|
interface TrackingContextInput {
|
|
26
42
|
packageName?: string | null;
|
|
@@ -1298,6 +1314,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1298
1314
|
unit_cost_cents?: number | null | undefined;
|
|
1299
1315
|
}>, "many">>;
|
|
1300
1316
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1317
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1318
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1319
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1301
1320
|
}, "strict", z.ZodTypeAny, {
|
|
1302
1321
|
currency: "USD" | "CAD";
|
|
1303
1322
|
amount_total_cents: number;
|
|
@@ -1315,6 +1334,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1315
1334
|
external_id?: string | null | undefined;
|
|
1316
1335
|
description?: string | null | undefined;
|
|
1317
1336
|
service?: string | null | undefined;
|
|
1337
|
+
customer_name?: string | null | undefined;
|
|
1338
|
+
customer_phone?: string | null | undefined;
|
|
1339
|
+
customer_email?: string | null | undefined;
|
|
1318
1340
|
}, {
|
|
1319
1341
|
currency: "USD" | "CAD";
|
|
1320
1342
|
amount_total_cents: number;
|
|
@@ -1332,6 +1354,9 @@ declare const saleCreateSchema: z.ZodObject<{
|
|
|
1332
1354
|
category?: string | null | undefined;
|
|
1333
1355
|
unit_cost_cents?: number | null | undefined;
|
|
1334
1356
|
}[] | undefined;
|
|
1357
|
+
customer_name?: string | null | undefined;
|
|
1358
|
+
customer_phone?: string | null | undefined;
|
|
1359
|
+
customer_email?: string | null | undefined;
|
|
1335
1360
|
}>;
|
|
1336
1361
|
declare const saleUpdateSchema: z.ZodObject<{
|
|
1337
1362
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -1362,6 +1387,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1362
1387
|
unit_cost_cents?: number | null | undefined;
|
|
1363
1388
|
}>, "many">>;
|
|
1364
1389
|
metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1390
|
+
customer_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1391
|
+
customer_phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1392
|
+
customer_email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1365
1393
|
}, "strict", z.ZodTypeAny, {
|
|
1366
1394
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1367
1395
|
description?: string | null | undefined;
|
|
@@ -1377,6 +1405,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1377
1405
|
category?: string | null | undefined;
|
|
1378
1406
|
unit_cost_cents?: number | null | undefined;
|
|
1379
1407
|
}[] | undefined;
|
|
1408
|
+
customer_name?: string | null | undefined;
|
|
1409
|
+
customer_phone?: string | null | undefined;
|
|
1410
|
+
customer_email?: string | null | undefined;
|
|
1380
1411
|
}, {
|
|
1381
1412
|
metadata?: Record<string, unknown> | null | undefined;
|
|
1382
1413
|
description?: string | null | undefined;
|
|
@@ -1392,6 +1423,9 @@ declare const saleUpdateSchema: z.ZodObject<{
|
|
|
1392
1423
|
category?: string | null | undefined;
|
|
1393
1424
|
unit_cost_cents?: number | null | undefined;
|
|
1394
1425
|
}[] | undefined;
|
|
1426
|
+
customer_name?: string | null | undefined;
|
|
1427
|
+
customer_phone?: string | null | undefined;
|
|
1428
|
+
customer_email?: string | null | undefined;
|
|
1395
1429
|
}>;
|
|
1396
1430
|
type SaleItemInput = z.input<typeof saleItemSchema>;
|
|
1397
1431
|
type SaleInput = z.input<typeof saleCreateSchema>;
|
|
@@ -1419,6 +1453,9 @@ interface Sale {
|
|
|
1419
1453
|
occurred_at: string;
|
|
1420
1454
|
environment: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1421
1455
|
metadata: Record<string, unknown> | null;
|
|
1456
|
+
customer_name: string | null;
|
|
1457
|
+
customer_phone: string | null;
|
|
1458
|
+
customer_email: string | null;
|
|
1422
1459
|
created_at: string;
|
|
1423
1460
|
updated_at: string;
|
|
1424
1461
|
items: SaleItem[];
|
|
@@ -1431,13 +1468,38 @@ interface SaleCursorPage {
|
|
|
1431
1468
|
items: Sale[];
|
|
1432
1469
|
next_cursor: string | null;
|
|
1433
1470
|
}
|
|
1434
|
-
|
|
1471
|
+
/**
|
|
1472
|
+
* Comprehensive filter shape mirrored from the backend's `SaleQueryFilters`.
|
|
1473
|
+
*
|
|
1474
|
+
* `search` runs case-insensitively across `customer_name`, `customer_phone`,
|
|
1475
|
+
* `customer_email`, `description`, and `external_id` — the human-facing
|
|
1476
|
+
* columns. `service_id` is the resolved per-business service UUID (different
|
|
1477
|
+
* from the create-time `service` *key*).
|
|
1478
|
+
*/
|
|
1479
|
+
interface SaleFilters {
|
|
1435
1480
|
business_id?: string;
|
|
1436
1481
|
external_id?: string;
|
|
1482
|
+
service_id?: string;
|
|
1437
1483
|
currency?: SupportedCurrency;
|
|
1438
1484
|
environment?: (typeof TRACKING_ENVIRONMENTS)[number];
|
|
1439
1485
|
since?: string;
|
|
1440
1486
|
until?: string;
|
|
1487
|
+
min_amount_cents?: number;
|
|
1488
|
+
max_amount_cents?: number;
|
|
1489
|
+
search?: string;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Full query input for `SalesClient.list()` — filters + pagination.
|
|
1493
|
+
*
|
|
1494
|
+
* Pagination is **keyset (cursor)**: `next_cursor` returned by one page is
|
|
1495
|
+
* passed back as `cursor` on the next. `null` / undefined cursor = first page.
|
|
1496
|
+
*
|
|
1497
|
+
* Ordering on this endpoint is fixed at **`occurred_at DESC, id DESC`** — the
|
|
1498
|
+
* cursor encodes a position in that index, so a different sort would
|
|
1499
|
+
* invalidate cursors mid-pagination. For ad-hoc sorted reads use the
|
|
1500
|
+
* dashboard admin endpoint, which is offset-paginated.
|
|
1501
|
+
*/
|
|
1502
|
+
interface SaleListQuery extends SaleFilters {
|
|
1441
1503
|
limit?: number;
|
|
1442
1504
|
cursor?: string | null;
|
|
1443
1505
|
}
|
|
@@ -1534,12 +1596,69 @@ declare class AranovaApiError extends Error {
|
|
|
1534
1596
|
}
|
|
1535
1597
|
|
|
1536
1598
|
/**
|
|
1537
|
-
* Default non-blocking consent banner
|
|
1599
|
+
* Default non-blocking consent banner.
|
|
1600
|
+
*
|
|
1601
|
+
* Renders only while consent is `pending`; collapses to `null` once the
|
|
1602
|
+
* visitor has chosen.
|
|
1603
|
+
*
|
|
1604
|
+
* **Styling is intentionally self-contained** — inline styles, zero CSS
|
|
1605
|
+
* dependencies, no Tailwind required at the consumer. The Tailwind-based
|
|
1606
|
+
* banner shipped before 0.9.1 rendered as transparent in any consumer that
|
|
1607
|
+
* didn't configure their content array to scan
|
|
1608
|
+
* `node_modules/@aranova/tracking-next/dist/**`; this version sidesteps that
|
|
1609
|
+
* class of bug entirely.
|
|
1610
|
+
*
|
|
1611
|
+
* For a fully bespoke banner, skip this component and use {@link useConsent}
|
|
1612
|
+
* directly to drive your own UI.
|
|
1538
1613
|
*
|
|
1539
|
-
*
|
|
1540
|
-
* in
|
|
1614
|
+
* @example
|
|
1615
|
+
* // Drop-in default
|
|
1616
|
+
* <ConsentBanner />
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* // Customized
|
|
1620
|
+
* <ConsentBanner
|
|
1621
|
+
* message="We use cookies to learn which ads drive bookings."
|
|
1622
|
+
* acceptLabel="Sounds good"
|
|
1623
|
+
* declineLabel="No thanks"
|
|
1624
|
+
* policyHref="/privacy"
|
|
1625
|
+
* policyLabel="Privacy policy"
|
|
1626
|
+
* theme="dark"
|
|
1627
|
+
* onAccept={() => track('consent_accepted')}
|
|
1628
|
+
* onDecline={() => track('consent_declined')}
|
|
1629
|
+
* />
|
|
1541
1630
|
*/
|
|
1542
|
-
|
|
1631
|
+
interface ConsentBannerProps {
|
|
1632
|
+
/** Body text. Defaults to the standard cookies-for-ad-performance message. */
|
|
1633
|
+
message?: ReactNode;
|
|
1634
|
+
/** Optional bold title above the body text. */
|
|
1635
|
+
title?: ReactNode;
|
|
1636
|
+
/** Label for the accept button. Default: `"Accept"`. */
|
|
1637
|
+
acceptLabel?: string;
|
|
1638
|
+
/** Label for the decline button. Default: `"Decline"`. */
|
|
1639
|
+
declineLabel?: string;
|
|
1640
|
+
/** Optional link inline with the message (e.g. to a privacy policy). */
|
|
1641
|
+
policyHref?: string;
|
|
1642
|
+
/** Visible text for {@link policyHref}. Default: `"Learn more"`. */
|
|
1643
|
+
policyLabel?: string;
|
|
1644
|
+
/**
|
|
1645
|
+
* Fires after the consent state is persisted + propagated to gtag. Useful
|
|
1646
|
+
* for emitting your own analytics event on the choice.
|
|
1647
|
+
*/
|
|
1648
|
+
onAccept?: () => void;
|
|
1649
|
+
onDecline?: () => void;
|
|
1650
|
+
/** Where the banner docks. Default: `"bottom"`. */
|
|
1651
|
+
position?: 'top' | 'bottom';
|
|
1652
|
+
/**
|
|
1653
|
+
* Visual theme. `"auto"` follows `prefers-color-scheme`. Default: `"light"`.
|
|
1654
|
+
*/
|
|
1655
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
1656
|
+
/** Class added to the outer wrapper for additional styling hooks. */
|
|
1657
|
+
className?: string;
|
|
1658
|
+
/** Inline style overrides applied to the outer wrapper after the defaults. */
|
|
1659
|
+
style?: CSSProperties;
|
|
1660
|
+
}
|
|
1661
|
+
declare function ConsentBanner({ message, title, acceptLabel, declineLabel, policyHref, policyLabel, onAccept, onDecline, position, theme, className, style, }?: ConsentBannerProps): ReactNode;
|
|
1543
1662
|
|
|
1544
1663
|
/**
|
|
1545
1664
|
* Read the captured Google Ads click id from first-party cookies.
|
|
@@ -1556,8 +1675,46 @@ declare function useTrackingParams(): TrackingParams;
|
|
|
1556
1675
|
/**
|
|
1557
1676
|
* Read the current visitor consent state and update when another tab changes
|
|
1558
1677
|
* the stored value.
|
|
1678
|
+
*
|
|
1679
|
+
* Prefer {@link useConsent} for new code — it returns the same state plus
|
|
1680
|
+
* the `accept` / `decline` / `reset` actions a custom consent UI needs.
|
|
1681
|
+
* `useConsentState` is kept as a convenience for callers that only need to
|
|
1682
|
+
* read.
|
|
1559
1683
|
*/
|
|
1560
1684
|
declare function useConsentState(): ConsentState;
|
|
1685
|
+
/**
|
|
1686
|
+
* The headless consent surface — state + actions in one hook.
|
|
1687
|
+
*
|
|
1688
|
+
* Build a fully-custom banner without losing the gtag-sync, localStorage
|
|
1689
|
+
* persistence, or cross-tab propagation:
|
|
1690
|
+
*
|
|
1691
|
+
* ```tsx
|
|
1692
|
+
* const { state, accept, decline, reset, isPending } = useConsent();
|
|
1693
|
+
*
|
|
1694
|
+
* if (!isPending) {
|
|
1695
|
+
* return <button onClick={reset}>Cookie preferences</button>;
|
|
1696
|
+
* }
|
|
1697
|
+
* return (
|
|
1698
|
+
* <MyBannerStyling>
|
|
1699
|
+
* <button onClick={decline}>No thanks</button>
|
|
1700
|
+
* <button onClick={accept}>Sure</button>
|
|
1701
|
+
* </MyBannerStyling>
|
|
1702
|
+
* );
|
|
1703
|
+
* ```
|
|
1704
|
+
*
|
|
1705
|
+
* The boolean helpers (`isPending` / `isGranted` / `isDenied`) are equivalent
|
|
1706
|
+
* to comparing `state` directly — they're there for readability at call sites.
|
|
1707
|
+
*/
|
|
1708
|
+
interface UseConsentResult {
|
|
1709
|
+
state: ConsentState;
|
|
1710
|
+
isPending: boolean;
|
|
1711
|
+
isGranted: boolean;
|
|
1712
|
+
isDenied: boolean;
|
|
1713
|
+
accept: () => void;
|
|
1714
|
+
decline: () => void;
|
|
1715
|
+
reset: () => void;
|
|
1716
|
+
}
|
|
1717
|
+
declare function useConsent(): UseConsentResult;
|
|
1561
1718
|
|
|
1562
1719
|
/**
|
|
1563
1720
|
* Props for the Next.js Google Ads tracking component.
|
|
@@ -1646,4 +1803,4 @@ interface CreateTrackingResult<TRegistry extends TriggerRegistryConfig> {
|
|
|
1646
1803
|
*/
|
|
1647
1804
|
declare function createTracking<TRegistry extends TriggerRegistryConfig>(options: CreateTrackingOptions<TRegistry>): CreateTrackingResult<TRegistry>;
|
|
1648
1805
|
|
|
1649
|
-
export { AranovaApiError, type AutomaticEventName, ConsentBanner, 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, TrackingClientContext, TrackingEventCreatePayload, TrackingInstallSurface, TrackingParams, type TrackingProviderProps, TrackingSessionUpsertPayload, type TriggerRegistryConfig, type TypedTrackEventOptions, type TypedTrackingClient, captureTrackingParamsFromLocation, createSalesClient, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, fetchServices, formatMoney, fromMinor, getConsentState, setConsentState, toMinor, useConsentState, useGclid, useTrackingParams };
|
|
1806
|
+
export { AranovaApiError, type AutomaticEventName, ConsentBanner, type ConsentBannerProps, 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, TrackingClientContext, TrackingEventCreatePayload, TrackingInstallSurface, TrackingParams, type TrackingProviderProps, 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 };
|