6 min read

How to Monitor Page Views in PostHog

PostHog captures page view events automatically, but you need to set it up correctly to see that data. If you're trying to understand which pages users visit, how long they stay, or where they drop off, you need page view tracking working end-to-end. Let's walk through installing the SDK, configuring page view capture, and analyzing the results.

Set Up Automatic Page View Tracking

PostHog's JavaScript SDK automatically fires a $pageview event when pages load. For traditional multi-page applications, this works out of the box. Single-page applications need a bit more setup.

Install the PostHog JavaScript SDK

Add the PostHog SDK to your project using npm. This package includes everything you need to initialize tracking and capture events.

javascript
npm install posthog-js

Initialize PostHog early in your app

Call posthog.init() as early as possible—ideally before any UI renders. For React apps, put this in your root component or a layout. Grab your API key from Settings > Project Settings in PostHog. The api_host defaults to PostHog Cloud, but point it to your self-hosted instance if you have one.

javascript
import posthog from 'posthog-js'

posthog.init('phc_YOUR_API_KEY_HERE', {
  api_host: 'https://app.posthog.com',
  loaded: (ph) => {
    console.log('PostHog is ready')
  }
})
Initialize PostHog in your app's entry point

Verify page views are being captured

Open PostHog and navigate to Events in the left sidebar. You should see $pageview events flowing in. Each event includes $current_url, $pathname, and browser metadata. If you don't see events after 30 seconds, check your browser's Network tab to confirm requests are reaching PostHog.

javascript
// Debug: Check if PostHog loaded and what it captured
console.log('PostHog library loaded:', !!window.posthog)
console.log('Config:', posthog.config)

// You can manually fire a pageview if needed
posthog.capture('$pageview', {
  $current_url: window.location.href,
  section: 'dashboard'
})
Watch out: Single-page applications don't reload the page on navigation, so $pageview won't fire automatically when routes change. You'll need to manually trigger page views (see the next section).

Customize Page View Tracking for SPAs and Add Metadata

The default setup works for traditional websites, but single-page apps need you to hook into the router. You can also add custom properties to segment page views by feature, user tier, or experiment variant.

Capture page views on route changes in SPAs

Hook into your router to fire $pageview every time the URL changes. This example uses React Router, but the same pattern applies to Next.js, Vue Router, or any client-side router. Place the effect at the top level so it runs on every navigation.

javascript
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import posthog from 'posthog-js'

export function PageViewTracker() {
  const location = useLocation()

  useEffect(() => {
    posthog.capture('$pageview', {
      $current_url: window.location.href,
      path: location.pathname,
      search: location.search
    })
  }, [location.pathname, location.search])

  return null
}

Add custom properties to all page views

Use posthog.register() to set properties that automatically attach to every subsequent event, including page views. This is useful for tagging pages by feature area, user tier, or A/B test variant. Properties persist until you call posthog.unregister(), so set them once when the context changes.

javascript
// On app load or user login
posthog.register({
  app_section: 'dashboard',
  user_tier: 'pro',
  experiment_variant: 'checkout_v2'
})

// Now every $pageview includes these properties
posthog.capture('$pageview')

// Clear a property when it no longer applies
posthog.unregister('experiment_variant')

Set user-level properties for segmentation

Call posthog.people.set() to attach properties to a user (identified by distinct_id). This lets you later segment all that user's page views by properties like email, plan, or signup date. These properties appear in every event that user generates.

javascript
// After user logs in or signs up
posthog.people.set({
  email: '[email protected]',
  plan: 'pro',
  company: 'Acme Inc',
  signup_date: '2025-01-15'
})

// Now all page views from this user are tagged with these properties
posthog.capture('$pageview')
Tip: Use posthog.unregister() to clean up properties when they're no longer relevant, like after a user logs out or an experiment ends. This prevents stale data from being attached to future events.

Analyze Page View Traffic

Once page views are flowing in, you can build dashboards, identify traffic patterns, and spot bottlenecks in your user journeys.

View page view trends over time

Go to Insights and create a new Trends graph. Select the $pageview event and watch traffic volume over time. Add a Breakdown by $current_url or $pathname to compare traffic across pages. You can segment by user properties too (e.g., traffic by country, device, or plan).

javascript
// Fetch page view data via PostHog API
const response = await fetch(
  'https://app.posthog.com/api/projects/YOUR_PROJECT_ID/insights/',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer phc_YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      events: [{ id: '$pageview' }],
      date_from: '-7d',
      breakdown: '$current_url'
    })
  }
)
const data = await response.json()

Build a navigation funnel

Use the Funnel view to see drop-off rates between pages. Create a funnel that goes: Homepage → Pricing → Signup → Dashboard. This shows where users abandon the flow. You can segment by user properties to see which cohorts drop off where.

javascript
// Capture page view with page identifier for funnel analysis
posthog.capture('$pageview', {
  page_step: 'pricing_page',
  flow_id: user_session_id
})

// Later, filter by page_step in Funnels
// Funnel: pricing_page → signup_page → dashboard
Tip: Enable Session Recording in PostHog settings. Sessions group page views and other events together, making it easier to understand the full user journey, not just isolated page visits.

Common Pitfalls

  • Forgetting to manually fire $pageview in single-page apps—automatic tracking only works on traditional page reloads, not client-side route changes.
  • Initializing PostHog after your app renders—this can miss the first page view. Always call posthog.init() at the very top of your app.
  • Over-fragmenting page views into too many custom events instead of using one $pageview with properties—this makes analysis harder and clutters your event list.
  • Not setting user properties with posthog.people.set() before capturing page views, which makes it impossible to segment traffic by user cohorts.

Wrapping Up

You now have page views flowing into PostHog, custom properties attached to segment by context, and the tools to analyze traffic patterns. PostHog automatically captures page views for traditional sites, but SPAs need manual routing hooks. Combine page view data with session recordings to see not just where users go, but what they do. If you want to monitor page views and other metrics across multiple tools in one place, Product Analyst can help.

Track these metrics automatically

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

Try Product Analyst — Free