As a developer, I’ve always had a love-hate relationship with analytics. Most tools feel like they were built for marketing teams—lots of pretty charts, but very little technical granularity. When I first started looking for a way to track exactly how users interact with my features without spending hours in a dashboard, I found PostHog. This posthog tutorial for developers is designed to get you from zero to a fully instrumented application using the tools we actually use daily.
PostHog isn’t just an analytics tool; it’s a product OS. It combines event tracking, session recording, feature flags, and A/B testing into one platform. If you’re debating between different options, you might find my PostHog vs Amplitude comparison useful, but for most indie hackers and small engineering teams, PostHog’s all-in-one approach is a game changer.
Prerequisites
Before we dive into the code, make sure you have the following ready:
- A PostHog account (Cloud or self-hosted analytics platforms for developers setup).
- A running web application (I’ll be using Next.js for the examples, but this works for any JS framework).
- Basic familiarity with npm/yarn and environment variables.
Step 1: Initializing PostHog in Your Project
The first step is getting the snippet into your app. While you can use the JS snippet in your HTML head, I prefer the posthog-js library for better type safety and control in modern frameworks.
npm install posthog-js
Now, create a PostHog initialization file (e.g., lib/posthog.ts) to ensure the client is a singleton across your app:
import posthog from 'posthog-js';
export const ph = posthog.init('<YOUR_PROJECT_API_KEY>', {
api_host: 'https://us.i.posthog.com',
person_profiles: 'identified_only',
capture_pageview: false // We'll handle this manually for SPAs
});
In my experience, setting capture_pageview: false is critical for Next.js or React apps to avoid duplicate page views during client-side routing.
Step 2: Tracking Custom Events
Page views are great, but they don’t tell you how a user is using your tool. The core of any posthog tutorial for developers is mastering custom events. Instead of generic clicks, track intent-based actions.
For example, if you have a ‘Export PDF’ button, don’t just track a click; track the export event with properties:
const handleExport = (fileType) => {
ph.capture('document_exported', {
format: fileType,
page_url: window.location.pathname,
is_premium_user: user.plan === 'pro'
});
// ... rest of your export logic
};
As shown in the image below, these events will appear in real-time in your Live Event stream, allowing you to verify your implementation immediately.
Step 3: Identifying Users
By default, PostHog assigns a random UUID to every visitor. To link these events to a real user in your database, you need to identify them after they log in.
// Call this immediately after a successful login or signup
ph.identify(
'user_id_12345',
{
email: 'dev@example.com',
name: 'Jane Developer',
plan: 'Enterprise'
}
);
Once identified, you can create cohorts based on these properties, such as “Users on the Enterprise plan who haven’t exported a document in 7 days.”
Step 4: Implementing Feature Flags
This is where PostHog moves from “analytics” to “development tool.” Feature flags allow you to merge code to production but keep the feature hidden until you’re ready.
if (ph.isFeatureEnabled('new-dashboard-v2')) {
return <NewDashboard />
}
return <OldDashboard />
I’ve found that using feature flags drastically reduces my deployment anxiety. You can roll out a feature to 10% of users, monitor the event logs for errors, and then scale to 100%.
Pro Tips for Developer Instrumentation
- Avoid Auto-capture Overload: PostHog’s auto-capture is powerful, but it creates a lot of noise. I recommend naming your critical events explicitly using
ph.capture()so your dashboards remain clean. - Use Groups: If you are building a B2B app, use
ph.group('company', 'company_id'). This lets you analyze behavior at the organization level rather than just the individual user level. - Environment Separation: Always use different Project API keys for your staging and production environments to avoid polluting your production data.
Troubleshooting Common Issues
Events not showing up? First, check your AdBlocker. Most blockers stop PostHog by default. To fix this in production, you should proxy PostHog through your own domain.
Duplicate Events? This usually happens in React’s StrictMode where components mount twice. Ensure your posthog.init is outside the component lifecycle or wrapped in a check.
What’s Next?
Now that you have the basics down, I recommend exploring Session Replays. It’s like having a DVR for your app; you can watch exactly where a user got stuck before they dropped off. If you’re looking to scale your infrastructure, check out my guide on self-hosted analytics platforms for developers to see if hosting your own instance makes sense for your privacy requirements.