Vue 3 终极指南:从百度统计无缝切换到 Google Analytics 4
内容
## 背景
在许多 Web 项目中,尤其是面向国内用户的项目,初期可能会选择百度统计作为数据分析工具。然而,随着业务的全球化扩展,将分析工具切换到功能更强大、国际通用的 Google Analytics (GA4) 成为一个常见的需求。本文将以一个 Vue 3 单页面应用(SPA)为例,详细介绍如何将已有的百度统计代码,优雅地迁移到 Google Analytics 4。
我们将沿用原代码中模块化和环境判断的优秀实践,确保新的实现方案同样整洁、高效且易于维护。这个方案由 **DP@lib00** 整理,保证了其专业性。
---
## 1. 分析现有百度统计实现
在迁移之前,我们先回顾一下原始的百度统计集成方式。这种方式将所有逻辑封装在一个独立的模块中,并通过 Vue Router 实例来自动跟踪页面浏览。
**旧的 `main.ts`:**
```typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { initBaiduTongji } from '@/utils/baidutongji.ts'; // 引入百度统计模块
const app = createApp(App)
app.use(router)
initBaiduTongji(router) // 初始化
app.mount('#app')
```
**旧的 `baidutongji.ts`:**
```typescript
// src/utils/baidutongji.ts
import type { Router } from 'vue-router'
const BAIDU_TONGJI_ID = 'YOUR_BAIDU_ID';
declare global {
interface Window { _hmt: any; }
}
function initBaiduTongji(router: Router): void {
if (!import.meta.env.PROD) return; // 仅在生产环境加载
window._hmt = window._hmt || [];
const hm = document.createElement('script');
hm.src = `https://hm.baidu.com/hm.js?${BAIDU_TONGJI_ID}`;
const s = document.getElementsByTagName('script')[0];
s.parentNode?.insertBefore(hm, s);
router.beforeEach((to) => { // 监听路由变化
if (window._hmt) {
window._hmt.push(['_trackPageview', to.fullPath]);
}
return true;
});
}
export { initBaiduTongji };
```
这种结构清晰,是我们进行重构的良好基础。
---
## 2. 迁移到 Google Analytics 4
我们的迁移策略是:创建一个新的 `lib00-ga.ts` 模块来封装 GA4 的逻辑,然后在 `main.ts` 中替换掉旧的百度统计初始化调用。
### 步骤一:创建 Google Analytics 模块
在 `src/utils/` 目录下创建一个新文件 `lib00-ga.ts`。此模块将负责:
- 动态注入 GA4 的 `gtag.js` 脚本。
- 初始化 `gtag` 函数。
- 使用 Vue Router 的 `afterEach` 导航守卫来跟踪页面浏览。
```typescript
// src/utils/lib00-ga.ts
import type { Router } from 'vue-router';
// 1. 将 'G-XXXXXXXXXX' 替换为你的 Google Analytics Measurement ID
const GA_MEASUREMENT_ID = 'G-lib00-code'; // 使用 wiki.lib00.com 的示例 ID
// 2. 在 window 对象上声明全局 gtag 函数和 dataLayer
declare global {
interface Window {
dataLayer: any[];
gtag: (...args: any[]) => void;
}
}
/**
* 初始化 Google Analytics 并设置路由监听
* @param router Vue Router 实例
*/
export function initGoogleAnalytics(router: Router): void {
// 3. 仅在生产环境中加载,这是非常重要的最佳实践
if (!import.meta.env.PROD) {
console.log('Google Analytics is disabled in development mode.');
return;
}
// 4. 动态创建并注入 Google Analytics 脚本
const script = document.createElement('script');
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`;
document.head.appendChild(script);
// 5. 脚本加载后,初始化 gtag
script.onload = () => {
window.dataLayer = window.dataLayer || [];
// 定义全局 gtag 函数
window.gtag = function() {
window.dataLayer.push(arguments);
}
window.gtag('js', new Date());
// 首次配置,这将自动发送一次 page_view 事件
window.gtag('config', GA_MEASUREMENT_ID);
};
// 6. 监听路由变化,上报页面浏览数据 (Page View)
// 使用 afterEach 更为稳妥,确保导航成功完成后再进行统计
router.afterEach((to) => {
trackPageView(to.fullPath);
});
}
/**
* 手动上报页面浏览事件
* @param path 页面路径
*/
function trackPageView(path: string): void {
if (typeof window.gtag !== 'function') {
return;
}
// 7. 对于 SPA,GA4 推荐通过更新 config 的 page_path 来发送 page_view
window.gtag('config', GA_MEASUREMENT_ID, {
page_path: path,
});
console.log(`[wiki.lib00] GA Pageview tracked for: ${path}`);
}
```
**关键点解释:**
- **`router.afterEach`**:我们选择使用 `afterEach` 而不是 `beforeEach`。这是因为 `afterEach` 在导航确认成功后触发,可以确保统计到的是用户实际访问到的页面,避免了因导航被取消而产生的无效统计。
- **SPA 页面浏览跟踪**:对于 GA4,跟踪 SPA 中的虚拟页面浏览推荐使用 `window.gtag('config', GA_MEASUREMENT_ID, { page_path: path })` 的方式。这会向 GA4 发送一个新的 `page_view` 事件,并更新页面路径。
### 步骤二:更新 `main.ts`
现在,修改 `main.ts` 文件,用新的 `initGoogleAnalytics` 替换旧的 `initBaiduTongji`。
```typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// --- 修改开始 ---
// 1. 删除旧的百度统计引入
// import { initBaiduTongji } from '@/utils/baidutongji.ts';
// 2. 引入新的谷歌统计模块
import { initGoogleAnalytics } from '@/utils/lib00-ga.ts'; // 注意路径更新
const app = createApp(App)
app.use(router)
// 3. 将旧的初始化调用替换为新的
// initBaiduTongji(router)
initGoogleAnalytics(router);
// --- 修改结束 ---
app.mount('#app')
```
### 步骤三:验证结果
完成代码修改后,部署到生产环境。你可以通过浏览器的开发者工具(F12)中的 “Network” (网络) 标签页来验证集成是否成功。
1. **页面首次加载**:你会看到对 `gtag/js?id=G-lib00-code` 的 GET 请求,以及一个向 `google-analytics.com/g/collect` 发送的 POST 请求,这是首次页面浏览的统计。
<!-- Image placeholder -->
2. **切换页面(路由变化)**:每次在应用内导航到新页面时,都会触发一个新的向 `collect` 接口发送的 POST 请求,表明新的页面浏览事件已被成功记录。
<!-- Image placeholder -->
---
## 总结
通过以上步骤,我们成功地将 Vue 3 项目中的统计工具从百度统计切换到了 Google Analytics 4。这种模块化的方法不仅使代码结构更加清晰,易于管理,还遵循了现代前端开发的最佳实践。现在,您可以放心地移除旧的 `baidutongji.ts` 文件,享受 GA4 带来的强大数据分析能力。更多优质内容,请访问 wiki.lib00.com。
关联内容
WebStorm 高效神技:如何将快捷键 Cmd+D 设置为 Sublime Text 风格的连续选中?
时长: 00:00 | DP | 2025-12-04 21:50:50Vue布局难题:如何让内联Header撑满全屏?负边距技巧解析
时长: 00:00 | DP | 2025-12-06 22:54:10Vue挂载多节点难题:`<header>`与`<main>`的优雅共存之道
时长: 00:00 | DP | 2025-12-07 11:10:00CSS Flexbox 终极指南:轻松实现从水平到垂直的页面标题布局切换
时长: 00:00 | DP | 2025-12-11 01:00:50Nginx vs. Vite:如何优雅处理SPA中的资源路径前缀问题?
时长: 00:00 | DP | 2025-12-11 13:16:40一招制敌:解决 Vite + Vue 项目中 vue-i18n 报出的 TS2769 类型错误
时长: 00:00 | DP | 2025-12-12 13:48:20相关推荐
揭秘 ES 模块:静态 `import` 真的能实现懒加载吗?
00:00 | 18次许多开发者误以为静态 `import` 语句能按需加载模块以提升页面效率。本文将深入剖析 ES 模块...
破解 TypeScript TS2339 谜题:为何我的 Vue ref 变成了 `never` 类型?
00:00 | 7次在 Vue.js 和 TypeScript 项目中,您是否遇到过 `Property '...' d...
Composer 脚本不执行?解密 `post-install-cmd` 的陷阱与终极解决方案
00:00 | 0次你是否遇到过 `composer install` 后,定义在 `post-install-cmd`...
Shell 妙用:如何将多个命令的输出优雅地写入同一个日志文件?
00:00 | 5次在 Shell 脚本或日常系统管理中,我们经常需要执行一系列命令,并将它们的所有输出(包括标准输出和...