# @mintel/observability Standardized observability package for the Mintel ecosystem, providing Umami analytics and Sentry/GlitchTip error tracking with a focus on privacy and ad-blocker resilience. ## Features - **Umami Smart Proxy**: Track analytics without external scripts and hide your Website ID. - **Sentry Relay**: Bypass ad-blockers for error tracking by relaying envelopes through your own server. - **Unified API**: consistent interface for tracking across multiple projects. ## Installation ```bash pnpm add @mintel/observability @sentry/nextjs ``` ## Usage ### 1. Unified Environment (via @mintel/next-utils) Define the following environment variables: ```bash # Analytics UMAMI_WEBSITE_ID=your-website-id UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me # Error Tracking SENTRY_DSN=your-sentry-dsn ``` Note: No `NEXT_PUBLIC_` prefix is required for these anymore, as they are handled by server-side proxies. ### 2. Analytics Setup In your root layout: ```tsx import { AnalyticsContextProvider, AnalyticsAutoTracker, UmamiAnalyticsService, } from "@mintel/observability"; const analytics = new UmamiAnalyticsService({ enabled: true, websiteId: process.env.UMAMI_WEBSITE_ID, // Server-side apiEndpoint: typeof window === "undefined" ? process.env.UMAMI_API_ENDPOINT : "/stats", }); export default function Layout({ children }) { return ( {children} ); } ``` ### 3. Route Handlers Create a proxy for Umami: `app/stats/api/send/route.ts` ```ts import { createUmamiProxyHandler } from "@mintel/observability"; export const POST = await createUmamiProxyHandler({ websiteId: process.env.UMAMI_WEBSITE_ID, apiEndpoint: process.env.UMAMI_API_ENDPOINT, }); ``` Create a relay for Sentry: `app/errors/api/relay/route.ts` ```ts import { createSentryRelayHandler } from "@mintel/observability"; export const POST = await createSentryRelayHandler({ dsn: process.env.SENTRY_DSN, }); ``` ### 4. Notification Setup (Server-side) ```ts import { GotifyNotificationService } from "@mintel/observability"; const notifications = new GotifyNotificationService({ enabled: true, url: process.env.GOTIFY_URL, token: process.env.GOTIFY_TOKEN, }); await notifications.notify({ title: "Lead Capture", message: "New contact form submission", priority: 5, }); ``` ### 5. Sentry Configuration Use `initSentry` in your `sentry.server.config.ts` and `sentry.client.config.ts`. On the client, use the tunnel: ```ts initSentry({ dsn: "https://public@errors.infra.mintel.me/1", // Placeholder tunnel: "/errors/api/relay", }); ``` ## Architecture This package implements the **Smart Proxy** pattern: - The client NEVER knows the real `UMAMI_WEBSITE_ID`. - Tracking events are sent to your own domain (`/stats/api/send`). - Your server injects the secret ID and forwards to Umami. - This bypasses ad-blockers and keeps your configuration secure.