@aranova/tracking-react 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
+ import { z } from 'zod';
3
4
 
4
5
  declare function ConsentBanner(): react_jsx_runtime.JSX.Element | null;
5
6
 
@@ -69,12 +70,7 @@ declare global {
69
70
  getTrackingParams: () => TrackingParams;
70
71
  getConsentState: () => ConsentState;
71
72
  setConsentState: (state: 'granted' | 'denied') => void;
72
- trackEvent: (input: {
73
- eventType: string;
74
- pageUrl?: string | null;
75
- metadata?: Record<string, unknown> | null;
76
- occurredAt?: Date | string | null;
77
- }) => void;
73
+ trackEvent: (eventType: string, metadata: Record<string, unknown>) => void;
78
74
  };
79
75
  }
80
76
  }
@@ -123,24 +119,518 @@ interface TrackingClient {
123
119
  destroy: () => void;
124
120
  }
125
121
 
122
+ declare const pageViewMetadataSchema: z.ZodObject<{
123
+ page: z.ZodObject<{
124
+ title: z.ZodNullable<z.ZodString>;
125
+ path: z.ZodString;
126
+ search: z.ZodString;
127
+ hash: z.ZodString;
128
+ }, "strip", z.ZodTypeAny, {
129
+ search: string;
130
+ title: string | null;
131
+ path: string;
132
+ hash: string;
133
+ }, {
134
+ search: string;
135
+ title: string | null;
136
+ path: string;
137
+ hash: string;
138
+ }>;
139
+ referrer: z.ZodNullable<z.ZodString>;
140
+ viewport: z.ZodOptional<z.ZodNullable<z.ZodObject<{
141
+ w: z.ZodNumber;
142
+ h: z.ZodNumber;
143
+ }, "strip", z.ZodTypeAny, {
144
+ w: number;
145
+ h: number;
146
+ }, {
147
+ w: number;
148
+ h: number;
149
+ }>>>;
150
+ }, "strict", z.ZodTypeAny, {
151
+ page: {
152
+ search: string;
153
+ title: string | null;
154
+ path: string;
155
+ hash: string;
156
+ };
157
+ referrer: string | null;
158
+ viewport?: {
159
+ w: number;
160
+ h: number;
161
+ } | null | undefined;
162
+ }, {
163
+ page: {
164
+ search: string;
165
+ title: string | null;
166
+ path: string;
167
+ hash: string;
168
+ };
169
+ referrer: string | null;
170
+ viewport?: {
171
+ w: number;
172
+ h: number;
173
+ } | null | undefined;
174
+ }>;
175
+ type PageViewMetadata = z.infer<typeof pageViewMetadataSchema>;
176
+ declare const pageViewConfigSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
177
+ type PageViewConfig = z.infer<typeof pageViewConfigSchema>;
178
+
179
+ declare const contactPageVisitMetadataSchema: z.ZodObject<{
180
+ page: z.ZodObject<{
181
+ path: z.ZodString;
182
+ }, "strip", z.ZodTypeAny, {
183
+ path: string;
184
+ }, {
185
+ path: string;
186
+ }>;
187
+ }, "strict", z.ZodTypeAny, {
188
+ page: {
189
+ path: string;
190
+ };
191
+ }, {
192
+ page: {
193
+ path: string;
194
+ };
195
+ }>;
196
+ type ContactPageVisitMetadata = z.infer<typeof contactPageVisitMetadataSchema>;
197
+ declare const contactPageVisitConfigSchema: z.ZodObject<{
198
+ pathPattern: z.ZodType<RegExp, z.ZodTypeDef, RegExp>;
199
+ }, "strict", z.ZodTypeAny, {
200
+ pathPattern: RegExp;
201
+ }, {
202
+ pathPattern: RegExp;
203
+ }>;
204
+ type ContactPageVisitConfig = z.infer<typeof contactPageVisitConfigSchema>;
205
+
206
+ declare const formSubmitMetadataSchema: z.ZodObject<{
207
+ form: z.ZodObject<{
208
+ id: z.ZodString;
209
+ action: z.ZodNullable<z.ZodString>;
210
+ }, "strip", z.ZodTypeAny, {
211
+ id: string;
212
+ action: string | null;
213
+ }, {
214
+ id: string;
215
+ action: string | null;
216
+ }>;
217
+ page: z.ZodObject<{
218
+ path: z.ZodString;
219
+ }, "strip", z.ZodTypeAny, {
220
+ path: string;
221
+ }, {
222
+ path: string;
223
+ }>;
224
+ }, "strict", z.ZodTypeAny, {
225
+ form: {
226
+ id: string;
227
+ action: string | null;
228
+ };
229
+ page: {
230
+ path: string;
231
+ };
232
+ }, {
233
+ form: {
234
+ id: string;
235
+ action: string | null;
236
+ };
237
+ page: {
238
+ path: string;
239
+ };
240
+ }>;
241
+ type FormSubmitMetadata = z.infer<typeof formSubmitMetadataSchema>;
242
+ declare const formSubmitConfigSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
243
+ type FormSubmitConfig = z.infer<typeof formSubmitConfigSchema>;
244
+
245
+ declare const phoneClickMetadataSchema: z.ZodObject<{
246
+ element: z.ZodObject<{
247
+ tag: z.ZodString;
248
+ text: z.ZodNullable<z.ZodString>;
249
+ href: z.ZodString;
250
+ }, "strip", z.ZodTypeAny, {
251
+ text: string | null;
252
+ tag: string;
253
+ href: string;
254
+ }, {
255
+ text: string | null;
256
+ tag: string;
257
+ href: string;
258
+ }>;
259
+ page: z.ZodObject<{
260
+ path: z.ZodString;
261
+ }, "strip", z.ZodTypeAny, {
262
+ path: string;
263
+ }, {
264
+ path: string;
265
+ }>;
266
+ }, "strict", z.ZodTypeAny, {
267
+ page: {
268
+ path: string;
269
+ };
270
+ element: {
271
+ text: string | null;
272
+ tag: string;
273
+ href: string;
274
+ };
275
+ }, {
276
+ page: {
277
+ path: string;
278
+ };
279
+ element: {
280
+ text: string | null;
281
+ tag: string;
282
+ href: string;
283
+ };
284
+ }>;
285
+ type PhoneClickMetadata = z.infer<typeof phoneClickMetadataSchema>;
286
+ declare const phoneClickConfigSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
287
+ type PhoneClickConfig = z.infer<typeof phoneClickConfigSchema>;
288
+
289
+ declare const timeOnSiteMetadataSchema: z.ZodObject<{
290
+ duration_ms: z.ZodNumber;
291
+ page: z.ZodObject<{
292
+ path: z.ZodString;
293
+ }, "strip", z.ZodTypeAny, {
294
+ path: string;
295
+ }, {
296
+ path: string;
297
+ }>;
298
+ }, "strict", z.ZodTypeAny, {
299
+ page: {
300
+ path: string;
301
+ };
302
+ duration_ms: number;
303
+ }, {
304
+ page: {
305
+ path: string;
306
+ };
307
+ duration_ms: number;
308
+ }>;
309
+ type TimeOnSiteMetadata = z.infer<typeof timeOnSiteMetadataSchema>;
310
+ declare const timeOnSiteConfigSchema: z.ZodObject<{
311
+ thresholdSeconds: z.ZodNumber;
312
+ }, "strict", z.ZodTypeAny, {
313
+ thresholdSeconds: number;
314
+ }, {
315
+ thresholdSeconds: number;
316
+ }>;
317
+ type TimeOnSiteConfig = z.infer<typeof timeOnSiteConfigSchema>;
318
+
319
+ declare const EVENT_REGISTRY: {
320
+ readonly page_view: {
321
+ readonly kind: "automatic";
322
+ readonly metadataSchema: z.ZodObject<{
323
+ page: z.ZodObject<{
324
+ title: z.ZodNullable<z.ZodString>;
325
+ path: z.ZodString;
326
+ search: z.ZodString;
327
+ hash: z.ZodString;
328
+ }, "strip", z.ZodTypeAny, {
329
+ search: string;
330
+ title: string | null;
331
+ path: string;
332
+ hash: string;
333
+ }, {
334
+ search: string;
335
+ title: string | null;
336
+ path: string;
337
+ hash: string;
338
+ }>;
339
+ referrer: z.ZodNullable<z.ZodString>;
340
+ viewport: z.ZodOptional<z.ZodNullable<z.ZodObject<{
341
+ w: z.ZodNumber;
342
+ h: z.ZodNumber;
343
+ }, "strip", z.ZodTypeAny, {
344
+ w: number;
345
+ h: number;
346
+ }, {
347
+ w: number;
348
+ h: number;
349
+ }>>>;
350
+ }, "strict", z.ZodTypeAny, {
351
+ page: {
352
+ search: string;
353
+ title: string | null;
354
+ path: string;
355
+ hash: string;
356
+ };
357
+ referrer: string | null;
358
+ viewport?: {
359
+ w: number;
360
+ h: number;
361
+ } | null | undefined;
362
+ }, {
363
+ page: {
364
+ search: string;
365
+ title: string | null;
366
+ path: string;
367
+ hash: string;
368
+ };
369
+ referrer: string | null;
370
+ viewport?: {
371
+ w: number;
372
+ h: number;
373
+ } | null | undefined;
374
+ }>;
375
+ readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
376
+ };
377
+ readonly time_on_site: {
378
+ readonly kind: "automatic";
379
+ readonly metadataSchema: z.ZodObject<{
380
+ duration_ms: z.ZodNumber;
381
+ page: z.ZodObject<{
382
+ path: z.ZodString;
383
+ }, "strip", z.ZodTypeAny, {
384
+ path: string;
385
+ }, {
386
+ path: string;
387
+ }>;
388
+ }, "strict", z.ZodTypeAny, {
389
+ page: {
390
+ path: string;
391
+ };
392
+ duration_ms: number;
393
+ }, {
394
+ page: {
395
+ path: string;
396
+ };
397
+ duration_ms: number;
398
+ }>;
399
+ readonly configSchema: z.ZodObject<{
400
+ thresholdSeconds: z.ZodNumber;
401
+ }, "strict", z.ZodTypeAny, {
402
+ thresholdSeconds: number;
403
+ }, {
404
+ thresholdSeconds: number;
405
+ }>;
406
+ };
407
+ readonly contact_page_visit: {
408
+ readonly kind: "automatic";
409
+ readonly metadataSchema: z.ZodObject<{
410
+ page: z.ZodObject<{
411
+ path: z.ZodString;
412
+ }, "strip", z.ZodTypeAny, {
413
+ path: string;
414
+ }, {
415
+ path: string;
416
+ }>;
417
+ }, "strict", z.ZodTypeAny, {
418
+ page: {
419
+ path: string;
420
+ };
421
+ }, {
422
+ page: {
423
+ path: string;
424
+ };
425
+ }>;
426
+ readonly configSchema: z.ZodObject<{
427
+ pathPattern: z.ZodType<RegExp, z.ZodTypeDef, RegExp>;
428
+ }, "strict", z.ZodTypeAny, {
429
+ pathPattern: RegExp;
430
+ }, {
431
+ pathPattern: RegExp;
432
+ }>;
433
+ };
434
+ readonly form_submit: {
435
+ readonly kind: "manual";
436
+ readonly metadataSchema: z.ZodObject<{
437
+ form: z.ZodObject<{
438
+ id: z.ZodString;
439
+ action: z.ZodNullable<z.ZodString>;
440
+ }, "strip", z.ZodTypeAny, {
441
+ id: string;
442
+ action: string | null;
443
+ }, {
444
+ id: string;
445
+ action: string | null;
446
+ }>;
447
+ page: z.ZodObject<{
448
+ path: z.ZodString;
449
+ }, "strip", z.ZodTypeAny, {
450
+ path: string;
451
+ }, {
452
+ path: string;
453
+ }>;
454
+ }, "strict", z.ZodTypeAny, {
455
+ form: {
456
+ id: string;
457
+ action: string | null;
458
+ };
459
+ page: {
460
+ path: string;
461
+ };
462
+ }, {
463
+ form: {
464
+ id: string;
465
+ action: string | null;
466
+ };
467
+ page: {
468
+ path: string;
469
+ };
470
+ }>;
471
+ readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
472
+ };
473
+ readonly phone_click: {
474
+ readonly kind: "manual";
475
+ readonly metadataSchema: z.ZodObject<{
476
+ element: z.ZodObject<{
477
+ tag: z.ZodString;
478
+ text: z.ZodNullable<z.ZodString>;
479
+ href: z.ZodString;
480
+ }, "strip", z.ZodTypeAny, {
481
+ text: string | null;
482
+ tag: string;
483
+ href: string;
484
+ }, {
485
+ text: string | null;
486
+ tag: string;
487
+ href: string;
488
+ }>;
489
+ page: z.ZodObject<{
490
+ path: z.ZodString;
491
+ }, "strip", z.ZodTypeAny, {
492
+ path: string;
493
+ }, {
494
+ path: string;
495
+ }>;
496
+ }, "strict", z.ZodTypeAny, {
497
+ page: {
498
+ path: string;
499
+ };
500
+ element: {
501
+ text: string | null;
502
+ tag: string;
503
+ href: string;
504
+ };
505
+ }, {
506
+ page: {
507
+ path: string;
508
+ };
509
+ element: {
510
+ text: string | null;
511
+ tag: string;
512
+ href: string;
513
+ };
514
+ }>;
515
+ readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
516
+ };
517
+ };
518
+ type EventName = keyof typeof EVENT_REGISTRY;
519
+ type AutomaticEventName = {
520
+ [K in EventName]: (typeof EVENT_REGISTRY)[K]['kind'] extends 'automatic' ? K : never;
521
+ }[EventName];
522
+ type ManualEventName = {
523
+ [K in EventName]: (typeof EVENT_REGISTRY)[K]['kind'] extends 'manual' ? K : never;
524
+ }[EventName];
525
+ type MetadataByName = {
526
+ page_view: PageViewMetadata;
527
+ time_on_site: TimeOnSiteMetadata;
528
+ contact_page_visit: ContactPageVisitMetadata;
529
+ form_submit: FormSubmitMetadata;
530
+ phone_click: PhoneClickMetadata;
531
+ };
532
+ type ConfigByName = {
533
+ page_view: PageViewConfig;
534
+ time_on_site: TimeOnSiteConfig;
535
+ contact_page_visit: ContactPageVisitConfig;
536
+ form_submit: FormSubmitConfig;
537
+ phone_click: PhoneClickConfig;
538
+ };
539
+ type EventMetadata<K extends EventName> = MetadataByName[K];
540
+ type EventConfig<K extends EventName> = ConfigByName[K];
541
+ type TriggerRegistryConfig = {
542
+ automatic: {
543
+ page_view: EventConfig<'page_view'>;
544
+ } & Partial<{
545
+ time_on_site: EventConfig<'time_on_site'>;
546
+ contact_page_visit: EventConfig<'contact_page_visit'>;
547
+ }>;
548
+ manual?: Partial<{
549
+ form_submit: EventConfig<'form_submit'>;
550
+ phone_click: EventConfig<'phone_click'>;
551
+ }>;
552
+ };
553
+ type RegisteredManualEvents<TRegistry extends TriggerRegistryConfig> = Extract<keyof NonNullable<TRegistry['manual']>, ManualEventName>;
554
+ type RegisteredAutomaticEvents<TRegistry extends TriggerRegistryConfig> = Extract<keyof TRegistry['automatic'], AutomaticEventName>;
555
+
556
+ interface TypedTrackEventOptions {
557
+ /** Override the page URL captured automatically. Rarely needed. */
558
+ pageUrl?: string | null;
559
+ /** Event timestamp override. Defaults to "now" at queue time. */
560
+ occurredAt?: Date | string | null;
561
+ }
562
+ interface TypedTrackingClient<TRegistry extends TriggerRegistryConfig> {
563
+ /**
564
+ * Fire a manually-registered event. The event name must be present in
565
+ * the registry's `manual` map and the metadata must match that event's
566
+ * canonical Zod-derived shape.
567
+ */
568
+ trackEvent<K extends RegisteredManualEvents<TRegistry>>(eventType: K, metadata: EventMetadata<K>, options?: TypedTrackEventOptions): void;
569
+ flush(): Promise<void>;
570
+ getSessionId(): string;
571
+ getVisitorId(): string;
572
+ }
573
+
126
574
  declare function useGclid(): string | null;
127
575
  declare function useTrackingParams(): TrackingParams;
128
576
  declare function useConsentState(): ConsentState;
129
577
 
130
- interface TrackingProviderProps {
578
+ interface CreateTrackingOptions<TRegistry extends TriggerRegistryConfig> {
131
579
  /** Public tracking API key issued for this business. Required. */
132
580
  apiKey: string;
133
581
  /** Full ingest endpoint base URL, e.g. https://api.aranova.io/tracking. Required. */
134
582
  endpoint: string;
583
+ /**
584
+ * Trigger registry. Determines which events the SDK fires automatically
585
+ * and which ones the consumer can fire manually via `trackEvent()`.
586
+ * `automatic.page_view` is required — every tracking install needs it.
587
+ */
588
+ triggers: TRegistry;
589
+ /**
590
+ * When true, the typed client validates every `trackEvent()` metadata
591
+ * payload through the Zod schema before forwarding. Errors are thrown
592
+ * loudly. Leave off in prod; turn on in dev to catch shape bugs early.
593
+ */
594
+ debug?: boolean;
595
+ }
596
+ interface TrackingProviderProps {
135
597
  /** Optional Google Ads gtag id. If omitted, no gtag script is loaded. */
136
598
  gtagId?: string;
137
- /** Disable automatic page_view emission (manual tracking only). */
138
- disableAutoPageView?: boolean;
139
- /** Optional debug flag — currently a no-op, reserved for verbose logging. */
140
- debug?: boolean;
141
599
  children: ReactNode;
142
600
  }
143
- declare function TrackingProvider({ apiKey, endpoint, gtagId, disableAutoPageView, debug, children, }: TrackingProviderProps): react_jsx_runtime.JSX.Element;
144
- declare function useTracking(): TrackingClient;
601
+ interface CreateTrackingResult<TRegistry extends TriggerRegistryConfig> {
602
+ TrackingProvider: (props: TrackingProviderProps) => ReactNode;
603
+ useTracking: () => TypedTrackingClient<TRegistry>;
604
+ }
605
+ /**
606
+ * Create a scoped TrackingProvider + useTracking hook for a specific
607
+ * trigger registry. Call this once at app startup (e.g. in a shared
608
+ * `lib/tracking.ts` file) and import the returned `TrackingProvider` /
609
+ * `useTracking` from that module, not from `@aranova/tracking-react`
610
+ * directly. This lets TypeScript thread the registry type through every
611
+ * consumer so `trackEvent()` autocompletes + rejects unregistered events.
612
+ *
613
+ * Example:
614
+ *
615
+ * ```ts
616
+ * // src/lib/tracking.ts
617
+ * import { createTracking } from '@aranova/tracking-react';
618
+ *
619
+ * export const { TrackingProvider, useTracking } = createTracking({
620
+ * apiKey: import.meta.env.VITE_ARANOVA_TRACKING_API_KEY,
621
+ * endpoint: import.meta.env.VITE_ARANOVA_TRACKING_ENDPOINT,
622
+ * triggers: {
623
+ * automatic: {
624
+ * page_view: {},
625
+ * time_on_site: { thresholdSeconds: 60 },
626
+ * },
627
+ * manual: {
628
+ * form_submit: {},
629
+ * },
630
+ * },
631
+ * });
632
+ * ```
633
+ */
634
+ declare function createTracking<TRegistry extends TriggerRegistryConfig>(options: CreateTrackingOptions<TRegistry>): CreateTrackingResult<TRegistry>;
145
635
 
146
- export { ConsentBanner, type ConsentState, GoogleAdsTracking, type GoogleAdsTrackingProps, TRACKING_PARAM_KEYS, type TrackingClient, type TrackingClientContext, type TrackingEventCreatePayload, type TrackingInitConfig, type TrackingInstallSurface, type TrackingParams, TrackingProvider, type TrackingProviderProps, type TrackingSessionUpsertPayload, captureTrackingParamsFromLocation, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, getConsentState, setConsentState, useConsentState, useGclid, useTracking, useTrackingParams };
636
+ export { type AutomaticEventName, ConsentBanner, type ConsentState, type ContactPageVisitConfig, type ContactPageVisitMetadata, type CreateTrackingOptions, type CreateTrackingResult, type EventConfig, type EventMetadata, type EventName, type FormSubmitConfig, type FormSubmitMetadata, GoogleAdsTracking, type GoogleAdsTrackingProps, type ManualEventName, type PageViewConfig, type PageViewMetadata, type PhoneClickConfig, type PhoneClickMetadata, type RegisteredAutomaticEvents, type RegisteredManualEvents, 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, createTracking, createTrackingClientContext, createTrackingEventCreatePayload, createTrackingSessionUpsertPayload, getConsentState, setConsentState, useConsentState, useGclid, useTrackingParams };