DEV Community

Roberto Luna
Roberto Luna

Posted on

Implementing PostHog Tracking and Web Vitals with Next.js

Implementing PostHog Tracking and Web Vitals with Next.js

TL;DR: I integrated PostHog tracking and web vitals into the lavanderia-crm project, replacing deprecated onFID with onINP and setting up a reverse proxy via /ingest rewrite. This enhances analytics and performance monitoring.

The Problem

The lavanderia-crm project needed improved analytics and performance tracking. The existing web vitals setup used the deprecated onFID metric, which was replaced by onINP in web-vitals v4. Additionally, I wanted to integrate PostHog for comprehensive tracking and engagement metrics.

What I Tried First

Initially, I focused on updating the web vitals metrics. I imported the web-vitals package and used the onFID function, which was deprecated. This approach failed because it caused compatibility issues with the latest version of web-vitals.

The Implementation

Step 1: Add PostHog Tracking

I started by installing posthog-js and adding it to the project:

// apps/web/package.json
"dependencies": {
  // ...
  "posthog-js": "^1.396.6",
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Then, I created a PostHogProvider component:

// apps/web/src/app/providers/PostHogProvider.tsx
'use client'

import posthog from 'posthog-js'
import { PostHogProvider as PHProvider } from 'posthog-js/react'
import { useEffect } from 'react'

function PostHogPageView() {
  useEffect(() => {
    if (!client || typeof window === 'undefined') return
    // ...
  }, [client])

  // Web Vitals
  useEffect(() => {
    if (!client || typeof window === 'undefined') return
    import('web-vitals').then(({ onCLS, onFCP, onINP }) => {
      onCLS((metric) => {
        posthog.capture('web_vitals', {
          metric: 'CLS',
          value: metric.value,
        })
      })
      onFCP((metric) => {
        posthog.capture('web_vitals', {
          metric: 'FCP',
          value: metric.value,
        })
      })
      onINP((metric) => {
        posthog.capture('web_vitals', {
          metric: 'INP',
          value: metric.value,
        })
      })
    })
  }, [client])

  return <PHProvider client={client}>{/* children */}</PHProvider>
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Web Vitals and Reverse Proxy

Next, I updated next.config.js to include a reverse proxy via /ingest rewrite:

// apps/web/next.config.js
const nextConfig = {
  // ...
  async rewrites() {
    return [
      {
        source: '/ingest',
        destination: 'https://app.posthog.com',
      },
    ]
  },
}
Enter fullscreen mode Exit fullscreen mode

I also updated the web-vitals package to v5 and replaced onFID with onINP:

// apps/web/src/app/providers/PostHogProvider.tsx
- import('web-vitals').then(({ onCLS, onFID, onFCP, onINP }) => {
-   onFID((metric) => {
-     posthog.capture('web_vitals', {
-       metric: 'FID',
-       value: metric.value,
-     })
-   })
+ import('web-vitals').then(({ onCLS, onFCP, onINP }) => {
Enter fullscreen mode Exit fullscreen mode

Step 3: Fix Page Leave Event

To properly track page leave events, I updated the usePathname hook:

// apps/web/src/app/providers/PostHogProvider.tsx
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'

function PostHogPageView() {
  const pathname = usePathname()

  useEffect(() => {
    if (!client || typeof window === 'undefined') return
    const handler = () => {
      posthog.capture('page_leave', {
        pathname,
      })
    }
    window.addEventListener('beforeunload', handler)
    return () => window.removeEventListener('beforeunload', handler)
  }, [client, pathname])

  // ...
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaway

The key takeaway from this implementation is the importance of keeping up with deprecations and updating metrics accordingly. Replacing onFID with onINP and integrating PostHog for comprehensive tracking significantly enhances the project's analytics and performance monitoring.

What's Next

Next, I plan to explore more PostHog features, such as custom event tracking and analytics dashboards, to further improve the project's insights and performance. Additionally, I will monitor the impact of these changes on the project's performance and make adjustments as needed.

vibecoding #buildinpublic #posthog #webvitals #nextjs


Part of my Build in Public series — sharing the real process of building Building Lavandería CRM from Playa del Carmen, México.

Repo: zaerohell/lavanderia-crm · 2026-07-04

#playadev #buildinpublic

Top comments (0)