Skip to content

feat(docs): add telemetry for page views, referrers and clicks - #107

Merged
Agustin-Delgado merged 1 commit into
mainfrom
feat/docs-telemetry
Sep 25, 2026
Merged

Agustin-Delgado merged 1 commit into
mainfrom
feat/docs-telemetry

Conversation

@Agustin-Delgado

Copy link
Copy Markdown
Collaborator

What this adds

Telemetry for the docs site, in two layers. One script cannot answer both
questions, so there are two.

The counts. src/routes/+layout.ts starts the analytics and the speed
report of the host. They give the views of a page, where a reader came from,
the country, the device and the speed of a page for real readers. These
scripts come from this domain, so a content blocker does not stop them. That
matters here: the readers of these docs are developers, and many of them run
a blocker. A blocker matches the host of a request, and the requests it stops
never arrive, so the loss is silent and it is not measurable.

The clicks. $lib/docs/telemetry loads an analytics client after the page
hydrates, in an idle moment, so it does not take the main thread from the
demos. It records each click with the element behind it, and it gives the heat
maps. hooks.server.ts puts its requests on a path of this domain, for the
same reason as above.

Privacy

The client writes nothing to the device of the reader (persistence: 'memory'),
so the site needs no consent dialog. The cost is that a reader who comes back
tomorrow is a new reader. The first layer carries the counts that need an
identity, so the cost is small. Session recording is off.

The events

Event Properties The question it answers
$pageview route Which page a reader opens.
search query, results What a reader looks for. results: 0 is a gap.
copy source, detail Which snippet a reader takes away.
demo_interact — The reader tried the demo, and did not only read it.
github_click — How many readers go to the repository.
theme_change to How many readers use the dark theme.

Each click also arrives by itself, because the client records them without
instructions. The six above are named by hand, because a name makes a chart.

search with results: 0 is the most valuable: the query is the name of a
component that is missing, or of a page that does not use the word the reader
knows.

To turn it on

Two public variables, read at build time: VITE_POSTHOG_KEY and
VITE_POSTHOG_REGION (eu or us, default eu). The region must be the
region of the project, or the vendor answers with an error that the browser
does not show. See docs/src/lib/docs/telemetry/README.md.

Without the key each function does nothing, the client is not in the bundle,
and no event leaves a test or a development page.

Also in this diff

pnpm-workspace.yaml had core-js: set this to true or false, a placeholder.
A new dependency brought core-js in, and the placeholder made
pnpm install --frozen-lockfile exit 1 with ERR_PNPM_IGNORED_BUILDS, which
would have stopped every job of the CI. core-js only prints a funding notice
at install time, so the answer is false.

Verification

  • pnpm run lint, pnpm run typecheck (1093 + 4678 files, 0 errors) and
    pnpm run build:docs are green.
  • The docs suite passes: 18 files, 72 tests. Seven of them are new, and they
    cover the proxy: the path it answers, the two hosts, the headers of one hop
    that a copied request must not carry, the address of the reader, and a post
    with its body.
  • A build with a key puts the client in a chunk of its own, and not in the
    entry. A build with no key leaves it out of the output.

Two layers, because one script cannot answer both questions.

The counts of the readers, of where they came from and of the speed of a
page come from the host of the site. Those scripts are served from this
domain, so a content blocker does not stop them, and they write nothing
to the device of the reader.

The clicks come from an analytics client that loads after the page
hydrates. It goes through a proxy on this domain for the same reason a
blocker matches the host of a request. It keeps the identity of a reader
in the tab and writes nothing to the device, so the site needs no
consent dialog.

Six events are named by hand: the page view, a search with the number of
results it found, a copy with what was copied, the first touch of a
demo, the link to the repository and the change of theme. A search that
finds nothing is the most valuable of them: the query is the name of a
component that is missing.

Without VITE_POSTHOG_KEY each function does nothing, and the client is
not in the bundle. See docs/src/lib/docs/telemetry/README.md.
@vercel

vercel Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
human-kit-ui-docs Ready Ready Preview Sep 25, 2026 2:57pm UTC

@Agustin-Delgado
Agustin-Delgado merged commit fe377d0 into main Sep 25, 2026
8 checks passed
@Agustin-Delgado
Agustin-Delgado deleted the feat/docs-telemetry branch September 25, 2026 23:23

This branch was successfully deployed

1 active deployment
Preview — 5bcfe1a9 Deployed Sep 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant