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.
catalog-info.yaml (frontend services only):spec:
analytics:
enabled: true
.npmrc:npm install @insureco/analytics
# .npmrc
@insureco:registry=https://git.insureco.io/api/packages/insureco/npm/
// app/layout.tsx
import { MatomoAnalytics } from '@insureco/analytics'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
{children}
<MatomoAnalytics />
</body>
</html>
)
}
tawa deploy --prod. Done.On deploy, for nextjs / static services with spec.analytics.enabled: true:
{service}.{env}.tawa.pro / {service}.tawa.pro).| Var | Example | Notes |
|---|---|---|
MATOMO_URL | https://engage.insureco.io | Matomo instance base URL |
MATOMO_SITE_ID | 218 | The provisioned site ID — public by design |
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.
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.)
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.
Client-side helpers — call them from 'use client' components:
'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 sites can't render the component. Build the snippet from the injected env
and paste it into <head> at build time:
import { buildMatomoSnippet } from '@insureco/analytics'
const snippet = buildMatomoSnippet({ url: process.env.MATOMO_URL!, siteId: process.env.MATOMO_SITE_ID! })
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.<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.NEXT_PUBLIC_MATOMO_SITE_ID config var by hand — unnecessary and
wrong; the value is runtime-injected and read server-side.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).Last updated: July 15, 2026