Skip to content
Back to skills

Umami Analytics

ASecurity

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.

  • 2 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added September 3, 2026
developmentnextjsapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add verbatra/verbatra --skill umami-analytics --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Umami Analytics?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Umami Analytics
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/verbatra-umami-analytics/badge)](https://www.skillsdirectory.com/skills/verbatra-umami-analytics)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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       |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.