@stacksjs/ts-analytics 0.1.6

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 (237) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +361 -0
  4. package/bin/cli.ts +169 -0
  5. package/dist/Analytics.d.ts +558 -0
  6. package/dist/api.d.ts +109 -0
  7. package/dist/batching.d.ts +93 -0
  8. package/dist/chunk-2mx7fq49.js +4 -0
  9. package/dist/chunk-3z29508k.js +204 -0
  10. package/dist/chunk-deephkz6.js +56 -0
  11. package/dist/chunk-j261vgyp.js +305 -0
  12. package/dist/chunk-xga17tz7.js +207 -0
  13. package/dist/config.d.ts +132 -0
  14. package/dist/dashboard/components/index.d.ts +80 -0
  15. package/dist/dashboard/composables/useAnalytics.d.ts +99 -0
  16. package/dist/dashboard/index.d.ts +110 -0
  17. package/dist/dashboard/types/index.d.ts +144 -0
  18. package/dist/dashboard/utils/index.d.ts +81 -0
  19. package/dist/dynamodb.d.ts +86 -0
  20. package/dist/funnels.d.ts +104 -0
  21. package/dist/geolocation.d.ts +96 -0
  22. package/dist/index.d.ts +371 -0
  23. package/dist/index.js +10211 -0
  24. package/dist/infrastructure/cdk.d.ts +60 -0
  25. package/dist/infrastructure/cloudformation.d.ts +44 -0
  26. package/dist/infrastructure/index.d.ts +45 -0
  27. package/dist/infrastructure/setup.d.ts +133 -0
  28. package/dist/integrations/cloudflare.d.ts +76 -0
  29. package/dist/integrations/hono.d.ts +60 -0
  30. package/dist/integrations/index.d.ts +24 -0
  31. package/dist/integrations/nuxt.d.ts +7 -0
  32. package/dist/integrations/nuxt.js +42 -0
  33. package/dist/integrations/runtime/use-ts-analytics.d.ts +18 -0
  34. package/dist/integrations/runtime/use-ts-analytics.js +17 -0
  35. package/dist/integrations/stx.d.ts +88 -0
  36. package/dist/integrations/stx.js +18 -0
  37. package/dist/lib/crypto-random.d.ts +4 -0
  38. package/dist/lib/salt.d.ts +16 -0
  39. package/dist/local.d.ts +56 -0
  40. package/dist/model-connector.d.ts +145 -0
  41. package/dist/models/AggregatedStats.d.ts +9 -0
  42. package/dist/models/CampaignStats.d.ts +9 -0
  43. package/dist/models/Conversion.d.ts +11 -0
  44. package/dist/models/CustomEvent.d.ts +11 -0
  45. package/dist/models/DeviceStats.d.ts +9 -0
  46. package/dist/models/EventStats.d.ts +9 -0
  47. package/dist/models/GeoStats.d.ts +9 -0
  48. package/dist/models/Goal.d.ts +9 -0
  49. package/dist/models/GoalStats.d.ts +9 -0
  50. package/dist/models/PageStats.d.ts +11 -0
  51. package/dist/models/PageView.d.ts +13 -0
  52. package/dist/models/RealtimeStats.d.ts +9 -0
  53. package/dist/models/ReferrerStats.d.ts +9 -0
  54. package/dist/models/Session.d.ts +11 -0
  55. package/dist/models/Site.d.ts +11 -0
  56. package/dist/models/index.d.ts +28 -0
  57. package/dist/models/types.d.ts +60 -0
  58. package/dist/sqs-buffering.d.ts +243 -0
  59. package/dist/stacks-integration.d.ts +159 -0
  60. package/dist/tracking-script.d.ts +71 -0
  61. package/dist/tracking.d.ts +17 -0
  62. package/dist/tracking.js +26 -0
  63. package/dist/types.d.ts +595 -0
  64. package/dist/utils/geolocation.d.ts +111 -0
  65. package/dist/utils/user-agent.d.ts +17 -0
  66. package/dist/version.d.ts +7 -0
  67. package/package.json +119 -0
  68. package/src/Analytics.ts +3349 -0
  69. package/src/api.ts +1286 -0
  70. package/src/assets/crosswind.css +2220 -0
  71. package/src/batching.ts +452 -0
  72. package/src/components/dashboard/index.ts +18 -0
  73. package/src/config.ts +456 -0
  74. package/src/dashboard/Dashboard.stx +1517 -0
  75. package/src/dashboard/components/AlertCard.stx +177 -0
  76. package/src/dashboard/components/AnalyticsDashboard.stx +354 -0
  77. package/src/dashboard/components/AnimatedNumber.stx +86 -0
  78. package/src/dashboard/components/BarChart.stx +220 -0
  79. package/src/dashboard/components/BrowserBreakdown.stx +98 -0
  80. package/src/dashboard/components/BrowsersTable.stx +125 -0
  81. package/src/dashboard/components/CampaignBreakdown.stx +163 -0
  82. package/src/dashboard/components/CampaignTable.stx +238 -0
  83. package/src/dashboard/components/CountryList.stx +101 -0
  84. package/src/dashboard/components/DataTable.stx +226 -0
  85. package/src/dashboard/components/DateRangePicker.stx +77 -0
  86. package/src/dashboard/components/DeviceBreakdown.stx +94 -0
  87. package/src/dashboard/components/DevicesTable.stx +163 -0
  88. package/src/dashboard/components/DonutChart.stories.ts +55 -0
  89. package/src/dashboard/components/DonutChart.stx +157 -0
  90. package/src/dashboard/components/EmptyState.stx +90 -0
  91. package/src/dashboard/components/EngagementMetrics.stx +183 -0
  92. package/src/dashboard/components/EventsSection.stx +192 -0
  93. package/src/dashboard/components/FilterBar.stx +104 -0
  94. package/src/dashboard/components/FullAnalyticsDashboard.stx +455 -0
  95. package/src/dashboard/components/FunnelChart.stx +142 -0
  96. package/src/dashboard/components/GeoTable.stx +337 -0
  97. package/src/dashboard/components/GoalsPanel.stx +109 -0
  98. package/src/dashboard/components/Header.stx +39 -0
  99. package/src/dashboard/components/HeatmapChart.stx +140 -0
  100. package/src/dashboard/components/LiveActivityFeed.stx +172 -0
  101. package/src/dashboard/components/MetricComparison.stx +106 -0
  102. package/src/dashboard/components/MiniStats.stx +96 -0
  103. package/src/dashboard/components/OSBreakdown.stx +124 -0
  104. package/src/dashboard/components/PageDetailCard.stx +102 -0
  105. package/src/dashboard/components/PagesTable.stx +127 -0
  106. package/src/dashboard/components/ProgressRing.stx +89 -0
  107. package/src/dashboard/components/RealtimeCounter.stories.ts +45 -0
  108. package/src/dashboard/components/RealtimeCounter.stx +46 -0
  109. package/src/dashboard/components/ReferrersTable.stx +180 -0
  110. package/src/dashboard/components/SparklineChart.stx +160 -0
  111. package/src/dashboard/components/StatCard.stories.ts +58 -0
  112. package/src/dashboard/components/StatCard.stx +90 -0
  113. package/src/dashboard/components/SummaryStats.stx +81 -0
  114. package/src/dashboard/components/TabNav.stx +66 -0
  115. package/src/dashboard/components/ThemeSwitcher.stx +124 -0
  116. package/src/dashboard/components/TimeSeriesChart.stx +106 -0
  117. package/src/dashboard/components/TopList.stories.ts +58 -0
  118. package/src/dashboard/components/TopList.stx +74 -0
  119. package/src/dashboard/components/TrendIndicator.stx +84 -0
  120. package/src/dashboard/components/heatmap/ClickHeatmap.stx +264 -0
  121. package/src/dashboard/components/heatmap/ElementClickList.stx +125 -0
  122. package/src/dashboard/components/heatmap/HeatmapControls.stx +125 -0
  123. package/src/dashboard/components/heatmap/HeatmapLegend.stx +69 -0
  124. package/src/dashboard/components/heatmap/PageHeatmap.stx +264 -0
  125. package/src/dashboard/components/heatmap/ScrollHeatmap.stx +127 -0
  126. package/src/dashboard/components/heatmap/index.ts +12 -0
  127. package/src/dashboard/components/index.ts +86 -0
  128. package/src/dashboard/composables/useAnalytics.ts +465 -0
  129. package/src/dashboard/demo/DemoApp.stx +370 -0
  130. package/src/dashboard/demo/index.ts +8 -0
  131. package/src/dashboard/demo/mockData.ts +234 -0
  132. package/src/dashboard/index.ts +117 -0
  133. package/src/dashboard/stx-shim.d.ts +4 -0
  134. package/src/dashboard/types/index.ts +203 -0
  135. package/src/dashboard/utils/index.ts +426 -0
  136. package/src/dynamodb.ts +344 -0
  137. package/src/funnels.ts +534 -0
  138. package/src/geolocation.ts +515 -0
  139. package/src/handlers/alerts.ts +328 -0
  140. package/src/handlers/annotations.ts +128 -0
  141. package/src/handlers/api-keys.ts +240 -0
  142. package/src/handlers/auth.ts +1020 -0
  143. package/src/handlers/authz.ts +137 -0
  144. package/src/handlers/collect.ts +724 -0
  145. package/src/handlers/data.ts +625 -0
  146. package/src/handlers/experiments.ts +138 -0
  147. package/src/handlers/funnels.ts +216 -0
  148. package/src/handlers/goals.ts +218 -0
  149. package/src/handlers/heatmaps.ts +272 -0
  150. package/src/handlers/index.ts +56 -0
  151. package/src/handlers/lib/read-cache.ts +63 -0
  152. package/src/handlers/misc.ts +486 -0
  153. package/src/handlers/oauth.ts +233 -0
  154. package/src/handlers/performance.ts +388 -0
  155. package/src/handlers/sessions.ts +413 -0
  156. package/src/handlers/sharing.ts +198 -0
  157. package/src/handlers/stats.ts +1368 -0
  158. package/src/handlers/team.ts +161 -0
  159. package/src/handlers/uptime.ts +283 -0
  160. package/src/handlers/views.ts +390 -0
  161. package/src/handlers/webhooks.ts +226 -0
  162. package/src/heatmap/index.ts +32 -0
  163. package/src/heatmap/tracking-script.ts +452 -0
  164. package/src/heatmap/types.ts +79 -0
  165. package/src/index.ts +387 -0
  166. package/src/infrastructure/cdk.ts +496 -0
  167. package/src/infrastructure/cloudformation.ts +595 -0
  168. package/src/infrastructure/index.ts +48 -0
  169. package/src/infrastructure/setup.ts +611 -0
  170. package/src/integrations/cloudflare.ts +732 -0
  171. package/src/integrations/hono.ts +589 -0
  172. package/src/integrations/index.ts +27 -0
  173. package/src/integrations/nuxt.ts +78 -0
  174. package/src/integrations/runtime/use-ts-analytics.ts +32 -0
  175. package/src/integrations/stx.ts +138 -0
  176. package/src/jobs/index.ts +127 -0
  177. package/src/lib/crypto-random.ts +41 -0
  178. package/src/lib/ddb-errors.ts +20 -0
  179. package/src/lib/dynamodb.ts +216 -0
  180. package/src/lib/email.ts +38 -0
  181. package/src/lib/ga-import.ts +471 -0
  182. package/src/lib/ga4-api.ts +244 -0
  183. package/src/lib/goals.ts +205 -0
  184. package/src/lib/index.ts +6 -0
  185. package/src/lib/ingest-counters.ts +123 -0
  186. package/src/lib/log.ts +36 -0
  187. package/src/lib/membership.ts +98 -0
  188. package/src/lib/plans.ts +90 -0
  189. package/src/lib/quota.ts +46 -0
  190. package/src/lib/rate-limit.ts +27 -0
  191. package/src/lib/rollups.ts +472 -0
  192. package/src/lib/salt.ts +97 -0
  193. package/src/lib/scheduler.ts +97 -0
  194. package/src/lib/significance.ts +66 -0
  195. package/src/lib/site-retention.ts +56 -0
  196. package/src/local.ts +360 -0
  197. package/src/model-connector.ts +616 -0
  198. package/src/models/AggregatedStats.ts +162 -0
  199. package/src/models/CampaignStats.ts +141 -0
  200. package/src/models/Conversion.ts +135 -0
  201. package/src/models/CustomEvent.ts +123 -0
  202. package/src/models/DeviceStats.ts +105 -0
  203. package/src/models/EventStats.ts +108 -0
  204. package/src/models/GeoStats.ts +112 -0
  205. package/src/models/Goal.ts +105 -0
  206. package/src/models/GoalStats.ts +106 -0
  207. package/src/models/PageStats.ts +152 -0
  208. package/src/models/PageView.ts +277 -0
  209. package/src/models/RealtimeStats.ts +96 -0
  210. package/src/models/ReferrerStats.ts +115 -0
  211. package/src/models/Session.ts +235 -0
  212. package/src/models/Site.ts +115 -0
  213. package/src/models/index.ts +50 -0
  214. package/src/models/orm/index.ts +2043 -0
  215. package/src/models/types.ts +71 -0
  216. package/src/router.ts +521 -0
  217. package/src/sqs-buffering.ts +806 -0
  218. package/src/stacks-integration.ts +527 -0
  219. package/src/tracking-script.ts +944 -0
  220. package/src/tracking.ts +27 -0
  221. package/src/types/analytics.ts +219 -0
  222. package/src/types/api.ts +75 -0
  223. package/src/types/bun-router.d.ts +15 -0
  224. package/src/types/dashboard.ts +62 -0
  225. package/src/types/index.ts +66 -0
  226. package/src/types/stx.d.ts +27 -0
  227. package/src/types/window.d.ts +101 -0
  228. package/src/types.ts +911 -0
  229. package/src/utils/cache.ts +148 -0
  230. package/src/utils/date.ts +118 -0
  231. package/src/utils/filters.ts +71 -0
  232. package/src/utils/geolocation.ts +323 -0
  233. package/src/utils/index.ts +9 -0
  234. package/src/utils/response.ts +180 -0
  235. package/src/utils/timezone-country.ts +242 -0
  236. package/src/utils/user-agent.ts +110 -0
  237. package/src/version.ts +7 -0
@@ -0,0 +1,558 @@
1
+ import type { AggregatedStats, AggregationPeriod, AnalyticsStoreOptions, CampaignStats, CustomEvent, DeviceStats, DeviceType, EventStats, GeoStats, Goal, GoalStats, GoalType, PageStats, PageView, RealtimeStats, ReferrerStats, Session, Site, SiteSettings } from './types';
2
+ // Re-export types from types.ts
3
+ export type {
4
+ AggregatedStats,
5
+ AggregationPeriod,
6
+ AnalyticsStoreOptions,
7
+ CampaignStats,
8
+ CustomEvent,
9
+ DeviceStats,
10
+ DeviceType,
11
+ EventStats,
12
+ GeoStats,
13
+ Goal,
14
+ GoalStats,
15
+ GoalType,
16
+ PageStats,
17
+ PageView,
18
+ RealtimeStats,
19
+ ReferrerStats,
20
+ Session,
21
+ Site,
22
+ SiteSettings,
23
+ };
24
+ /**
25
+ * Generate minimal tracking script
26
+ */
27
+ /* eslint-disable prefer-const, pickier/no-unused-vars, general/prefer-template */
28
+ export declare function generateTrackingScript(options: TrackingScriptOptions): string;
29
+ /**
30
+ * DynamoDB key patterns for analytics entities
31
+ */
32
+ export declare const AnalyticsKeyPatterns: ({
33
+ // Sites
34
+ site: {
35
+ pk: (siteId: string)) => string;
36
+ /**
37
+ * Aggregator options
38
+ */
39
+ export declare interface AggregatorOptions {
40
+ store: AnalyticsStore
41
+ batchSize?: number
42
+ }
43
+ /**
44
+ * Result of a goal match check
45
+ */
46
+ export declare interface GoalMatchResult {
47
+ matched: boolean
48
+ goal: Goal
49
+ value: number
50
+ trigger: PageView | CustomEvent
51
+ timestamp: Date
52
+ }
53
+ /**
54
+ * Conversion record for storage
55
+ */
56
+ export declare interface Conversion {
57
+ id: string
58
+ siteId: string
59
+ goalId: string
60
+ visitorId: string
61
+ sessionId: string
62
+ value: number
63
+ path: string
64
+ timestamp: Date
65
+ ttl?: number
66
+ }
67
+ /**
68
+ * Date range for queries
69
+ */
70
+ export declare interface DateRange {
71
+ start: Date
72
+ end: Date
73
+ }
74
+ /**
75
+ * Dashboard summary data
76
+ */
77
+ export declare interface DashboardSummary {
78
+ pageViews: number
79
+ uniqueVisitors: number
80
+ sessions: number
81
+ bounceRate: number
82
+ avgSessionDuration: number
83
+ avgPagesPerSession: number
84
+ comparison?: {
85
+ pageViewsChange: number
86
+ visitorsChange: number
87
+ bounceRateChange: number
88
+ }
89
+ }
90
+ /**
91
+ * Time series data point
92
+ */
93
+ export declare interface TimeSeriesPoint {
94
+ timestamp: string
95
+ pageViews: number
96
+ uniqueVisitors: number
97
+ sessions: number
98
+ bounceRate: number
99
+ }
100
+ /**
101
+ * Top item (page, referrer, country, etc.)
102
+ */
103
+ export declare interface TopItem {
104
+ name: string
105
+ value: number
106
+ percentage: number
107
+ change?: number
108
+ }
109
+ /**
110
+ * Dashboard data response
111
+ */
112
+ export declare interface DashboardData {
113
+ summary: DashboardSummary
114
+ timeSeries: TimeSeriesPoint[]
115
+ topPages: TopItem[]
116
+ topReferrers: TopItem[]
117
+ topCountries: TopItem[]
118
+ topDevices: TopItem[]
119
+ topBrowsers: TopItem[]
120
+ goals?: GoalPerformance[]
121
+ realtime?: RealtimeData
122
+ }
123
+ /**
124
+ * Goal performance data
125
+ */
126
+ export declare interface GoalPerformance {
127
+ goalId: string
128
+ goalName: string
129
+ conversions: number
130
+ conversionRate: number
131
+ revenue: number
132
+ }
133
+ /**
134
+ * Realtime dashboard data
135
+ */
136
+ export declare interface RealtimeData {
137
+ currentVisitors: number
138
+ pageViewsLastHour: number
139
+ topActivePages: TopItem[]
140
+ }
141
+ /**
142
+ * Query options
143
+ */
144
+ export declare interface QueryOptions {
145
+ siteId: string
146
+ dateRange: DateRange
147
+ includeComparison?: boolean
148
+ includeRealtime?: boolean
149
+ includeGoals?: boolean
150
+ topLimit?: number
151
+ timezone?: string
152
+ }
153
+ /**
154
+ * Pipeline job configuration
155
+ */
156
+ export declare interface PipelineJobConfig {
157
+ siteId: string
158
+ period: AggregationPeriod
159
+ windowStart: Date
160
+ windowEnd: Date
161
+ deleteRawEvents?: boolean
162
+ }
163
+ /**
164
+ * Pipeline job result
165
+ */
166
+ export declare interface PipelineJobResult {
167
+ config: PipelineJobConfig
168
+ success: boolean
169
+ error?: string
170
+ pageViewsProcessed: number
171
+ sessionsProcessed: number
172
+ eventsProcessed: number
173
+ conversionsTracked: number
174
+ commands: Array<{
175
+ command: string
176
+ input: Record<string, unknown>
177
+ }>
178
+ durationMs: number
179
+ }
180
+ /**
181
+ * Aggregation job status
182
+ */
183
+ export declare interface AggregationJobStatus {
184
+ jobId: string
185
+ siteId: string
186
+ period: AggregationPeriod
187
+ status: 'pending' | 'running' | 'completed' | 'failed'
188
+ startedAt?: Date
189
+ completedAt?: Date
190
+ error?: string
191
+ progress: number
192
+ }
193
+ /**
194
+ * Options for generating tracking script
195
+ */
196
+ export declare interface TrackingScriptOptions {
197
+ siteId: string
198
+ apiEndpoint: string
199
+ honorDnt?: boolean
200
+ trackHashChanges?: boolean
201
+ trackOutboundLinks?: boolean
202
+ trackLinkClicks?: boolean
203
+ trackSpaRoutes?: boolean
204
+ trackEngagement?: boolean
205
+ stealthMode?: boolean
206
+ trackWebVitals?: boolean
207
+ }
208
+ /**
209
+ * Analytics Store for DynamoDB
210
+ */
211
+ export declare class AnalyticsStore {
212
+ constructor(options: AnalyticsStoreOptions);
213
+ createSiteCommand(site: Site): {
214
+ command: 'PutItem'
215
+ input: {
216
+ TableName: string
217
+ Item: Record<string, unknown>
218
+ ConditionExpression: string
219
+ }
220
+ };
221
+ getSiteCommand(siteId: string): {
222
+ command: 'GetItem'
223
+ input: {
224
+ TableName: string
225
+ Key: Record<string, unknown>
226
+ }
227
+ };
228
+ listSitesByOwnerCommand(ownerId: string): {
229
+ command: 'Query'
230
+ input: {
231
+ TableName: string
232
+ IndexName: string
233
+ KeyConditionExpression: string
234
+ ExpressionAttributeValues: Record<string, unknown>
235
+ }
236
+ };
237
+ recordPageViewCommand(pageView: PageView): {
238
+ command: 'PutItem'
239
+ input: {
240
+ TableName: string
241
+ Item: Record<string, unknown>
242
+ }
243
+ };
244
+ queryPageViewsCommand(siteId: string, startDate: Date, endDate: Date, options?: { path?: string, limit?: number }): {
245
+ command: 'Query'
246
+ input: {
247
+ TableName: string
248
+ KeyConditionExpression: string
249
+ ExpressionAttributeNames: Record<string, string>
250
+ ExpressionAttributeValues: Record<string, unknown>
251
+ FilterExpression?: string
252
+ Limit?: number
253
+ ScanIndexForward: boolean
254
+ }
255
+ };
256
+ upsertSessionCommand(session: Session): {
257
+ command: 'PutItem'
258
+ input: {
259
+ TableName: string
260
+ Item: Record<string, unknown>
261
+ }
262
+ };
263
+ recordCustomEventCommand(event: CustomEvent): {
264
+ command: 'PutItem'
265
+ input: {
266
+ TableName: string
267
+ Item: Record<string, unknown>
268
+ }
269
+ };
270
+ upsertAggregatedStatsCommand(stats: AggregatedStats): {
271
+ command: 'UpdateItem'
272
+ input: {
273
+ TableName: string
274
+ Key: Record<string, unknown>
275
+ UpdateExpression: string
276
+ ExpressionAttributeNames: Record<string, string>
277
+ ExpressionAttributeValues: Record<string, unknown>
278
+ }
279
+ };
280
+ getAggregatedStatsCommand(siteId: string, period: AggregationPeriod, startPeriod: string, endPeriod: string): {
281
+ command: 'Query'
282
+ input: {
283
+ TableName: string
284
+ KeyConditionExpression: string
285
+ ExpressionAttributeValues: Record<string, unknown>
286
+ ScanIndexForward: boolean
287
+ }
288
+ };
289
+ upsertPageStatsCommand(stats: PageStats): {
290
+ command: 'UpdateItem'
291
+ input: {
292
+ TableName: string
293
+ Key: Record<string, unknown>
294
+ UpdateExpression: string
295
+ ExpressionAttributeNames: Record<string, string>
296
+ ExpressionAttributeValues: Record<string, unknown>
297
+ }
298
+ };
299
+ getTopPagesCommand(siteId: string, period: AggregationPeriod, periodStart: string, limit?: number): {
300
+ command: 'Query'
301
+ input: {
302
+ TableName: string
303
+ IndexName: string
304
+ KeyConditionExpression: string
305
+ ExpressionAttributeValues: Record<string, unknown>
306
+ Limit: number
307
+ ScanIndexForward: boolean
308
+ }
309
+ };
310
+ upsertReferrerStatsCommand(stats: ReferrerStats): {
311
+ command: 'UpdateItem'
312
+ input: {
313
+ TableName: string
314
+ Key: Record<string, unknown>
315
+ UpdateExpression: string
316
+ ExpressionAttributeNames: Record<string, string>
317
+ ExpressionAttributeValues: Record<string, unknown>
318
+ }
319
+ };
320
+ createGoalCommand(goal: Goal): {
321
+ command: 'PutItem'
322
+ input: {
323
+ TableName: string
324
+ Item: Record<string, unknown>
325
+ ConditionExpression: string
326
+ }
327
+ };
328
+ listGoalsCommand(siteId: string): {
329
+ command: 'Query'
330
+ input: {
331
+ TableName: string
332
+ KeyConditionExpression: string
333
+ ExpressionAttributeValues: Record<string, unknown>
334
+ }
335
+ };
336
+ updateRealtimeStatsCommand(stats: RealtimeStats & { visitorId?: string }): {
337
+ command: 'UpdateItem'
338
+ input: {
339
+ TableName: string
340
+ Key: Record<string, unknown>
341
+ UpdateExpression: string
342
+ ExpressionAttributeNames: Record<string, string>
343
+ ExpressionAttributeValues: Record<string, unknown>
344
+ }
345
+ };
346
+ getRealtimeStatsCommand(siteId: string, minutes?: number): {
347
+ command: 'Query'
348
+ input: {
349
+ TableName: string
350
+ KeyConditionExpression: string
351
+ ExpressionAttributeValues: Record<string, unknown>
352
+ ScanIndexForward: boolean
353
+ Limit: number
354
+ }
355
+ };
356
+ upsertGeoStatsCommand(stats: GeoStats): {
357
+ command: 'UpdateItem'
358
+ input: {
359
+ TableName: string
360
+ Key: Record<string, unknown>
361
+ UpdateExpression: string
362
+ ExpressionAttributeNames: Record<string, string>
363
+ ExpressionAttributeValues: Record<string, unknown>
364
+ }
365
+ };
366
+ getGeoStatsCommand(siteId: string, period: AggregationPeriod, periodStart: string, limit?: number): {
367
+ command: 'Query'
368
+ input: {
369
+ TableName: string
370
+ KeyConditionExpression: string
371
+ ExpressionAttributeValues: Record<string, unknown>
372
+ Limit: number
373
+ }
374
+ };
375
+ getRegionsCommand(siteId: string, period: AggregationPeriod, periodStart: string, country?: string, limit?: number): {
376
+ command: 'Query'
377
+ input: {
378
+ TableName: string
379
+ KeyConditionExpression: string
380
+ ExpressionAttributeValues: Record<string, unknown>
381
+ FilterExpression?: string
382
+ ExpressionAttributeNames?: Record<string, string>
383
+ Limit: number
384
+ }
385
+ };
386
+ getCitiesCommand(siteId: string, period: AggregationPeriod, periodStart: string, options?: { country?: string, region?: string }, limit?: number): {
387
+ command: 'Query'
388
+ input: {
389
+ TableName: string
390
+ KeyConditionExpression: string
391
+ ExpressionAttributeValues: Record<string, unknown>
392
+ FilterExpression?: string
393
+ ExpressionAttributeNames?: Record<string, string>
394
+ Limit: number
395
+ }
396
+ };
397
+ upsertDeviceStatsCommand(stats: DeviceStats): {
398
+ command: 'UpdateItem'
399
+ input: {
400
+ TableName: string
401
+ Key: Record<string, unknown>
402
+ UpdateExpression: string
403
+ ExpressionAttributeNames: Record<string, string>
404
+ ExpressionAttributeValues: Record<string, unknown>
405
+ }
406
+ };
407
+ getDeviceStatsCommand(siteId: string, period: AggregationPeriod, periodStart: string, dimension?: 'device' | 'browser' | 'os' | 'screen'): {
408
+ command: 'Query'
409
+ input: {
410
+ TableName: string
411
+ KeyConditionExpression: string
412
+ ExpressionAttributeValues: Record<string, unknown>
413
+ FilterExpression?: string
414
+ ExpressionAttributeNames?: Record<string, string>
415
+ }
416
+ };
417
+ upsertEventStatsCommand(stats: EventStats): {
418
+ command: 'UpdateItem'
419
+ input: {
420
+ TableName: string
421
+ Key: Record<string, unknown>
422
+ UpdateExpression: string
423
+ ExpressionAttributeNames: Record<string, string>
424
+ ExpressionAttributeValues: Record<string, unknown>
425
+ }
426
+ };
427
+ getEventStatsCommand(siteId: string, period: AggregationPeriod, periodStart: string): {
428
+ command: 'Query'
429
+ input: {
430
+ TableName: string
431
+ KeyConditionExpression: string
432
+ ExpressionAttributeValues: Record<string, unknown>
433
+ }
434
+ };
435
+ upsertGoalStatsCommand(stats: GoalStats): {
436
+ command: 'UpdateItem'
437
+ input: {
438
+ TableName: string
439
+ Key: Record<string, unknown>
440
+ UpdateExpression: string
441
+ ExpressionAttributeNames: Record<string, string>
442
+ ExpressionAttributeValues: Record<string, unknown>
443
+ }
444
+ };
445
+ getGoalStatsCommand(siteId: string, goalId: string, period: AggregationPeriod, startPeriod: string, endPeriod: string): {
446
+ command: 'Query'
447
+ input: {
448
+ TableName: string
449
+ KeyConditionExpression: string
450
+ ExpressionAttributeValues: Record<string, unknown>
451
+ ScanIndexForward: boolean
452
+ }
453
+ };
454
+ upsertCampaignStatsCommand(stats: CampaignStats): {
455
+ command: 'UpdateItem'
456
+ input: {
457
+ TableName: string
458
+ Key: Record<string, unknown>
459
+ UpdateExpression: string
460
+ ExpressionAttributeNames: Record<string, string>
461
+ ExpressionAttributeValues: Record<string, unknown>
462
+ }
463
+ };
464
+ getCampaignStatsCommand(siteId: string, period: AggregationPeriod, periodStart: string): {
465
+ command: 'Query'
466
+ input: {
467
+ TableName: string
468
+ KeyConditionExpression: string
469
+ ExpressionAttributeValues: Record<string, unknown>
470
+ }
471
+ };
472
+ static getPeriodStart(date: Date, period: AggregationPeriod): string;
473
+ static generateId(): string;
474
+ static hashVisitorId(ip: string, userAgent: string, siteId: string, salt: string): Promise<string>;
475
+ static parseReferrerSource(referrer: string | undefined): string;
476
+ static parseUserAgent(userAgent: string): {
477
+ deviceType: DeviceType
478
+ browser: string
479
+ browserVersion: string
480
+ os: string
481
+ osVersion: string
482
+ };
483
+ }
484
+ /**
485
+ * Analytics Aggregator for rolling up raw events into aggregated stats
486
+ */
487
+ export declare class AnalyticsAggregator {
488
+ constructor(options: AggregatorOptions);
489
+ aggregateHourlyStats(siteId: string, hourStart: Date, pageViews: PageView[], sessions: Session[]): AggregatedStats;
490
+ aggregatePageStats(siteId: string, period: AggregationPeriod, periodStart: Date, pageViews: PageView[]): PageStats[];
491
+ aggregateReferrerStats(siteId: string, period: AggregationPeriod, periodStart: Date, sessions: Session[]): ReferrerStats[];
492
+ aggregateGeoStats(siteId: string, period: AggregationPeriod, periodStart: Date, sessions: Session[]): GeoStats[];
493
+ aggregateDeviceStats(siteId: string, period: AggregationPeriod, periodStart: Date, sessions: Session[]): DeviceStats[];
494
+ }
495
+ /**
496
+ * Goal Matcher for checking if pageviews/events match goal definitions
497
+ */
498
+ export declare class GoalMatcher {
499
+ constructor(goals: Goal[]);
500
+ matchPageView(pageView: PageView): GoalMatchResult[];
501
+ matchEvent(event: CustomEvent): GoalMatchResult[];
502
+ getActiveGoals(): Goal[];
503
+ static createConversion(siteId: string, match: GoalMatchResult): Conversion;
504
+ }
505
+ /**
506
+ * Analytics Query API for dashboard data
507
+ */
508
+ export declare class AnalyticsQueryAPI {
509
+ constructor(store: AnalyticsStore);
510
+ static determinePeriod(dateRange: DateRange): AggregationPeriod;
511
+ static getPreviousPeriod(dateRange: DateRange): DateRange;
512
+ generateDashboardQueries(options: QueryOptions): {
513
+ aggregatedStats: ReturnType<AnalyticsStore['getAggregatedStatsCommand']>
514
+ topPages: ReturnType<AnalyticsStore['getTopPagesCommand']>
515
+ realtimeStats?: ReturnType<AnalyticsStore['getRealtimeStatsCommand']>
516
+ goals?: ReturnType<AnalyticsStore['listGoalsCommand']>
517
+ previousPeriodStats?: ReturnType<AnalyticsStore['getAggregatedStatsCommand']>
518
+ };
519
+ getRegions(siteId: string, options: {
520
+ dateRange: DateRange
521
+ country?: string
522
+ limit?: number
523
+ }): ReturnType<AnalyticsStore['getRegionsCommand']>;
524
+ getCities(siteId: string, options: {
525
+ dateRange: DateRange
526
+ country?: string
527
+ region?: string
528
+ limit?: number
529
+ }): ReturnType<AnalyticsStore['getCitiesCommand']>;
530
+ static processSummary(stats: AggregatedStats[], previousStats?: AggregatedStats[]): DashboardSummary;
531
+ static processTimeSeries(stats: AggregatedStats[]): TimeSeriesPoint[];
532
+ static processTopPages(pageStats: PageStats[], totalPageViews: number): TopItem[];
533
+ static processTopReferrers(referrerStats: ReferrerStats[], totalVisitors: number): TopItem[];
534
+ static processTopCountries(geoStats: GeoStats[], totalVisitors: number): TopItem[];
535
+ static processTopRegions(geoStats: GeoStats[], totalVisitors: number): TopItem[];
536
+ static processTopCities(geoStats: GeoStats[], totalVisitors: number): TopItem[];
537
+ static processTopDevices(deviceStats: DeviceStats[], dimension: 'device' | 'browser' | 'os', totalVisitors: number): TopItem[];
538
+ static processRealtimeData(realtimeStats: RealtimeStats[]): RealtimeData;
539
+ static processGoalPerformance(goals: Goal[], goalStats: GoalStats[], totalVisitors: number): GoalPerformance[];
540
+ }
541
+ /**
542
+ * Aggregation Pipeline for scheduled processing of analytics data
543
+ */
544
+ export declare class AggregationPipeline {
545
+ constructor(store: AnalyticsStore, aggregator?: AnalyticsAggregator);
546
+ runAggregationJob(config: PipelineJobConfig, pageViews: PageView[], sessions: Session[], events: CustomEvent[], goals: Goal[]): PipelineJobResult;
547
+ static getScheduledJobTimes(now?: Date): {
548
+ hourly: Date
549
+ daily: Date
550
+ monthly: Date
551
+ };
552
+ static getCronExpression(period: AggregationPeriod): string;
553
+ static getAggregationWindow(period: AggregationPeriod, referenceTime?: Date): {
554
+ start: Date
555
+ end: Date
556
+ };
557
+ static createJobConfig(siteId: string, period: AggregationPeriod, referenceTime?: Date): PipelineJobConfig;
558
+ }
package/dist/api.d.ts ADDED
@@ -0,0 +1,109 @@
1
+ import { AggregationPipeline, AnalyticsQueryAPI, AnalyticsStore } from './Analytics';
2
+ import type { Goal, Session, Site } from './Analytics';
3
+ /**
4
+ * Create a Bun/Hono compatible router handler
5
+ */
6
+ export declare function createBunRouter(api: AnalyticsAPI, executeCommand: HandlerContext['executeCommand']): void;
7
+ /**
8
+ * Create AWS Lambda handler
9
+ */
10
+ export declare function createLambdaHandler(api: AnalyticsAPI, executeCommand: HandlerContext['executeCommand']): (event: {
11
+ httpMethod: string
12
+ path: string
13
+ pathParameters?: Record<string, string>
14
+ queryStringParameters?: Record<string, string>
15
+ body?: string
16
+ headers: Record<string, string>
17
+ requestContext?: { identity?: { sourceIp?: string } }
18
+ }) => Promise<{ statusCode: number, headers: Record<string, string>, body: string }>;
19
+ /**
20
+ * Generic HTTP request interface (framework-agnostic)
21
+ */
22
+ export declare interface AnalyticsRequest {
23
+ method: string
24
+ path: string
25
+ params: Record<string, string>
26
+ query: Record<string, string>
27
+ body: unknown
28
+ headers: Record<string, string>
29
+ ip?: string
30
+ userAgent?: string
31
+ }
32
+ /**
33
+ * Generic HTTP response interface
34
+ */
35
+ export declare interface AnalyticsResponse {
36
+ status: number
37
+ headers: Record<string, string>
38
+ body: unknown
39
+ }
40
+ /**
41
+ * API handler context
42
+ */
43
+ export declare interface HandlerContext {
44
+ store: AnalyticsStore
45
+ queryApi: AnalyticsQueryAPI
46
+ pipeline: AggregationPipeline
47
+ visitorSalt: string
48
+ executeCommand: (command: { command: string, input: Record<string, unknown> }) => Promise<unknown>
49
+ getGoals?: (siteId: string) => Promise<Goal[]>
50
+ getSite?: (siteId: string) => Promise<Site | null>
51
+ sessionStore?: SessionStore
52
+ }
53
+ /**
54
+ * Simple in-memory session store interface
55
+ */
56
+ export declare interface SessionStore {
57
+ get: (key: string) => Promise<Session | null>
58
+ set: (key: string, session: Session, ttlSeconds?: number) => Promise<void>
59
+ delete: (key: string) => Promise<void>
60
+ }
61
+ /**
62
+ * Collect endpoint payload (from tracking script)
63
+ */
64
+ export declare interface CollectPayload {
65
+ s: string
66
+ sid: string
67
+ e: 'pageview' | 'event' | 'outbound' | 'error'
68
+ p?: Record<string, unknown>
69
+ u: string
70
+ r?: string
71
+ t?: string
72
+ sw?: number
73
+ sh?: number
74
+ }
75
+ /**
76
+ * API configuration
77
+ */
78
+ export declare interface AnalyticsAPIConfig {
79
+ tableName: string
80
+ corsOrigins?: string[]
81
+ useTtl?: boolean
82
+ rawEventTtl?: number
83
+ basePath?: string
84
+ }
85
+ /**
86
+ * Analytics API - handles all analytics HTTP endpoints
87
+ */
88
+ export declare class AnalyticsAPI {
89
+ constructor(config: AnalyticsAPIConfig);
90
+ createContext(executeCommand: HandlerContext['executeCommand'], options?: Partial<Pick<HandlerContext, 'getGoals' | 'getSite' | 'sessionStore'>>): HandlerContext;
91
+ getCorsHeaders(origin?: string): Record<string, string>;
92
+ handleOptions(req: AnalyticsRequest): AnalyticsResponse;
93
+ handleCollect(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
94
+ handleListSites(req: AnalyticsRequest, ctx: HandlerContext, ownerId: string): Promise<AnalyticsResponse>;
95
+ handleCreateSite(req: AnalyticsRequest, ctx: HandlerContext, ownerId: string): Promise<AnalyticsResponse>;
96
+ handleGetSite(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
97
+ handleGetStats(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
98
+ handleGetRealtime(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
99
+ handleGetScript(req: AnalyticsRequest): AnalyticsResponse;
100
+ handleListGoals(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
101
+ handleCreateGoal(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
102
+ handleGetTopPages(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
103
+ handleGetRegions(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
104
+ handleGetCities(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
105
+ handleAggregate(req: AnalyticsRequest, ctx: HandlerContext): Promise<AnalyticsResponse>;
106
+ getStore(): AnalyticsStore;
107
+ getQueryAPI(): AnalyticsQueryAPI;
108
+ getPipeline(): AggregationPipeline;
109
+ }