@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
package/src/types.ts ADDED
@@ -0,0 +1,911 @@
1
+ /**
2
+ * Analytics TypeScript Types
3
+ *
4
+ * These interfaces are derived from the Stacks model definitions
5
+ * in the ./models directory. They provide TypeScript typing for
6
+ * the analytics system.
7
+ *
8
+ * TODO: When dynamodb-tooling v0.4.0+ is released with fixed type exports,
9
+ * re-export SingleTableDesignConfig, BillingMode, GSIDefinition, etc. from there
10
+ * instead of duplicating them here.
11
+ *
12
+ * @see ./models for Stacks model definitions
13
+ * @see https://github.com/stacksjs/dynamodb-tooling
14
+ */
15
+
16
+ // ============================================================================
17
+ // DynamoDB Single-Table Design Types
18
+ // These types are compatible with dynamodb-tooling's SingleTableDesignConfig
19
+ // ============================================================================
20
+
21
+ /**
22
+ * DynamoDB billing mode
23
+ */
24
+ export type BillingMode = 'PAY_PER_REQUEST' | 'PROVISIONED'
25
+
26
+ /**
27
+ * Projection type for indexes
28
+ */
29
+ export type ProjectionType = 'ALL' | 'KEYS_ONLY' | 'INCLUDE'
30
+
31
+ /**
32
+ * GSI projection configuration
33
+ */
34
+ export interface IndexProjection {
35
+ type: ProjectionType
36
+ attributes?: string[]
37
+ }
38
+
39
+ /**
40
+ * Global Secondary Index definition
41
+ */
42
+ export interface GSIDefinition {
43
+ name: string
44
+ partitionKey: string
45
+ sortKey?: string
46
+ projection: IndexProjection
47
+ readCapacity?: number
48
+ writeCapacity?: number
49
+ }
50
+
51
+ /**
52
+ * Local Secondary Index definition
53
+ */
54
+ export interface LSIDefinition {
55
+ name: string
56
+ sortKey: string
57
+ projection: IndexProjection
58
+ }
59
+
60
+ /**
61
+ * Single-table design configuration (compatible with dynamodb-tooling)
62
+ */
63
+ export interface SingleTableDesignConfig {
64
+ enabled: boolean
65
+ partitionKeyName: string
66
+ sortKeyName: string
67
+ gsi1pkName: string
68
+ gsi1skName: string
69
+ gsi2pkName: string
70
+ gsi2skName: string
71
+ entityTypeAttribute: string
72
+ pkPrefix: string
73
+ skPrefix: string
74
+ gsiCount: number
75
+ keyDelimiter: string
76
+ }
77
+
78
+ /**
79
+ * Analytics DynamoDB table configuration
80
+ */
81
+ export interface AnalyticsTableConfig {
82
+ tableName: string
83
+ billingMode: BillingMode
84
+ singleTable: SingleTableDesignConfig
85
+ globalSecondaryIndexes: GSIDefinition[]
86
+ localSecondaryIndexes: LSIDefinition[]
87
+ ttlAttributeName?: string
88
+ }
89
+
90
+ // ============================================================================
91
+ // Analytics Single-Table Key Patterns
92
+ // ============================================================================
93
+
94
+ /**
95
+ * Analytics entity types for single-table design
96
+ */
97
+ export type AnalyticsEntityType =
98
+ | 'SITE'
99
+ | 'PAGEVIEW'
100
+ | 'SESSION'
101
+ | 'EVENT'
102
+ | 'GOAL'
103
+ | 'CONVERSION'
104
+ | 'STATS_AGG'
105
+ | 'STATS_PAGE'
106
+ | 'STATS_REF'
107
+ | 'STATS_GEO'
108
+ | 'STATS_DEVICE'
109
+ | 'STATS_CAMPAIGN'
110
+ | 'STATS_EVENT'
111
+ | 'STATS_GOAL'
112
+ | 'REALTIME'
113
+
114
+ /**
115
+ * Key pattern templates for analytics entities
116
+ *
117
+ * Single-table design following Alex DeBrie patterns:
118
+ * - PK: ENTITY#id (for direct lookups)
119
+ * - SK: ENTITY#id or composite for hierarchical data
120
+ * - GSI1: For access patterns like site-based queries
121
+ * - GSI2: For time-based queries
122
+ */
123
+ export interface AnalyticsKeyPatterns {
124
+ // Sites
125
+ site: {
126
+ pk: `SITE#${string}` // SITE#siteId
127
+ sk: `SITE#${string}` // SITE#siteId
128
+ }
129
+
130
+ // Page views (raw events)
131
+ pageView: {
132
+ pk: `SITE#${string}` // SITE#siteId
133
+ sk: `PV#${string}#${string}` // PV#timestamp#pageViewId
134
+ gsi1pk: `SESSION#${string}` // SESSION#sessionId
135
+ gsi1sk: `PV#${string}` // PV#timestamp
136
+ }
137
+
138
+ // Sessions
139
+ session: {
140
+ pk: `SITE#${string}` // SITE#siteId
141
+ sk: `SESSION#${string}` // SESSION#sessionId
142
+ gsi1pk: `VISITOR#${string}` // VISITOR#visitorId
143
+ gsi1sk: `SESSION#${string}` // SESSION#timestamp
144
+ }
145
+
146
+ // Custom events
147
+ event: {
148
+ pk: `SITE#${string}` // SITE#siteId
149
+ sk: `EVENT#${string}#${string}` // EVENT#timestamp#eventId
150
+ gsi1pk: `SESSION#${string}` // SESSION#sessionId
151
+ gsi1sk: `EVENT#${string}` // EVENT#timestamp
152
+ }
153
+
154
+ // Goals
155
+ goal: {
156
+ pk: `SITE#${string}` // SITE#siteId
157
+ sk: `GOAL#${string}` // GOAL#goalId
158
+ }
159
+
160
+ // Conversions
161
+ conversion: {
162
+ pk: `SITE#${string}` // SITE#siteId
163
+ sk: `CONV#${string}#${string}` // CONV#goalId#timestamp
164
+ gsi1pk: `GOAL#${string}` // GOAL#goalId
165
+ gsi1sk: `CONV#${string}` // CONV#timestamp
166
+ }
167
+
168
+ // Aggregated stats
169
+ aggregatedStats: {
170
+ pk: `SITE#${string}` // SITE#siteId
171
+ sk: `STATS#${string}#${string}` // STATS#period#periodStart
172
+ }
173
+
174
+ // Page stats
175
+ pageStats: {
176
+ pk: `SITE#${string}` // SITE#siteId
177
+ sk: `PSTATS#${string}#${string}#${string}` // PSTATS#period#periodStart#pathHash
178
+ }
179
+
180
+ // Referrer stats
181
+ referrerStats: {
182
+ pk: `SITE#${string}` // SITE#siteId
183
+ sk: `RSTATS#${string}#${string}#${string}` // RSTATS#period#periodStart#source
184
+ }
185
+
186
+ // Realtime stats
187
+ realtimeStats: {
188
+ pk: `SITE#${string}` // SITE#siteId
189
+ sk: `RT#${string}` // RT#minute
190
+ }
191
+ }
192
+
193
+ // ============================================================================
194
+ // Core Entity Types
195
+ // ============================================================================
196
+
197
+ /**
198
+ * Site settings
199
+ */
200
+ export interface SiteSettings {
201
+ /** Whether to collect IP-based geolocation (privacy setting) */
202
+ collectGeolocation: boolean
203
+ /** Whether to track referrers */
204
+ trackReferrers: boolean
205
+ /** Whether to track UTM parameters */
206
+ trackUtmParams: boolean
207
+ /** Whether to track device type */
208
+ trackDeviceType: boolean
209
+ /** Public dashboard enabled */
210
+ publicDashboard: boolean
211
+ /** Public dashboard password (hashed) */
212
+ publicDashboardPassword?: string
213
+ /** Excluded paths (regex patterns) */
214
+ excludedPaths: string[]
215
+ /** Excluded IPs */
216
+ excludedIps: string[]
217
+ /** Data retention days (0 = forever) */
218
+ dataRetentionDays: number
219
+ }
220
+
221
+ /**
222
+ * Site/Website being tracked
223
+ */
224
+ export interface Site {
225
+ /** Unique site ID */
226
+ id: string
227
+ /** Site name */
228
+ name: string
229
+ /** Domain(s) for this site */
230
+ domains: string[]
231
+ /** Site timezone */
232
+ timezone: string
233
+ /** Whether site is active */
234
+ isActive: boolean
235
+ /** Owner user ID */
236
+ ownerId: string
237
+ /** Site settings */
238
+ settings: SiteSettings
239
+ /** Created timestamp */
240
+ createdAt: Date
241
+ /** Updated timestamp */
242
+ updatedAt: Date
243
+ }
244
+
245
+ /**
246
+ * Device type
247
+ */
248
+ export type DeviceType = 'desktop' | 'mobile' | 'tablet' | 'unknown'
249
+
250
+ /**
251
+ * Page view event (raw event - stored temporarily for aggregation)
252
+ */
253
+ export interface PageView {
254
+ /** Unique page view ID */
255
+ id: string
256
+ /** Site ID */
257
+ siteId: string
258
+ /** Visitor ID (hashed, anonymous) */
259
+ visitorId: string
260
+ /** Session ID */
261
+ sessionId: string
262
+ /** Page path */
263
+ path: string
264
+ /** Page hostname */
265
+ hostname: string
266
+ /** Page title (optional) */
267
+ title?: string
268
+ /** Referrer URL */
269
+ referrer?: string
270
+ /** Referrer source (e.g., google, twitter, direct) */
271
+ referrerSource?: string
272
+ /** UTM source */
273
+ utmSource?: string
274
+ /** UTM medium */
275
+ utmMedium?: string
276
+ /** UTM campaign */
277
+ utmCampaign?: string
278
+ /** UTM content */
279
+ utmContent?: string
280
+ /** UTM term */
281
+ utmTerm?: string
282
+ /** Google Ads click ID */
283
+ gclid?: string
284
+ /** Meta/Facebook Ads click ID */
285
+ fbclid?: string
286
+ /** Country code (ISO 3166-1 alpha-2) */
287
+ country?: string
288
+ /** Region/state */
289
+ region?: string
290
+ /** City */
291
+ city?: string
292
+ /** Device type */
293
+ deviceType?: DeviceType
294
+ /** Browser name */
295
+ browser?: string
296
+ /** Browser version */
297
+ browserVersion?: string
298
+ /** Operating system */
299
+ os?: string
300
+ /** OS version */
301
+ osVersion?: string
302
+ /** Screen width */
303
+ screenWidth?: number
304
+ /** Screen height */
305
+ screenHeight?: number
306
+ /** Is unique (first page view in session) */
307
+ isUnique: boolean
308
+ /** Is bounce (only page view in session) */
309
+ isBounce: boolean
310
+ /** Time on page (milliseconds) - updated on next page view or session end */
311
+ timeOnPage?: number
312
+ /** Timestamp */
313
+ timestamp: Date
314
+ /** TTL for auto-deletion after aggregation */
315
+ ttl?: number
316
+ }
317
+
318
+ /**
319
+ * Custom event (non-pageview events like button clicks, form submissions)
320
+ */
321
+ export interface CustomEvent {
322
+ /** Unique event ID */
323
+ id: string
324
+ /** Site ID */
325
+ siteId: string
326
+ /** Visitor ID (hashed, anonymous) */
327
+ visitorId: string
328
+ /** Session ID */
329
+ sessionId: string
330
+ /** Event name */
331
+ name: string
332
+ /** Event category (optional, for grouping events) */
333
+ category?: string
334
+ /** Event value (optional, for revenue tracking etc.) */
335
+ value?: number
336
+ /** Event properties */
337
+ properties?: Record<string, string | number | boolean>
338
+ /** Page path where event occurred */
339
+ path: string
340
+ /** Timestamp */
341
+ timestamp: Date
342
+ /** TTL for auto-deletion after aggregation */
343
+ ttl?: number
344
+ }
345
+
346
+ /**
347
+ * Session (visitor session)
348
+ */
349
+ export interface Session {
350
+ /** Session ID */
351
+ id: string
352
+ /** Site ID */
353
+ siteId: string
354
+ /** Visitor ID (hashed, anonymous) */
355
+ visitorId: string
356
+ /** Entry page path */
357
+ entryPath: string
358
+ /** Exit page path */
359
+ exitPath: string
360
+ /** Referrer URL */
361
+ referrer?: string
362
+ /** Referrer source */
363
+ referrerSource?: string
364
+ /** UTM parameters */
365
+ utmSource?: string
366
+ utmMedium?: string
367
+ utmCampaign?: string
368
+ utmContent?: string
369
+ utmTerm?: string
370
+ /** Google Ads click ID */
371
+ gclid?: string
372
+ /** Meta/Facebook Ads click ID */
373
+ fbclid?: string
374
+ /** Country code (ISO 3166-1 alpha-2) */
375
+ country?: string
376
+ /** Region/state code or name */
377
+ region?: string
378
+ /** City name */
379
+ city?: string
380
+ /** Device type */
381
+ deviceType?: DeviceType
382
+ /** Browser */
383
+ browser?: string
384
+ /** OS */
385
+ os?: string
386
+ /** Page view count */
387
+ pageViewCount: number
388
+ /** Event count */
389
+ eventCount: number
390
+ /** Is bounce (single page session) */
391
+ isBounce: boolean
392
+ /** Session duration (milliseconds) */
393
+ duration: number
394
+ /** Session start */
395
+ startedAt: Date
396
+ /** Session end (last activity) */
397
+ endedAt: Date
398
+ /** TTL for auto-deletion */
399
+ ttl?: number
400
+ }
401
+
402
+ /**
403
+ * Goal type
404
+ */
405
+ export type GoalType = 'pageview' | 'event'
406
+
407
+ /**
408
+ * Goal/Conversion definition
409
+ */
410
+ export interface Goal {
411
+ /** Goal ID */
412
+ id: string
413
+ /** Site ID */
414
+ siteId: string
415
+ /** Goal name */
416
+ name: string
417
+ /** Goal type */
418
+ type: GoalType
419
+ /** Match pattern (path pattern or event name) */
420
+ pattern: string
421
+ /** Match type */
422
+ matchType: 'exact' | 'contains' | 'regex'
423
+ /** Revenue value per conversion (optional) */
424
+ value?: number
425
+ /** Is active */
426
+ isActive: boolean
427
+ /** Created timestamp */
428
+ createdAt: Date
429
+ /** Updated timestamp */
430
+ updatedAt: Date
431
+ }
432
+
433
+ /**
434
+ * Conversion record (goal completion)
435
+ */
436
+ export interface Conversion {
437
+ /** Conversion ID */
438
+ id: string
439
+ /** Site ID */
440
+ siteId: string
441
+ /** Goal ID */
442
+ goalId: string
443
+ /** Visitor ID */
444
+ visitorId: string
445
+ /** Session ID */
446
+ sessionId: string
447
+ /** Conversion value */
448
+ value?: number
449
+ /** Page path where conversion occurred */
450
+ path: string
451
+ /** Referrer source */
452
+ referrerSource?: string
453
+ /** UTM source */
454
+ utmSource?: string
455
+ /** UTM campaign */
456
+ utmCampaign?: string
457
+ /** Timestamp */
458
+ timestamp: Date
459
+ /** TTL */
460
+ ttl?: number
461
+ }
462
+
463
+ // ============================================================================
464
+ // Aggregation Types
465
+ // ============================================================================
466
+
467
+ /**
468
+ * Time period for aggregations
469
+ */
470
+ export type AggregationPeriod = 'hour' | 'day' | 'month'
471
+
472
+ /**
473
+ * Aggregated stats (pre-computed for fast dashboard queries)
474
+ */
475
+ export interface AggregatedStats {
476
+ /** Site ID */
477
+ siteId: string
478
+ /** Period type */
479
+ period: AggregationPeriod
480
+ /** Period start timestamp (ISO string for consistency) */
481
+ periodStart: string
482
+ /** Page views */
483
+ pageViews: number
484
+ /** Unique visitors */
485
+ uniqueVisitors: number
486
+ /** Sessions */
487
+ sessions: number
488
+ /** Bounces */
489
+ bounces: number
490
+ /** Bounce rate (0-1) */
491
+ bounceRate: number
492
+ /** Average session duration (milliseconds) */
493
+ avgSessionDuration: number
494
+ /** Average pages per session */
495
+ avgPagesPerSession: number
496
+ /** Total time on site (milliseconds) */
497
+ totalTimeOnSite: number
498
+ /** New visitors */
499
+ newVisitors: number
500
+ /** Returning visitors */
501
+ returningVisitors: number
502
+ /** Created timestamp */
503
+ createdAt: Date
504
+ /** Updated timestamp */
505
+ updatedAt: Date
506
+ }
507
+
508
+ /**
509
+ * Page-level aggregated stats
510
+ */
511
+ export interface PageStats {
512
+ /** Site ID */
513
+ siteId: string
514
+ /** Period type */
515
+ period: AggregationPeriod
516
+ /** Period start timestamp */
517
+ periodStart: string
518
+ /** Page path */
519
+ path: string
520
+ /** Page title (most recent) */
521
+ title?: string
522
+ /** Page views */
523
+ pageViews: number
524
+ /** Unique visitors */
525
+ uniqueVisitors: number
526
+ /** Entries (sessions starting on this page) */
527
+ entries: number
528
+ /** Exits (sessions ending on this page) */
529
+ exits: number
530
+ /** Bounces */
531
+ bounces: number
532
+ /** Average time on page (milliseconds) */
533
+ avgTimeOnPage: number
534
+ /** Exit rate (0-1) */
535
+ exitRate: number
536
+ }
537
+
538
+ /**
539
+ * Referrer stats
540
+ */
541
+ export interface ReferrerStats {
542
+ /** Site ID */
543
+ siteId: string
544
+ /** Period type */
545
+ period: AggregationPeriod
546
+ /** Period start timestamp */
547
+ periodStart: string
548
+ /** Referrer source (e.g., google, twitter, direct) */
549
+ source: string
550
+ /** Full referrer URL (for non-grouped view) */
551
+ referrer?: string
552
+ /** Visitors from this referrer */
553
+ visitors: number
554
+ /** Page views from this referrer */
555
+ pageViews: number
556
+ /** Bounce rate (0-1) */
557
+ bounceRate: number
558
+ /** Average session duration (milliseconds) */
559
+ avgSessionDuration: number
560
+ }
561
+
562
+ /**
563
+ * Geographic stats
564
+ */
565
+ export interface GeoStats {
566
+ /** Site ID */
567
+ siteId: string
568
+ /** Period type */
569
+ period: AggregationPeriod
570
+ /** Period start timestamp */
571
+ periodStart: string
572
+ /** Country code */
573
+ country: string
574
+ /** Region (optional, for country drilldown) */
575
+ region?: string
576
+ /** City (optional, for region drilldown) */
577
+ city?: string
578
+ /** Visitors */
579
+ visitors: number
580
+ /** Page views */
581
+ pageViews: number
582
+ /** Bounce rate */
583
+ bounceRate: number
584
+ }
585
+
586
+ /**
587
+ * Device/Browser stats
588
+ */
589
+ export interface DeviceStats {
590
+ /** Site ID */
591
+ siteId: string
592
+ /** Period type */
593
+ period: AggregationPeriod
594
+ /** Period start timestamp */
595
+ periodStart: string
596
+ /** Dimension type */
597
+ dimension: 'device' | 'browser' | 'os' | 'screen'
598
+ /** Dimension value (e.g., "mobile", "Chrome", "Windows", "1920x1080") */
599
+ value: string
600
+ /** Visitors */
601
+ visitors: number
602
+ /** Page views */
603
+ pageViews: number
604
+ /** Bounce rate */
605
+ bounceRate: number
606
+ }
607
+
608
+ /**
609
+ * UTM Campaign stats
610
+ */
611
+ export interface CampaignStats {
612
+ /** Site ID */
613
+ siteId: string
614
+ /** Period type */
615
+ period: AggregationPeriod
616
+ /** Period start timestamp */
617
+ periodStart: string
618
+ /** UTM source */
619
+ utmSource: string
620
+ /** UTM medium */
621
+ utmMedium?: string
622
+ /** UTM campaign */
623
+ utmCampaign?: string
624
+ /** Visitors */
625
+ visitors: number
626
+ /** Page views */
627
+ pageViews: number
628
+ /** Conversions (custom events marked as goals) */
629
+ conversions: number
630
+ /** Conversion rate (0-1) */
631
+ conversionRate: number
632
+ /** Revenue (if tracking) */
633
+ revenue: number
634
+ /** Bounce rate */
635
+ bounceRate: number
636
+ }
637
+
638
+ /**
639
+ * Custom event stats
640
+ */
641
+ export interface EventStats {
642
+ /** Site ID */
643
+ siteId: string
644
+ /** Period type */
645
+ period: AggregationPeriod
646
+ /** Period start timestamp */
647
+ periodStart: string
648
+ /** Event name */
649
+ eventName: string
650
+ /** Total occurrences */
651
+ count: number
652
+ /** Unique visitors who triggered event */
653
+ uniqueVisitors: number
654
+ /** Total value (for revenue tracking) */
655
+ totalValue: number
656
+ /** Average value per event */
657
+ avgValue: number
658
+ }
659
+
660
+ /**
661
+ * Goal stats (conversions)
662
+ */
663
+ export interface GoalStats {
664
+ /** Site ID */
665
+ siteId: string
666
+ /** Goal ID */
667
+ goalId: string
668
+ /** Period type */
669
+ period: AggregationPeriod
670
+ /** Period start timestamp */
671
+ periodStart: string
672
+ /** Conversions */
673
+ conversions: number
674
+ /** Unique visitors who converted */
675
+ uniqueConversions: number
676
+ /** Conversion rate (0-1) */
677
+ conversionRate: number
678
+ /** Total revenue */
679
+ revenue: number
680
+ }
681
+
682
+ /**
683
+ * Real-time stats (last 5 minutes, stored with short TTL)
684
+ */
685
+ export interface RealtimeStats {
686
+ /** Site ID */
687
+ siteId: string
688
+ /** Minute bucket (ISO timestamp truncated to minute) */
689
+ minute: string
690
+ /** Current visitors (active in this minute) - computed from visitorIds */
691
+ currentVisitors: number
692
+ /** Page views in this minute */
693
+ pageViews: number
694
+ /** Active pages (path -> visitor count) */
695
+ activePages: Record<string, number>
696
+ /** Set of unique visitor IDs for this minute (for counting unique visitors) */
697
+ visitorIds?: string[]
698
+ /** TTL (auto-delete after 10 minutes) */
699
+ ttl: number
700
+ }
701
+
702
+ // ============================================================================
703
+ // Query & Dashboard Types
704
+ // ============================================================================
705
+
706
+ /**
707
+ * Date range for queries
708
+ */
709
+ export interface DateRange {
710
+ start: Date
711
+ end: Date
712
+ }
713
+
714
+ /**
715
+ * Query options
716
+ */
717
+ export interface QueryOptions {
718
+ siteId: string
719
+ dateRange: DateRange
720
+ includeComparison?: boolean
721
+ groupBy?: 'hour' | 'day' | 'month'
722
+ }
723
+
724
+ /**
725
+ * Dashboard summary data
726
+ */
727
+ export interface DashboardSummary {
728
+ pageViews: number
729
+ uniqueVisitors: number
730
+ sessions: number
731
+ bounceRate: number
732
+ avgSessionDuration: number
733
+ avgPagesPerSession: number
734
+ change?: {
735
+ pageViews: number
736
+ uniqueVisitors: number
737
+ sessions: number
738
+ bounceRate: number
739
+ avgSessionDuration: number
740
+ }
741
+ }
742
+
743
+ /**
744
+ * Time series data point
745
+ */
746
+ export interface TimeSeriesPoint {
747
+ date: string
748
+ pageViews: number
749
+ uniqueVisitors: number
750
+ sessions: number
751
+ }
752
+
753
+ /**
754
+ * Top item (page, referrer, etc.)
755
+ */
756
+ export interface TopItem {
757
+ name: string
758
+ value: number
759
+ percentage: number
760
+ /** Optional metadata (e.g., country/region for cities) */
761
+ metadata?: Record<string, string | undefined>
762
+ }
763
+
764
+ /**
765
+ * Realtime data
766
+ */
767
+ export interface RealtimeData {
768
+ currentVisitors: number
769
+ pageViewsLastHour: number
770
+ topActivePages: TopItem[]
771
+ }
772
+
773
+ /**
774
+ * Dashboard data
775
+ */
776
+ export interface DashboardData {
777
+ summary: DashboardSummary
778
+ timeSeries: TimeSeriesPoint[]
779
+ topPages: TopItem[]
780
+ topReferrers: TopItem[]
781
+ deviceBreakdown: TopItem[]
782
+ realtime?: RealtimeData
783
+ }
784
+
785
+ // ============================================================================
786
+ // Goal Matching Types
787
+ // ============================================================================
788
+
789
+ /**
790
+ * Goal match result
791
+ */
792
+ export interface GoalMatchResult {
793
+ goalId: string
794
+ goalName: string
795
+ value?: number
796
+ matchedAt: Date
797
+ matchedPath: string
798
+ matchedEvent?: string
799
+ }
800
+
801
+ /**
802
+ * Goal performance metrics
803
+ */
804
+ export interface GoalPerformance {
805
+ goalId: string
806
+ goalName: string
807
+ conversions: number
808
+ conversionRate: number
809
+ revenue: number
810
+ topConvertingPages: TopItem[]
811
+ topConvertingSources: TopItem[]
812
+ }
813
+
814
+ // ============================================================================
815
+ // Aggregation Pipeline Types
816
+ // ============================================================================
817
+
818
+ /**
819
+ * Aggregation job status
820
+ */
821
+ export interface AggregationJobStatus {
822
+ jobId: string
823
+ siteId: string
824
+ period: AggregationPeriod
825
+ status: 'pending' | 'running' | 'completed' | 'failed'
826
+ startedAt?: Date
827
+ completedAt?: Date
828
+ error?: string
829
+ stats?: {
830
+ pageViewsProcessed: number
831
+ sessionsProcessed: number
832
+ eventsProcessed: number
833
+ }
834
+ }
835
+
836
+ /**
837
+ * Pipeline job configuration
838
+ */
839
+ export interface PipelineJobConfig {
840
+ siteId: string
841
+ period: AggregationPeriod
842
+ windowStart: Date
843
+ windowEnd: Date
844
+ processPageViews: boolean
845
+ processSessions: boolean
846
+ processEvents: boolean
847
+ processGoals: boolean
848
+ }
849
+
850
+ /**
851
+ * Pipeline job result
852
+ */
853
+ export interface PipelineJobResult {
854
+ success: boolean
855
+ aggregatedStats?: AggregatedStats
856
+ pageStats?: PageStats[]
857
+ referrerStats?: ReferrerStats[]
858
+ geoStats?: GeoStats[]
859
+ deviceStats?: DeviceStats[]
860
+ campaignStats?: CampaignStats[]
861
+ eventStats?: EventStats[]
862
+ goalStats?: GoalStats[]
863
+ errors?: string[]
864
+ }
865
+
866
+ // ============================================================================
867
+ // Tracking Script Types
868
+ // ============================================================================
869
+
870
+ /**
871
+ * Tracking script options
872
+ */
873
+ export interface TrackingScriptOptions {
874
+ siteId: string
875
+ apiEndpoint?: string
876
+ honorDnt?: boolean
877
+ trackHashChanges?: boolean
878
+ trackOutboundLinks?: boolean
879
+ /** Use stealth mode (shorter endpoint paths, less identifiable) */
880
+ stealthMode?: boolean
881
+ }
882
+
883
+ // ============================================================================
884
+ // Store Types
885
+ // ============================================================================
886
+
887
+ /**
888
+ * Analytics store options
889
+ */
890
+ export interface AnalyticsStoreOptions {
891
+ /** Table name */
892
+ tableName: string
893
+ /** Whether to use TTL for raw events */
894
+ useTtl?: boolean
895
+ /** TTL duration for raw events (seconds, default 30 days) */
896
+ rawEventTtl?: number
897
+ /** TTL duration for hourly aggregates (seconds, default 90 days) */
898
+ hourlyAggregateTtl?: number
899
+ /** TTL duration for daily aggregates (seconds, default 2 years) */
900
+ dailyAggregateTtl?: number
901
+ }
902
+
903
+ /**
904
+ * Aggregator options
905
+ */
906
+ export interface AggregatorOptions {
907
+ /** Analytics store instance */
908
+ store: unknown // AnalyticsStore - using unknown to avoid circular dependency
909
+ /** Batch size for processing events */
910
+ batchSize?: number
911
+ }