From posthog-pack
Deploys PostHog analytics to Vercel with Next.js (reverse proxy, edge functions, server-side capture), self-hosted Docker, and Cloud Run. Includes CLI env setup and code configs.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin posthog-packThis skill is limited to using the following tools:
Deploy PostHog analytics to production platforms. Covers Next.js with Vercel (reverse proxy, server-side capture, edge functions), self-hosted PostHog with Docker, and Google Cloud Run deployment patterns.
Installs PostHog SDKs for browser JS, Node.js server, Python; configures project/personal API keys and env vars for new integrations.
Implements PostHog analytics for event tracking, user identification, feature flags, and dashboards in Next.js and React apps. Use when adding product analytics.
Adds PostHog product analytics events to track user actions. Installs and initializes SDK across frameworks like Next.js, Django, React Native. Use after features or PR reviews.
Share bugs, ideas, or general feedback.
Deploy PostHog analytics to production platforms. Covers Next.js with Vercel (reverse proxy, server-side capture, edge functions), self-hosted PostHog with Docker, and Google Cloud Run deployment patterns.
phc_...)phx_...) for server featuresvercel, docker, or gcloud)set -euo pipefail
# Set environment variables in Vercel
vercel env add NEXT_PUBLIC_POSTHOG_KEY production # phc_... (public)
vercel env add NEXT_PUBLIC_POSTHOG_HOST production # /ingest (if using proxy)
vercel env add POSTHOG_PERSONAL_API_KEY production # phx_... (server-only)
vercel env add POSTHOG_PROJECT_ID production # Project ID number
// next.config.js — Reverse proxy to bypass ad blockers
module.exports = {
async rewrites() {
return [
{
source: '/ingest/static/:path*',
destination: 'https://us-assets.i.posthog.com/static/:path*',
},
{
source: '/ingest/:path*',
destination: 'https://us.i.posthog.com/:path*',
},
];
},
};
// app/providers.tsx — Client-side PostHog with proxy
'use client';
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react';
import { useEffect } from 'react';
export function PHProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: '/ingest', // Routes through your domain's reverse proxy
capture_pageview: false, // Handle manually in App Router
capture_pageleave: true,
});
}, []);
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
// app/api/track/route.ts — Server-side event capture
import { PostHog } from 'posthog-node';
import { NextResponse } from 'next/server';
export const runtime = 'edge';
export async function POST(request: Request) {
const body = await request.json();
const { userId, event, properties } = body;
const posthog = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
host: 'https://us.i.posthog.com',
flushAt: 1, // Immediate flush in serverless
flushInterval: 0,
});
try {
posthog.capture({ distinctId: userId, event, properties });
await posthog.shutdown(); // CRITICAL: flush before function exits
return NextResponse.json({ status: 'ok' });
} catch (error) {
return NextResponse.json({ error: 'capture failed' }, { status: 500 });
}
}
set -euo pipefail
# Deploy PostHog self-hosted (hobby tier)
git clone https://github.com/PostHog/posthog.git
cd posthog
# Configure environment
cat > .env <<'EOF'
SECRET_KEY=your-random-secret-key-here
SITE_URL=https://posthog.yourcompany.com
IS_BEHIND_PROXY=true
EOF
# Start PostHog
docker compose -f docker-compose.hobby.yml up -d
# PostHog runs at http://localhost:8000
# Complete setup wizard in browser
# Health check
curl -s http://localhost:8000/_health | jq .
// Point SDKs to your self-hosted instance
posthog.init('phc_your_key', {
api_host: 'https://posthog.yourcompany.com', // Your self-hosted URL
});
set -euo pipefail
# Set secrets in GCP Secret Manager
echo -n "phc_your_key" | gcloud secrets create posthog-project-key --data-file=-
echo -n "phx_your_key" | gcloud secrets create posthog-personal-key --data-file=-
# Deploy with PostHog secrets
gcloud run deploy my-app \
--image gcr.io/my-project/my-app:latest \
--set-secrets "NEXT_PUBLIC_POSTHOG_KEY=posthog-project-key:latest" \
--set-secrets "POSTHOG_PERSONAL_API_KEY=posthog-personal-key:latest" \
--set-env-vars "POSTHOG_HOST=https://us.i.posthog.com" \
--region us-central1 \
--allow-unauthenticated
set -euo pipefail
# Create annotation on each deploy so you can correlate metric changes with releases
curl -X POST "https://app.posthog.com/api/projects/$POSTHOG_PROJECT_ID/annotations/" \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"content\": \"Deploy: $(git rev-parse --short HEAD) — $(git log -1 --pretty=%s)\",
\"date_marker\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
\"scope\": \"project\"
}"
| Issue | Cause | Solution |
|---|---|---|
| Events not appearing | Wrong api_host | Use us.i.posthog.com (not app.posthog.com) |
| Ad blocker blocks events | Direct PostHog requests | Set up reverse proxy via Next.js rewrites |
| Edge function events lost | No shutdown() call | Always await posthog.shutdown() in serverless |
| Self-hosted 502 | Under-provisioned | Increase Docker memory (min 4GB RAM) |
| Cloud Run cold start lag | PostHog init in handler | Move init to module scope, only shutdown in handler |
For webhook handling, see posthog-webhooks-events.