Analytics & Monitoring
Track user behavior and monitor errors with PostHog and Sentry
Analytics & Monitoring
BetterCone includes production-ready analytics and error monitoring out of the box.
PostHog Analytics
PostHog provides user behavior tracking, feature flags, and session replay.
Features Included
- ✅ Automatic page view tracking
- ✅ User identification
- ✅ Custom event tracking
- ✅ Subscription lifecycle events
- ✅ Debug mode for development
Configuration
PostHog is already integrated in lib/posthog.tsx:
import posthog from "posthog-js";
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
person_profiles: "identified_only",
capture_pageview: false, // Manual control
loaded: (posthog) => {
if (process.env.NODE_ENV === "development") {
posthog.debug();
}
},
});Environment Variables
Add to .env.local:
NEXT_PUBLIC_POSTHOG_KEY=phc_your_key_here
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.comGet your PostHog key from app.posthog.com. The free tier includes 1M events/month.
Usage
Automatic Page Tracking
Page views are tracked automatically via PageViewTracker:
import { PageViewTracker } from "@/lib/posthog-pageview";
export default function RootLayout({ children }) {
return (
<PostHogProvider>
<PageViewTracker />
{children}
</PostHogProvider>
);
}User Identification
Identify users on sign-in:
import { analytics } from "@/lib/analytics";
// On sign in
analytics.identifyUser(user.id, {
email: user.email,
name: user.name,
createdAt: user.createdAt,
});
// On sign out
analytics.resetUser();Custom Events
Track user actions:
import { analytics } from "@/lib/analytics";
// Sign up
analytics.trackSignUp({ method: "email" });
// Sign in
analytics.trackSignIn({ method: "google" });
// Subscription created
analytics.trackSubscriptionCreated({
plan: "pro",
interval: "monthly",
amount: 29,
});
// Subscription upgraded
analytics.trackSubscriptionUpgraded({
fromPlan: "starter",
toPlan: "pro",
fromInterval: "monthly",
toInterval: "yearly",
});
// Subscription cancelled
analytics.trackSubscriptionCancelled({
plan: "pro",
reason: "too expensive",
});
// Subscription reactivated
analytics.trackSubscriptionReactivated({
plan: "pro",
});Custom Event Helper
Create your own events:
import { posthog } from "@/lib/posthog";
// Track any custom event
posthog.capture("feature_used", {
feature: "api_dashboard",
organizationId: org.id,
timestamp: new Date().toISOString(),
});
// Track with user properties
posthog.capture("report_generated", {
reportType: "analytics",
dateRange: "30days",
format: "pdf",
});Sentry Error Monitoring
Sentry captures errors, exceptions, and performance issues in production.
Features Included
- ✅ Server-side error tracking
- ✅ Client-side error tracking
- ✅ Edge runtime support
- ✅ Global error boundary
- ✅ Request error capture
- ✅ Performance monitoring
Configuration
Sentry is pre-configured with three files using environment variables:
Server-side (sentry.server.config.ts)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1,
enableLogs: true,
sendDefaultPii: true,
});Client-side (instrumentation-client.ts)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1,
enableLogs: true,
sendDefaultPii: true,
});Edge runtime (sentry.edge.config.ts)
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1,
enableLogs: true,
sendDefaultPii: true,
});Environment Variables
Add to .env.local:
NEXT_PUBLIC_SENTRY_DSN=https://your-dsn@sentry.io/your-project-idGet your Sentry DSN from sentry.io → Create Project → Project Settings → Client Keys (DSN).
Global Error Handling
Errors are automatically captured via global-error.tsx:
"use client";
import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";
export default function GlobalError({ error }: { error: Error }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
<NextError statusCode={500} />
</body>
</html>
);
}Instrumentation
Automatic request error capture in instrumentation.ts:
import * as Sentry from '@sentry/nextjs';
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('../sentry.server.config');
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('../sentry.edge.config');
}
}
export const onRequestError = Sentry.captureRequestError;Manual Error Capture
Capture errors manually:
import * as Sentry from "@sentry/nextjs";
try {
// Risky operation
await dangerousFunction();
} catch (error) {
Sentry.captureException(error, {
level: "error",
tags: {
section: "billing",
action: "subscription_create",
},
extra: {
userId: user.id,
organizationId: org.id,
},
});
throw error;
}User Context
Add user context to errors:
import * as Sentry from "@sentry/nextjs";
Sentry.setUser({
id: user.id,
email: user.email,
username: user.name,
});
// Clear on sign out
Sentry.setUser(null);Best Practices
1. Environment-Specific Tracking
Only track in production or explicitly enable:
const shouldTrack =
process.env.NODE_ENV === "production" ||
process.env.NEXT_PUBLIC_ENABLE_ANALYTICS === "true";
if (shouldTrack) {
posthog.capture("event");
}2. Privacy Compliance
Don't track PII unless necessary:
// ❌ Bad - tracking sensitive data
posthog.capture("payment_failed", {
creditCardLast4: "1234",
billingAddress: "123 Main St",
});
// ✅ Good - tracking anonymized data
posthog.capture("payment_failed", {
paymentMethod: "card",
failureReason: "insufficient_funds",
});3. Event Naming
Use consistent naming:
// ✅ Good - snake_case, descriptive
posthog.capture("subscription_upgraded");
posthog.capture("team_member_invited");
posthog.capture("api_limit_reached");
// ❌ Bad - inconsistent, vague
posthog.capture("upgrade");
posthog.capture("TeamInvite");
posthog.capture("limit");4. Error Context
Add context to errors:
Sentry.captureException(error, {
tags: {
feature: "billing",
user_role: member.role,
},
extra: {
subscriptionId: subscription.id,
attemptedAction: "upgrade",
},
});Dashboard
PostHog Dashboard
View analytics at app.posthog.com:
- Insights: User trends, retention, funnels
- Session Replay: Watch user sessions
- Feature Flags: A/B testing
- Experiments: Test variations
Sentry Dashboard
Monitor errors at sentry.io:
- Issues: Error tracking and grouping
- Performance: Transaction monitoring
- Releases: Deploy tracking
- Alerts: Email/Slack notifications
Troubleshooting
PostHog not tracking
- Check environment variables are set
- Verify PostHog key is correct
- Check browser console for errors
- Enable debug mode:
posthog.debug()
Sentry not capturing errors
- Check DSN is correct
- Verify
instrumentation.tsis loaded - Check Sentry dashboard for events
- Test with
Sentry.captureException(new Error("Test"))
Next Steps
- Deployment - Deploy with monitoring
- Production Checklist - Pre-launch checks
- Customization - Customize tracking events