posthog

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PostHog Implementation (Next.js 2025)

PostHog 集成实现(Next.js 2025)

What This Skill Covers

本技能涵盖内容

  1. Analytics - Event tracking, user identification, group analytics
  2. Feature Flags - Boolean flags, multivariate, A/B testing
  3. Session Replay - Recording setup, privacy controls
  4. Analytics Queries - HogQL, Query API, extracting insights
  5. Reporting - Funnel analysis, retention, error reports, SEO
  1. 分析功能 - 事件追踪、用户识别、群组分析
  2. 功能标志 - 布尔型标志、多变量配置、A/B测试
  3. 会话重放 - 录制设置、隐私控制
  4. 分析查询 - HogQL、Query API、洞察提取
  5. 报告功能 - 漏斗分析、用户留存、错误报告、SEO

Reference Files

参考文件

Load these files as needed based on the task:
FileLoad When
references/nextjs-implementation.md
Setting up PostHog from scratch, detailed code patterns
references/event-taxonomy.md
Designing event naming conventions, property patterns
references/feature-flags.md
Implementing feature flags, A/B tests, experiments
根据任务需求按需加载以下文件:
文件加载场景
references/nextjs-implementation.md
从零开始搭建PostHog,详细代码示例
references/event-taxonomy.md
设计事件命名规范、属性格式
references/feature-flags.md
实现功能标志、A/B测试、实验配置

Quick Setup

快速设置

Environment Variables

环境变量

bash
undefined
bash
undefined

.env.local

.env.local

NEXT_PUBLIC_POSTHOG_KEY=phc_your_project_key NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
undefined
NEXT_PUBLIC_POSTHOG_KEY=phc_your_project_key NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
undefined

Reverse Proxy Setup (RECOMMENDED)

反向代理设置(推荐)

IMPORTANT: Ad blockers block direct PostHog requests. Use a reverse proxy to route through your own domain.
Add to
next.config.ts
:
typescript
const nextConfig: NextConfig = {
  async rewrites() {
    return [
      {
        source: "/ingest/static/:path*",
        destination: "https://us-assets.i.posthog.com/static/:path*",
      },
      {
        source: "/ingest/:path*",
        destination: "https://us.i.posthog.com/:path*",
      },
      {
        source: "/ingest/decide",
        destination: "https://us.i.posthog.com/decide",
      },
    ];
  },
  // ... rest of config
};
Also update CSP headers to allow PostHog connections:
typescript
"connect-src 'self' ... https://*.posthog.com https://us.i.posthog.com https://us-assets.i.posthog.com",
重要提示: 广告拦截器会阻止直接的PostHog请求。请使用反向代理通过自有域名路由请求。
next.config.ts
中添加以下配置:
typescript
const nextConfig: NextConfig = {
  async rewrites() {
    return [
      {
        source: "/ingest/static/:path*",
        destination: "https://us-assets.i.posthog.com/static/:path*",
      },
      {
        source: "/ingest/:path*",
        destination: "https://us.i.posthog.com/:path*",
      },
      {
        source: "/ingest/decide",
        destination: "https://us.i.posthog.com/decide",
      },
    ];
  },
  // ... 其他配置
};
同时更新CSP头以允许PostHog连接:
typescript
"connect-src 'self' ... https://*.posthog.com https://us.i.posthog.com https://us-assets.i.posthog.com",

PostHog Provider (Client-Side)

PostHog 客户端提供者

Create
app/providers.tsx
:
typescript
'use client'

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

export function PostHogProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      // Use reverse proxy to bypass ad blockers
      api_host: '/ingest',
      ui_host: 'https://us.i.posthog.com',
      defaults: '2025-05-24',
      capture_pageview: false, // We handle manually for accurate funnels
      person_profiles: 'identified_only',
    })
  }, [])

  return <PHProvider client={posthog}>{children}</PHProvider>
}
创建
app/providers.tsx
typescript
'use client'

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

export function PostHogProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      // 使用反向代理绕过广告拦截器
      api_host: '/ingest',
      ui_host: 'https://us.i.posthog.com',
      defaults: '2025-05-24',
      capture_pageview: false, // 手动处理以确保漏斗分析准确性
      person_profiles: 'identified_only',
    })
  }, [])

  return <PHProvider client={posthog}>{children}</PHProvider>
}

PostHog Server Client

PostHog 服务端客户端

Create
lib/posthog-server.ts
:
typescript
import { PostHog } from 'posthog-node'

let posthogClient: PostHog | null = null

export function getPostHogServer(): PostHog {
  if (!posthogClient) {
    posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com',
      flushAt: 1,
      flushInterval: 0,
    })
  }
  return posthogClient
}
创建
lib/posthog-server.ts
typescript
import { PostHog } from 'posthog-node'

let posthogClient: PostHog | null = null

export function getPostHogServer(): PostHog {
  if (!posthogClient) {
    posthogClient = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
      host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.i.posthog.com',
      flushAt: 1,
      flushInterval: 0,
    })
  }
  return posthogClient
}

Event Naming Convention

事件命名规范

PatternExampleUse Case
category:object_action
signup:form_submit
User actions
feature:action
dashboard:project_create
Feature usage
lifecycle:event
user:signup_complete
User journey
格式示例适用场景
category:object_action
signup:form_submit
用户操作
feature:action
dashboard:project_create
功能使用
lifecycle:event
user:signup_complete
用户旅程

Property Naming

属性命名规则

PatternExampleType
object_adjective
user_id
,
item_price
Any
is_
prefix
is_subscribed
,
is_first_time
Boolean
has_
prefix
has_seen_onboarding
Boolean
_count
suffix
item_count
,
generation_count
Number
_at
suffix
created_at
,
upgraded_at
Timestamp
格式示例类型
object_adjective
user_id
,
item_price
任意类型
is_
前缀
is_subscribed
,
is_first_time
布尔值
has_
前缀
has_seen_onboarding
布尔值
_count
后缀
item_count
,
generation_count
数值
_at
后缀
created_at
,
upgraded_at
时间戳

Server vs Client Decision Tree

服务端与客户端追踪决策树

Where to track?
├── User action in browser → Client (posthog-js)
├── API route / webhook → Server (posthog-node)
├── Server Component render → Server (posthog-node)
├── Need 100% accuracy → Server (no ad blockers)
└── Real-time UI feedback → Client (posthog-js)
选择追踪位置?
├── 浏览器中的用户操作 → 客户端(posthog-js)
├── API路由 / Webhook → 服务端(posthog-node)
├── 服务端组件渲染 → 服务端(posthog-node)
├── 需要100%准确性 → 服务端(无广告拦截)
└── 实时UI反馈 → 客户端(posthog-js)

Common Pitfalls

常见问题与解决方案

PitfallSolution
Ad blockers blocking PostHogUse reverse proxy (
/ingest
→ PostHog). See setup above
Events not appearingCheck ad blockers, verify API key, use reverse proxy
Duplicate pageviewsUse
capture_pageview: false
and handle manually
Feature flag flickerBootstrap flags via middleware
Missing user dataCall
identify()
BEFORE
$pageview
for accurate funnels
Inconsistent namingUse
category:object_action
pattern
Failed to fetch
errors
Browser extension blocking - use reverse proxy
503 from
us-assets.i.posthog.com
Ad blocker injecting fake response - use reverse proxy
问题解决方案
广告拦截器阻止PostHog请求使用反向代理(
/ingest
→ PostHog),详见上述设置
事件未显示检查广告拦截器、验证API密钥、使用反向代理
重复页面浏览事件设置
capture_pageview: false
并手动处理
功能标志闪烁通过中间件预加载标志
用户数据缺失
$pageview
之前调用
identify()
以确保漏斗分析准确性
命名不一致使用
category:object_action
格式
Failed to fetch
错误
浏览器扩展拦截 - 使用反向代理
us-assets.i.posthog.com
返回503错误
广告拦截器注入虚假响应 - 使用反向代理

Clarifying Questions

需要明确的问题

Before implementing PostHog, ask:
  1. What events are most important to track? (signups, conversions, feature usage)
  2. Do you need server-side tracking? (for accuracy, API routes)
  3. Are you running A/B tests? (need experiment setup)
  4. What's your auth provider? (for user identification pattern)
  5. Do you need session replay? (privacy considerations)
在实现PostHog之前,请确认以下问题:
  1. 最需要追踪的事件是什么?(注册、转化、功能使用)
  2. 是否需要服务端追踪?(为了准确性、API路由场景)
  3. 是否要运行A/B测试?(需要实验配置)
  4. 使用的认证提供者是什么?(用于确定用户识别方式)
  5. 是否需要会话重放?(需考虑隐私问题)