@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/CHANGELOG.md ADDED
@@ -0,0 +1,68 @@
1
+ [Compare changes](https://github.com/stacksjs/ts-analytics/compare/v0.1.5...v0.1.6)
2
+
3
+ ## 🤖 Continuous Integration
4
+
5
+ - **release**: use pantry action @main (matches the working publish setup) ([c5bd2db](https://github.com/stacksjs/ts-analytics/commit/c5bd2db)) _(by Chris <chrisbreuer93@gmail.com>)_
6
+
7
+ ## 🧹 Chores
8
+
9
+ - release v0.1.6 ([2d0da27](https://github.com/stacksjs/ts-analytics/commit/2d0da27)) _(by Chris <chrisbreuer93@gmail.com>)_
10
+
11
+ ## Contributors
12
+
13
+ - _Chris <chrisbreuer93@gmail.com>_
14
+
15
+ [Compare changes](https://github.com/stacksjs/ts-analytics/compare/v0.1.4...v0.1.5)
16
+
17
+ ## 🐛 Bug Fixes
18
+
19
+ - **publish**: set publishConfig.access to public ([9f98feb](https://github.com/stacksjs/ts-analytics/commit/9f98feb)) _(by Chris <chrisbreuer93@gmail.com>)_
20
+
21
+ ## 🧹 Chores
22
+
23
+ - release v0.1.5 ([97b857c](https://github.com/stacksjs/ts-analytics/commit/97b857c)) _(by Chris <chrisbreuer93@gmail.com>)_
24
+
25
+ ## Contributors
26
+
27
+ - _Chris <chrisbreuer93@gmail.com>_
28
+
29
+ [Compare changes](https://github.com/stacksjs/ts-analytics/compare/v0.1.3...v0.1.4)
30
+
31
+ ## 🧹 Chores
32
+
33
+ - release v0.1.4 ([fee7677](https://github.com/stacksjs/ts-analytics/commit/fee7677)) _(by Chris <chrisbreuer93@gmail.com>)_
34
+ - remove orphaned error-sdk (@stacksjs/error-tracker) ([b451ce5](https://github.com/stacksjs/ts-analytics/commit/b451ce5)) _(by Chris <chrisbreuer93@gmail.com>)_
35
+
36
+ ## Contributors
37
+
38
+ - _Chris <chrisbreuer93@gmail.com>_
39
+
40
+ [Compare changes](https://github.com/stacksjs/ts-analytics/compare/v0.1.2...v0.1.3)
41
+
42
+ ## 🚀 Features
43
+
44
+ - **tracking**: restore dependency-free /tracking entry point ([76651b6](https://github.com/stacksjs/ts-analytics/commit/76651b6)) _(by glennmichael123 <gtorregosa@gmail.com>)_
45
+
46
+ ## 🧹 Chores
47
+
48
+ - release v0.1.3 ([229e391](https://github.com/stacksjs/ts-analytics/commit/229e391)) _(by Chris <chrisbreuer93@gmail.com>)_
49
+ - **deps**: refresh bun.lock to pick up pickier 0.1.37 ([e81ebd1](https://github.com/stacksjs/ts-analytics/commit/e81ebd1)) _(by glennmichael123 <gtorregosa@gmail.com>)_
50
+
51
+ ## Contributors
52
+
53
+ - _Chris <chrisbreuer93@gmail.com>_
54
+ - _glennmichael123 <gtorregosa@gmail.com>_
55
+
56
+ [Compare changes](https://github.com/stacksjs/ts-analytics/compare/v0.1.1...v0.1.2)
57
+
58
+ ## 🚀 Features
59
+
60
+ - **tracking**: add dependency-free ./tracking subpath export ([20bba2c](https://github.com/stacksjs/ts-analytics/commit/20bba2c)) _(by Chris <chrisbreuer93@gmail.com>)_
61
+
62
+ ## 🧹 Chores
63
+
64
+ - release v0.1.2 ([9b41b91](https://github.com/stacksjs/ts-analytics/commit/9b41b91)) _(by Chris <chrisbreuer93@gmail.com>)_
65
+
66
+ ## Contributors
67
+
68
+ - _Chris <chrisbreuer93@gmail.com>_
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2024 Open Web Foundation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,361 @@
1
+ <p align="center"><img src="https://github.com/stacksjs/ts-analytics/blob/main/.github/art/cover.png?raw=true" alt="Social Card of this repo"></p>
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![GitHub Actions][github-actions-src]][github-actions-href]
5
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
6
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
7
+
8
+ # @stacksjs/analytics
9
+
10
+ A privacy-first analytics toolkit for web applications, powered by DynamoDB single-table design.
11
+
12
+ ## Features
13
+
14
+ - **Privacy-First**: No cookies, no personal data collection, GDPR-compliant by design
15
+ - **DynamoDB Single-Table Design**: Efficient, scalable, and cost-effective storage
16
+ - **Real-time Analytics**: Live visitor tracking and dashboard updates
17
+ - **Goal Tracking**: Define and track conversion goals
18
+ - **Vue Dashboard Components**: Ready-to-use dashboard UI components
19
+ - **Framework Agnostic**: Works with Bun, Express, Hono, AWS Lambda, and more
20
+ - **Stacks Integration**: First-class support for the Stacks framework
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ bun add @stacksjs/analytics
26
+ ```
27
+
28
+ ## Integrate on Your Site (the 3-step recipe)
29
+
30
+ The validated pattern for adding ts-analytics to any site (docs sites included):
31
+
32
+ 1. **Create a project** in the dashboard (or let the first event auto-create it), then copy the one-liner from **Settings → Installation**:
33
+
34
+ ```html
35
+ <script defer src="https://your-analytics-host/api/sites/YOUR_SITE_ID/script.js"></script>
36
+ ```
37
+
38
+ It captures page views, SPA route changes, link & outbound clicks, engagement time, web vitals, and JS errors — no cookies, no consent banner needed.
39
+
40
+ 2. **Verify** with the *Verify installation* button in Settings (fires a real event through `/collect` and confirms the round trip), or just visit your site and watch the dashboard.
41
+
42
+ 3. **Optional hardening**: append `?stealth=true` for the unlisted beacon path, or serve it first-party from your own domain — see the [ad-blocker resilience guide](docs/guide/tracking-script.md#ad-blocker-resilience-first-party-proxy). Error tracking without analytics: grab the DSN + SDK snippet from the same Settings page.
43
+
44
+ ## Quick Start
45
+
46
+ ### 1. Set Up the Analytics Store
47
+
48
+ ```typescript
49
+ import { AnalyticsStore, createAnalyticsTable } from '@stacksjs/analytics'
50
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
51
+ import { CreateTableCommand, DescribeTableCommand } from '@aws-sdk/client-dynamodb'
52
+
53
+ const client = new DynamoDBClient({ region: 'us-east-1' })
54
+
55
+ // Create the analytics table (one-time setup)
56
+ await createAnalyticsTable(client, {
57
+ tableName: 'my-analytics',
58
+ billingMode: 'PAY_PER_REQUEST',
59
+ }, { CreateTableCommand, DescribeTableCommand })
60
+
61
+ // Initialize the store
62
+ const store = new AnalyticsStore({
63
+ tableName: 'my-analytics',
64
+ })
65
+ ```
66
+
67
+ ### 2. Add the Tracking Script
68
+
69
+ ```typescript
70
+ import { generateTrackingScript } from '@stacksjs/analytics'
71
+
72
+ const script = generateTrackingScript({
73
+ siteId: 'my-site-id',
74
+ endpoint: 'https://api.example.com/collect',
75
+ // Optional settings
76
+ trackPageviews: true,
77
+ trackOutboundLinks: true,
78
+ respectDoNotTrack: true,
79
+ })
80
+
81
+ // Inject into your HTML
82
+ const html = `<html><head>${script}</head>...</html>`
83
+ ```
84
+
85
+ ### 3. Create API Handlers
86
+
87
+ ```typescript
88
+ import { AnalyticsAPI, createBunRouter } from '@stacksjs/analytics'
89
+
90
+ const api = new AnalyticsAPI({
91
+ tableName: 'my-analytics',
92
+ siteId: 'my-site-id',
93
+ })
94
+
95
+ // For Bun
96
+ const router = createBunRouter(api, executeCommand)
97
+
98
+ // For AWS Lambda
99
+ import { createLambdaHandler } from '@stacksjs/analytics'
100
+ export const handler = createLambdaHandler(api, executeCommand)
101
+ ```
102
+
103
+ ## Architecture: Source of Truth
104
+
105
+ The repository has two API layers — only one is live:
106
+
107
+ | Layer | Status | Where |
108
+ |---|---|---|
109
+ | **Live server** | ✅ source of truth | `src/router.ts` + `src/handlers/*` (DynamoDB-backed), served by `server/index.ts`; jobs in `src/jobs/`, pre-aggregation in `src/lib/rollups.ts` |
110
+ | Legacy library | ⚠️ compatibility only | `src/api.ts`, `src/stacks-integration.ts`, and the in-memory `AnalyticsStore`/`AnalyticsQueryAPI`/`AggregationPipeline` classes in `src/Analytics.ts` |
111
+
112
+ New endpoints and features belong in `src/router.ts` + `src/handlers/`. The legacy layer is kept so existing imports of the published package keep compiling; it does not serve the bundled server or dashboard. (`generateTrackingScript` in `src/Analytics.ts` **is** live — it builds the served `/script.js`.)
113
+
114
+ ## Core Concepts
115
+
116
+ ### Analytics Store
117
+
118
+ The `AnalyticsStore` provides DynamoDB operations for all analytics entities:
119
+
120
+ ```typescript
121
+ const store = new AnalyticsStore({
122
+ tableName: 'analytics',
123
+ useTtl: true,
124
+ rawEventTtl: 30 _ 24 _ 60 * 60, // 30 days
125
+ })
126
+
127
+ // Create a site
128
+ const siteCommand = store.createSiteCommand({
129
+ id: 'site-123',
130
+ name: 'My Website',
131
+ domains: ['example.com'],
132
+ ownerId: 'user-456',
133
+ })
134
+
135
+ // Record a page view
136
+ const pvCommand = store.recordPageViewCommand({
137
+ id: 'pv-789',
138
+ siteId: 'site-123',
139
+ path: '/blog/hello-world',
140
+ visitorId: 'visitor-hash',
141
+ sessionId: 'session-abc',
142
+ timestamp: new Date(),
143
+ })
144
+ ```
145
+
146
+ ### Aggregation Pipeline
147
+
148
+ Pre-compute statistics for fast dashboard queries:
149
+
150
+ ```typescript
151
+ import { AggregationPipeline, AnalyticsAggregator } from '@stacksjs/analytics'
152
+
153
+ const pipeline = new AggregationPipeline({
154
+ tableName: 'analytics',
155
+ })
156
+
157
+ // Run hourly aggregation
158
+ const aggregator = new AnalyticsAggregator({
159
+ tableName: 'analytics',
160
+ })
161
+
162
+ await aggregator.aggregateHourly('site-123', new Date())
163
+ ```
164
+
165
+ ### Query API
166
+
167
+ Fetch analytics data for dashboards:
168
+
169
+ ```typescript
170
+ import { AnalyticsQueryAPI } from '@stacksjs/analytics'
171
+
172
+ const queryApi = new AnalyticsQueryAPI({
173
+ tableName: 'analytics',
174
+ })
175
+
176
+ // Generate dashboard queries
177
+ const queries = queryApi.generateDashboardQueries({
178
+ siteId: 'site-123',
179
+ dateRange: { start: new Date('2024-01-01'), end: new Date() },
180
+ })
181
+ ```
182
+
183
+ ### Goal Tracking
184
+
185
+ Define and track conversion goals:
186
+
187
+ ```typescript
188
+ import { GoalMatcher } from '@stacksjs/analytics'
189
+
190
+ const goals = [
191
+ { id: 'signup', type: 'pageview', pattern: '/signup/complete', matchType: 'exact' },
192
+ { id: 'purchase', type: 'event', pattern: 'purchase', matchType: 'exact' },
193
+ ]
194
+
195
+ const matcher = new GoalMatcher(goals)
196
+
197
+ // Check if a page view matches any goals
198
+ const matches = matcher.matchPageView('/signup/complete')
199
+ // => [{ goalId: 'signup', value: undefined }]
200
+ ```
201
+
202
+ ## Dashboard Components
203
+
204
+ Vue 3 components for building analytics dashboards:
205
+
206
+ ```vue
207
+ <script setup>
208
+ import {
209
+ AnalyticsDashboard,
210
+ StatCard,
211
+ TimeSeriesChart,
212
+ TopList,
213
+ DeviceBreakdown,
214
+ RealtimeCounter,
215
+ DateRangePicker,
216
+ } from '@stacksjs/analytics'
217
+ </script>
218
+
219
+ <template>
220
+ <AnalyticsDashboard
221
+ :config="{ baseUrl: '/api/analytics', siteId: 'my-site' }"
222
+ />
223
+ </template>
224
+ ```
225
+
226
+ ### Composables
227
+
228
+ ```typescript
229
+ import { createAnalyticsComposable, fetchDashboardData } from '@stacksjs/analytics'
230
+
231
+ // Create a composable for Vue
232
+ const analytics = createAnalyticsComposable({
233
+ baseUrl: '/api/analytics',
234
+ siteId: 'my-site',
235
+ })
236
+
237
+ // Or fetch data directly
238
+ const data = await fetchDashboardData(
239
+ { baseUrl: '/api/analytics', siteId: 'my-site' },
240
+ { startDate: new Date('2024-01-01'), endDate: new Date() }
241
+ )
242
+ ```
243
+
244
+ ## Stacks Framework Integration
245
+
246
+ First-class integration with the Stacks framework:
247
+
248
+ ```typescript
249
+ import { createAnalyticsDriver, createAnalyticsMiddleware } from '@stacksjs/analytics'
250
+
251
+ // Create the driver
252
+ const driver = await createAnalyticsDriver({
253
+ tableName: 'analytics',
254
+ siteId: 'my-site',
255
+ region: 'us-east-1',
256
+ })
257
+
258
+ // Add tracking middleware
259
+ app.use(createAnalyticsMiddleware(driver))
260
+
261
+ // Server-side tracking
262
+ app.use(createServerTrackingMiddleware(driver, {
263
+ excludedPaths: [/^\/api/, /^\/admin/],
264
+ }))
265
+
266
+ // Dashboard actions
267
+ const actions = createDashboardActions(driver)
268
+ const stats = await actions.getDashboardStats({ startDate: '2024-01-01' })
269
+ ```
270
+
271
+ ## Infrastructure
272
+
273
+ Generate infrastructure code for deployment:
274
+
275
+ ```typescript
276
+ import {
277
+ generateCloudFormationTemplate,
278
+ generateCdkCode,
279
+ generateSamTemplate,
280
+ generateAwsCliCommands,
281
+ } from '@stacksjs/analytics'
282
+
283
+ // CloudFormation
284
+ const cfn = generateCloudFormationTemplate({ tableName: 'analytics' })
285
+
286
+ // AWS CDK
287
+ const cdk = generateCdkCode({ tableName: 'analytics' })
288
+
289
+ // SAM
290
+ const sam = generateSamTemplate({ tableName: 'analytics' })
291
+
292
+ // AWS CLI commands
293
+ const cli = generateAwsCliCommands({ tableName: 'analytics' })
294
+ ```
295
+
296
+ ## Models
297
+
298
+ Stacks-compatible model definitions for all analytics entities:
299
+
300
+ ```typescript
301
+ import {
302
+ SiteModel,
303
+ PageViewModel,
304
+ SessionModel,
305
+ CustomEventModel,
306
+ GoalModel,
307
+ AggregatedStatsModel,
308
+ // ... and more
309
+ } from '@stacksjs/analytics'
310
+ ```
311
+
312
+ ## Testing
313
+
314
+ ```bash
315
+ bun test
316
+ ```
317
+
318
+ ## Changelog
319
+
320
+ Please see our [releases](https://github.com/stacksjs/analytics/releases) page for more information on what has changed recently.
321
+
322
+ ## Contributing
323
+
324
+ Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.
325
+
326
+ ## Community
327
+
328
+ For help, discussion about best practices, or any other conversation that would benefit from being searchable:
329
+
330
+ [Discussions on GitHub](https://github.com/stacksjs/stacks/discussions)
331
+
332
+ For casual chit-chat with others using this package:
333
+
334
+ [Join the Stacks Discord Server](https://discord.gg/stacksjs)
335
+
336
+ ## Postcardware
337
+
338
+ Stacks OSS will always stay open-sourced, and we will always love to receive postcards from wherever Stacks is used! _And we also determine the OSS dependencies we utilize._
339
+
340
+ Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, USA
341
+
342
+ ## Sponsors
343
+
344
+ We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.
345
+
346
+ - [JetBrains](https://www.jetbrains.com/)
347
+ - [The Solana Foundation](https://solana.com/)
348
+
349
+ ## License
350
+
351
+ The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.
352
+
353
+ Made with love by [Chris Breuer](https://github.com/chrisbbreuer) and [contributors](https://github.com/stacksjs/analytics/graphs/contributors).
354
+
355
+ <!-- Badges -->
356
+ [npm-version-src]: https://img.shields.io/npm/v/@stacksjs/analytics?style=flat-square
357
+ [npm-version-href]: https://npmjs.com/package/@stacksjs/analytics
358
+ [github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/analytics/ci.yml?style=flat-square&branch=main
359
+ [github-actions-href]: https://github.com/stacksjs/analytics/actions?query=workflow%3Aci
360
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@stacksjs/analytics?style=flat-square
361
+ [npm-downloads-href]: https://npmjs.com/package/@stacksjs/analytics
package/bin/cli.ts ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Analytics CLI
4
+ *
5
+ * Command-line interface for managing analytics.
6
+ *
7
+ * Usage:
8
+ * analytics setup - Print setup instructions
9
+ * analytics create-table - Generate create table command
10
+ * analytics docker-compose - Generate docker-compose.yml
11
+ * analytics seed - Generate seed data
12
+ * analytics tracking-script - Generate tracking script
13
+ */
14
+
15
+ import {
16
+ defineConfig,
17
+ generateAwsCliCommand,
18
+ generateDockerCompose,
19
+ generateLocalCreateTableInput,
20
+ generateSeedData,
21
+ generateTrackingScript,
22
+ printLocalSetupInstructions,
23
+ } from '../src'
24
+
25
+ const args = process.argv.slice(2)
26
+ const command = args[0]
27
+
28
+ function printHelp(): void {
29
+ console.log(`
30
+ Analytics CLI - Privacy-first web analytics toolkit
31
+
32
+ Usage:
33
+ analytics <command> [options]
34
+
35
+ Commands:
36
+ setup Print local development setup instructions
37
+ create-table Generate AWS CLI command to create DynamoDB table
38
+ docker-compose Generate docker-compose.yml for local development
39
+ seed [options] Generate seed data for testing
40
+ tracking-script Generate tracking script for a site
41
+ help Show this help message
42
+
43
+ Options:
44
+ --table-name <name> Table name (default: AnalyticsTable)
45
+ --region <region> AWS region (default: us-east-1)
46
+ --port <port> DynamoDB Local port (default: 8000)
47
+ --site-id <id> Site ID for tracking script
48
+ --api-endpoint <url> API endpoint for tracking script
49
+ --sites <n> Number of sites to seed (default: 1)
50
+ --page-views <n> Page views per site (default: 100)
51
+ --sessions <n> Sessions per site (default: 50)
52
+ --days <n> Days of history (default: 7)
53
+
54
+ Examples:
55
+ analytics setup
56
+ analytics create-table --table-name MyAnalytics
57
+ analytics docker-compose --port 8001
58
+ analytics seed --sites 3 --page-views 500
59
+ analytics tracking-script --site-id site_001 --api-endpoint https://api.example.com
60
+ `)
61
+ }
62
+
63
+ function getArg(name: string, defaultValue?: string): string | undefined {
64
+ const index = args.indexOf(`--${name}`)
65
+ if (index === -1)
66
+ return defaultValue
67
+ return args[index + 1] || defaultValue
68
+ }
69
+
70
+ function getNumericArg(name: string, defaultValue: number): number {
71
+ const value = getArg(name)
72
+ return value ? Number.parseInt(value, 10) : defaultValue
73
+ }
74
+
75
+ async function main(): Promise<void> {
76
+ switch (command) {
77
+ case 'setup':
78
+ printLocalSetupInstructions()
79
+ break
80
+
81
+ case 'create-table': {
82
+ const tableName = getArg('table-name', 'AnalyticsTable')!
83
+ const config = defineConfig({
84
+ table: { tableName },
85
+ region: getArg('region', 'us-east-1'),
86
+ })
87
+
88
+ console.log('# Create DynamoDB table for analytics\n')
89
+ console.log(generateAwsCliCommand(config))
90
+ console.log('\n# Or use this JSON input:')
91
+ console.log(JSON.stringify(generateLocalCreateTableInput(config), null, 2))
92
+ break
93
+ }
94
+
95
+ case 'docker-compose': {
96
+ const port = getNumericArg('port', 8000)
97
+ console.log(generateDockerCompose({ port }))
98
+ break
99
+ }
100
+
101
+ case 'seed': {
102
+ const options = {
103
+ sites: getNumericArg('sites', 1),
104
+ pageViewsPerSite: getNumericArg('page-views', 100),
105
+ sessionsPerSite: getNumericArg('sessions', 50),
106
+ daysOfHistory: getNumericArg('days', 7),
107
+ }
108
+
109
+ console.log(`Generating seed data:`)
110
+ console.log(` Sites: ${options.sites}`)
111
+ console.log(` Page views per site: ${options.pageViewsPerSite}`)
112
+ console.log(` Sessions per site: ${options.sessionsPerSite}`)
113
+ console.log(` Days of history: ${options.daysOfHistory}`)
114
+ console.log('')
115
+
116
+ const data = generateSeedData(options)
117
+
118
+ console.log(`Generated:`)
119
+ console.log(` ${data.sites.length} sites`)
120
+ console.log(` ${data.sessions.length} sessions`)
121
+ console.log(` ${data.pageViews.length} page views`)
122
+ console.log('')
123
+ console.log('// Seed data JSON:')
124
+ console.log(JSON.stringify(data, null, 2))
125
+ break
126
+ }
127
+
128
+ case 'tracking-script': {
129
+ const siteId = getArg('site-id')
130
+ const apiEndpoint = getArg('api-endpoint', 'https://api.example.com/analytics')!
131
+
132
+ if (!siteId) {
133
+ console.error('Error: --site-id is required')
134
+ console.error('Usage: analytics tracking-script --site-id <id> [--api-endpoint <url>]')
135
+ process.exit(1)
136
+ }
137
+
138
+ const script = generateTrackingScript({
139
+ siteId,
140
+ apiEndpoint,
141
+ honorDnt: true,
142
+ trackHashChanges: false,
143
+ trackOutboundLinks: true,
144
+ })
145
+
146
+ console.log('<!-- Add this script to your website -->')
147
+ console.log(script)
148
+ break
149
+ }
150
+
151
+ case 'help':
152
+ case '--help':
153
+ case '-h':
154
+ printHelp()
155
+ break
156
+
157
+ default:
158
+ if (command) {
159
+ console.error(`Unknown command: ${command}`)
160
+ }
161
+ printHelp()
162
+ process.exit(command ? 1 : 0)
163
+ }
164
+ }
165
+
166
+ main().catch((error) => {
167
+ console.error('Error:', error.message)
168
+ process.exit(1)
169
+ })