Skip to content
Buse Turgay Sönmez

Design Engineer, Belgrade

Site Reports

Every site I launch needs someone to look at its numbers. This does it for me: it reads Google Analytics for each site and sends a daily, a weekly and a monthly report to Telegram. It runs on GitHub Actions, so it does not depend on my machine being on, and it installs nothing: the package has zero dependencies.

  • 2026
  • Workflow
  • CLI

In short

Covers
3 sites in 3 project groups, from one JSON file
Schedule
Daily at 07:30, weekly on Monday 09:00, monthly on the 1st at 09:30 (Istanbul time)
Runs on
GitHub Actions, Node 22, 10 minute limit
Dependencies
0. The Google Analytics client is written by hand on Node's built-in modules
Language model
None in the daily report. An optional comment on the weekly and monthly ones
Secrets
In GitHub Actions only; none in the repository

Deterministic where it counts

The daily report is arithmetic. A site that deviates from its own baseline is shown, the normal ones are folded into one line, and the same input always produces the same message. A language model there would add cost and noise, and a report that words things differently every morning is harder to scan.

The weekly and monthly reports can carry a short written comment from Claude. It is optional by construction: with no API key the step is skipped without an error and the report goes out without it.

Zero dependencies, on purpose

A scheduled job that starts with an install step can break on a day nobody touched it. This one imports only what ships with Node, including the signing of the Google service account token, so a run is a checkout and a script.

A site with no analytics property attached yet is not an error. The report says so in words and carries on.

Controls

Speed
1.00×
--ground
oklch(0.985 0.003 85)
--surface
oklch(0.958 0.005 85)
--raised
oklch(1 0 0)
--ink
oklch(0.2 0.006 85)
--muted
oklch(0.43 0.008 85)
--faint
oklch(0.5 0.008 85)
--line
oklch(0.9 0.004 85)
--line-strong
oklch(0.6 0.006 85)
--accent
oklch(0.66 0.22 38)
--accent-ink
oklch(0.52 0.19 38)
--stage
oklch(0.152 0.004 85)
--radius-stage
36px
--radius-stage-sm
28px
--radius-media
24px
--radius-panel
16px
--radius-field
10px
--ease-out-expo
cubic-bezier(0.16, 1, 0.3, 1)

This week · W39One WebGL context, three leaksGeometry · 2026