Skip to content

数据统计

为你的 VitePress 站点选择合适的访问统计方案,了解用户行为和内容表现。

方案对比

特性Google Analytics百度统计CloudflareUmamiPlausibleMicrosoft Clarity
类型云服务云服务云服务自托管/云自托管/云云服务
免费✅ 开源⚠️ 付费
国内访问⚠️ 较慢✅ 快速✅ 快速✅ 快速⚠️ 较慢⚠️ 较慢
隐私友好⚠️ 一般⚠️ 一般✅ 良好✅ 优秀✅ 优秀✅ 良好
热力图
会话录制
实时统计
功能丰富度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
GDPR 合规⚠️ 需配置

选择建议

场景推荐原因
国际站点Google Analytics功能全面、行业标准
国内站点百度统计访问快速、SEO 加分
隐私优先Umami / Plausible无 Cookie、符合 GDPR
免费功能Cloudflare完全免费、无限量
用户行为分析Microsoft Clarity免费热力图、会话录制
开源爱好者Umami完全开源可自托管
企业级Google Analytics + ClarityGA 看数据,Clarity 看行为

Google Analytics

最流行的网站分析工具,功能全面,适合需要深入分析的站点。

基本配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX' }],
    ['script', {}, `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-XXXXXXXXXX');`]
  ]
})

SPA 页面追踪

VitePress 是 SPA 应用,需要在路由切换时手动发送页面浏览事件:

ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { onMounted } from 'vue'
import { useRouter } from 'vitepress'

export default {
  extends: DefaultTheme,
  setup() {
    if (typeof window !== 'undefined') {
      const router = useRouter()

      onMounted(() => {
        // 监听路由变化,发送页面浏览数据
        router.onAfterRouteChanged = (to) => {
          // @ts-expect-error gtag 全局变量
          if (typeof gtag !== 'undefined') {
            // @ts-expect-error gtag 全局变量
            gtag('config', 'G-XXXXXXXXXX', {
              page_path: to,
              page_title: document.title
            })
          }
        }
      })
    }
  }
}

事件追踪

追踪用户在文档中的关键行为:

ts
// .vitepress/theme/composables/useAnalytics.ts
import { onMounted } from 'vue'
import { useData } from 'vitepress'

export function useAnalytics() {
  const { page } = useData()

  function trackEvent(eventName: string, params?: Record<string, string>) {
    if (typeof window !== 'undefined' && typeof gtag !== 'undefined') {
      // @ts-expect-error gtag 全局变量
      gtag('event', eventName, params)
    }
  }

  // 追踪代码复制
  function trackCodeCopy(language: string) {
    trackEvent('code_copy', { language })
  }

  // 追踪搜索
  function trackSearch(query: string) {
    trackEvent('search', { search_term: query })
  }

  // 追踪外部链接点击
  function trackOutboundLink(url: string) {
    trackEvent('outbound_click', { url })
  }

  return { trackEvent, trackCodeCopy, trackSearch, trackOutboundLink }
}

GDPR 要求在用户同意前不加载分析脚本:

vue
<!-- .vitepress/theme/components/CookieConsent.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const showBanner = ref(false)

onMounted(() => {
  const consent = localStorage.getItem('cookie-consent')
  if (!consent) {
    showBanner.value = true
  } else if (consent === 'accepted') {
    loadAnalytics()
  }
})

function accept() {
  localStorage.setItem('cookie-consent', 'accepted')
  showBanner.value = false
  loadAnalytics()
}

function decline() {
  localStorage.setItem('cookie-consent', 'declined')
  showBanner.value = false
}

function loadAnalytics() {
  const script1 = document.createElement('script')
  script1.async = true
  script1.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX'
  document.head.appendChild(script1)

  const script2 = document.createElement('script')
  script2.textContent = `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-XXXXXXXXXX',{anonymize_ip:true});`
  document.head.appendChild(script2)
}
</script>

<template>
  <div v-if="showBanner" class="cookie-consent">
    <p>本站使用 Cookie 进行数据分析,以改善用户体验。</p>
    <div class="cookie-actions">
      <button class="accept" @click="accept">同意</button>
      <button class="decline" @click="decline">拒绝</button>
    </div>
  </div>
</template>

<style scoped>
.cookie-consent {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--vp-c-bg-soft);
  border-top: 1px solid var(--vp-c-divider);
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 999;
}
.cookie-actions {
  display: flex;
  gap: 8px;
}
.accept, .decline {
  padding: 6px 16px;
  border-radius: 6px;
  border: none;
  cursor: pointer;
}
.accept {
  background: var(--vp-c-brand);
  color: white;
}
.decline {
  background: var(--vp-c-bg);
  border: 1px solid var(--vp-c-divider);
}
</style>

百度统计

国内访问速度最快的统计方案,对 SEO 有加分效果。

基本配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', {}, `var _hmt=_hmt||[];(function(){var hm=document.createElement("script");hm.src="https://hm.baidu.com/hm.js?YOUR_SITE_ID";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(hm,s);})();`]
  ]
})

SPA 页面追踪

ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { onMounted } from 'vue'
import { useRouter } from 'vitepress'

export default {
  extends: DefaultTheme,
  setup() {
    if (typeof window !== 'undefined') {
      const router = useRouter()

      onMounted(() => {
        router.onAfterRouteChanged = (to) => {
          // @ts-expect-error _hmt 全局变量
          if (window._hmt) {
            // @ts-expect-error _hmt 全局变量
            window._hmt.push(['_trackPageview', to])
          }
        }
      })
    }
  }
}

Cloudflare Analytics

Cloudflare 提供的免费 Web Analytics,无需 Cookie,隐私友好。

基本配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { defer: '', src: 'https://static.cloudflareinsights.com/beacon.min.js', 'data-cf-beacon': '{"token":"YOUR_TOKEN"}' }]
  ]
})

特点

  • 完全免费,无限量页面浏览
  • 无需 Cookie,不侵犯用户隐私
  • 国内访问快速
  • 自动追踪 SPA 路由切换,无需额外配置

Umami

开源、自托管的网站分析工具,界面简洁,隐私友好。

Docker 自托管

bash
docker run -d --name umami \
  -p 3000:3000 \
  -e DATABASE_URL=postgresql://umami:umami@db:5432/umami \
  -e APP_SECRET=your-app-secret \
  ghcr.io/umami-software/umami:postgresql-latest

Vercel 一键部署

  1. Fork Umami 仓库
  2. 在 Vercel 导入并部署
  3. 配置数据库环境变量

基本配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { defer: '', src: 'https://your-umami.com/script.js', 'data-website-id': 'YOUR_WEBSITE_ID' }]
  ]
})

SPA 路由追踪

ts
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { onMounted } from 'vue'
import { useRouter } from 'vitepress'

export default {
  extends: DefaultTheme,
  setup() {
    if (typeof window !== 'undefined') {
      const router = useRouter()

      onMounted(() => {
        router.onAfterRouteChanged = (to) => {
          // @ts-expect-error umami 全局变量
          if (typeof umami !== 'undefined') {
            // @ts-expect-error umami 全局变量
            umami.track()
          }
        }
      })
    }
  }
}

自定义事件追踪

ts
// 追踪代码复制
function trackCopy(language: string) {
  // @ts-expect-error umami 全局变量
  if (typeof umami !== 'undefined') {
    // @ts-expect-error umami 全局变量
    umami.track('code_copy', { language })
  }
}

// 追踪搜索
function trackSearch(query: string) {
  // @ts-expect-error umami 全局变量
  if (typeof umami !== 'undefined') {
    // @ts-expect-error umami 全局变量
    umami.track('search', { query })
  }
}

Plausible

简单、隐私友好的分析工具,无 Cookie,完全符合 GDPR。

云服务配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { defer: '', 'data-domain': 'your-site.com', src: 'https://plausible.io/js/script.js' }]
  ]
})

自托管配置

bash
# Docker Compose 部署
docker compose up -d
yaml
# docker-compose.yml
version: '3'
services:
  plausible:
    image: plausible/analytics:latest
    ports:
      - "8000:8000"
    environment:
      - BASE_URL=https://analytics.your-site.com
      - SECRET_KEY_BASE=your-secret-key
      - DATABASE_URL=postgresql://plausible:plausible@db:5432/plausible

SPA 页面追踪

Plausible 的 script.hash.js 版本自动支持 SPA 路由追踪:

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { defer: '', 'data-domain': 'your-site.com', src: 'https://plausible.io/js/script.hash.js' }]
  ]
})

Microsoft Clarity

微软提供的免费行为分析工具,支持热力图和会话录制。

基本配置

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    ['script', { type: 'text/javascript' }, `(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script","YOUR_PROJECT_ID");`]
  ]
})

核心功能

功能说明
热力图可视化用户点击、滚动行为
会话录制回放用户操作过程
死区分析发现用户忽略的区域
互动分析统计点击最多的元素
实时仪表板查看当前在线用户行为

自定义标签

ts
// 标记用户类型
// @ts-expect-error clarity 全局变量
if (typeof clarity !== 'undefined') {
  // @ts-expect-error clarity 全局变量
  clarity('set', 'user_type', 'developer')
}

多方案组合

有时一个方案无法满足所有需求,可以组合使用:

组合优势
Google Analytics + ClarityGA 看数据指标,Clarity 看用户行为
Umami + Clarity隐私友好的数据 + 免费热力图
百度统计 + GA国内 SEO 加分 + 国际分析

组合配置示例

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    // Google Analytics
    ['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX' }],
    ['script', {}, `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-XXXXXXXXXX',{anonymize_ip:true});`],

    // Microsoft Clarity
    ['script', { type: 'text/javascript' }, `(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script","YOUR_PROJECT_ID");`]
  ]
})

统计组件开发

访问计数徽章

vue
<!-- .vitepress/theme/components/PageViewBadge.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useData } from 'vitepress'

const { page } = useData()
const pageViews = ref('---')

onMounted(async () => {
  try {
    // 使用 Umami API 获取页面浏览量
    const res = await fetch(
      `https://your-umami.com/api/websites/YOUR_WEBSITE_ID/stats?url=${page.value.relativePath}`,
      { headers: { Authorization: 'Bearer YOUR_API_KEY' } }
    )
    const data = await res.json()
    pageViews.value = data.pageviews.value.toLocaleString()
  } catch {
    pageViews.value = '---'
  }
})
</script>

<template>
  <span class="page-view-badge">
    👁 {{ pageViews }} 次浏览
  </span>
</template>

<style scoped>
.page-view-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  font-size: 12px;
  color: var(--vp-c-text-2);
  background: var(--vp-c-bg-soft);
  border-radius: 12px;
}
</style>

阅读时间统计

vue
<!-- .vitepress/theme/components/ReadingTime.vue -->
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'

const { page } = useData()

const readingTime = computed(() => {
  const content = page.value.content || ''
  // 移除 frontmatter 和代码块
  const text = content
    .replace(/^---[\s\S]*?---/, '')
    .replace(/```[\s\S]*?```/g, '')
    .trim()

  // 中文按字符计算,英文按单词计算
  const chineseChars = (text.match(/[\u4e00-\u9fff]/g) || []).length
  const englishWords = (text.match(/[a-zA-Z]+/g) || []).length
  const totalWords = chineseChars + englishWords

  // 中文阅读速度约 300 字/分钟,英文约 200 词/分钟
  const minutes = chineseChars / 300 + englishWords / 200

  if (minutes < 1) return '1 分钟'
  if (minutes < 60) return `${Math.ceil(minutes)} 分钟`
  return `${Math.floor(minutes / 60)} 小时 ${Math.ceil(minutes % 60)} 分钟`
})
</script>

<template>
  <span class="reading-time">📖 {{ readingTime }}</span>
</template>

进阶配置

自定义统计组件、Cookie 同意弹窗、隐私合规等进阶内容:

常见问题

统计数据不准确?

检查以下可能原因:

  1. SPA 路由追踪:确保配置了路由变化监听
  2. 广告拦截器:很多用户使用广告拦截器屏蔽了统计脚本
  3. Cookie 限制:隐私设置可能阻止统计脚本运行
  4. 机器人流量:搜索引擎爬虫会被统计为访问

国内用户无法加载 Google Analytics?

Google Analytics 在国内加载较慢甚至被屏蔽。解决方案:

  1. 切换到百度统计或 Umami
  2. 使用 Cloudflare Analytics 作为替代
  3. 通过国内 CDN 代理 GA 脚本(需自建)

如何满足 GDPR 要求?

  1. 获取用户同意后再加载统计脚本
  2. 使用 anonymize_ip 隐藏 IP 地址
  3. 提供隐私政策页面说明数据收集情况
  4. 优先选择隐私友好的方案(Umami / Plausible)

相关链接

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献