posthog-debugger

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PostHog Debugger

PostHog调试器

Inspect and debug PostHog implementations on any website using browser automation tools. This skill helps developers and product teams understand exactly how PostHog is configured and what data is being captured.
使用浏览器自动化工具检查和调试任意网站上的PostHog实现。此技能可帮助开发人员和产品团队准确了解PostHog的配置方式以及正在捕获的数据。

Critical Rules

核心规则

  1. Always ask for the URL first if not provided.
  2. Always ask if the page requires login. If yes, guide the user to log in via Chrome first.
  3. Use browser tools to navigate and inspect. Prefer Chrome DevTools MCP (
    mcp__chrome-devtools__*
    ) or Playwright MCP (
    mcp__playwright__*
    ) tools.
  4. Check multiple signals. PostHog can be implemented in various ways - check scripts, network requests, and the window object.
  5. Report findings clearly. Summarize what you find in a structured format.
  6. Never modify anything. This is read-only inspection.
  1. 若未提供URL,务必先询问
  2. 务必询问页面是否需要登录。如果需要,引导用户先通过Chrome登录。
  3. 使用浏览器工具进行导航和检查。优先使用Chrome DevTools MCP(
    mcp__chrome-devtools__*
    )或Playwright MCP(
    mcp__playwright__*
    )工具。
  4. 检查多种信号。PostHog的实现方式多种多样——检查脚本、网络请求和window对象。
  5. 清晰报告发现结果。以结构化格式总结你的发现。
  6. 绝不修改任何内容。此技能仅用于只读检查。

Initial Flow

初始流程

When a user asks to inspect a PostHog implementation:
  1. Get the URL (if not provided)
  2. Navigate to the URL with
    ?__posthog_debug=true
    appended
  3. Check if login is required by taking a snapshot and looking for login indicators
  4. If login required, ask the user to authenticate in the browser
  5. Once authenticated, proceed with inspection
当用户要求检查PostHog实现时:
  1. 获取URL(若未提供)
  2. 导航到附加了
    ?__posthog_debug=true
    的URL
  3. 通过截图并查找登录标识来检查是否需要登录
  4. 若需要登录,请用户在浏览器中完成认证
  5. 认证完成后,继续进行检查

Detecting Login Pages

检测登录页面

After navigating, take a snapshot and look for login indicators:
  • Page title contains "login", "sign in", "authenticate"
  • URL contains "login", "signin", "auth", "sso"
  • Page has username/password fields
  • Page shows "Sign in with Google/GitHub/etc." buttons
导航后,截取页面截图并查找以下登录标识:
  • 页面标题包含"login"、"sign in"、"authenticate"
  • URL包含"login"、"signin"、"auth"、"sso"
  • 页面存在用户名/密码输入框
  • 页面显示"Sign in with Google/GitHub/etc."按钮

Authenticated Pages Workflow

已认证页面流程

If you detect a login page or the user mentions the page requires auth:
  1. Keep the browser open - you've already navigated there
  2. Ask the user to log in:
    "This page requires authentication. Please log in using the Chrome browser I just opened. Let me know when you're logged in and on the page you want to inspect."
  3. Once the user confirms, take a new snapshot to verify they're authenticated
  4. Add the debug parameter if not already present and reload if needed
  5. Proceed with inspection
若检测到登录页面或用户提及页面需要认证:
  1. 保持浏览器打开——你已导航到该页面
  2. 请用户登录
    "该页面需要认证。请使用我刚刚打开的Chrome浏览器登录。登录完成并进入你想要检查的页面后,请告知我。"
  3. 用户确认后,截取新截图以验证已认证
  4. 若尚未添加调试参数则添加,必要时重新加载页面
  5. 继续进行检查

Available Browser Tools

可用浏览器工具

Chrome DevTools MCP

Chrome DevTools MCP

  • mcp__chrome-devtools__navigate_page
    - Navigate to URL
  • mcp__chrome-devtools__take_snapshot
    - Get page accessibility tree
  • mcp__chrome-devtools__evaluate_script
    - Run JavaScript to inspect PostHog
  • mcp__chrome-devtools__list_network_requests
    - See network traffic
  • mcp__chrome-devtools__get_network_request
    - Get request details
  • mcp__chrome-devtools__list_console_messages
    - Check for errors
  • mcp__chrome-devtools__navigate_page
    - 导航到URL
  • mcp__chrome-devtools__take_snapshot
    - 获取页面可访问性树
  • mcp__chrome-devtools__evaluate_script
    - 运行JavaScript检查PostHog
  • mcp__chrome-devtools__list_network_requests
    - 查看网络流量
  • mcp__chrome-devtools__get_network_request
    - 获取请求详情
  • mcp__chrome-devtools__list_console_messages
    - 检查错误信息

Playwright MCP

Playwright MCP

  • mcp__playwright__browser_navigate
    - Navigate to URL
  • mcp__playwright__browser_snapshot
    - Get page snapshot
  • mcp__playwright__browser_evaluate
    - Run JavaScript
  • mcp__playwright__browser_network_requests
    - See network traffic
  • mcp__playwright__browser_console_messages
    - Check console
  • mcp__playwright__browser_navigate
    - 导航到URL
  • mcp__playwright__browser_snapshot
    - 获取页面截图
  • mcp__playwright__browser_evaluate
    - 运行JavaScript
  • mcp__playwright__browser_network_requests
    - 查看网络流量
  • mcp__playwright__browser_console_messages
    - 检查控制台

Inspection Workflow

检查流程

Step 1: Navigate to the Page with Debug Mode

步骤1:导航到开启调试模式的页面

Always add
?__posthog_debug=true
to the URL to enable PostHog's debug mode. This outputs detailed logs to the console.
  • If URL has no query string:
    https://example.com?__posthog_debug=true
  • If URL already has query string:
    https://example.com?foo=bar&__posthog_debug=true
Workflow:
  1. Navigate to the URL with the debug parameter
  2. Take a snapshot to see what loaded
  3. Check for login page indicators:
    • URL redirected to
      /login
      ,
      /signin
      ,
      /auth
      ,
      /sso
    • Page title contains "log in", "sign in"
    • Page has login form fields
  4. If login detected:
    • Tell the user: "I've opened the page but it requires login. Please log in using Chrome, then let me know when you're ready."
    • Wait for user confirmation
    • Take a new snapshot to verify authentication
    • Add debug parameter to the new URL if needed
  5. If no login needed: Proceed with inspection
**务必在URL中添加
?__posthog_debug=true
**以启用PostHog的调试模式。此模式会在控制台输出详细日志。
  • 若URL无查询字符串:
    https://example.com?__posthog_debug=true
  • 若URL已有查询字符串:
    https://example.com?foo=bar&__posthog_debug=true
流程:
  1. 导航到附加调试参数的URL
  2. 截取截图查看页面加载情况
  3. 检查登录页面标识
    • URL重定向到
      /login
      /signin
      /auth
      /sso
    • 页面标题包含"log in"、"sign in"
    • 页面存在登录表单输入框
  4. 若检测到登录
    • 告知用户:"我已打开页面,但该页面需要登录。请使用Chrome完成登录,准备好后告知我。"
    • 等待用户确认
    • 截取新截图验证认证状态
    • 必要时为新URL添加调试参数
  5. 若无需登录:继续检查

Step 2: Check PostHog Global Object

步骤2:检查PostHog全局对象

Execute JavaScript to inspect the
posthog
object on the window:
javascript
(() => {
  if (typeof posthog === 'undefined') {
    return { installed: false };
  }

  const ph = posthog;
  return {
    installed: true,
    version: ph.version || ph.LIB_VERSION || 'unknown',
    config: {
      token: ph.config?.token || ph.get_config?.('token') || 'not accessible',
      apiHost: ph.config?.api_host || ph.get_config?.('api_host') || 'not accessible',
      autocapture: ph.config?.autocapture ?? ph.get_config?.('autocapture') ?? 'not accessible',
      capturePageview: ph.config?.capture_pageview ?? ph.get_config?.('capture_pageview') ?? 'not accessible',
      capturePageleave: ph.config?.capture_pageleave ?? ph.get_config?.('capture_pageleave') ?? 'not accessible',
      sessionRecording: ph.config?.enable_recording_console_log !== undefined ||
                        ph.sessionRecording?.started ||
                        'check network',
      persistence: ph.config?.persistence || ph.get_config?.('persistence') || 'not accessible',
      debug: ph.config?.debug ?? ph.get_config?.('debug') ?? false
    },
    distinctId: ph.get_distinct_id?.() || 'not accessible',
    sessionId: ph.get_session_id?.() || 'not accessible',
    featureFlags: ph.getFeatureFlag ? Object.keys(ph.featureFlags?.flags || {}) : [],
    activeFeatureFlags: ph.getFeatureFlag ?
      Object.entries(ph.featureFlags?.flags || {})
        .filter(([_, v]) => v)
        .map(([k]) => k) : []
  };
})()
执行JavaScript检查window上的
posthog
对象:
javascript
(() => {
  if (typeof posthog === 'undefined') {
    return { installed: false };
  }

  const ph = posthog;
  return {
    installed: true,
    version: ph.version || ph.LIB_VERSION || 'unknown',
    config: {
      token: ph.config?.token || ph.get_config?.('token') || 'not accessible',
      apiHost: ph.config?.api_host || ph.get_config?.('api_host') || 'not accessible',
      autocapture: ph.config?.autocapture ?? ph.get_config?.('autocapture') ?? 'not accessible',
      capturePageview: ph.config?.capture_pageview ?? ph.get_config?.('capture_pageview') ?? 'not accessible',
      capturePageleave: ph.config?.capture_pageleave ?? ph.get_config?.('capture_pageleave') ?? 'not accessible',
      sessionRecording: ph.config?.enable_recording_console_log !== undefined ||
                        ph.sessionRecording?.started ||
                        'check network',
      persistence: ph.config?.persistence || ph.get_config?.('persistence') || 'not accessible',
      debug: ph.config?.debug ?? ph.get_config?.('debug') ?? false
    },
    distinctId: ph.get_distinct_id?.() || 'not accessible',
    sessionId: ph.get_session_id?.() || 'not accessible',
    featureFlags: ph.getFeatureFlag ? Object.keys(ph.featureFlags?.flags || {}) : [],
    activeFeatureFlags: ph.getFeatureFlag ?
      Object.entries(ph.featureFlags?.flags || {})
        .filter(([_, v]) => v)
        .map(([k]) => k) : []
  };
})()

Step 2b: Check for Bundled PostHog (Remote Config)

步骤2b:检查捆绑式PostHog(远程配置)

If
posthog
is not on
window
, check for bundled implementations that use
_POSTHOG_REMOTE_CONFIG
:
javascript
(() => {
  const remoteConfig = window._POSTHOG_REMOTE_CONFIG;
  if (!remoteConfig) {
    return { found: false };
  }

  const tokens = Object.keys(remoteConfig);
  const configs = tokens.map(token => {
    const cfg = remoteConfig[token]?.config || {};
    return {
      token,
      hasFeatureFlags: cfg.hasFeatureFlags || false,
      autocapture: !cfg.autocapture_opt_out,
      sessionRecording: cfg.sessionRecording || false,
      heatmaps: cfg.heatmaps || false,
      surveys: cfg.surveys || false,
      capturePerformance: cfg.capturePerformance || {},
      defaultIdentifiedOnly: cfg.defaultIdentifiedOnly || false
    };
  });

  return {
    found: true,
    bundled: true,
    configs
  };
})()
posthog
不在
window
上,检查使用
_POSTHOG_REMOTE_CONFIG
的捆绑式实现:
javascript
(() => {
  const remoteConfig = window._POSTHOG_REMOTE_CONFIG;
  if (!remoteConfig) {
    return { found: false };
  }

  const tokens = Object.keys(remoteConfig);
  const configs = tokens.map(token => {
    const cfg = remoteConfig[token]?.config || {};
    return {
      token,
      hasFeatureFlags: cfg.hasFeatureFlags || false,
      autocapture: !cfg.autocapture_opt_out,
      sessionRecording: cfg.sessionRecording || false,
      heatmaps: cfg.heatmaps || false,
      surveys: cfg.surveys || false,
      capturePerformance: cfg.capturePerformance || {},
      defaultIdentifiedOnly: cfg.defaultIdentifiedOnly || false
    };
  });

  return {
    found: true,
    bundled: true,
    configs
  };
})()

Step 2c: Check Console for PostHog Debug Messages

步骤2c:检查控制台中的PostHog调试消息

With
?__posthog_debug=true
, PostHog outputs detailed logs. Use
list_console_messages
and look for
[PostHog.js]
entries:
Key messages to look for:
  • [PostHog.js] Persistence loaded
    - Shows persistence type (localStorage, sessionStorage, cookie)
  • [PostHog.js] [Surveys] Surveys loaded successfully
    - Surveys module loaded
  • [PostHog.js] [Surveys] flags response received, isSurveysEnabled: X
    - Whether surveys are enabled
  • [PostHog.js] [SessionRecording]
    - Session recording status
  • [PostHog.js] [WebExperiments]
    - Web experiments/feature flags
  • [PostHog.js] set_config
    - Configuration changes
Important distinction:
  • Module loaded = The JavaScript file loaded successfully
  • Feature enabled = The feature is turned on in PostHog settings
A module can load but still be disabled. For example:
[PostHog.js] [Surveys] Surveys loaded successfully  <- Module loaded
[PostHog.js] [Surveys] flags response received, isSurveysEnabled: false  <- Feature disabled
开启
?__posthog_debug=true
后,PostHog会输出详细日志。使用
list_console_messages
查找
[PostHog.js]
条目:
需重点关注的消息:
  • [PostHog.js] Persistence loaded
    - 显示持久化类型(localStorage、sessionStorage、cookie)
  • [PostHog.js] [Surveys] Surveys loaded successfully
    - 调查模块已加载
  • [PostHog.js] [Surveys] flags response received, isSurveysEnabled: X
    - 调查功能是否启用
  • [PostHog.js] [SessionRecording]
    - 会话录制状态
  • [PostHog.js] [WebExperiments]
    - Web实验/功能标志
  • [PostHog.js] set_config
    - 配置变更
重要区别:
  • 模块已加载 = JavaScript文件加载成功
  • 功能已启用 = 该功能在PostHog设置中已开启
模块可能已加载但仍处于禁用状态。例如:
[PostHog.js] [Surveys] Surveys loaded successfully  <- 模块已加载
[PostHog.js] [Surveys] flags response received, isSurveysEnabled: false  <- 功能已禁用

Step 3: Check for PostHog Script

步骤3:检查PostHog脚本

Look for PostHog scripts in the page:
javascript
(() => {
  const scripts = Array.from(document.querySelectorAll('script'));
  const posthogScripts = scripts.filter(s =>
    (s.src && (s.src.includes('posthog') || s.src.includes('ph.js'))) ||
    (s.textContent && (s.textContent.includes('posthog.init') || s.textContent.includes('!function(t,e)')))
  );

  return {
    found: posthogScripts.length > 0,
    scripts: posthogScripts.map(s => ({
      src: s.src || 'inline',
      async: s.async,
      defer: s.defer,
      type: s.type || 'text/javascript'
    }))
  };
})()
在页面中查找PostHog脚本:
javascript
(() => {
  const scripts = Array.from(document.querySelectorAll('script'));
  const posthogScripts = scripts.filter(s =>
    (s.src && (s.src.includes('posthog') || s.src.includes('ph.js'))) ||
    (s.textContent && (s.textContent.includes('posthog.init') || s.textContent.includes('!function(t,e)')))
  );

  return {
    found: posthogScripts.length > 0,
    scripts: posthogScripts.map(s => ({
      src: s.src || 'inline',
      async: s.async,
      defer: s.defer,
      type: s.type || 'text/javascript'
    }))
  };
})()

Step 4: Check Network Requests

步骤4:检查网络请求

Filter network requests to find PostHog traffic. PostHog may use:
Standard domains:
  • *.posthog.com
  • us.i.posthog.com
    /
    eu.i.posthog.com
  • us-assets.i.posthog.com
    /
    eu-assets.i.posthog.com
Custom proxy domains (common patterns):
  • ph.yourcompany.com
  • analytics.yourcompany.com
  • t.yourcompany.com
  • Any domain with
    /array/phc_
    in the path (PostHog config)
Endpoints to look for:
  • /e/
    or
    /capture/
    - Events
  • /s/
    - Session recording
  • /decide/
    or
    /flags/
    - Feature flags
  • /batch/
    - Batched events
  • /array/phc_*/config.js
    - Remote config (bundled implementations)
  • /static/surveys.js
    - Surveys module
  • /static/recorder.js
    - Session recording module
How to identify a custom proxy:
  1. Look for requests with PostHog-specific paths (
    /flags/
    ,
    /array/phc_
    )
  2. Check network request details for PostHog headers
  3. Look for
    phc_
    tokens in request URLs or bodies
筛选网络请求以查找PostHog流量。PostHog可能使用:
标准域名:
  • *.posthog.com
  • us.i.posthog.com
    /
    eu.i.posthog.com
  • us-assets.i.posthog.com
    /
    eu-assets.i.posthog.com
自定义代理域名(常见模式):
  • ph.yourcompany.com
  • analytics.yourcompany.com
  • t.yourcompany.com
  • 路径中包含
    /array/phc_
    的任意域名(PostHog配置)
需查找的端点:
  • /e/
    /capture/
    - 事件
  • /s/
    - 会话录制
  • /decide/
    /flags/
    - 功能标志
  • /batch/
    - 批量事件
  • /array/phc_*/config.js
    - 远程配置(捆绑式实现)
  • /static/surveys.js
    - 调查模块
  • /static/recorder.js
    - 会话录制模块
如何识别自定义代理:
  1. 查找带有PostHog特定路径(
    /flags/
    /array/phc_
    )的请求
  2. 检查网络请求详情中的PostHog头部
  3. 在请求URL或主体中查找
    phc_
    令牌

Step 5: Check for Common Issues

步骤5:检查常见问题

Run diagnostics:
javascript
(() => {
  const issues = [];

  // Check if posthog exists
  if (typeof posthog === 'undefined') {
    issues.push('PostHog not found on window object');
    return { issues };
  }

  // Check for multiple instances
  if (window.__POSTHOG_INSTANCES__ && window.__POSTHOG_INSTANCES__.length > 1) {
    issues.push('Multiple PostHog instances detected - may cause duplicate events');
  }

  // Check if initialized
  if (!posthog.get_distinct_id || !posthog.get_distinct_id()) {
    issues.push('PostHog may not be fully initialized');
  }

  // Check consent mode
  if (posthog.has_opted_out_capturing && posthog.has_opted_out_capturing()) {
    issues.push('User has opted out of tracking');
  }

  // Check for debug mode in production
  const isDebug = posthog.config?.debug || posthog.get_config?.('debug');
  const hostname = window.location.hostname;
  if (isDebug && !hostname.includes('localhost') && !hostname.includes('127.0.0.1')) {
    issues.push('Debug mode is enabled in production');
  }

  // Check autocapture
  const autocapture = posthog.config?.autocapture ?? posthog.get_config?.('autocapture');
  if (autocapture === false) {
    issues.push('Autocapture is disabled - only manual events will be tracked');
  }

  return {
    issues: issues.length > 0 ? issues : ['No issues detected'],
    checksRun: true
  };
})()
运行诊断:
javascript
(() => {
  const issues = [];

  // 检查posthog是否存在
  if (typeof posthog === 'undefined') {
    issues.push('PostHog未在window对象中找到');
    return { issues };
  }

  // 检查是否存在多个实例
  if (window.__POSTHOG_INSTANCES__ && window.__POSTHOG_INSTANCES__.length > 1) {
    issues.push('检测到多个PostHog实例 - 可能导致重复事件');
  }

  // 检查是否已初始化
  if (!posthog.get_distinct_id || !posthog.get_distinct_id()) {
    issues.push('PostHog可能未完全初始化');
  }

  // 检查同意模式
  if (posthog.has_opted_out_capturing && posthog.has_opted_out_capturing()) {
    issues.push('用户已选择退出追踪');
  }

  // 检查生产环境中是否启用调试模式
  const isDebug = posthog.config?.debug || posthog.get_config?.('debug');
  const hostname = window.location.hostname;
  if (isDebug && !hostname.includes('localhost') && !hostname.includes('127.0.0.1')) {
    issues.push('生产环境中启用了调试模式');
  }

  // 检查自动捕获
  const autocapture = posthog.config?.autocapture ?? posthog.get_config?.('autocapture');
  if (autocapture === false) {
    issues.push('自动捕获已禁用 - 仅会追踪手动事件');
  }

  return {
    issues: issues.length > 0 ? issues : ['未检测到问题'],
    checksRun: true
  };
})()

Step 6: Capture Recent Events (if debug available)

步骤6:捕获最近事件(若调试可用)

If debug mode is on or we can access the queue:
javascript
(() => {
  if (typeof posthog === 'undefined') return { events: [] };

  // Try to get queued events
  const queue = posthog._requestQueue?.queue ||
                posthog.requestQueue?.queue ||
                [];

  // Get recent events from persistence if available
  const stored = posthog.persistence?.props?.$stored_events || [];

  return {
    queuedEvents: queue.length,
    recentEventTypes: [...new Set([...queue, ...stored].map(e => e?.event || 'unknown').slice(0, 20))]
  };
})()
若调试模式已开启或可访问队列:
javascript
(() => {
  if (typeof posthog === 'undefined') return { events: [] };

  // 尝试获取队列中的事件
  const queue = posthog._requestQueue?.queue ||
                posthog.requestQueue?.queue ||
                [];

  // 从持久化存储中获取最近事件(若可用)
  const stored = posthog.persistence?.props?.$stored_events || [];

  return {
    queuedEvents: queue.length,
    recentEventTypes: [...new Set([...queue, ...stored].map(e => e?.event || 'unknown').slice(0, 20))]
  };
})()

Step 7: Detect Other Analytics Tools

步骤7:检测其他分析工具

Scan network requests and scripts to identify all analytics/tracking tools on the page. Use known patterns for named tools, and detect unknown tracking scripts as a fallback.
javascript
(() => {
  const scripts = Array.from(document.querySelectorAll('script[src]')).map(s => s.src);
  const hostname = window.location.hostname.replace('www.', '');
  const knownTools = [];
  const matchedScripts = new Set();

  const patterns = {
    'Google Analytics': /google-analytics\.com|gtag\/js/i,
    'Google Tag Manager': /googletagmanager\.com\/gtm/i,
    'Facebook Pixel': /connect\.facebook\.net.*fbevents/i,
    'LinkedIn Insight': /snap\.licdn\.com/i,
    'HubSpot': /js\.hs-scripts\.com|js\.hsforms\.com/i,
    'Hotjar': /static\.hotjar\.com/i,
    'Segment': /cdn\.segment\.com/i,
    'Mixpanel': /cdn\.mxpnl\.com|mixpanel\.com/i,
    'Amplitude': /cdn\.amplitude\.com/i,
    'Heap': /heap-analytics\.com|heapanalytics\.com/i,
    'Intercom': /widget\.intercom\.io|intercomcdn\.com/i,
    'Drift': /js\.driftt\.com/i,
    'Zendesk': /static\.zdassets\.com/i,
    'Crisp': /client\.crisp\.chat/i,
    'FullStory': /fullstory\.com\/s\/fs\.js/i,
    'LogRocket': /cdn\.logrocket\.com/i,
    'Sentry': /browser\.sentry-cdn\.com/i,
    'Datadog': /datadoghq\.com/i,
    'Snowplow': /cdn\.snowplow/i,
    'Rudderstack': /cdn\.rudderlabs\.com/i,
    'Clearbit': /tag\.clearbitscripts\.com/i,
    'Dreamdata': /cdn\.dreamdata\.cloud/i,
    'GrowthBook': /cdn\.growthbook\.io/i,
    'LaunchDarkly': /sdk\.launchdarkly\.com/i,
    'Optimizely': /cdn\.optimizely\.com/i,
    'VWO': /dev\.visualwebsiteoptimizer\.com/i,
    'Ahrefs': /analytics\.ahrefs\.com/i,
    'AdRoll': /s\.adroll\.com/i,
    'Factors.ai': /app\.factors\.ai/i,
    'Vector': /cdn\.vector\.co/i,
    'Leadfeeder': /sc\.lfeeder\.com/i,
    'Pendo': /cdn\.pendo\.io/i,
    'Chameleon': /fast\.chameleon\.io/i,
    'Appcues': /fast\.appcues\.com/i,
    'UserPilot': /js\.userpilot\.io/i,
    'Mouseflow': /cdn\.mouseflow\.com/i,
    'Lucky Orange': /tools\.luckyorange\.com/i,
    'Crazy Egg': /script\.crazyegg\.com/i,
    'Plausible': /plausible\.io\/js/i,
    'Fathom': /cdn\.usefathom\.com/i,
    'Simple Analytics': /scripts\.simpleanalyticscdn\.com/i,
    'Matomo': /matomo\.js|piwik\.js/i,
    'Klaviyo': /static\.klaviyo\.com/i,
    'Customer.io': /track\.customer\.io/i,
    'Braze': /sdk\.iad-\d+\.braze\.com/i,
    'OneSignal': /cdn\.onesignal\.com/i,
    'Insider': /insr\.io/i,
    'Mutiny': /cdn\.mutinycdn\.com/i,
    'Qualified': /js\.qualified\.com/i,
    'Chilipiper': /js\.chilipiper\.com/i,
    'Typekit': /use\.typekit\.net/i,
    'Google Fonts': /fonts\.googleapis\.com/i,
    'Cookiebot': /consent\.cookiebot\.com/i,
    'OneTrust': /cdn\.cookielaw\.org/i,
    'TrustArc': /consent\.trustarc\.com/i,
    'Osano': /cmp\.osano\.com/i,
    'Usercentrics': /app\.usercentrics\.eu/i,
    'OpenLI/Legal Monster': /widgets\.legalmonster\.com|openli\.com/i,
    'Nelio A/B Testing': /nelio-ab-testing/i,
    'Mesh': /mesh-interactive|withmesh\.com/i,
    'Reddit Pixel': /redditstatic\.com|rdt\.li/i,
    'Webflow': /wdfl\.co|webflow\.com\/js/i,
    'Dub.co': /dubcdn\.com|dub\.co/i
  };

  // Match known tools
  for (const [name, pattern] of Object.entries(patterns)) {
    for (const src of scripts) {
      if (pattern.test(src)) {
        knownTools.push(name);
        matchedScripts.add(src);
        break;
      }
    }
  }

  // Find unknown tracking scripts
  const trackingKeywords = /track|analytics|pixel|tag|beacon|collect|measure|metric|event|telemetry|monitor/i;
  const unknownScripts = scripts.filter(src => {
    if (matchedScripts.has(src)) return false;
    try {
      const url = new URL(src);
      const scriptHost = url.hostname.replace('www.', '');
      // Skip same-domain scripts
      if (scriptHost === hostname || scriptHost.endsWith('.' + hostname)) return false;
      // Skip common CDNs that host non-tracking code
      if (/unpkg\.com|jsdelivr\.net|cdnjs\.cloudflare\.com|ajax\.googleapis\.com/i.test(scriptHost)) return false;
      // Include if it has tracking-like keywords or is from a third-party
      return trackingKeywords.test(src) || true;
    } catch {
      return false;
    }
  });

  // Extract just the domain from unknown scripts for cleaner output
  const unknownDomains = [...new Set(unknownScripts.map(src => {
    try {
      return new URL(src).hostname;
    } catch {
      return src;
    }
  }))].sort();

  return {
    knownTools: [...new Set(knownTools)].sort(),
    unknownScripts: unknownDomains
  };
})()
扫描网络请求和脚本以识别页面上的所有分析/追踪工具。使用已知工具的模式进行匹配,将未匹配的追踪脚本作为回退检测为未知工具。
javascript
(() => {
  const scripts = Array.from(document.querySelectorAll('script[src]')).map(s => s.src);
  const hostname = window.location.hostname.replace('www.', '');
  const knownTools = [];
  const matchedScripts = new Set();

  const patterns = {
    'Google Analytics': /google-analytics\.com|gtag\/js/i,
    'Google Tag Manager': /googletagmanager\.com\/gtm/i,
    'Facebook Pixel': /connect\.facebook\.net.*fbevents/i,
    'LinkedIn Insight': /snap\.licdn\.com/i,
    'HubSpot': /js\.hs-scripts\.com|js\.hsforms\.com/i,
    'Hotjar': /static\.hotjar\.com/i,
    'Segment': /cdn\.segment\.com/i,
    'Mixpanel': /cdn\.mxpnl\.com|mixpanel\.com/i,
    'Amplitude': /cdn\.amplitude\.com/i,
    'Heap': /heap-analytics\.com|heapanalytics\.com/i,
    'Intercom': /widget\.intercom\.io|intercomcdn\.com/i,
    'Drift': /js\.driftt\.com/i,
    'Zendesk': /static\.zdassets\.com/i,
    'Crisp': /client\.crisp\.chat/i,
    'FullStory': /fullstory\.com\/s\/fs\.js/i,
    'LogRocket': /cdn\.logrocket\.com/i,
    'Sentry': /browser\.sentry-cdn\.com/i,
    'Datadog': /datadoghq\.com/i,
    'Snowplow': /cdn\.snowplow/i,
    'Rudderstack': /cdn\.rudderlabs\.com/i,
    'Clearbit': /tag\.clearbitscripts\.com/i,
    'Dreamdata': /cdn\.dreamdata\.cloud/i,
    'GrowthBook': /cdn\.growthbook\.io/i,
    'LaunchDarkly': /sdk\.launchdarkly\.com/i,
    'Optimizely': /cdn\.optimizely\.com/i,
    'VWO': /dev\.visualwebsiteoptimizer\.com/i,
    'Ahrefs': /analytics\.ahrefs\.com/i,
    'AdRoll': /s\.adroll\.com/i,
    'Factors.ai': /app\.factors\.ai/i,
    'Vector': /cdn\.vector\.co/i,
    'Leadfeeder': /sc\.lfeeder\.com/i,
    'Pendo': /cdn\.pendo\.io/i,
    'Chameleon': /fast\.chameleon\.io/i,
    'Appcues': /fast\.appcues\.com/i,
    'UserPilot': /js\.userpilot\.io/i,
    'Mouseflow': /cdn\.mouseflow\.com/i,
    'Lucky Orange': /tools\.luckyorange\.com/i,
    'Crazy Egg': /script\.crazyegg\.com/i,
    'Plausible': /plausible\.io\/js/i,
    'Fathom': /cdn\.usefathom\.com/i,
    'Simple Analytics': /scripts\.simpleanalyticscdn\.com/i,
    'Matomo': /matomo\.js|piwik\.js/i,
    'Klaviyo': /static\.klaviyo\.com/i,
    'Customer.io': /track\.customer\.io/i,
    'Braze': /sdk\.iad-\d+\.braze\.com/i,
    'OneSignal': /cdn\.onesignal\.com/i,
    'Insider': /insr\.io/i,
    'Mutiny': /cdn\.mutinycdn\.com/i,
    'Qualified': /js\.qualified\.com/i,
    'Chilipiper': /js\.chilipiper\.com/i,
    'Typekit': /use\.typekit\.net/i,
    'Google Fonts': /fonts\.googleapis\.com/i,
    'Cookiebot': /consent\.cookiebot\.com/i,
    'OneTrust': /cdn\.cookielaw\.org/i,
    'TrustArc': /consent\.trustarc\.com/i,
    'Osano': /cmp\.osano\.com/i,
    'Usercentrics': /app\.usercentrics\.eu/i,
    'OpenLI/Legal Monster': /widgets\.legalmonster\.com|openli\.com/i,
    'Nelio A/B Testing': /nelio-ab-testing/i,
    'Mesh': /mesh-interactive|withmesh\.com/i,
    'Reddit Pixel': /redditstatic\.com|rdt\.li/i,
    'Webflow': /wdfl\.co|webflow\.com\/js/i,
    'Dub.co': /dubcdn\.com|dub\.co/i
  };

  // 匹配已知工具
  for (const [name, pattern] of Object.entries(patterns)) {
    for (const src of scripts) {
      if (pattern.test(src)) {
        knownTools.push(name);
        matchedScripts.add(src);
        break;
      }
    }
  }

  // 查找未知追踪脚本
  const trackingKeywords = /track|analytics|pixel|tag|beacon|collect|measure|metric|event|telemetry|monitor/i;
  const unknownScripts = scripts.filter(src => {
    if (matchedScripts.has(src)) return false;
    try {
      const url = new URL(src);
      const scriptHost = url.hostname.replace('www.', '');
      // 跳过同域脚本
      if (scriptHost === hostname || scriptHost.endsWith('.' + hostname)) return false;
      // 跳过托管非追踪代码的常见CDN
      if (/unpkg\.com|jsdelivr\.net|cdnjs\.cloudflare\.com|ajax\.googleapis\.com/i.test(scriptHost)) return false;
      // 若包含类追踪关键词或来自第三方则纳入
      return trackingKeywords.test(src) || true;
    } catch {
      return false;
    }
  });

  // 从未知脚本中提取域名以简化输出
  const unknownDomains = [...new Set(unknownScripts.map(src => {
    try {
      return new URL(src).hostname;
    } catch {
      return src;
    }
  }))].sort();

  return {
    knownTools: [...new Set(knownTools)].sort(),
    unknownScripts: unknownDomains
  };
})()

Response Format

响应格式

After inspection, provide a structured summary. Be factual and concise - no commentary or recommendations unless asked. Use emojis to indicate status at a glance.
Status emojis:
  • ✅ = Yes / Enabled / Active / Installed
  • ❌ = No / Disabled / Not found
  • ⚠️ = Warning / Issue detected
undefined
检查完成后,提供结构化总结。内容需真实简洁——除非被询问,否则不添加评论或建议。使用表情符号快速指示状态。
状态表情符号:
  • ✅ = 是/已启用/活跃/已安装
  • ❌ = 否/已禁用/未找到
  • ⚠️ = 警告/检测到问题
undefined

PostHog Implementation Summary

PostHog实现总结

Status

状态

✅ Installed / ✅ Installed (bundled) / ❌ Not Found
✅ 已安装 / ✅ 已安装(捆绑式) / ❌ 未找到

Implementation Type

实现类型

[Global window.posthog / Bundled (not exposed globally) / Custom proxy]
[全局window.posthog / 捆绑式(未全局暴露) / 自定义代理]

Configuration

配置

  • Version: [version]
  • API Host: [host] ([US/EU Cloud] / [Custom proxy] / [Self-hosted])
  • Project Token: [full token]
  • Persistence: [localStorage/sessionStorage/cookie/memory]
  • 版本: [version]
  • API主机: [host] ([美国/欧盟云] / [自定义代理] / [自托管])
  • 项目令牌: [完整令牌]
  • 持久化: [localStorage/sessionStorage/cookie/memory]

Features (Module Loaded → Feature Enabled)

功能(模块已加载 → 功能已启用)

FeatureModule LoadedEnabled
Autocapture✅ / ❌✅ / ❌
Session Recording✅ / ❌✅ / ❌
Surveys✅ / ❌✅ / ❌
Heatmaps✅ / ❌✅ / ❌
Feature Flags✅ / ❌✅ / ❌
Web Vitals✅ / ❌✅ / ❌
功能模块已加载已启用
自动捕获✅ / ❌✅ / ❌
会话录制✅ / ❌✅ / ❌
调查✅ / ❌✅ / ❌
热力图✅ / ❌✅ / ❌
功能标志✅ / ❌✅ / ❌
Web性能指标✅ / ❌✅ / ❌

Identifiers

标识符

  • Distinct ID: [id]
  • Session ID: [id]
  • Distinct ID: [id]
  • Session ID: [id]

Feature Flags

功能标志

[List of active flags or "None loaded"]
[活跃标志列表或"未加载任何标志"]

Network Activity

网络活动

  • Events endpoint: ✅ / ❌
  • Session recording: ✅ / ❌
  • Decide/flags endpoint: ✅ / ❌
  • Surveys endpoint: ✅ / ❌
  • 事件端点:✅ / ❌
  • 会话录制:✅ / ❌
  • Decide/flags端点:✅ / ❌
  • 调查端点:✅ / ❌

Issues Found

检测到的问题

✅ None detected — or — ⚠️ [Issue description]
✅ 未检测到问题 — 或 — ⚠️ [问题描述]

Script Loading

脚本加载

  • Source: [CDN/Self-hosted/NPM bundle/Custom proxy]
  • Loading: [Async/Sync/Defer]
  • 来源: [CDN/自托管/NPM包/自定义代理]
  • 加载方式: [异步/同步/延迟]

Other Analytics Tools Detected

检测到的其他分析工具

[List of recognized analytics, tracking, and marketing tools]
[已识别的分析、追踪和营销工具列表]

Other External Scripts

其他外部脚本

[Third-party script domains not matched to known tools]
undefined
[未匹配到已知工具的第三方脚本域名]
undefined

Common Questions and How to Answer Them

常见问题及回答方式

"How is PostHog implemented on this page?"

"PostHog在该页面上是如何实现的?"

Run full inspection workflow and provide complete summary.
运行完整检查流程并提供完整总结。

"Is PostHog tracking working?"

"PostHog追踪是否正常工作?"

  1. Check if posthog object exists
  2. Verify network requests are being sent
  3. Check for any errors in console
  4. Look for opted-out status
  1. 检查posthog对象是否存在
  2. 验证是否正在发送网络请求
  3. 检查控制台中的错误信息
  4. 查看用户是否选择退出追踪

"What events are being tracked?"

"正在追踪哪些事件?"

  1. Check autocapture status
  2. Look at network requests to
    /e/
    or
    /capture/
  3. Try to access event queue
  4. Note if $pageview, $pageleave, etc. are enabled
  1. 检查自动捕获状态
  2. 查看发送到
    /e/
    /capture/
    的网络请求
  3. 尝试访问事件队列
  4. 记录$pageview、$pageleave等是否已启用

"Is session recording enabled?"

"会话录制是否已启用?"

  1. Check config for recording settings
  2. Look for
    /s/
    network requests
  3. Check sessionRecording object state
  1. 检查配置中的录制设置
  2. 查找
    /s/
    网络请求
  3. 检查sessionRecording对象状态

"What feature flags are active?"

"哪些功能标志处于活跃状态?"

  1. Check featureFlags object on posthog
  2. Look for
    /decide/
    network request
  3. List all flags and their values
  1. 检查posthog上的featureFlags对象
  2. 查找
    /decide/
    网络请求
  3. 列出所有标志及其值

"Are there any issues with the implementation?"

"实现中存在哪些问题?"

Run the diagnostic checks and report findings.
运行诊断检查并报告发现结果。

"Is this using the EU or US cloud?"

"这使用的是欧盟还是美国云?"

Check the api_host configuration:
  • us.i.posthog.com
    = US Cloud
  • eu.i.posthog.com
    = EU Cloud
  • app.posthog.com
    = Legacy (defaults to US)
  • Custom domain = Self-hosted or proxy
检查api_host配置:
  • us.i.posthog.com
    = 美国云
  • eu.i.posthog.com
    = 欧盟云
  • app.posthog.com
    = 旧版(默认美国)
  • 自定义域名 = 自托管或代理

Example Conversation

对话示例

User: "How is PostHog implemented on https://example.com?"
Claude: "I'll navigate to example.com with debug mode enabled and inspect the PostHog implementation."
[Navigates to https://example.com?__posthog_debug=true] [Runs JavaScript checks] [Checks console for PostHog debug messages] [Analyzes network requests]
Claude:
undefined
Claude: "我将开启调试模式导航到example.com并检查PostHog实现。"
[导航到https://example.com?__posthog_debug=true] [运行JavaScript检查] [检查控制台中的PostHog调试消息] [分析网络请求]
Claude:
undefined

PostHog Implementation Summary

PostHog实现总结

Status

状态

✅ Installed
✅ 已安装

Implementation Type

实现类型

Global window.posthog
全局window.posthog

Configuration

配置

  • Version: 1.96.1
  • API Host: https://us.i.posthog.com (US Cloud)
  • Project Token: phc_abc123def456ghi789jkl012mno345
  • Persistence: localStorage+cookie

Features (Module Loaded → Feature Enabled)

功能(模块已加载 → 功能已启用)

FeatureModule LoadedEnabled
Autocapture
Session Recording
Surveys
Heatmaps
Feature Flags
Web Vitals
功能模块已加载已启用
自动捕获
会话录制
调查
热力图
功能标志
Web性能指标

Identifiers

标识符

  • Distinct ID: 018d4f2a-1234-7abc-def0-123456789abc
  • Session ID: 018d4f2a-5678-7xyz-abc0-987654321xyz
  • Distinct ID: 018d4f2a-1234-7abc-def0-123456789abc
  • Session ID: 018d4f2a-5678-7xyz-abc0-987654321xyz

Feature Flags

功能标志

  • new-checkout-flow
  • beta-features
  • new-checkout-flow
  • beta-features

Network Activity

网络活动

  • Events endpoint: ✅
  • Session recording: ✅
  • Decide/flags endpoint: ✅
  • Surveys endpoint: ✅
  • 事件端点:✅
  • 会话录制:✅
  • Decide/flags端点:✅
  • 调查端点:✅

Issues Found

检测到的问题

✅ None detected
✅ 未检测到问题

Script Loading

脚本加载

  • Source: CDN (us-assets.i.posthog.com)
  • Loading: Async
  • 来源: CDN(us-assets.i.posthog.com)
  • 加载方式: 异步

Other Analytics Tools Detected

检测到的其他分析工具

  • Google Tag Manager
  • Google Analytics
  • HubSpot
  • Google Tag Manager
  • Google Analytics
  • HubSpot

Other External Scripts

其他外部脚本

  • cdn.example-vendor.com

---

**Example 2: Authenticated page with custom proxy**

**User:** "Check PostHog on https://app.example.com/dashboard"

**Claude:** "I'll navigate to that page with debug mode enabled."

[Navigates to https://app.example.com/dashboard?__posthog_debug=true]
[Takes snapshot, sees login page]

**Claude:** "I've opened the page but it requires login. Please log in using the Chrome browser I just opened. Let me know when you're on the dashboard."

**User:** "I'm logged in"

**Claude:** [Takes new snapshot, verifies authenticated, runs inspection]
  • cdn.example-vendor.com

---

**示例2:带自定义代理的已认证页面**

**用户:** "检查https://app.example.com/dashboard上的PostHog"

**Claude:** "我将开启调试模式导航到该页面。"

[导航到https://app.example.com/dashboard?__posthog_debug=true]
[截取截图,发现登录页面]

**Claude:** "我已打开页面,但该页面需要登录。请使用我刚刚打开的Chrome浏览器登录。进入仪表板后请告知我。"

**用户:** "我已登录"

**Claude:** [截取新截图,验证已认证,运行检查]

PostHog Implementation Summary

PostHog实现总结

Status

状态

✅ Installed (bundled)
✅ 已安装(捆绑式)

Implementation Type

实现类型

Bundled (not exposed globally) via custom proxy
捆绑式(未全局暴露)通过自定义代理

Configuration

配置

  • Version: 1.257.2
  • API Host: ph.example.com (Custom proxy)
  • Project Token: phc_abc123def456ghi789jkl012mno345
  • Persistence: sessionStorage
  • 版本: 1.257.2
  • API主机: ph.example.com(自定义代理)
  • 项目令牌: phc_abc123def456ghi789jkl012mno345
  • 持久化: sessionStorage

Features (Module Loaded → Feature Enabled)

功能(模块已加载 → 功能已启用)

FeatureModule LoadedEnabled
Autocapture
Session Recording
Surveys
Heatmaps
Feature Flags
Web Vitals
功能模块已加载已启用
自动捕获
会话录制
调查
热力图
功能标志
Web性能指标

Identifiers

标识符

  • Distinct ID: (not accessible - bundled)
  • Session ID: (not accessible - bundled)
  • Distinct ID: (无法访问 - 捆绑式)
  • Session ID: (无法访问 - 捆绑式)

Network Activity

网络活动

  • Events endpoint: ✅
  • Session recording: ❌
  • Decide/flags endpoint: ✅
  • Surveys endpoint: ✅ (module loaded, feature disabled)
  • 事件端点:✅
  • 会话录制:❌
  • Decide/flags端点:✅
  • 调查端点:✅(模块已加载,功能已禁用)

Issues Found

检测到的问题

✅ None detected
✅ 未检测到问题

Script Loading

脚本加载

  • Source: Custom proxy (ph.example.com)
  • Loading: Bundled in app
undefined
  • 来源: 自定义代理(ph.example.com)
  • 加载方式: 捆绑到应用中
undefined