Utility · Intermediate
Analytics Tracker
PostHog wrapper with auto page-view hook, user identification, a Supabase self-hosted fallback, and six pre-written SQL queries for DAU, WAU, funnel, revenue, and retention analysis.
Read the Getting Access guideif you haven't yet.
1. Get the file
Sign in at marrowstack.dev, open the Analytics Tracker block, and click Copy all files. Paste lib/analytics.ts into your project.
2. Prerequisites
- Next.js 14 or 15, App Router
- PostHog project at
app.posthog.com(free tier available) - Supabase project (optional — only needed for the self-hosted event fallback)
3. Install
- Copy
lib/analytics.tsfrom the block detail page into your project. - Install peer dependencies:
npm install posthog-js4. Environment
| Variable | Required | Default | Purpose |
|---|---|---|---|
| NEXT_PUBLIC_POSTHOG_KEY | yes | — | PostHog project API key from Project Settings → API Keys |
| NEXT_PUBLIC_POSTHOG_HOST | no | — | PostHog instance URL. Defaults to https://app.posthog.com |
| NEXT_PUBLIC_SUPABASE_URL | no | — | Supabase URL — only needed for the self-hosted event fallback |
| SUPABASE_SERVICE_ROLE_KEY | no | — | Service role key — only for self-hosted fallback |
5. Wire it in
import { AnalyticsProvider } from '@/lib/analytics'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<AnalyticsProvider>
{children}
</AnalyticsProvider>
</body>
</html>
)
}'use client'
import { usePageView } from '@/lib/analytics'
// Drop this in your root layout or a client wrapper
export function PageViewTracker() {
usePageView() // tracks route changes automatically
return null
}'use client'
import { useAnalytics } from '@/lib/analytics'
export function UpgradeButton() {
const { track, identify } = useAnalytics()
return (
<button
onClick={() => {
track('upgrade_clicked', { plan: 'pro', source: 'navbar' })
}}
>
Upgrade to Pro
</button>
)
}6. Verify it works
- Open PostHog → Activity — navigate a few pages and confirm page view events appear within 30 seconds.
- Call
track('test_event', { foo: 'bar' })and confirm it appears in PostHog Live Events. - Call
identify(userId, { email })after login and confirm the user profile is created in PostHog.
7. Failure modes & fixes
Events not appearing in PostHog
Cause: Ad blockers intercept PostHog requests in the browser.
Fix: Set up a PostHog reverse proxy at /ingest in your Next.js rewrites. Instructions are in the PostHog docs under Reverse Proxy.
NEXT_PUBLIC_POSTHOG_KEY is not defined
Cause: The env var is set without the NEXT_PUBLIC_ prefix, or not set at all.
Fix: Ensure the variable is prefixed with NEXT_PUBLIC_ so Next.js exposes it to the browser bundle.
Duplicate page view events
Cause: usePageView() is mounted in multiple components or at multiple levels of the component tree.
Fix: Mount usePageView() (or PageViewTracker) exactly once, in the root layout.