5 min read

How to Track Page Views in PostHog

Page view tracking is how you understand what your users are actually doing on your site. PostHog captures these automatically by default, but you might need manual tracking if you're building a single-page app or want custom metadata attached to each view.

Enable Auto Page View Tracking

The easiest approach: let PostHog handle page views automatically as part of its web SDK initialization.

Install the PostHog SDK

Add the posthog-js package to your project.

javascript
npm install posthog-js

Initialize PostHog with auto-capture enabled

In your app's entry point, call posthog.init() with capture_pageview: true. This tells PostHog to automatically fire a $pageview event whenever the URL changes.

javascript
import posthog from 'posthog-js'

posthog.init('phc_YOUR_API_KEY', {
  api_host: 'https://us.i.posthog.com',
  capture_pageview: true
})
PostHog initialization with auto page view tracking. Replace phc_YOUR_API_KEY with your project token from the PostHog dashboard.

View page views in the **Events** table

Once initialized, navigate your app normally. Go to Data management > Events and filter by $pageview. Each entry shows $pathname, $current_url, and timestamp.

javascript
// PostHog automatically captures:
// {
//   event: '$pageview',
//   properties: {
//     $current_url: 'https://example.com/docs',
//     $pathname: '/docs',
//     $host: 'example.com'
//   }
// }
Watch out: Auto-capture only tracks full page reloads and browser history changes. If you're using hash-based routing in a single-page app, you'll need manual tracking.

Manually Track Page Views in Single-Page Apps

For React, Vue, or Next.js apps with client-side routing, auto-capture might miss route changes. Manually fire page view events when your router detects navigation.

Listen for route changes in your router

Detect when the URL has changed. In Next.js, use the router's routeChangeComplete event. In React Router, use useEffect with useLocation.

javascript
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import posthog from 'posthog-js'

export default function App() {
  const router = useRouter()

  useEffect(() => {
    const handleRouteChange = (url) => {
      posthog.capture('$pageview', {
        $current_url: window.location.href
      })
    }

    router.events.on('routeChangeComplete', handleRouteChange)
    return () => router.events.off('routeChangeComplete', handleRouteChange)
  }, [router.events])

  return null
}
Next.js example. Call this in your root _app.js component to track all route changes.

Attach custom properties to describe the page

Add metadata so you can segment page views later. Include page type, section, user tier, or any ID relevant to your product.

javascript
posthog.capture('$pageview', {
  $current_url: window.location.href,
  page_type: 'product-listing',
  category: 'electronics',
  filters_applied: ['in-stock', 'under-$50']
})
Capture a page view with custom properties for segmentation and funnels.

Disable auto-capture to avoid double-counting

If you're manually tracking, set capture_pageview: false in your init config to prevent the same page view from being recorded twice.

javascript
posthog.init('phc_YOUR_API_KEY', {
  api_host: 'https://us.i.posthog.com',
  capture_pageview: false  // Manual tracking only
})
Tip: If you control both auto and manual tracking, disable auto-capture. Otherwise every route change gets counted as two events.

Build Insights from Page Views

Once you're capturing page views, segment them to find patterns and drop-off points.

Create a trends insight to see your most visited pages

Go to Insights > New insight > Trends. Filter by $pageview and break down by $pathname. This shows you which pages get the most traffic and how it changes over time.

javascript
// Example filtering via the Events table:
// Filter: event = '$pageview'
// Break down by: $pathname
// Date range: Last 7 days

Build a funnel to track the user journey

Use Insights > New funnel to add page views as conversion steps. For example: //pricing/signup/onboarding. This shows where users drop off.

javascript
// Funnel steps (configure in PostHog UI):
// Step 1: $pageview where $pathname = '/'
// Step 2: $pageview where $pathname = '/pricing'
// Step 3: $pageview where $pathname = '/signup'
// Step 4: $pageview where $pathname = '/onboarding'

Common Pitfalls

  • Forgetting to disable capture_pageview when switching to manual tracking — this causes every route change to be counted twice.
  • Not including custom properties on page views — $pathname alone doesn't tell you what type of content the user saw (article, product, settings, etc.).
  • Tracking PII in pageview events — avoid storing user names, emails, or sensitive data in $current_url or custom properties.
  • Hash-based route changes not being tracked — PostHog's auto-capture doesn't detect changes to #/route patterns; use manual tracking instead.

Wrapping Up

Page views are your first lens into user behavior. With auto-capture, you get them for free; with manual tracking, you get control and SPA support. Once you're tracking consistently, you can build funnels and cohorts to understand the full user journey. If you want to track this automatically across tools, Product Analyst can help.

Track these metrics automatically

Product Analyst connects to your stack and surfaces the insights that matter.

Try Product Analyst — Free