@jayfarei/lazyanalytics 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@jayfarei/lazyanalytics",
3
+ "version": "0.1.0",
4
+ "description": "Agent-first web analytics on Cloudflare Workers + Analytics Engine. Self-hosted, privacy-friendly, queryable from the command line.",
5
+ "license": "MIT",
6
+ "author": "JayFarei",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/JayFarei/lazyanalytics.git"
10
+ },
11
+ "homepage": "https://github.com/JayFarei/lazyanalytics#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/JayFarei/lazyanalytics/issues"
14
+ },
15
+ "keywords": [
16
+ "analytics",
17
+ "web-analytics",
18
+ "cloudflare-workers",
19
+ "analytics-engine",
20
+ "privacy",
21
+ "cli",
22
+ "agent"
23
+ ],
24
+ "type": "module",
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "workspaces": [
32
+ "worker",
33
+ "cli"
34
+ ],
35
+ "bin": {
36
+ "lazyanalytics": "cli/dist/index.js"
37
+ },
38
+ "files": [
39
+ "cli/dist",
40
+ "dist/worker.js",
41
+ "templates",
42
+ "skill/SKILL.md",
43
+ "README.md",
44
+ "CHANGELOG.md",
45
+ "LICENSE"
46
+ ],
47
+ "scripts": {
48
+ "build": "node scripts/build-worker.mjs && npm run build --workspace cli",
49
+ "test": "npm test --workspace worker",
50
+ "prepublishOnly": "npm run build && npm test"
51
+ },
52
+ "dependencies": {
53
+ "commander": "^13.0.0"
54
+ },
55
+ "devDependencies": {
56
+ "esbuild": "^0.25.0"
57
+ }
58
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: lazyanalytics
3
+ description: |
4
+ Set up, manage, and query self-hosted web analytics on Cloudflare Workers — deploy the
5
+ analytics worker, add or list tracked sites, install tracking snippets, rotate secrets,
6
+ and query pageviews, visitors, referrers, geo, browsers, and timeseries. Use when the
7
+ user asks about website traffic ("how is my site doing", "pageviews for"), wants to set
8
+ up or deploy analytics, add/remove a tracked site, get a tracking snippet, or check
9
+ analytics usage and cost.
10
+ version: 0.1.0
11
+ ---
12
+
13
+ # lazyanalytics
14
+
15
+ Self-hosted, privacy-friendly web analytics (Cloudflare Workers + Analytics Engine).
16
+ Run every command as `npx @jayfarei/lazyanalytics ...` (works globally installed or not).
17
+
18
+ ## 1. Prerequisites & config discovery
19
+
20
+ Query commands need `ANALYTICS_API_URL` (e.g. `https://lazyanalytics.YOUR-SUBDOMAIN.workers.dev`)
21
+ and `ANALYTICS_API_TOKEN`. The CLI auto-loads them from `./.env` or `~/.config/lazyanalytics/.env`.
22
+
23
+ Check setup state with `npx @jayfarei/lazyanalytics config get ANALYTICS_API_URL` (exit 2 if unset).
24
+ If neither env vars nor the config file exist, the service is not set up — go to section 2.
25
+
26
+ ## 2. Setup (deploy the worker)
27
+
28
+ Non-interactive (preferred for agents):
29
+
30
+ ```bash
31
+ CLOUDFLARE_API_TOKEN=<cf-token> CF_ACCOUNT_ID=<32-hex-account-id> \
32
+ npx @jayfarei/lazyanalytics setup --sites example.com,blog.example.com --yes
33
+ ```
34
+
35
+ - The Cloudflare API token needs only: **Workers Scripts: Edit** and **Account Analytics: Read**.
36
+ - Flags: `--sites <csv>`, `--account-id <id>`, `--name <worker-name>` (default `lazyanalytics`),
37
+ `--rotate-secrets`, `-y/--yes` (never prompt, fail on missing input).
38
+ - Setup scaffolds `~/.config/lazyanalytics/worker/`, deploys via wrangler, generates
39
+ `API_SECRET` and `HASH_SALT` automatically, sets them as worker secrets without echoing
40
+ them, writes `~/.config/lazyanalytics/.env` (mode 0600), health-checks `/health`, and
41
+ prints the tracking snippet for each site.
42
+ - Idempotent: re-running reuses the existing secrets and site list. Only pass
43
+ `--rotate-secrets` if the user explicitly asks to rotate credentials.
44
+
45
+ **NEVER print `ANALYTICS_API_TOKEN`, `API_SECRET`, `HASH_SALT`, or `CLOUDFLARE_API_TOKEN`
46
+ values.** Do not `cat` the config file; `config get <KEY>` masks sensitive values.
47
+
48
+ ## 3. Site management
49
+
50
+ | Command | What it does | Needs |
51
+ |---|---|---|
52
+ | `sites list` | List tracked sites (worker `/api/sites`) | API URL + token |
53
+ | `sites add example.com` | Add to ALLOWED_SITES and redeploy worker | `CLOUDFLARE_API_TOKEN` + setup scaffold |
54
+ | `sites remove example.com` | Remove and redeploy (refuses to remove the last site) | `CLOUDFLARE_API_TOKEN` + setup scaffold |
55
+ | `snippet [-s example.com]` | Print tracking `<script>` tag(s); omit `-s` for all sites | API URL |
56
+
57
+ Tracking snippet shape (place in the site's `<head>`):
58
+
59
+ ```html
60
+ <script defer id="analytics" data-site-id="example.com" src="https://lazyanalytics.YOUR-SUBDOMAIN.workers.dev/tracker.js"></script>
61
+ ```
62
+
63
+ ## 4. Querying
64
+
65
+ All query commands: `npx @jayfarei/lazyanalytics <command> -s example.com [options]`
66
+
67
+ | Command | Returns | Extra options |
68
+ |---|---|---|
69
+ | `stats` | Pageviews, approx visitors, avg screen width | — |
70
+ | `pages` | Top pages by view count | — |
71
+ | `referrers` | Top referrer domains | — |
72
+ | `geo` | Breakdown by country | — |
73
+ | `browsers` | Browser/OS/device breakdown | `--type browser\|os\|device` (default `browser`) |
74
+ | `timeseries` | Pageviews over time | `--unit hour\|day` (default `day`) |
75
+ | `usage` | Worker request usage, free-plan headroom, est. cost | `-p today\|7d\|30d` (default `today`), `-w/--worker <name>`; needs `CF_ACCOUNT_ID` + `CLOUDFLARE_API_TOKEN`, not the analytics token |
76
+
77
+ Common options (stats/pages/referrers/geo/browsers/timeseries):
78
+
79
+ - `-s, --site <site>` — required, e.g. `example.com`
80
+ - `-p, --period <period>` — `Nd` format (`7d`, `30d`, `90d`), default `7d`
81
+ - `-l, --limit <n>` — max rows, default `10`
82
+ - `--table` — human-readable table; default output is JSON
83
+
84
+ Example: `npx @jayfarei/lazyanalytics pages -s example.com -p 30d -l 5`
85
+
86
+ ## 5. Reading results
87
+
88
+ JSON shape: `{ "data": [...], "meta": { "site", "period", "sampled" } }`
89
+
90
+ Exit codes:
91
+
92
+ | Code | Meaning |
93
+ |---|---|
94
+ | 0 | Success |
95
+ | 1 | Error (bad request, API failure) |
96
+ | 2 | Success but no data for the query |
97
+ | 3 | Config missing (URL/token/credentials not set) |
98
+
99
+ Sampling: Analytics Engine samples data under load. If `meta.sampled` is `true`,
100
+ numbers are extrapolated estimates — say so when reporting them to the user.
101
+
102
+ ## 6. Error handling
103
+
104
+ | Symptom | Cause | Fix |
105
+ |---|---|---|
106
+ | Exit 3 / HTTP 401 "Authentication failed" | Missing or wrong `ANALYTICS_API_URL`/`ANALYTICS_API_TOKEN` | Check `config get`, or re-run `setup` |
107
+ | 400 "Unknown site: X" | Site not in worker's ALLOWED_SITES | `npx @jayfarei/lazyanalytics sites add X` |
108
+ | 500 "Server not configured" | Worker secrets missing | Re-run `npx @jayfarei/lazyanalytics setup` |
109
+ | "worker scaffold not found" | `sites add/remove` before setup on this machine | Run `npx @jayfarei/lazyanalytics setup` first |
110
+ | "Invalid period format" | Period not in `Nd` form | Use `7d`, `30d`, `90d` |
111
+ | Exit 2, empty data | No traffic recorded yet | Verify the snippet is installed; data appears within minutes |
@@ -0,0 +1,14 @@
1
+ # lazyanalytics worker config (scaffolded by `lazyanalytics setup`)
2
+ # Account is provided via the CLOUDFLARE_ACCOUNT_ID env var at deploy time;
3
+ # do not add an account_id line here.
4
+ name = "__WORKER_NAME__"
5
+ main = "worker.js"
6
+ compatibility_date = "2026-03-01"
7
+
8
+ [vars]
9
+ # Comma-separated list of sites to track
10
+ ALLOWED_SITES = "__ALLOWED_SITES__"
11
+
12
+ [[analytics_engine_datasets]]
13
+ binding = "ANALYTICS"
14
+ dataset = "agent_analytics"