@pl4yzonellc/empire-analytics 0.0.2
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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +744 -0
- package/dist/chunk-J5GXHJNU.js +1105 -0
- package/dist/chunk-J5GXHJNU.js.map +1 -0
- package/dist/index.d.ts +200 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/testing/index.d.ts +91 -0
- package/dist/testing/index.js +108 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-Bzaq1v4t.d.ts +507 -0
- package/package.json +97 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error model.
|
|
3
|
+
*
|
|
4
|
+
* Every error the library surfaces is an {@link AnalyticsError} carrying a stable
|
|
5
|
+
* machine-readable `code`. Provider implementation details are never leaked through
|
|
6
|
+
* the `message`; the originating error (if any) is attached as `cause` for opt-in
|
|
7
|
+
* inspection by `config.onError`.
|
|
8
|
+
*/
|
|
9
|
+
type AnalyticsErrorCode = 'config_invalid' | 'initialization_failed' | 'provider_unavailable' | 'script_load_failed' | 'track_failed' | 'pageview_failed' | 'destroy_failed' | 'privacy_violation' | 'unknown';
|
|
10
|
+
interface AnalyticsErrorOptions {
|
|
11
|
+
code?: AnalyticsErrorCode;
|
|
12
|
+
cause?: unknown;
|
|
13
|
+
}
|
|
14
|
+
declare class AnalyticsError extends Error {
|
|
15
|
+
readonly code: AnalyticsErrorCode;
|
|
16
|
+
readonly cause?: unknown;
|
|
17
|
+
constructor(message: string, options?: AnalyticsErrorOptions);
|
|
18
|
+
}
|
|
19
|
+
/** Thrown synchronously from `initialize()` when the supplied config is invalid. */
|
|
20
|
+
declare class AnalyticsConfigError extends AnalyticsError {
|
|
21
|
+
constructor(message: string, options?: Omit<AnalyticsErrorOptions, 'code'>);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Normalize an unknown thrown value into an {@link AnalyticsError} with a generic,
|
|
25
|
+
* provider-neutral message. Existing `AnalyticsError`s pass through unchanged.
|
|
26
|
+
*/
|
|
27
|
+
declare function toAnalyticsError(value: unknown, code: AnalyticsErrorCode): AnalyticsError;
|
|
28
|
+
|
|
29
|
+
/** How the sanitizer reacts to a prohibited key. */
|
|
30
|
+
type PrivacyViolationMode = 'strip' | 'warn' | 'throw';
|
|
31
|
+
/** How the sanitizer reacts to a personally-identifiable key. */
|
|
32
|
+
type PiiMode = 'allow' | 'strip' | 'warn' | 'throw';
|
|
33
|
+
/**
|
|
34
|
+
* Application-facing privacy configuration. Everything is optional; sensible,
|
|
35
|
+
* environment-aware defaults are applied by `resolveConfig`.
|
|
36
|
+
*/
|
|
37
|
+
interface PrivacyConfig {
|
|
38
|
+
/**
|
|
39
|
+
* Handling for always-blocked sensitive keys (passwords, tokens, card data…).
|
|
40
|
+
* Default: `throw` when `debug` is on, `warn` on staging/test, `strip` in production.
|
|
41
|
+
* `throw` is always downgraded to `strip` in the `production` environment so
|
|
42
|
+
* analytics can never crash a production app.
|
|
43
|
+
*/
|
|
44
|
+
onSensitive?: PrivacyViolationMode;
|
|
45
|
+
/**
|
|
46
|
+
* Handling for direct personal identifiers (email, phone, name, address…).
|
|
47
|
+
* Default: `warn`. `throw` is downgraded to `warn` in `production`.
|
|
48
|
+
*/
|
|
49
|
+
onPii?: PiiMode;
|
|
50
|
+
/** Extra keys to always block (normalized substring match). */
|
|
51
|
+
blockKeys?: readonly string[];
|
|
52
|
+
/** Keys to force-allow even when a built-in rule matches (normalized exact match). */
|
|
53
|
+
allowKeys?: readonly string[];
|
|
54
|
+
/** Maximum object nesting depth to traverse. Default `4`. */
|
|
55
|
+
maxDepth?: number;
|
|
56
|
+
/** Maximum number of properties kept (across the whole tree). Default `64`. */
|
|
57
|
+
maxProperties?: number;
|
|
58
|
+
/** Strings longer than this are truncated. Default `1024`. */
|
|
59
|
+
maxStringLength?: number;
|
|
60
|
+
/** Arrays longer than this are truncated. Default `64`. */
|
|
61
|
+
maxArrayLength?: number;
|
|
62
|
+
}
|
|
63
|
+
/** Fully-resolved policy consumed by the sanitizer. */
|
|
64
|
+
interface ResolvedPrivacyPolicy {
|
|
65
|
+
onSensitive: PrivacyViolationMode;
|
|
66
|
+
onPii: PiiMode;
|
|
67
|
+
blockKeys: readonly string[];
|
|
68
|
+
allowKeys: readonly string[];
|
|
69
|
+
maxDepth: number;
|
|
70
|
+
maxProperties: number;
|
|
71
|
+
maxStringLength: number;
|
|
72
|
+
maxArrayLength: number;
|
|
73
|
+
}
|
|
74
|
+
interface SanitizeResult {
|
|
75
|
+
/** Safe, adapter-ready property bag. */
|
|
76
|
+
value: Record<string, unknown>;
|
|
77
|
+
/** Key paths that were removed because they matched a privacy rule. */
|
|
78
|
+
blocked: string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface Logger {
|
|
82
|
+
debug(message: string, data?: unknown): void;
|
|
83
|
+
info(message: string, data?: unknown): void;
|
|
84
|
+
warn(message: string, data?: unknown): void;
|
|
85
|
+
error(message: string, data?: unknown): void;
|
|
86
|
+
/** Returns a logger with an extra scope segment appended to the prefix. */
|
|
87
|
+
child(scope: string): Logger;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Provider contract.
|
|
92
|
+
*
|
|
93
|
+
* The core client depends on *this interface only*. Everything Plausible-specific
|
|
94
|
+
* lives behind `PlausibleAdapter`.
|
|
95
|
+
*
|
|
96
|
+
* Refinements over the naive `initialize(config: unknown)` shape:
|
|
97
|
+
* - provider config is injected through the constructor / factory and is
|
|
98
|
+
* strongly typed per provider, so `unknown` never travels through the core
|
|
99
|
+
* - `initialize()` may be sync or async; the core always awaits it
|
|
100
|
+
* - adapters expose a stable `name` for diagnostics
|
|
101
|
+
* - `track()` receives an already privacy-sanitized property bag
|
|
102
|
+
*/
|
|
103
|
+
interface AnalyticsAdapter {
|
|
104
|
+
/** Stable identifier, e.g. `'plausible'`. */
|
|
105
|
+
readonly name: string;
|
|
106
|
+
/** Prepare the provider (load scripts, wire globals). Awaited by the core. */
|
|
107
|
+
initialize(): Promise<void> | void;
|
|
108
|
+
/** Send a business event. `properties` is already sanitized. */
|
|
109
|
+
track(eventName: string, properties?: Record<string, unknown>): void;
|
|
110
|
+
/** Send an explicit page view. `path` is already sanitized when provided. */
|
|
111
|
+
pageView(path?: string): void;
|
|
112
|
+
/** Release resources: remove injected scripts, drop listeners, null out globals. */
|
|
113
|
+
destroy(): void;
|
|
114
|
+
}
|
|
115
|
+
/** Everything an adapter is handed at construction time. */
|
|
116
|
+
interface AnalyticsAdapterContext {
|
|
117
|
+
logger: Logger;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Factory for a custom adapter, supplied via `{ provider: 'custom', adapter }`.
|
|
121
|
+
* This is the extension point for future first-class providers
|
|
122
|
+
* (`GoogleAnalyticsAdapter`, `PostHogAdapter`, …) without touching app code.
|
|
123
|
+
*/
|
|
124
|
+
type AnalyticsAdapterFactory = (context: AnalyticsAdapterContext) => AnalyticsAdapter;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Optional Plausible script variants. The library composes the CDN filename
|
|
128
|
+
* (`script.manual.revenue.tagged-events.js`) from these flags.
|
|
129
|
+
* @see https://plausible.io/docs/script-extensions
|
|
130
|
+
*/
|
|
131
|
+
type PlausibleScriptExtension = 'manual' | 'hash' | 'outbound-links' | 'file-downloads' | 'tagged-events' | 'revenue' | 'pageview-props' | 'compat' | 'local';
|
|
132
|
+
/**
|
|
133
|
+
* How the Plausible tracker runs in the browser:
|
|
134
|
+
* - `'cdn'` — inject the hosted `<script data-domain>` from plausible.io (default)
|
|
135
|
+
* - `'package'` — load the official `@plausible-analytics/tracker` npm module via a
|
|
136
|
+
* lazy dynamic import (no remote `<script>`, pinned version, friendlier to CSP and
|
|
137
|
+
* ad-blockers). The consuming app must install it: `pnpm add @plausible-analytics/tracker`.
|
|
138
|
+
*/
|
|
139
|
+
type PlausibleRuntimeMode = 'cdn' | 'package';
|
|
140
|
+
/**
|
|
141
|
+
* Provider-specific configuration block. This is the *only* place Plausible
|
|
142
|
+
* terminology is allowed to surface in the public API.
|
|
143
|
+
*/
|
|
144
|
+
interface PlausibleProviderConfig {
|
|
145
|
+
/** The site domain registered in Plausible, e.g. `"example.com"`. Required. */
|
|
146
|
+
domain: string;
|
|
147
|
+
/**
|
|
148
|
+
* Runtime for the tracker. Default `'cdn'`.
|
|
149
|
+
* `'package'` uses `@plausible-analytics/tracker` (an **optional peer dependency**,
|
|
150
|
+
* loaded via dynamic `import()`); `scriptUrl`, `injectScript` and `taggedEvents`
|
|
151
|
+
* are ignored in that mode.
|
|
152
|
+
*/
|
|
153
|
+
mode?: PlausibleRuntimeMode;
|
|
154
|
+
/**
|
|
155
|
+
* Full URL of the tracking script (`mode: 'cdn'` only). Overrides the composed
|
|
156
|
+
* CDN URL entirely. Use this for a self-hosted Plausible instance or a first-party proxy.
|
|
157
|
+
*/
|
|
158
|
+
scriptUrl?: string;
|
|
159
|
+
/** Custom events API endpoint (`data-api`). Use with a first-party proxy. */
|
|
160
|
+
endpoint?: string;
|
|
161
|
+
/**
|
|
162
|
+
* Inject the browser script automatically. Default `true`.
|
|
163
|
+
* Set to `false` if the host page already includes the Plausible snippet.
|
|
164
|
+
*/
|
|
165
|
+
injectScript?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Let Plausible auto-track SPA navigations. Default `true`.
|
|
168
|
+
* When `false`, the `manual` script variant is used and page views only happen
|
|
169
|
+
* via explicit `analytics.pageView()` calls.
|
|
170
|
+
*/
|
|
171
|
+
autoPageViews?: boolean;
|
|
172
|
+
/** Use the `hash` script variant for hash-based routing. Default `false`. */
|
|
173
|
+
hashRouting?: boolean;
|
|
174
|
+
/** Load the `outbound-links` script variant. Default `false`. */
|
|
175
|
+
outboundLinks?: boolean;
|
|
176
|
+
/** Load the `file-downloads` script variant. Default `false`. */
|
|
177
|
+
fileDownloads?: boolean;
|
|
178
|
+
/** Load the `tagged-events` script variant. Default `false`. */
|
|
179
|
+
taggedEvents?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Enable revenue tracking (`revenue` script variant). Default `true` — the SDK's
|
|
182
|
+
* revenue abstraction depends on it. Individual goals must still be marked as
|
|
183
|
+
* revenue goals in the Plausible dashboard.
|
|
184
|
+
*/
|
|
185
|
+
revenue?: boolean;
|
|
186
|
+
/** Load the `local` script variant so events fire on `localhost`. Default `false`. */
|
|
187
|
+
trackLocalhost?: boolean;
|
|
188
|
+
}
|
|
189
|
+
interface ResolvedPlausibleConfig {
|
|
190
|
+
domain: string;
|
|
191
|
+
mode: PlausibleRuntimeMode;
|
|
192
|
+
scriptUrl?: string;
|
|
193
|
+
endpoint?: string;
|
|
194
|
+
injectScript: boolean;
|
|
195
|
+
autoPageViews: boolean;
|
|
196
|
+
hashRouting: boolean;
|
|
197
|
+
outboundLinks: boolean;
|
|
198
|
+
fileDownloads: boolean;
|
|
199
|
+
taggedEvents: boolean;
|
|
200
|
+
revenue: boolean;
|
|
201
|
+
trackLocalhost: boolean;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
interface ConsoleProviderConfig {
|
|
205
|
+
/** Where to write. Defaults to the global `console`. */
|
|
206
|
+
sink?: Pick<Console, 'log' | 'info' | 'group' | 'groupEnd'>;
|
|
207
|
+
/** Prefix for every line. Default `"[Analytics:console]"`. */
|
|
208
|
+
prefix?: string;
|
|
209
|
+
}
|
|
210
|
+
interface ResolvedConsoleConfig {
|
|
211
|
+
sink: Pick<Console, 'log' | 'info' | 'group' | 'groupEnd'>;
|
|
212
|
+
prefix: string;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Typed event system
|
|
217
|
+
* ==================
|
|
218
|
+
*
|
|
219
|
+
* The library deliberately does *not* recommend `track(event: string)`. Instead it
|
|
220
|
+
* ships a shared catalog (`BaseAnalyticsEventMap`) and lets each application extend
|
|
221
|
+
* an open registry interface (`AnalyticsEventMap`) via TypeScript module augmentation:
|
|
222
|
+
*
|
|
223
|
+
* ```ts
|
|
224
|
+
* // app/src/analytics-events.ts
|
|
225
|
+
* declare module '@pl4yzonellc/empire-analytics' {
|
|
226
|
+
* interface AnalyticsEventMap {
|
|
227
|
+
* quote_requested: { service: string; budgetRange?: string };
|
|
228
|
+
* }
|
|
229
|
+
* }
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* After that, `analytics.track('quote_requested', { service: 'roofing' })` is fully
|
|
233
|
+
* typed everywhere (hooks, `<Track>`, the global client) with zero generic plumbing,
|
|
234
|
+
* while unknown strings are rejected by the compiler.
|
|
235
|
+
*/
|
|
236
|
+
/** Common UI interactions shared by most applications. */
|
|
237
|
+
interface CommonEventMap {
|
|
238
|
+
cta_clicked: {
|
|
239
|
+
id?: string;
|
|
240
|
+
label?: string;
|
|
241
|
+
location?: string;
|
|
242
|
+
};
|
|
243
|
+
outbound_link_clicked: {
|
|
244
|
+
url: string;
|
|
245
|
+
location?: string;
|
|
246
|
+
};
|
|
247
|
+
download_clicked: {
|
|
248
|
+
file: string;
|
|
249
|
+
location?: string;
|
|
250
|
+
};
|
|
251
|
+
/** `query` is free text — never put PII in it. */
|
|
252
|
+
search_performed: {
|
|
253
|
+
query?: string;
|
|
254
|
+
resultsCount?: number;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/** Lead-generation / contact funnels. */
|
|
258
|
+
interface LeadGenerationEventMap {
|
|
259
|
+
contact_form_started: {
|
|
260
|
+
form: string;
|
|
261
|
+
};
|
|
262
|
+
contact_form_submitted: {
|
|
263
|
+
form: string;
|
|
264
|
+
};
|
|
265
|
+
phone_clicked: {
|
|
266
|
+
location?: string;
|
|
267
|
+
};
|
|
268
|
+
email_clicked: {
|
|
269
|
+
location?: string;
|
|
270
|
+
};
|
|
271
|
+
appointment_started: {
|
|
272
|
+
service?: string;
|
|
273
|
+
};
|
|
274
|
+
appointment_completed: {
|
|
275
|
+
service?: string;
|
|
276
|
+
durationMinutes?: number;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/** Authentication lifecycle. */
|
|
280
|
+
interface AuthenticationEventMap {
|
|
281
|
+
login_started: {
|
|
282
|
+
method?: string;
|
|
283
|
+
};
|
|
284
|
+
login_completed: {
|
|
285
|
+
method?: string;
|
|
286
|
+
};
|
|
287
|
+
login_failed: {
|
|
288
|
+
method?: string;
|
|
289
|
+
reason?: string;
|
|
290
|
+
};
|
|
291
|
+
signup_started: {
|
|
292
|
+
method?: string;
|
|
293
|
+
};
|
|
294
|
+
signup_completed: {
|
|
295
|
+
method?: string;
|
|
296
|
+
plan?: string;
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/** Ecommerce funnel. `purchase_completed` carries first-class revenue fields. */
|
|
300
|
+
interface EcommerceEventMap {
|
|
301
|
+
product_viewed: {
|
|
302
|
+
productId: string;
|
|
303
|
+
name?: string;
|
|
304
|
+
price?: number;
|
|
305
|
+
currency?: string;
|
|
306
|
+
category?: string;
|
|
307
|
+
};
|
|
308
|
+
add_to_cart: {
|
|
309
|
+
productId: string;
|
|
310
|
+
quantity?: number;
|
|
311
|
+
price?: number;
|
|
312
|
+
currency?: string;
|
|
313
|
+
};
|
|
314
|
+
remove_from_cart: {
|
|
315
|
+
productId: string;
|
|
316
|
+
quantity?: number;
|
|
317
|
+
};
|
|
318
|
+
checkout_started: {
|
|
319
|
+
cartValue?: number;
|
|
320
|
+
itemCount?: number;
|
|
321
|
+
currency?: string;
|
|
322
|
+
};
|
|
323
|
+
checkout_completed: {
|
|
324
|
+
cartValue?: number;
|
|
325
|
+
itemCount?: number;
|
|
326
|
+
currency?: string;
|
|
327
|
+
};
|
|
328
|
+
purchase_completed: {
|
|
329
|
+
revenue: number;
|
|
330
|
+
currency: string;
|
|
331
|
+
orderId?: string;
|
|
332
|
+
itemCount?: number;
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/** Content engagement. */
|
|
336
|
+
interface EngagementEventMap {
|
|
337
|
+
video_started: {
|
|
338
|
+
id?: string;
|
|
339
|
+
title?: string;
|
|
340
|
+
};
|
|
341
|
+
video_completed: {
|
|
342
|
+
id?: string;
|
|
343
|
+
title?: string;
|
|
344
|
+
durationSeconds?: number;
|
|
345
|
+
};
|
|
346
|
+
document_downloaded: {
|
|
347
|
+
file: string;
|
|
348
|
+
category?: string;
|
|
349
|
+
};
|
|
350
|
+
social_link_clicked: {
|
|
351
|
+
network: string;
|
|
352
|
+
location?: string;
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The standardized, framework-agnostic event catalog. Applications should reuse
|
|
357
|
+
* these names rather than inventing near-duplicates.
|
|
358
|
+
*/
|
|
359
|
+
interface BaseAnalyticsEventMap extends CommonEventMap, LeadGenerationEventMap, AuthenticationEventMap, EcommerceEventMap, EngagementEventMap {
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Open registry. Augment this interface from application code to add strongly
|
|
363
|
+
* typed application-specific events. It extends {@link BaseAnalyticsEventMap} so
|
|
364
|
+
* the standard catalog is always available.
|
|
365
|
+
*/
|
|
366
|
+
interface AnalyticsEventMap extends BaseAnalyticsEventMap {
|
|
367
|
+
}
|
|
368
|
+
/** Every known event name (standard catalog + application augmentations). */
|
|
369
|
+
type AnalyticsEventName = Extract<keyof AnalyticsEventMap, string>;
|
|
370
|
+
/** The typed property model for a given event. */
|
|
371
|
+
type AnalyticsEventProperties<K extends AnalyticsEventName> = AnalyticsEventMap[K];
|
|
372
|
+
type HasRequiredKeys<T> = {
|
|
373
|
+
[K in keyof T]-?: undefined extends T[K] ? never : K;
|
|
374
|
+
}[keyof T] extends never ? false : true;
|
|
375
|
+
/**
|
|
376
|
+
* The `track()` argument tuple for an event. Events with at least one required
|
|
377
|
+
* property force a `properties` argument; events with only optional properties
|
|
378
|
+
* (or none) make it optional.
|
|
379
|
+
*/
|
|
380
|
+
type TrackArgs<K extends AnalyticsEventName> = HasRequiredKeys<AnalyticsEventProperties<K>> extends true ? [properties: AnalyticsEventProperties<K>] : [properties?: AnalyticsEventProperties<K>];
|
|
381
|
+
|
|
382
|
+
type AnalyticsEnvironment = 'development' | 'test' | 'staging' | 'production';
|
|
383
|
+
type AnalyticsProviderName = 'plausible' | 'console' | 'custom';
|
|
384
|
+
type AnalyticsErrorHandler = (error: AnalyticsError) => void;
|
|
385
|
+
/** Observability payload passed to `config.onEvent` for every attempted send. */
|
|
386
|
+
interface AnalyticsEventInfo {
|
|
387
|
+
type: 'event' | 'pageview';
|
|
388
|
+
name: string;
|
|
389
|
+
provider: AnalyticsProviderName;
|
|
390
|
+
environment: AnalyticsEnvironment;
|
|
391
|
+
enabled: boolean;
|
|
392
|
+
/** `false` when analytics is disabled or the provider was unavailable. */
|
|
393
|
+
delivered: boolean;
|
|
394
|
+
/** Human-readable explanation when `delivered` is `false`. */
|
|
395
|
+
reason?: string;
|
|
396
|
+
/** Sanitized properties actually forwarded (never contains blocked keys). */
|
|
397
|
+
properties?: Record<string, unknown>;
|
|
398
|
+
/** Key paths removed by the privacy layer. */
|
|
399
|
+
blockedKeys?: string[];
|
|
400
|
+
}
|
|
401
|
+
interface AnalyticsConfigBase {
|
|
402
|
+
/**
|
|
403
|
+
* Current environment. Drives the enabled/disabled default:
|
|
404
|
+
* `development` → off, `test` → off, `staging` → off (opt-in), `production` → on.
|
|
405
|
+
*/
|
|
406
|
+
environment: AnalyticsEnvironment;
|
|
407
|
+
/**
|
|
408
|
+
* Explicit master switch. When set it always wins over the environment default —
|
|
409
|
+
* e.g. `enabled: true` in `development`, or `enabled: false` in `production`.
|
|
410
|
+
*/
|
|
411
|
+
enabled?: boolean;
|
|
412
|
+
/** Verbose logging + stricter privacy handling. Default: `true` in `development`. */
|
|
413
|
+
debug?: boolean;
|
|
414
|
+
/**
|
|
415
|
+
* Multi-tenant metadata. Treated as configuration only — it is **not** sent as a
|
|
416
|
+
* property unless `includeTenantKey` is `true`.
|
|
417
|
+
*/
|
|
418
|
+
tenantKey?: string;
|
|
419
|
+
/** Send `tenantKey` as a property on every event. Default `false`. */
|
|
420
|
+
includeTenantKey?: boolean;
|
|
421
|
+
/** Property name used when `includeTenantKey` is `true`. Default `"tenant"`. */
|
|
422
|
+
tenantPropertyName?: string;
|
|
423
|
+
/** Properties merged into every event (lowest precedence). */
|
|
424
|
+
defaultProperties?: Record<string, unknown>;
|
|
425
|
+
/** Privacy / sanitization overrides. */
|
|
426
|
+
privacy?: PrivacyConfig;
|
|
427
|
+
/** Observability hook for internal errors. Never receives provider internals. */
|
|
428
|
+
onError?: AnalyticsErrorHandler;
|
|
429
|
+
/** Observability hook fired for every `track`/`pageView` attempt. */
|
|
430
|
+
onEvent?: (info: AnalyticsEventInfo) => void;
|
|
431
|
+
}
|
|
432
|
+
interface PlausibleAnalyticsConfig extends AnalyticsConfigBase {
|
|
433
|
+
provider: 'plausible';
|
|
434
|
+
plausible: PlausibleProviderConfig;
|
|
435
|
+
}
|
|
436
|
+
interface ConsoleAnalyticsConfig extends AnalyticsConfigBase {
|
|
437
|
+
provider: 'console';
|
|
438
|
+
console?: ConsoleProviderConfig;
|
|
439
|
+
}
|
|
440
|
+
interface CustomAnalyticsConfig extends AnalyticsConfigBase {
|
|
441
|
+
provider: 'custom';
|
|
442
|
+
/** Factory for a bespoke adapter — the forward-compatibility hook for new providers. */
|
|
443
|
+
adapter: AnalyticsAdapterFactory;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Strongly typed, provider-agnostic configuration. A discriminated union on
|
|
447
|
+
* `provider` so the compiler requires the matching provider block.
|
|
448
|
+
*/
|
|
449
|
+
type AnalyticsConfig = PlausibleAnalyticsConfig | ConsoleAnalyticsConfig | CustomAnalyticsConfig;
|
|
450
|
+
/** Config after defaults, validation and environment resolution have been applied. */
|
|
451
|
+
interface ResolvedAnalyticsConfig {
|
|
452
|
+
provider: AnalyticsProviderName;
|
|
453
|
+
environment: AnalyticsEnvironment;
|
|
454
|
+
enabled: boolean;
|
|
455
|
+
disabledReason?: string;
|
|
456
|
+
debug: boolean;
|
|
457
|
+
tenantKey?: string;
|
|
458
|
+
includeTenantKey: boolean;
|
|
459
|
+
tenantPropertyName: string;
|
|
460
|
+
defaultProperties: Record<string, unknown>;
|
|
461
|
+
privacy: ResolvedPrivacyPolicy;
|
|
462
|
+
onError?: AnalyticsErrorHandler;
|
|
463
|
+
onEvent?: (info: AnalyticsEventInfo) => void;
|
|
464
|
+
plausible?: ResolvedPlausibleConfig;
|
|
465
|
+
console?: ResolvedConsoleConfig;
|
|
466
|
+
adapter?: AnalyticsAdapterFactory;
|
|
467
|
+
}
|
|
468
|
+
/** Small, safe snapshot of client state (no internal config leaks). */
|
|
469
|
+
interface AnalyticsClientState {
|
|
470
|
+
initialized: boolean;
|
|
471
|
+
enabled: boolean;
|
|
472
|
+
environment: AnalyticsEnvironment | null;
|
|
473
|
+
provider: AnalyticsProviderName | null;
|
|
474
|
+
debug: boolean;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* The framework-independent analytics client. The core never imports React.
|
|
478
|
+
*/
|
|
479
|
+
interface AnalyticsClient {
|
|
480
|
+
/**
|
|
481
|
+
* Configure and start the client. Idempotent: calling again with an equivalent
|
|
482
|
+
* config is a no-op; calling with a different config reconfigures in place.
|
|
483
|
+
*/
|
|
484
|
+
initialize(config: AnalyticsConfig): Promise<void>;
|
|
485
|
+
/** Send a strongly typed business event (revenue fields included where relevant). */
|
|
486
|
+
track<K extends AnalyticsEventName>(event: K, ...args: TrackArgs<K>): void;
|
|
487
|
+
/**
|
|
488
|
+
* Send an explicit page view. Normal SPA navigation is handled by the provider
|
|
489
|
+
* itself — use this only for special cases (virtual pages, wizards, modals).
|
|
490
|
+
*/
|
|
491
|
+
pageView(path?: string): void;
|
|
492
|
+
/** `true` when analytics is currently sending events. */
|
|
493
|
+
isEnabled(): boolean;
|
|
494
|
+
/** `true` once `initialize()` has been called (and not since `destroy()`d). */
|
|
495
|
+
isInitialized(): boolean;
|
|
496
|
+
/**
|
|
497
|
+
* Toggle sending at runtime (e.g. after a consent decision). Enabling a client
|
|
498
|
+
* that was initialized while disabled will lazily create + start the provider.
|
|
499
|
+
*/
|
|
500
|
+
setEnabled(enabled: boolean): void;
|
|
501
|
+
/** Safe state snapshot for debugging / dev tooling. */
|
|
502
|
+
getState(): AnalyticsClientState;
|
|
503
|
+
/** Tear down the provider and reset to the pre-`initialize()` state. */
|
|
504
|
+
destroy(): void;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export { type AnalyticsClient as A, type BaseAnalyticsEventMap as B, type CommonEventMap as C, type PrivacyConfig as D, type EcommerceEventMap as E, type PrivacyViolationMode as F, type ResolvedAnalyticsConfig as G, toAnalyticsError as H, type Logger as L, type PiiMode as P, type ResolvedPrivacyPolicy as R, type SanitizeResult as S, type TrackArgs as T, AnalyticsError as a, type AnalyticsEnvironment as b, type AnalyticsConfig as c, type AnalyticsEventName as d, type AnalyticsAdapter as e, type AnalyticsAdapterContext as f, type AnalyticsAdapterFactory as g, type AnalyticsClientState as h, type AnalyticsConfigBase as i, AnalyticsConfigError as j, type AnalyticsErrorCode as k, type AnalyticsErrorHandler as l, type AnalyticsEventInfo as m, type AnalyticsEventMap as n, type AnalyticsEventProperties as o, type AnalyticsProviderName as p, type AuthenticationEventMap as q, type ConsoleAnalyticsConfig as r, type ConsoleProviderConfig as s, type CustomAnalyticsConfig as t, type EngagementEventMap as u, type LeadGenerationEventMap as v, type PlausibleAnalyticsConfig as w, type PlausibleProviderConfig as x, type PlausibleRuntimeMode as y, type PlausibleScriptExtension as z };
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pl4yzonellc/empire-analytics",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Provider-agnostic analytics SDK for React 19 applications. First provider: Plausible.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "pl4yzonellc",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"CHANGELOG.md"
|
|
20
|
+
],
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./testing": {
|
|
30
|
+
"types": "./dist/testing/index.d.ts",
|
|
31
|
+
"import": "./dist/testing/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@plausible-analytics/tracker": "^0.4.0",
|
|
37
|
+
"react": "^19.0.0",
|
|
38
|
+
"react-dom": "^19.0.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"@plausible-analytics/tracker": {
|
|
42
|
+
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"react": {
|
|
45
|
+
"optional": true
|
|
46
|
+
},
|
|
47
|
+
"react-dom": {
|
|
48
|
+
"optional": true
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@eslint/js": "^9.18.0",
|
|
53
|
+
"@plausible-analytics/tracker": "^0.4.6",
|
|
54
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
55
|
+
"@testing-library/react": "^16.1.0",
|
|
56
|
+
"@testing-library/user-event": "^14.5.2",
|
|
57
|
+
"@types/node": "^22.10.5",
|
|
58
|
+
"@types/react": "^19.0.7",
|
|
59
|
+
"@types/react-dom": "^19.0.3",
|
|
60
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
61
|
+
"eslint": "^9.18.0",
|
|
62
|
+
"eslint-config-prettier": "^9.1.0",
|
|
63
|
+
"eslint-plugin-react": "^7.37.4",
|
|
64
|
+
"eslint-plugin-react-hooks": "^5.1.0",
|
|
65
|
+
"jsdom": "^25.0.1",
|
|
66
|
+
"prettier": "^3.4.2",
|
|
67
|
+
"react": "^19.0.0",
|
|
68
|
+
"react-dom": "^19.0.0",
|
|
69
|
+
"rimraf": "^6.0.1",
|
|
70
|
+
"tsup": "^8.3.5",
|
|
71
|
+
"typescript": "^5.7.3",
|
|
72
|
+
"typescript-eslint": "^8.20.0",
|
|
73
|
+
"vitest": "^3.0.5"
|
|
74
|
+
},
|
|
75
|
+
"keywords": [
|
|
76
|
+
"analytics",
|
|
77
|
+
"plausible",
|
|
78
|
+
"react",
|
|
79
|
+
"sdk",
|
|
80
|
+
"provider-agnostic",
|
|
81
|
+
"typescript",
|
|
82
|
+
"privacy"
|
|
83
|
+
],
|
|
84
|
+
"scripts": {
|
|
85
|
+
"build": "tsup",
|
|
86
|
+
"dev": "tsup --watch",
|
|
87
|
+
"clean": "rimraf dist coverage",
|
|
88
|
+
"test": "vitest run",
|
|
89
|
+
"test:watch": "vitest",
|
|
90
|
+
"test:coverage": "vitest run --coverage",
|
|
91
|
+
"typecheck": "tsc --noEmit",
|
|
92
|
+
"lint": "eslint .",
|
|
93
|
+
"lint:fix": "eslint . --fix",
|
|
94
|
+
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\"",
|
|
95
|
+
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,yml,yaml}\""
|
|
96
|
+
}
|
|
97
|
+
}
|