@agentuity/frontend 0.0.110 → 0.0.112

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.
Files changed (88) hide show
  1. package/dist/analytics/beacon.d.ts +15 -0
  2. package/dist/analytics/beacon.d.ts.map +1 -0
  3. package/dist/analytics/beacon.js +177 -0
  4. package/dist/analytics/beacon.js.map +1 -0
  5. package/dist/analytics/collectors/clicks.d.ts +10 -0
  6. package/dist/analytics/collectors/clicks.d.ts.map +1 -0
  7. package/dist/analytics/collectors/clicks.js +84 -0
  8. package/dist/analytics/collectors/clicks.js.map +1 -0
  9. package/dist/analytics/collectors/errors.d.ts +5 -0
  10. package/dist/analytics/collectors/errors.d.ts.map +1 -0
  11. package/dist/analytics/collectors/errors.js +43 -0
  12. package/dist/analytics/collectors/errors.js.map +1 -0
  13. package/dist/analytics/collectors/forms.d.ts +5 -0
  14. package/dist/analytics/collectors/forms.d.ts.map +1 -0
  15. package/dist/analytics/collectors/forms.js +55 -0
  16. package/dist/analytics/collectors/forms.js.map +1 -0
  17. package/dist/analytics/collectors/pageview.d.ts +15 -0
  18. package/dist/analytics/collectors/pageview.d.ts.map +1 -0
  19. package/dist/analytics/collectors/pageview.js +64 -0
  20. package/dist/analytics/collectors/pageview.js.map +1 -0
  21. package/dist/analytics/collectors/scroll.d.ts +17 -0
  22. package/dist/analytics/collectors/scroll.d.ts.map +1 -0
  23. package/dist/analytics/collectors/scroll.js +93 -0
  24. package/dist/analytics/collectors/scroll.js.map +1 -0
  25. package/dist/analytics/collectors/spa.d.ts +10 -0
  26. package/dist/analytics/collectors/spa.d.ts.map +1 -0
  27. package/dist/analytics/collectors/spa.js +53 -0
  28. package/dist/analytics/collectors/spa.js.map +1 -0
  29. package/dist/analytics/collectors/visibility.d.ts +18 -0
  30. package/dist/analytics/collectors/visibility.d.ts.map +1 -0
  31. package/dist/analytics/collectors/visibility.js +81 -0
  32. package/dist/analytics/collectors/visibility.js.map +1 -0
  33. package/dist/analytics/collectors/webvitals.d.ts +6 -0
  34. package/dist/analytics/collectors/webvitals.d.ts.map +1 -0
  35. package/dist/analytics/collectors/webvitals.js +111 -0
  36. package/dist/analytics/collectors/webvitals.js.map +1 -0
  37. package/dist/analytics/events.d.ts +18 -0
  38. package/dist/analytics/events.d.ts.map +1 -0
  39. package/dist/analytics/events.js +126 -0
  40. package/dist/analytics/events.js.map +1 -0
  41. package/dist/analytics/index.d.ts +12 -0
  42. package/dist/analytics/index.d.ts.map +1 -0
  43. package/dist/analytics/index.js +12 -0
  44. package/dist/analytics/index.js.map +1 -0
  45. package/dist/analytics/offline.d.ts +19 -0
  46. package/dist/analytics/offline.d.ts.map +1 -0
  47. package/dist/analytics/offline.js +145 -0
  48. package/dist/analytics/offline.js.map +1 -0
  49. package/dist/analytics/types.d.ts +113 -0
  50. package/dist/analytics/types.d.ts.map +1 -0
  51. package/dist/analytics/types.js +2 -0
  52. package/dist/analytics/types.js.map +1 -0
  53. package/dist/analytics/utils/storage.d.ts +13 -0
  54. package/dist/analytics/utils/storage.d.ts.map +1 -0
  55. package/dist/analytics/utils/storage.js +63 -0
  56. package/dist/analytics/utils/storage.js.map +1 -0
  57. package/dist/analytics/utils/utm.d.ts +12 -0
  58. package/dist/analytics/utils/utm.d.ts.map +1 -0
  59. package/dist/analytics/utils/utm.js +27 -0
  60. package/dist/analytics/utils/utm.js.map +1 -0
  61. package/dist/client/index.d.ts.map +1 -1
  62. package/dist/client/index.js +93 -15
  63. package/dist/client/index.js.map +1 -1
  64. package/dist/client/types.d.ts +51 -5
  65. package/dist/client/types.d.ts.map +1 -1
  66. package/dist/index.d.ts +1 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +2 -0
  69. package/dist/index.js.map +1 -1
  70. package/package.json +3 -3
  71. package/src/analytics/beacon.ts +203 -0
  72. package/src/analytics/collectors/clicks.ts +100 -0
  73. package/src/analytics/collectors/errors.ts +49 -0
  74. package/src/analytics/collectors/forms.ts +64 -0
  75. package/src/analytics/collectors/pageview.ts +76 -0
  76. package/src/analytics/collectors/scroll.ts +112 -0
  77. package/src/analytics/collectors/spa.ts +60 -0
  78. package/src/analytics/collectors/visibility.ts +94 -0
  79. package/src/analytics/collectors/webvitals.ts +129 -0
  80. package/src/analytics/events.ts +144 -0
  81. package/src/analytics/index.ts +21 -0
  82. package/src/analytics/offline.ts +163 -0
  83. package/src/analytics/types.ts +139 -0
  84. package/src/analytics/utils/storage.ts +64 -0
  85. package/src/analytics/utils/utm.ts +36 -0
  86. package/src/client/index.ts +109 -15
  87. package/src/client/types.ts +104 -17
  88. package/src/index.ts +18 -0
@@ -86,26 +86,61 @@ export interface StreamClient {
86
86
  */
87
87
  cancel(): Promise<void>;
88
88
  }
89
+ /**
90
+ * Options object for endpoints without path params (optional query support).
91
+ */
92
+ export interface EndpointOptionsWithQuery<Input = unknown, Query = Record<string, string>> {
93
+ input?: Input;
94
+ query?: Query;
95
+ }
96
+ /**
97
+ * Additional options that can be passed after positional path params.
98
+ */
99
+ export interface EndpointExtraOptions<Input = unknown, Query = Record<string, string>> {
100
+ input?: Input;
101
+ query?: Query;
102
+ }
103
+ /**
104
+ * Convert a path params object to a tuple of its value types.
105
+ * Used for positional argument typing.
106
+ * Note: For proper ordering, we rely on the generated PathParamsTuple type.
107
+ */
108
+ export type PathParamsToTuple<P> = P extends readonly [infer First, ...infer Rest] ? [First, ...PathParamsToTuple<Rest>] : P extends readonly [] ? [] : string[];
89
109
  /**
90
110
  * API endpoint - callable function for regular HTTP calls.
111
+ * - Without path params: accepts input directly OR options object with query
112
+ * - With path params: accepts positional arguments followed by optional options object
113
+ *
114
+ * @example
115
+ * // No path params
116
+ * client.hello.post({ name: 'World' })
117
+ *
118
+ * // Single path param
119
+ * client.users.userId.get('123')
120
+ *
121
+ * // Multiple path params
122
+ * client.orgs.orgId.members.memberId.get('org-1', 'user-2')
123
+ *
124
+ * // With additional options
125
+ * client.users.userId.get('123', { query: { include: 'posts' } })
91
126
  */
92
- export type APIEndpoint<Input = unknown, Output = unknown> = (input?: Input) => Promise<Output>;
127
+ export type APIEndpoint<Input = unknown, Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => Promise<Output> : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => Promise<Output>;
93
128
  /**
94
129
  * WebSocket endpoint - callable function that returns WebSocket client.
95
130
  */
96
- export type WebSocketEndpoint<Input = unknown, _Output = unknown> = (input?: Input) => WebSocketClient;
131
+ export type WebSocketEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => WebSocketClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => WebSocketClient;
97
132
  /**
98
133
  * Server-Sent Events endpoint - callable function that returns EventStream client.
99
134
  */
100
- export type SSEEndpoint<Input = unknown, _Output = unknown> = (input?: Input) => EventStreamClient;
135
+ export type SSEEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => EventStreamClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => EventStreamClient;
101
136
  /**
102
137
  * Streaming endpoint - callable function that returns Stream client.
103
138
  */
104
- export type StreamEndpoint<Input = unknown, _Output = unknown> = (input?: Input) => StreamClient;
139
+ export type StreamEndpoint<Input = unknown, _Output = unknown, PathParams = never, PathParamsTuple extends unknown[] = string[]> = [PathParams] extends [never] ? (inputOrOptions?: Input | EndpointOptionsWithQuery<Input>) => StreamClient : (...args: [...PathParamsTuple, options?: EndpointExtraOptions<Input>]) => StreamClient;
105
140
  /**
106
141
  * Route endpoint - discriminated union based on route type.
107
142
  */
108
- export type RouteEndpoint<Input = unknown, Output = unknown, Type extends string = 'api'> = Type extends 'websocket' ? WebSocketEndpoint<Input, Output> : Type extends 'sse' ? SSEEndpoint<Input, Output> : Type extends 'stream' ? StreamEndpoint<Input, Output> : APIEndpoint<Input, Output>;
143
+ export type RouteEndpoint<Input = unknown, Output = unknown, Type extends string = 'api', PathParams = never, PathParamsTuple extends unknown[] = []> = Type extends 'websocket' ? WebSocketEndpoint<Input, Output, PathParams, PathParamsTuple> : Type extends 'sse' ? SSEEndpoint<Input, Output, PathParams, PathParamsTuple> : Type extends 'stream' ? StreamEndpoint<Input, Output, PathParams, PathParamsTuple> : APIEndpoint<Input, Output, PathParams, PathParamsTuple>;
109
144
  /**
110
145
  * Recursively build the client proxy type from a RouteRegistry.
111
146
  */
@@ -114,6 +149,17 @@ export type Client<R> = {
114
149
  input: infer I;
115
150
  output: infer O;
116
151
  type: infer T;
152
+ params: infer P;
153
+ paramsTuple: infer PT;
154
+ } ? PT extends unknown[] ? RouteEndpoint<I, O, T extends string ? T : 'api', P, PT> : RouteEndpoint<I, O, T extends string ? T : 'api', P> : R[K] extends {
155
+ input: infer I;
156
+ output: infer O;
157
+ type: infer T;
158
+ params: infer P;
159
+ } ? RouteEndpoint<I, O, T extends string ? T : 'api', P> : R[K] extends {
160
+ input: infer I;
161
+ output: infer O;
162
+ type: infer T;
117
163
  } ? RouteEndpoint<I, O, T extends string ? T : 'api'> : R[K] extends {
118
164
  input: infer I;
119
165
  output: infer O;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export { WebSocketManager, type MessageHandler as WebSocketMessageHandler, type
8
8
  export { EventStreamManager, type MessageHandler as EventStreamMessageHandler, type EventStreamCallbacks, type EventStreamManagerOptions, type EventStreamManagerState, } from './eventstream-manager';
9
9
  export { createClient } from './client/index';
10
10
  export type { Client, ClientOptions, RouteEndpoint, WebSocketClient, EventStreamClient, StreamClient, EventHandler, } from './client/types';
11
+ export { getAnalytics, track, initBeacon, trackPageview, createBaseEvent, getVisitorId, isOptedOut, setOptOut, getUTMParams, type AnalyticsClient, type AnalyticsEvent, type AnalyticsEventType, type AnalyticsBatchPayload, type AnalyticsPageConfig, } from './analytics';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EACN,gBAAgB,EAChB,KAAK,cAAc,IAAI,uBAAuB,EAC9C,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,kBAAkB,EAClB,KAAK,cAAc,IAAI,yBAAyB,EAChD,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,GAC5B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACX,MAAM,EACN,aAAa,EACb,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACZ,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EACN,gBAAgB,EAChB,KAAK,cAAc,IAAI,uBAAuB,EAC9C,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,kBAAkB,EAClB,KAAK,cAAc,IAAI,yBAAyB,EAChD,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,GAC5B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACX,MAAM,EACN,aAAa,EACb,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACN,YAAY,EACZ,KAAK,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -7,4 +7,6 @@ export { WebSocketManager, } from './websocket-manager';
7
7
  export { EventStreamManager, } from './eventstream-manager';
8
8
  // Export client implementation (local to this package)
9
9
  export { createClient } from './client/index';
10
+ // Export analytics
11
+ export { getAnalytics, track, initBeacon, trackPageview, createBaseEvent, getVisitorId, isOptedOut, setOptOut, getUTMParams, } from './analytics';
10
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAgD,MAAM,aAAa,CAAC;AAEnG,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EACN,gBAAgB,GAKhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,kBAAkB,GAKlB,MAAM,uBAAuB,CAAC;AAE/B,uDAAuD;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAgD,MAAM,aAAa,CAAC;AAEnG,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EACN,gBAAgB,GAKhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,kBAAkB,GAKlB,MAAM,uBAAuB,CAAC;AAE/B,uDAAuD;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAW9C,mBAAmB;AACnB,OAAO,EACN,YAAY,EACZ,KAAK,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,GAMZ,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentuity/frontend",
3
- "version": "0.0.110",
3
+ "version": "0.0.112",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Agentuity employees and contributors",
6
6
  "type": "module",
@@ -26,10 +26,10 @@
26
26
  "prepublishOnly": "bun run clean && bun run build"
27
27
  },
28
28
  "dependencies": {
29
- "@agentuity/core": "0.0.110"
29
+ "@agentuity/core": "0.0.112"
30
30
  },
31
31
  "devDependencies": {
32
- "@agentuity/test-utils": "0.0.110",
32
+ "@agentuity/test-utils": "0.0.112",
33
33
  "@types/bun": "latest",
34
34
  "bun-types": "latest",
35
35
  "typescript": "^5.9.0"
@@ -0,0 +1,203 @@
1
+ import type { AnalyticsPageConfig, AnalyticsClient } from './types';
2
+ import { initEventQueue, queueEvent, flushEvents } from './events';
3
+ import { initPageviewTracking, createBaseEvent, trackPageview } from './collectors/pageview';
4
+ import { initSPATracking } from './collectors/spa';
5
+ import { initClickTracking, initOutboundLinkTracking } from './collectors/clicks';
6
+ import { initScrollTracking } from './collectors/scroll';
7
+ import { initErrorTracking } from './collectors/errors';
8
+ import { initVisibilityTracking } from './collectors/visibility';
9
+ import { initFormTracking } from './collectors/forms';
10
+ import { initWebVitalsTracking } from './collectors/webvitals';
11
+ import { isOptedOut, setOptOut } from './utils/storage';
12
+ import { initOfflineSupport, getAndClearOfflineEvents } from './offline';
13
+
14
+ let initialized = false;
15
+ let trackingStarted = false;
16
+ let analyticsEnabled = true;
17
+ let consentRequired = false;
18
+ let consentGiven = false;
19
+
20
+ /**
21
+ * Check if analytics should run
22
+ */
23
+ function shouldTrack(): boolean {
24
+ if (!analyticsEnabled) return false;
25
+ if (isOptedOut()) return false;
26
+ if (consentRequired && !consentGiven) return false;
27
+ return true;
28
+ }
29
+
30
+ /**
31
+ * Initialize the analytics beacon
32
+ * Called automatically when the script loads
33
+ */
34
+ export function initBeacon(): void {
35
+ if (initialized) {
36
+ return;
37
+ }
38
+
39
+ const config = window.__AGENTUITY_ANALYTICS__;
40
+ if (!config || !config.enabled) {
41
+ analyticsEnabled = false;
42
+ return;
43
+ }
44
+
45
+ initialized = true;
46
+ consentRequired = config.requireConsent ?? false;
47
+
48
+ // If consent is required and not given, wait for optIn
49
+ if (consentRequired && !consentGiven) {
50
+ return;
51
+ }
52
+
53
+ startTracking(config);
54
+ }
55
+
56
+ /**
57
+ * Start all tracking based on config
58
+ */
59
+ function startTracking(config: AnalyticsPageConfig): void {
60
+ if (trackingStarted) {
61
+ return;
62
+ }
63
+ trackingStarted = true;
64
+
65
+ // Initialize event queue
66
+ initEventQueue(config);
67
+
68
+ // Initialize offline support
69
+ initOfflineSupport(async () => {
70
+ // Flush offline events when coming back online
71
+ const offlineEvents = await getAndClearOfflineEvents();
72
+ for (const event of offlineEvents) {
73
+ queueEvent(event);
74
+ }
75
+ flushEvents();
76
+ });
77
+
78
+ // Always track pageviews
79
+ initPageviewTracking();
80
+
81
+ // Initialize visibility tracking (for time on page)
82
+ initVisibilityTracking();
83
+
84
+ // Conditional tracking based on config (all default to true except requireConsent)
85
+ if (config.trackSPANavigation !== false) {
86
+ initSPATracking();
87
+ }
88
+
89
+ if (config.trackClicks !== false) {
90
+ initClickTracking();
91
+ }
92
+
93
+ if (config.trackOutboundLinks !== false) {
94
+ initOutboundLinkTracking();
95
+ }
96
+
97
+ if (config.trackScroll !== false) {
98
+ initScrollTracking();
99
+ }
100
+
101
+ if (config.trackErrors !== false) {
102
+ initErrorTracking();
103
+ }
104
+
105
+ if (config.trackForms !== false) {
106
+ initFormTracking();
107
+ }
108
+
109
+ if (config.trackWebVitals !== false) {
110
+ initWebVitalsTracking();
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Create the analytics client API
116
+ */
117
+ function createClient(): AnalyticsClient {
118
+ return {
119
+ track(eventName: string, properties?: Record<string, unknown>): void {
120
+ if (!shouldTrack()) return;
121
+
122
+ const event = createBaseEvent('custom');
123
+ event.event_name = eventName;
124
+ if (properties) {
125
+ event.event_data = properties;
126
+ }
127
+ queueEvent(event);
128
+ },
129
+
130
+ identify(userId: string, traits?: Record<string, unknown>): void {
131
+ if (!shouldTrack()) return;
132
+
133
+ const event = createBaseEvent('custom');
134
+ event.event_name = 'identify';
135
+ event.event_data = {
136
+ user_id: userId,
137
+ ...traits,
138
+ };
139
+ queueEvent(event);
140
+ },
141
+
142
+ pageview(path?: string): void {
143
+ if (!shouldTrack()) return;
144
+ trackPageview(path);
145
+ },
146
+
147
+ async flush(): Promise<void> {
148
+ flushEvents();
149
+ },
150
+
151
+ optOut(): void {
152
+ setOptOut(true);
153
+ analyticsEnabled = false;
154
+ },
155
+
156
+ optIn(): void {
157
+ setOptOut(false);
158
+ analyticsEnabled = true;
159
+ consentGiven = true;
160
+
161
+ // If consent was required and now given, start tracking
162
+ if (consentRequired && !trackingStarted) {
163
+ const config = window.__AGENTUITY_ANALYTICS__;
164
+ if (config) {
165
+ startTracking(config);
166
+ }
167
+ }
168
+ },
169
+
170
+ isEnabled(): boolean {
171
+ return shouldTrack();
172
+ },
173
+ };
174
+ }
175
+
176
+ // Singleton client instance
177
+ let clientInstance: AnalyticsClient | null = null;
178
+
179
+ /**
180
+ * Get the analytics client instance
181
+ */
182
+ export function getAnalytics(): AnalyticsClient {
183
+ if (!clientInstance) {
184
+ clientInstance = createClient();
185
+ }
186
+ return clientInstance;
187
+ }
188
+
189
+ /**
190
+ * Convenience function to track a custom event
191
+ */
192
+ export function track(eventName: string, properties?: Record<string, unknown>): void {
193
+ getAnalytics().track(eventName, properties);
194
+ }
195
+
196
+ // Auto-initialize when script loads
197
+ if (typeof window !== 'undefined') {
198
+ if (document.readyState === 'loading') {
199
+ document.addEventListener('DOMContentLoaded', initBeacon);
200
+ } else {
201
+ initBeacon();
202
+ }
203
+ }
@@ -0,0 +1,100 @@
1
+ import { createBaseEvent } from './pageview';
2
+ import { queueEvent } from '../events';
3
+
4
+ /**
5
+ * Initialize click tracking
6
+ * Tracks clicks on elements with data-analytics attribute
7
+ */
8
+ export function initClickTracking(): void {
9
+ if (typeof document === 'undefined') {
10
+ return;
11
+ }
12
+
13
+ document.addEventListener(
14
+ 'click',
15
+ (e) => {
16
+ const target = e.target as HTMLElement | null;
17
+ if (!target) return;
18
+
19
+ // Find closest element with data-analytics attribute
20
+ const analyticsElement = target.closest('[data-analytics]');
21
+ if (!analyticsElement) return;
22
+
23
+ const eventName = analyticsElement.getAttribute('data-analytics');
24
+ if (!eventName) return;
25
+
26
+ const event = createBaseEvent('click');
27
+ event.event_name = eventName;
28
+
29
+ // Collect additional data attributes
30
+ const eventData: Record<string, unknown> = {};
31
+ for (const attr of Array.from(analyticsElement.attributes)) {
32
+ if (attr.name.startsWith('data-analytics-')) {
33
+ const key = attr.name.replace('data-analytics-', '');
34
+ eventData[key] = attr.value;
35
+ }
36
+ }
37
+
38
+ // Add element info
39
+ eventData.tag = analyticsElement.tagName.toLowerCase();
40
+ if (analyticsElement.id) {
41
+ eventData.id = analyticsElement.id;
42
+ }
43
+ const text = (analyticsElement as HTMLElement).innerText?.slice(0, 100);
44
+ if (text) {
45
+ eventData.text = text;
46
+ }
47
+
48
+ if (Object.keys(eventData).length > 0) {
49
+ event.event_data = eventData;
50
+ }
51
+
52
+ queueEvent(event);
53
+ },
54
+ { capture: true, passive: true }
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Initialize outbound link tracking
60
+ */
61
+ export function initOutboundLinkTracking(): void {
62
+ if (typeof document === 'undefined') {
63
+ return;
64
+ }
65
+
66
+ document.addEventListener(
67
+ 'click',
68
+ (e) => {
69
+ const target = e.target as HTMLElement | null;
70
+ if (!target) return;
71
+
72
+ const link = target.closest('a');
73
+ if (!link) return;
74
+
75
+ const href = link.href;
76
+ if (!href) return;
77
+
78
+ // Check if it's an outbound link
79
+ try {
80
+ const url = new URL(href, window.location.origin);
81
+ if (url.hostname === window.location.hostname) {
82
+ return; // Same domain, not outbound
83
+ }
84
+
85
+ const event = createBaseEvent('outbound_link');
86
+ event.event_name = 'outbound_link';
87
+ event.event_data = {
88
+ href,
89
+ hostname: url.hostname,
90
+ text: link.innerText?.slice(0, 100) || '',
91
+ };
92
+
93
+ queueEvent(event);
94
+ } catch {
95
+ // Invalid URL, ignore
96
+ }
97
+ },
98
+ { capture: true, passive: true }
99
+ );
100
+ }
@@ -0,0 +1,49 @@
1
+ import { createBaseEvent } from './pageview';
2
+ import { queueEvent } from '../events';
3
+
4
+ /**
5
+ * Initialize JavaScript error tracking
6
+ */
7
+ export function initErrorTracking(): void {
8
+ if (typeof window === 'undefined') {
9
+ return;
10
+ }
11
+
12
+ // Handle uncaught errors
13
+ window.addEventListener('error', (e) => {
14
+ const event = createBaseEvent('error');
15
+ event.event_name = 'js_error';
16
+ event.event_data = {
17
+ message: e.message || 'Unknown error',
18
+ filename: e.filename || '',
19
+ lineno: e.lineno || 0,
20
+ colno: e.colno || 0,
21
+ stack: e.error?.stack?.slice(0, 1000) || '',
22
+ };
23
+
24
+ queueEvent(event);
25
+ });
26
+
27
+ // Handle unhandled promise rejections
28
+ window.addEventListener('unhandledrejection', (e) => {
29
+ const event = createBaseEvent('error');
30
+ event.event_name = 'unhandled_rejection';
31
+
32
+ let message = 'Unhandled Promise Rejection';
33
+ let stack = '';
34
+
35
+ if (e.reason instanceof Error) {
36
+ message = e.reason.message;
37
+ stack = e.reason.stack?.slice(0, 1000) || '';
38
+ } else if (typeof e.reason === 'string') {
39
+ message = e.reason;
40
+ }
41
+
42
+ event.event_data = {
43
+ message,
44
+ stack,
45
+ };
46
+
47
+ queueEvent(event);
48
+ });
49
+ }
@@ -0,0 +1,64 @@
1
+ import { createBaseEvent } from './pageview';
2
+ import { queueEvent } from '../events';
3
+
4
+ /**
5
+ * Initialize form submission tracking
6
+ */
7
+ export function initFormTracking(): void {
8
+ if (typeof document === 'undefined') {
9
+ return;
10
+ }
11
+
12
+ document.addEventListener(
13
+ 'submit',
14
+ (e) => {
15
+ const form = e.target as HTMLFormElement | null;
16
+ if (!form || form.tagName !== 'FORM') {
17
+ return;
18
+ }
19
+
20
+ const event = createBaseEvent('form_submit');
21
+ event.event_name = 'form_submit';
22
+
23
+ const eventData: Record<string, unknown> = {};
24
+
25
+ // Form identification
26
+ if (form.id) {
27
+ eventData.form_id = form.id;
28
+ }
29
+ if (form.name) {
30
+ eventData.form_name = form.name;
31
+ }
32
+ if (form.action) {
33
+ eventData.form_action = form.action;
34
+ }
35
+ eventData.form_method = form.method || 'get';
36
+
37
+ // Count form fields (don't capture values for privacy)
38
+ const inputs = form.querySelectorAll('input, select, textarea');
39
+ eventData.field_count = inputs.length;
40
+
41
+ // Check for common form types
42
+ const hasEmail = form.querySelector('input[type="email"]') !== null;
43
+ const hasPassword = form.querySelector('input[type="password"]') !== null;
44
+ const hasSearch = form.querySelector('input[type="search"]') !== null;
45
+
46
+ if (hasEmail && hasPassword) {
47
+ eventData.form_type = 'auth';
48
+ } else if (hasEmail) {
49
+ eventData.form_type = 'email';
50
+ } else if (hasSearch) {
51
+ eventData.form_type = 'search';
52
+ } else if (hasPassword) {
53
+ eventData.form_type = 'password';
54
+ } else {
55
+ eventData.form_type = 'other';
56
+ }
57
+
58
+ event.event_data = eventData;
59
+
60
+ queueEvent(event);
61
+ },
62
+ { capture: true }
63
+ );
64
+ }
@@ -0,0 +1,76 @@
1
+ import type { AnalyticsEvent } from '../types';
2
+ import { queueEvent } from '../events';
3
+ import { getUTMParams } from '../utils/utm';
4
+
5
+ /**
6
+ * Create a base event with common properties
7
+ */
8
+ export function createBaseEvent(eventType: AnalyticsEvent['event_type']): AnalyticsEvent {
9
+ const utm = getUTMParams();
10
+
11
+ return {
12
+ id: crypto.randomUUID
13
+ ? crypto.randomUUID()
14
+ : `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
15
+ timestamp: Date.now(),
16
+ timezone_offset: new Date().getTimezoneOffset(),
17
+
18
+ event_type: eventType,
19
+
20
+ url: window.location.href,
21
+ path: window.location.pathname,
22
+ referrer: document.referrer || '',
23
+ title: document.title || '',
24
+
25
+ screen_width: window.screen?.width || 0,
26
+ screen_height: window.screen?.height || 0,
27
+ viewport_width: window.innerWidth || 0,
28
+ viewport_height: window.innerHeight || 0,
29
+ device_pixel_ratio: window.devicePixelRatio || 1,
30
+ user_agent: navigator.userAgent || '',
31
+ language: navigator.language || '',
32
+
33
+ ...utm,
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Track a pageview event
39
+ */
40
+ export function trackPageview(customPath?: string): void {
41
+ const event = createBaseEvent('pageview');
42
+
43
+ if (customPath) {
44
+ event.path = customPath;
45
+ event.url = window.location.origin + customPath;
46
+ }
47
+
48
+ // Add performance timing if available
49
+ if (typeof performance !== 'undefined') {
50
+ const timing = performance.getEntriesByType('navigation')[0] as
51
+ | PerformanceNavigationTiming
52
+ | undefined;
53
+ if (timing) {
54
+ event.load_time = Math.round(timing.loadEventEnd - timing.startTime);
55
+ event.dom_ready = Math.round(timing.domContentLoadedEventEnd - timing.startTime);
56
+ event.ttfb = Math.round(timing.responseStart - timing.requestStart);
57
+ }
58
+ }
59
+
60
+ queueEvent(event);
61
+ }
62
+
63
+ /**
64
+ * Initialize pageview tracking
65
+ * Tracks initial pageview when called
66
+ */
67
+ export function initPageviewTracking(): void {
68
+ // Track initial pageview after DOM is ready
69
+ if (document.readyState === 'complete') {
70
+ trackPageview();
71
+ } else {
72
+ window.addEventListener('load', () => {
73
+ trackPageview();
74
+ });
75
+ }
76
+ }