在 React SPA 中使用 Google Analytics 4 跟踪页面浏览量

发布: (2026年2月23日 GMT+8 10:30)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Cover image for Tracking Page Views in a React SPA with Google Analytics 4

将 Google Analytics(GA4)添加到普通的 HTML 网站非常简单:把跟踪代码粘贴到 <head> 中即可。每当用户点击链接时,浏览器会请求一个新的 HTML 页面,GA 就会记录一次页面浏览。

但如果你使用 React、Vite 和 React Router 构建单页应用(SPA),这种开箱即用的行为就会失效。

在 React SPA 中,点击链接不会触发页面重新加载。React 只会卸载旧组件并挂载新组件,同时操作浏览器的 URL 历史。由于页面实际上没有重新加载,Google Analytics 无法记录新的 URL,你的分析数据会显示用户似乎永远停留在首页。

下面是一套我在个人作品集站点中使用的逐步解决方案。

1. 环境设置

避免在源代码中硬编码跟踪 ID。将您的测量 ID(在 GA 仪表板中找到,通常以 G-XXXXXXXXXX 开头)添加到 .env 文件中:

VITE_GA_TRACKING_ID=G-**********

2. 初始 HTML 代码片段(已修改)

index.html 中加入基础的 Google Analytics 跟踪代码,但 禁用自动的 page_view 跟踪 以防止重复计数。

<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){ dataLayer.push(arguments); }
  gtag('js', new Date());

  // IMPORTANT: Disable the default page_view tracking here!
  gtag('config', '%VITE_GA_TRACKING_ID%', { send_page_view: false });
</script>

关于 Vite: %VITE_GA_TRACKING_ID% 在构建时注入环境变量。

3. 创建路由监听组件

创建一个轻量、不可见的组件,使用 react-router-domuseLocation 监听 URL 变化。

src/components/Analytics.tsx

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

// Extend window object for TypeScript
declare global {
  interface Window {
    gtag: (...args: any[]) => void;
  }
}

export const Analytics = () => {
  const location = useLocation();

  useEffect(() => {
    const GA_MEASUREMENT_ID = import.meta.env.VITE_GA_TRACKING_ID;

    if (GA_MEASUREMENT_ID && typeof window.gtag === 'function') {
      window.gtag('config', GA_MEASUREMENT_ID, {
        page_path: location.pathname + location.search,
      });
    }
  }, [location]);

  return null; // Invisible component
};

4. 将其连接到 Router

<BrowserRouter> 内部<Routes>外部 挂载 <Analytics />

src/index.tsx

import { Analytics } from './components/Analytics';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';
import { Suspense } from 'react';
import ScrollToTop from './components/ScrollToTop';
import LoadingFallback from './components/LoadingFallback';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
// ...other imports

const App = () => {
  return (
    <HelmetProvider>
      <BrowserRouter>
        {/* Place the listener here! */}
        <Analytics />

        <ScrollToTop />
        <Suspense fallback={<LoadingFallback />}>
          <Routes>
            <Route path="/" element={<HomePage />} />
            <Route path="/about" element={<AboutPage />} />
            {/* ... other routes */}
          </Routes>
        </Suspense>
      </BrowserRouter>
    </HelmetProvider>
  );
};

export default App;

5. 结果

  • 当用户访问 vicentereyes.org 时,GA 脚本加载。
  • React 启动,挂载路由器,<Analytics /> 组件触发对 / 的页面浏览事件。
  • 随后导航(例如点击 “Projects”)会更新 URL,触发 <Analytics /> 中的 useEffect,并发送对 /projects 的干净页面浏览事件。

这提供了精确的 SPA 跟踪,而无需使用庞大的外部库。

0 浏览
Back to Blog

相关文章

阅读更多 »

理解 importmap-rails

介绍 如果你使用过现代 JavaScript,你会熟悉 ES 模块和 import 语句。Rails 应用可以使用 esbuild、vite 或 bun 来实现这些功能……