GA4 tells you what happened. PostHog tells you how it happened.
That distinction sounds small. It isn't. GA4 can tell you that 60% of visitors to your pricing page bounced. PostHog can show you the session replay where they scrolled down, hovered over the enterprise tier for 4 seconds, looked for a "talk to sales" button that didn't exist, and left. One is a metric. The other is an explanation.
We run both on warehows.ai. Most of our clients run both. They answer different questions.
What PostHog actually is
PostHog is an open-source product analytics platform. It does:
- Session replays — watch exactly what a user did on your site, click by click
- Event tracking — autocapture clicks, pageviews, form submissions without manual instrumentation
- Funnels — define a multi-step path and see where users drop off
- Feature flags — roll out changes to a percentage of users
- Heatmaps — see where users click and how far they scroll
- Surveys — collect in-app feedback tied to specific pages or events
The self-hosted version is free. The cloud version has a generous free tier (1M events/month). For most SMBs, the cost is effectively zero.
GA4 vs PostHog — what each does better
| Capability | GA4 | PostHog |
|---|---|---|
| Traffic attribution (source/medium) | Strong | Basic |
| Search Console integration | Native | None |
| Session replays | No | Yes |
| Heatmaps | No | Yes |
| Feature flags | No | Yes |
| Individual user paths | Aggregate only | Per-session |
| Funnel analysis | Good (aggregated) | Better (individual paths visible) |
| BigQuery export | Free, native | Via API or warehouse connector |
| Self-hosting | No | Yes |
| Cost | Free | Free tier, then usage-based |
The pattern is clear: GA4 is a traffic tool. PostHog is a product tool. GA4 tells you where visitors came from and how many there were. PostHog tells you what they did and why they left.
The "why" gap
This is the gap that burns most teams.
Your GA4 funnel shows a 40% drop-off between the pricing page and the contact form. You know that people are dropping off. You don't know why. Was the form too long? Was the pricing confusing? Did they get distracted by a broken layout on mobile?
GA4 can't answer these questions. PostHog can.
Session replay is the feature that changes the conversation. You pull up the 20 sessions that dropped off at the pricing page and watch them. Within 10 minutes, you notice a pattern: mobile users can't see the "Book a call" button because it's below the fold. Or desktop users spend 15 seconds looking at the enterprise tier and leave because there's no way to talk to a human without committing to a form.
That's actionable in a way that "40% drop-off" never is.
Setting it up
PostHog setup is a single script tag or SDK install:
// Next.js / React — PostHog provider
import posthog from 'posthog-js'
posthog.init('phc_your_project_key', {
api_host: 'https://us.i.posthog.com',
capture_pageview: false, // manual pageview for SPA routing
capture_pageleave: true,
session_recording: {
recordCrossOriginIframes: true,
},
})Autocapture handles the rest — clicks, pageviews, form interactions are all tracked without writing custom event code. Session recording starts automatically.
For specific conversion events, add manual captures:
// Track form submission with metadata
posthog.capture('contact_form_submitted', {
form_page: window.location.pathname,
has_company: Boolean(formData.company),
message_length: formData.message.length,
})Combining PostHog with GA4 in your warehouse
PostHog alone is powerful. PostHog + GA4 + your CRM in a warehouse is a different level.
The architecture:
GA4 ──→ BigQuery (native export)
PostHog ──→ BigQuery (via Fivetran, API export, or PostHog warehouse connector)
CRM ──→ BigQuery (via Fivetran)
│
▼
dbt models
│
▼
Sigma / Looker
Staging the PostHog data
-- models/staging/stg_posthog__events.sql
SELECT
uuid AS event_id,
event AS event_name,
distinct_id AS posthog_user_id,
TIMESTAMP(timestamp) AS event_at,
properties.$current_url AS page_url,
properties.$referrer AS referrer_url,
properties.$device_type AS device_type,
properties.$session_id AS session_id
FROM {{ source('posthog', 'events') }}
WHERE event NOT IN ('$feature_flag_called') -- filter noiseJoining PostHog sessions with GA4 traffic
-- models/intermediate/int_unified_sessions.sql
SELECT
COALESCE(ph.session_id, ga.ga_session_id) AS session_id,
ga.utm_source,
ga.utm_medium,
ph.total_events,
ph.session_duration_seconds,
ph.pages_viewed,
ph.had_rage_click,
ph.reached_contact_form
FROM {{ ref('int_posthog__sessions') }} ph
LEFT JOIN {{ ref('int_ga4__sessions') }} ga
ON ph.landing_page_url = ga.landing_page_url
AND ph.session_start BETWEEN ga.session_start AND ga.session_endNow you can answer: "Users from LinkedIn organic who rage-clicked on the pricing page — which ones ended up submitting the contact form?"
What changes when you add PostHog
| Question | GA4 alone | GA4 + PostHog |
|---|---|---|
| How many sessions this month? | Yes | Yes |
| Where did they come from? | Yes | Yes |
| What did they do on the page? | Aggregate events | Individual session replays |
| Why did they leave? | No | Yes — watch the replay |
| Did they get frustrated? | No | Yes — rage clicks, dead clicks |
| How far did they scroll? | Basic (scroll_depth event) | Heatmap + per-session data |
| Which variant converts better? | Requires Optimize (deprecated) | Feature flags + experiments |
| What do users say? | No | In-app surveys tied to pages |
PostHog for visitor identification
One pattern we've explored: using PostHog as a lightweight visitor deanonymization layer.
PostHog captures IP addresses (configurable). With an IP-to-company enrichment service (IPinfo, Clearbit), you can identify which companies are visiting your site — without buying a dedicated tool like RB2B or Leadfeeder.
-- models/intermediate/int_posthog__company_visits.sql
SELECT
ph.ip_address,
ip.company_name,
ip.company_domain,
ip.employee_count,
COUNT(DISTINCT ph.session_id) AS sessions,
MIN(ph.session_start) AS first_visit,
MAX(ph.session_start) AS last_visit
FROM {{ ref('stg_posthog__events') }} ph
LEFT JOIN {{ ref('stg_ipinfo__companies') }} ip
ON ph.ip_address = ip.ip_address
WHERE ip.company_name IS NOT NULL
GROUP BY 1, 2, 3, 4It's not as granular as RB2B (you get company, not individual), but it's effectively free and doesn't require a third-party pixel.
The honest take
PostHog doesn't replace GA4. GA4 is better at traffic attribution, search console integration, and the BigQuery export ecosystem. PostHog is better at everything that happens after the click — understanding behavior, diagnosing friction, watching users interact with your product.
If you're a content site optimizing for SEO traffic, GA4 alone might be enough. If you're a SaaS product, an e-commerce store, or any business where the on-site experience drives conversion, PostHog fills a gap that GA4 leaves wide open.
Your GA4 says bounce rate is 60%. PostHog shows you the exact 8 seconds where every user gets confused and leaves. One tells you there's a problem. The other shows you the fix.
We wire PostHog into warehouse stacks alongside GA4, CRM, and ad platforms — so the "why" joins the "what" and the "who." If your analytics setup gives you numbers but not explanations, book a discovery call.