Analytics — Matomo Auto-Provisioning
The platform runs a Matomo instance at `engage.insureco.io`. Declare one line in your catalog and the builder provisions a per-environment Matomo site and…
Ruleplatform
About
The platform runs a Matomo instance at `engage.insureco.io`. Declare one line in your catalog and the builder provisions a per-environment Matomo site and injects the tracking config into your pod. Add the `@insureco/analytics` component and you're tracking — no manual site creation, no hardcoded site IDs.
Skill Content
This is the raw markdown that gets installed as a Claude Code rule.
# Analytics — Matomo Auto-Provisioning
The platform runs a Matomo instance at `engage.insureco.io`. Declare one line in
your catalog and the builder provisions a per-environment Matomo site and injects
the tracking config into your pod. Add the `@insureco/analytics` component and
you're tracking — no manual site creation, no hardcoded site IDs.
## Quick start
1. Declare analytics in `catalog-info.yaml` (frontend services only):
```yaml
spec:
analytics:
enabled: true
```
2. Install the SDK and add `.npmrc`:
```bash
npm install @insureco/analytics
```
```
# .npmrc
@insureco:registry=https://git.insureco.io/api/packages/insureco/npm/
```
3. Drop the component into your root layout (a Server Component):
```tsx
// app/layout.tsx
import { MatomoAnalytics } from '@insureco/analytics'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<MatomoAnalytics />
</body>
</html>
)
}
```
4. `tawa deploy --prod`. Done.
## What the builder does
On deploy, for `nextjs` / `static` services with `spec.analytics.enabled: true`:
1. Resolves the service's public URL for the environment (custom domain if
verified, else `{service}.{env}.tawa.pro` / `{service}.tawa.pro`).
2. Finds or creates a Matomo site for that URL (idempotent — keyed by a stored
record per environment, with a URL-lookup fallback so redeploys never create
duplicates).
3. Injects two **runtime** env vars into the pod:
| Var | Example | Notes |
|-----|---------|-------|
| `MATOMO_URL` | `https://engage.insureco.io` | Matomo instance base URL |
| `MATOMO_SITE_ID` | `218` | The provisioned site ID — public by design |
## Per-environment sites
Each environment gets its **own** Matomo site, because the site's `main_url` is
the environment-specific hostname. Prod traffic, sandbox traffic, and UAT traffic
are recorded under separate site IDs and never mix.
## Frontend-only
Analytics is provisioned **only** for `nextjs` and `static` frameworks. A JS page
tracker is meaningless for a backend API, so `express` / `hono` / `fastify` /
`worker` services that declare `spec.analytics` get a build warning and no
injection. (Server-side event tracking via Matomo's HTTP Tracking API is a
possible future path, not covered here.)
## Why runtime injection (not `NEXT_PUBLIC_*`)
`MATOMO_SITE_ID` is **not** a `NEXT_PUBLIC_*` variable. `NEXT_PUBLIC_*` values are
inlined into the client bundle at **Docker build time** — but the builder doesn't
know your site ID until the provisioning step, which runs *after* the image is
built. The `@insureco/analytics` component sidesteps this by reading the value in
a **Server Component at request time** and rendering it into the HTML. This is the
same runtime-vs-build-time rule described in [nextjs.md](nextjs.md).
## Custom events, goals, search
Client-side helpers — call them from `'use client'` components:
```tsx
'use client'
import { trackEvent, trackGoal, trackSiteSearch } from '@insureco/analytics'
trackEvent('Quote', 'Started', 'auto')
trackGoal(3, 49.99) // goal id 3, $49.99 revenue
trackSiteSearch('flood coverage', 'policies', 12)
```
## Static (non-React) sites
`static` sites can't render the component. Build the snippet from the injected env
and paste it into `<head>` at build time:
```ts
import { buildMatomoSnippet } from '@insureco/analytics'
const snippet = buildMatomoSnippet({ url: process.env.MATOMO_URL!, siteId: process.env.MATOMO_SITE_ID! })
```
## Security
- The Matomo **admin token** is a superuser credential. It lives ONLY on the
builder (`MATOMO_ADMIN_TOKEN`) and is used solely to create sites. It is **never**
injected into a service pod.
- `MATOMO_SITE_ID` is safe to expose — site IDs appear in client-side tracking JS
by design.
## Common mistakes
- Putting `<MatomoAnalytics />` in a `'use client'` file — it must be a Server
Component so it can read `process.env` at runtime. Place it in `app/layout.tsx`.
- Expecting analytics on a backend service — frontend-only.
- Adding a `NEXT_PUBLIC_MATOMO_SITE_ID` config var by hand — unnecessary and
wrong; the value is runtime-injected and read server-side.
- Declaring `spec.analytics` but seeing no data locally — the env vars are only
injected on deploy; `getMatomoConfig()` returns null in local dev, so the
component renders nothing (by design).
Install
Copy the skill content and save it to:
~/.claude/rules/tawa-analytics.mdComing soon via CLI:
tawa chaac install tawa-analyticsDetails
- Format
- Rule
- Category
- platform
- Version
- 1.0.81140
- Tokens
- ~1,106
- Updated
- 2026-08-28
platform