Skip to content

Google Analytics 集成

集成 Google Analytics 4 进行网站访问统计和分析。

获取跟踪 ID

  1. 访问 Google Analytics
  2. 创建 GA4 媒体资源
  3. 获取衡量 ID(格式:G-XXXXXXXXXX

方式一:配置文件集成

ts
// .vitepress/config.mts
export default defineConfig({
  head: [
    [
      'script',
      {
        async: true,
        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');
      `
    ]
  ]
})

方式二:组件集成

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

const GA_ID = 'G-XXXXXXXXXX'

const { isDark } = useData()

declare global {
  interface Window {
    dataLayer: any[]
    gtag: (...args: any[]) => void
  }
}

function initGA() {
  window.dataLayer = window.dataLayer || []
  window.gtag = function gtag(...args: any[]) {
    window.dataLayer.push(args)
  }
  
  window.gtag('js', new Date())
  window.gtag('config', GA_ID, {
    page_path: window.location.pathname,
    theme: isDark.value ? 'dark' : 'light'
  })
}

function loadScript() {
  const script = document.createElement('script')
  script.async = true
  script.src = `https://www.googletagmanager.com/gtag/js?id=${GA_ID}`
  document.head.appendChild(script)
}

onMounted(() => {
  loadScript()
  initGA()
})

// 监听路由变化
if (typeof window !== 'undefined') {
  const originalPushState = history.pushState
  history.pushState = function(...args) {
    originalPushState.apply(this, args)
    if (window.gtag) {
      window.gtag('config', GA_ID, {
        page_path: window.location.pathname
      })
    }
  }
}
</script>

<template>
  <!-- 无渲染 -->
</template>

注册组件

ts
// .vitepress/theme/index.ts
import GoogleAnalytics from './components/GoogleAnalytics.vue'

export default {
  extends: DefaultTheme,
  Layout: () => h(DefaultTheme.Layout, null, {
    'layout-bottom': () => h(GoogleAnalytics)
  })
}

高级配置

自定义维度

ts
gtag('config', GA_ID, {
  custom_map: {
    dimension1: 'article_category',
    dimension2: 'reading_level'
  }
})

// 发送自定义维度
gtag('event', 'page_view', {
  article_category: 'VitePress',
  reading_level: 'Beginner'
})

事件追踪

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

// 追踪下载
function trackDownload(file: string) {
  gtag('event', 'download', {
    file_name: file
  })
}

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

// 追踪阅读进度
function trackReadingProgress(percentage: number) {
  if (percentage >= 25 && percentage < 50) {
    gtag('event', 'reading_progress', { progress: 25 })
  } else if (percentage >= 50 && percentage < 75) {
    gtag('event', 'reading_progress', { progress: 50 })
  } else if (percentage >= 75 && percentage < 100) {
    gtag('event', 'reading_progress', { progress: 75 })
  } else if (percentage >= 100) {
    gtag('event', 'reading_progress', { progress: 100 })
  }
}

隐私合规

vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const showConsent = ref(false)
const hasConsent = ref(false)

onMounted(() => {
  hasConsent.value = localStorage.getItem('ga_consent') === 'true'
  showConsent.value = !localStorage.getItem('ga_consent')
})

const acceptConsent = () => {
  localStorage.setItem('ga_consent', 'true')
  hasConsent.value = true
  showConsent.value = false
  // 初始化 GA
  initGA()
}

const rejectConsent = () => {
  localStorage.setItem('ga_consent', 'false')
  showConsent.value = false
}
</script>

<template>
  <div v-if="showConsent" class="cookie-consent">
    <p>我们使用 Cookie 来改善您的体验并提供个性化内容。</p>
    <div class="buttons">
      <button @click="acceptConsent">接受</button>
      <button @click="rejectConsent">拒绝</button>
    </div>
  </div>
</template>

条件加载

ts
// 仅在用户同意后加载
if (localStorage.getItem('ga_consent') === 'true') {
  loadGA()
}

其他统计工具

百度统计

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

Umami

ts
export default defineConfig({
  head: [
    [
      'script',
      {
        async: true,
        src: 'https://analytics.umami.is/script.js',
        'data-website-id': 'YOUR_WEBSITE_ID'
      }
    ]
  ]
})

参考链接

贡献者

加载中...

想要成为贡献者?

在 CNB 上参与贡献