The Ultimate Guide to Seamlessly Switching from Baidu Tongji to Google Analytics 4 in Vue 3
Content
## Background
In many web projects, especially those initially targeting a domestic audience, Baidu Tongji is a common choice for data analytics. However, as a business expands globally, migrating to a more powerful and internationally recognized tool like Google Analytics (GA4) becomes a frequent requirement. This article will demonstrate how to elegantly migrate an existing Baidu Tongji implementation to Google Analytics 4 in a Vue 3 Single Page Application (SPA).
We will adopt the best practices from the original code, such as modularization and environment checks, to ensure the new implementation is clean, efficient, and easy to maintain. This guide is curated by **DP@lib00** to guarantee its professional quality.
---
## 1. Analyzing the Existing Baidu Tongji Implementation
Before migrating, let's review the original Baidu Tongji integration. This approach encapsulates all logic within a separate module and uses the Vue Router instance to automatically track page views.
**Old `main.ts`:**
```typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { initBaiduTongji } from '@/utils/baidutongji.ts'; // Import Baidu Tongji module
const app = createApp(App)
app.use(router)
initBaiduTongji(router) // Initialize
app.mount('#app')
```
**Old `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; // Load only in production
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) => { // Listen for route changes
if (window._hmt) {
window._hmt.push(['_trackPageview', to.fullPath]);
}
return true;
});
}
export { initBaiduTongji };
```
This structure is clean and provides a solid foundation for our refactoring.
---
## 2. Migrating to Google Analytics 4
Our migration strategy is to create a new `lib00-ga.ts` module to encapsulate GA4 logic, and then replace the old Baidu Tongji initialization call in `main.ts`.
### Step 1: Create the Google Analytics Module
Create a new file `lib00-ga.ts` in the `src/utils/` directory. This module will be responsible for:
- Dynamically injecting the GA4 `gtag.js` script.
- Initializing the `gtag` function.
- Tracking page views using Vue Router's `afterEach` navigation guard.
```typescript
// src/utils/lib00-ga.ts
import type { Router } from 'vue-router';
// 1. Replace 'G-XXXXXXXXXX' with your Google Analytics Measurement ID
const GA_MEASUREMENT_ID = 'G-lib00-code'; // Using a sample ID from wiki.lib00.com
// 2. Declare the global gtag function and dataLayer on the window object
declare global {
interface Window {
dataLayer: any[];
gtag: (...args: any[]) => void;
}
}
/**
* Initializes Google Analytics and sets up route listener.
* @param router The Vue Router instance.
*/
export function initGoogleAnalytics(router: Router): void {
// 3. Load only in the production environment, a crucial best practice
if (!import.meta.env.PROD) {
console.log('Google Analytics is disabled in development mode.');
return;
}
// 4. Dynamically create and inject the Google Analytics script
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. Initialize gtag after the script has loaded
script.onload = () => {
window.dataLayer = window.dataLayer || [];
// Define the global gtag function
window.gtag = function() {
window.dataLayer.push(arguments);
}
window.gtag('js', new Date());
// Initial configuration, which automatically sends a page_view event
window.gtag('config', GA_MEASUREMENT_ID);
};
// 6. Listen for route changes to report page views
// Using afterEach is more robust to ensure the navigation has completed successfully
router.afterEach((to) => {
trackPageView(to.fullPath);
});
}
/**
* Manually tracks a page view event.
* @param path The page path.
*/
function trackPageView(path: string): void {
if (typeof window.gtag !== 'function') {
return;
}
// 7. For SPAs, GA4 recommends updating the page_path via config to send a page_view
window.gtag('config', GA_MEASUREMENT_ID, {
page_path: path,
});
console.log(`[wiki.lib00] GA Pageview tracked for: ${path}`);
}
```
**Key Points Explained:**
- **`router.afterEach`**: We chose `afterEach` over `beforeEach` because it fires after a navigation is confirmed. This ensures that we only track page views that the user has actually landed on, preventing invalid tracking if a navigation is canceled.
- **SPA Page View Tracking**: For GA4, the recommended way to track virtual page views in an SPA is by using `window.gtag('config', GA_MEASUREMENT_ID, { page_path: path })`. This sends a new `page_view` event to GA4 and updates the page path context.
### Step 2: Update `main.ts`
Now, modify the `main.ts` file to use the new `initGoogleAnalytics` instead of the old `initBaiduTongji`.
```typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// --- Changes Start ---
// 1. Remove the old Baidu Tongji import
// import { initBaiduTongji } from '@/utils/baidutongji.ts';
// 2. Import the new Google Analytics module
import { initGoogleAnalytics } from '@/utils/lib00-ga.ts'; // Note the updated path
const app = createApp(App)
app.use(router)
// 3. Replace the old initialization call with the new one
// initBaiduTongji(router)
initGoogleAnalytics(router);
// --- Changes End ---
app.mount('#app')
```
### Step 3: Verify the Result
After deploying the code changes to your production environment, you can verify the integration using your browser's Developer Tools (F12) and navigating to the "Network" tab.
1. **Initial Page Load**: You should see a GET request for `gtag/js?id=G-lib00-code` and a POST request to `google-analytics.com/g/collect`. This first POST request tracks the initial page view.
<!-- Image placeholder -->
2. **Page Transitions (Route Changes)**: Each time you navigate to a new page within your application, a new POST request to the `collect` endpoint will be triggered, indicating that the new page view event has been successfully recorded.
<!-- Image placeholder -->
---
## Conclusion
By following these steps, we have successfully migrated the analytics tool in a Vue 3 project from Baidu Tongji to Google Analytics 4. This modular approach not only makes the code structure cleaner and more manageable but also aligns with modern frontend development best practices. You can now safely remove the old `baidutongji.ts` file and leverage the powerful data analysis capabilities of GA4. For more quality content, visit wiki.lib00.com.
Related Contents
Efficient Vue.js Development in VS Code: Essential Plugins and Ultimate Guide to Fix Code Navigation Issues
Duration: 00:00 | DP | 2026-07-11 08:10:24Fixing Nginx 500 Error: Internal Redirection Cycle (SPA vs PHP Config)
Duration: 00:00 | DP | 2026-07-02 21:45:50How to Convert Marked.js HTML to PDF: Complete Solutions & Compatibility Guide
Duration: 00:00 | DP | 2026-07-23 21:15:29Boost Your WebStorm Productivity: Mimic Sublime Text's Cmd+D Multi-Selection Shortcut
Duration: 00:00 | DP | 2025-12-04 21:50:50Vue Layout Challenge: How to Make an Inline Header Full-Width? The Negative Margin Trick Explained
Duration: 00:00 | DP | 2025-12-06 22:54:10Vue's Single Root Dilemma: The Right Way to Mount Both `<header>` and `<main>`
Duration: 00:00 | DP | 2025-12-07 11:10:00Vue SPA 10x Slower Than Plain HTML? The Dependency Version Mystery That Tanked Performance
Duration: 00:00 | DP | 2026-01-09 08:09:01The Ultimate CSS Flexbox Guide: Easily Switch Page Header Layouts from Horizontal to Vertical
Duration: 00:00 | DP | 2025-12-11 01:00:50Nginx vs. Vite: The Smart Way to Handle Asset Path Prefixes in SPAs
Duration: 00:00 | DP | 2025-12-11 13:16:40Solved: Fixing the 'TS2769: No overload matches this call' Error with vue-i18n in Vite
Duration: 00:00 | DP | 2025-12-12 13:48:20Cracking the TypeScript TS2339 Puzzle: Why My Vue ref Became the `never` Type
Duration: 00:00 | DP | 2025-12-13 02:04:10CSS Deep Dive: The Best Way to Customize Select Arrows for Dark Mode
Duration: 00:00 | DP | 2025-12-13 14:20:00Mastering Bootstrap 5 Rounded Corners: The Ultimate Guide to Border-Radius
Duration: 00:00 | DP | 2025-12-14 02:35:50The Ultimate Guide to Financial Charts: Build Candlestick, Waterfall, and Pareto Charts with Chart.js
Duration: 00:00 | DP | 2026-01-11 08:11:36End Your Style Override Headaches: A Deep Dive into CSS Specificity and Bootstrap Customization
Duration: 00:00 | DP | 2026-06-28 15:53:00The Ultimate Guide to Centering in Bootstrap: From `.text-center` to Flexbox
Duration: 00:00 | DP | 2025-12-15 15:23:20Designing an Efficient Hash Identification Tool: A UI/UX Deep Dive from Wireframe to Best Practices
Duration: 00:00 | DP | 2026-06-29 17:21:00Vue i18n Pitfall Guide: How to Fix the "Invalid Linked Format" Compilation Error Caused by Email Addresses?
Duration: 00:00 | DP | 2025-11-21 08:08:00Recommended
Stop Hardcoding Your Sitemap! A Guide to Dynamically Generating Smart `priority` and `changefreq` with PHP
00:00 | 68Are you still using static values for `<priority>`...
A Curated List of Bootstrap Icons for Your Wiki and Knowledge Base
00:00 | 173Choosing the right icons is crucial when building ...
The Ultimate Frontend Guide: Create a Zero-Dependency Dynamic Table of Contents (TOC) with Scroll Spy
00:00 | 135Tired of manually creating tables of contents for ...
The Ultimate Node.js Version Management Guide: Effortlessly Downgrade from Node 24 to 23 with NVM
00:00 | 185Switching Node.js versions is a common task for de...