Self-hosted Umami analytics configuration and verification for the verbatra docs site (apps/docs). Use when updating the Umami script tag, website ID, or tracker attributes in apps/docs/app/[lang]/layout.tsx, or when adding data-umami-event tracking to docs UI elements.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add verbatra/verbatra --skill umami-analytics --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Umami Analytics?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/verbatra-umami-analytics)More formats (shields.io, HTML) on the badges page.
---
name: umami-analytics
description: 'Self-hosted Umami analytics configuration and verification for the verbatra docs site (apps/docs). Use when updating the Umami script tag, website ID, or tracker attributes in apps/docs/app/[lang]/layout.tsx, or when adding data-umami-event tracking to docs UI elements.'
license: MIT
metadata:
author: verbatra
version: '1.0'
source: 'internal'
user-invocable: false
---
# Umami Analytics (apps/docs)
## Overview
apps/docs embeds a single self-hosted Umami tracker in the root layout
(apps/docs/app/[lang]/layout.tsx). It is cookieless, collects no personal data, and
needs no consent banner (see apps/docs/messages/en.json, legal.privacy.s5/s6 for the
GDPR basis already documented on /privacy). This skill covers the one file that
holds the embed, verifying a website ID or host change, and the pattern for adding
new tracked events.
**When to use:** rotating or changing the Umami data-website-id or script host,
adding data-umami-event tracking to a new docs UI element, verifying the tracker
loads correctly after a change.
**When NOT to use:** general Next.js Script component questions unrelated to Umami,
GDPR/privacy-policy wording changes (that is prose content in messages/*.json, not
this skill's concern).
## Key Concepts
- **Self-hosted host** - the tracker script and API both live at
https://umami.kreitz-webdev.de (script.js). No data-host-url override is needed
because the script is already served from the self-hosted domain, not
cloud.umami.is.
- **Website ID** - a UUID identifying one tracked site in the Umami instance. Lives
only as a literal string in the Script component's data-website-id prop; there is
no env var or config file for it.
- **Script strategy** - next/script's afterInteractive strategy is correct for
Umami: it loads after hydration, so it never blocks the first paint or
interactivity, and Umami has no reason to load before interactive (unlike, say, a
consent-gating script).
- **Automatic SPA tracking** - Umami's tracker watches pushState/replaceState/popstate
and sends a pageview on every client-side route change automatically. Do not add a
manual umami.track() call on route change; that produces duplicate pageviews.
- **Event tracking** - two mechanisms, both real Umami APIs:
- Declarative: data-umami-event="name" plus data-umami-event-key="value" attributes
on any element. All values become strings.
- Programmatic: window.umami.track(name, data) inside an event handler, for
dynamic or typed values. Event names are capped at 50 characters.
## Quick Reference
| Task | Location |
| ---------------------------------- | ------------------------------------------------------------ |
| Change the website ID or host | apps/docs/app/[lang]/layout.tsx, the Script component |
| Update preconnect/dns-prefetch | apps/docs/app/[lang]/layout.tsx, the two <link> tags in head |
| Add a declarative click event | data-umami-event="..." on the target element's JSX |
| Add a dynamic/typed event | window.umami?.track("name", { ... }) inside the onClick handler |
| Verify the tracker loaded | open the deployed page, check Network for a script.js request to the self-hosted host, then check the Umami dashboard's Realtime view for a session |
| Privacy policy wording for Umami | apps/docs/messages/{en,de,es,fr}.json, legal.privacy.s5.body (update all four locales together, per docs.md) |
## Common Mistakes
| Mistake | Correct Pattern |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Using strategy="beforeInteractive" for the Umami script | Use "afterInteractive"; analytics scripts never need to block hydration |
| Manually calling umami.track() on every route change | Umami's tracker already auto-tracks SPA navigations; don't duplicate it |
| Editing the website ID in an env var or config file | It is a literal prop value in layout.tsx; there is no env var for it |
| Adding a data-host-url override | Not needed; the script is already served from the self-hosted domain |
| Updating the English privacy-policy Umami paragraph only | Update de.json, es.json, fr.json in the same change (docs.md rule) |
| Assuming Umami auto-tracks outbound link clicks | It does not; add data-umami-event manually to each external <a> tag |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!