gatsby-plugin-google-gtag:在 Gatsby 站点中集成 Google Global Site Tag 的完整实践
2026/9/20 20:43:31 网站建设 项目流程

gatsby-plugin-google-gtag:在 Gatsby 站点中集成 Google Global Site Tag 的完整实践

【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby

本篇以 Gatsby 仓库中的 gatsby-plugin-google-gtag 插件文档 为核心,完整覆盖该插件的安装、配置参数(trackingIdsgtagConfigpluginConfig)、自定义事件与<OutboundLink>组件的使用方式,并结合仓库源码剖析其在 SSR 阶段注入追踪脚本、在浏览器端发送page_view事件的具体实现链路,帮助你在 Gatsby 5 站点中正确接入 GA4 / Google Ads 等 Google 标签体系。

什么是 Global Site Tag(gtag.js)

Google 的 global site tag(gtag.js)是一个 JavaScript 标签框架与 API,允许你将事件数据发送到 Google Analytics、Google Ads、Campaign Manager、Display & Video 360 以及 Search Ads 360。它的设计目标是合并多个 Google 标签系统,因此可以取代较旧的 analytics.js(对应 Gatsby 生态中的gatsby-plugin-google-analytics插件)。

gatsby-plugin-google-gtag的定位就是在 Gatsby 站点中方便地注入 gtag.js。相比手动复制粘贴 Google 给出的代码片段,该插件额外解决了 SPA 场景下的几个关键问题:

  • 在每次 Gatsby 路由变化时自动发送pageview事件(传统<script>标签只会在首次加载时发一次);
  • 通过exclude选项按 glob 表达式排除某些路径;
  • 通过respectDNT选项尊重浏览器的 "Do Not Track" 设置;
  • 通过<OutboundLink>组件便捷地追踪出站链接点击。

重要前提:该插件仅在 production 模式下工作。要验证 Global Site Tag 是否正确安装并触发事件,需要运行gatsby build && gatsby serve。这一点在源码中得到直接印证——gatsby-ssr.js 的onRenderBody开头即有守卫:

if (process.env.NODE_ENV !== `production` && process.env.NODE_ENV !== `test`) return null

即非 production(且非测试)环境下,插件在渲染阶段直接不做任何注入。

安装

npm install gatsby-plugin-google-gtag

插件的 package.json 中声明了对gatsby ^5.0.0的 peer 依赖,运行环境要求 Node>=18.0.0 <26

基本配置

trackingIds必填选项,缺失时插件无法正常工作。完整的配置示例如下:

module.exports = { plugins: [ { resolve: `gatsby-plugin-google-gtag`, options: { // You can add multiple tracking ids and a pageview event will be fired for all of them. trackingIds: [ "GA-TRACKING_ID", // Google Analytics / GA "AW-CONVERSION_ID", // Google Ads / Adwords / AW "DC-FLOODIGHT_ID", // Marketing Platform advertising products (Display & Video 360, Search Ads 360, and Campaign Manager) ], // This object gets passed directly to the gtag config command // This config will be shared across all trackingIds gtagConfig: { optimize_id: "OPT_CONTAINER_ID", anonymize_ip: true, cookie_expires: 0, }, // This object is used for configuration specific to this plugin's specific configuration pluginConfig: { // Puts tracking script in the head instead of the body head: false, // Setting this parameter is also optional respectDNT: true, // Avoids sending pageview hits from custom paths exclude: ["/preview/**", "/do-not-track/me/too/"], // Defaults to https://www.googletagmanager.com origin: "YOUR_SELF_HOSTED_ORIGIN", // Delays processing pageview events on route update (in milliseconds) delayOnRouteUpdate: 0, }, }, }, ], }

选项的合法性由 gatsby-node.js 中导出的pluginOptionsSchema通过 Joi 在插件加载时校验,默认值与约束如下(源码中的定义):

选项类型默认值说明
trackingIdsstring[]无(required追踪 ID 列表,没有它们不会生成追踪代码
gtagConfigobject{}直接透传给gtag('config', ...)命令
gtagConfig.anonymize_ipbooleanfalse启用 IP 匿名化(_anonymizeIP
pluginConfig.headbooleanfalse将追踪脚本放入<head>而非<body>
pluginConfig.respectDNTbooleanfalse对开启 "Do Not Track" 的访客完全不加载 gtag
pluginConfig.excludestring[][]以 glob 表达式排除的路径
pluginConfig.originstringhttps://www.googletagmanager.com自托管脚本的 origin
pluginConfig.delayOnRouteUpdatenumber0路由更新后处理 pageview 事件的延迟(毫秒)

仓库中的 schema 测试 明确验证了错误配置会产生的报错信息,例如缺失trackingIds时报"trackingIds" is requiredpluginConfig.origin传数字时报"pluginConfig.origin" must be a string等。gtagConfig使用了unknown(true),因此除了显式声明的optimize_idanonymize_ip,其余键都会原样透传。

选项详解

gtagConfig.anonymize_ip

某些国家(例如德国)要求对 Google Site Tag 使用_anonymizeIP函数,否则不允许使用。开启该选项后,插件会注入如下代码块(对应 gatsby-ssr.js 中的内联脚本生成逻辑):

function gaOptout() { ;(document.cookie = disableStr + "=true; expires=Thu, 31 Dec 2099 23:59:59 UTC;path=/"), (window[disableStr] = !0) } var gaProperty = "UA-XXXXXXXX-X", disableStr = "ga-disable-" + gaProperty document.cookie.indexOf(disableStr + "=true") > -1 && (window[disableStr] = !0)

从源码看,gaProperty取的是trackingIds数组中的第一个ID,ga-disable-<ID>cookie 会被检查并在页面加载时同步到window标志位。

如果希望访客能够主动设置 Opt-Out-Cookie(即不再被追踪),可以在站点页脚/法律声明等位置放置一个链接:

<a href="javascript:gaOptout();">Deactivate Google Tracking</a>

gtagConfig.optimize_id

如果需要使用 Google Optimize 做 A/B 测试,可以添加这个可选的 Optimize 容器 ID,以便 Google Optimize 为你的站点加载正确的测试参数。

其他gtagConfig选项

gtagConfig原样传入gtag 的 config 命令,因此它支持的一切字段都可以使用,例如gtagConfig.cookie_namegtagConfig.sample_rate。如果你正在从 analytics.js 插件迁移过来,意味着所有 Create Only Fields 都应改为 snake_case 命名(如cookieNamecookie_name)。

pluginConfig.respectDNT

启用该可选项后,开启了 "Do Not Track" 的访客将完全不会加载 Google Global Site Tag。虽然使用 Global Site Tag 不一定构成法律意义上的 "追踪",但为更重视隐私的用户群体服务时,这是一个有价值的开关。

从实现看,gatsby-ssr.js 会在整个dataLayer/gtag初始化代码外层包裹一个条件判断:

if(!(navigator.doNotTrack == "1" || window.doNotTrack == "1")) { window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); // ... gtag('config', ...) 对每个 trackingId 执行 }

respectDNTfalse(默认)时,该条件渲染为if(true),即不做任何 DNT 检查。对应的测试用例 分别断言了默认情况下输出 HTML 中不含 DNT 字符串、开启后包含该字符串。

pluginConfig.exclude

如果需要将某些路径排除在追踪体系之外,可以把一个或多个路径以glob 表达式的形式加入该可选数组,例如["/preview/**", "/do-not-track/me/too/"]

底层实现分两步:

  1. SSR 阶段(gatsby-ssr.js):使用minimatch(插件的运行时依赖之一)将每个 glob 转换为正则,并写入页面内联脚本:window.excludeGtagPaths=[/^\S*.../, ...]
  2. 浏览器阶段(gatsby-browser.js):路由更新时逐一用这些正则测试location.pathname,命中任一正则则跳过本次page_view事件。

pluginConfig.origin

默认脚本来源为https://www.googletagmanager.com。如果你自托管了 gtag 脚本,可以替换为自有 origin。从 SSR 源码 可以看到,origin同时作用于两处:

  • <head>中注入的<link rel="preconnect"><link rel="dns-prefetch">(Lighthouse 建议对 Google Tag Manager 域名做预连接,以降低脚本加载延迟);
  • 实际<script async src="${origin}/gtag/js?id=${firstTrackingId}">src

相关测试 验证了默认 origin 与自定义 origin 两种情况下上述三处均使用同一 origin。

pluginConfig.delayOnRouteUpdate

如果需要延迟处理路由更新时的 pageview 事件(例如等待gatsby-plugin-transition-link的页面过渡动画完成),该选项会在生成 pageview 事件之前加入指定的毫秒级延迟。

插件在 Gatsby 生命周期中的工作方式

SSR 阶段:onRenderBody注入脚本

gatsby-ssr.js 导出的onRenderBody是插件的核心。它做了以下几件事:

  1. preconnect / dns-prefetch:为 origin 域注入<head>链接,优化脚本加载性能;
  2. 关闭 gtag 内置的初始 pageview:在透传的gtagConfig中强制设置gtagConfig.send_page_view = false(L25)。这是为了避免首次加载时由config命令触发一次、而 SPA 路由又由浏览器端再发一次,从而造成重复的 pageview 事件
  3. head选项决定脚本位置pluginConfig.head为真时通过setHeadComponents注入<head>,否则通过setPostBodyComponents注入到<body>之后(L40-L42);
  4. 生成内联配置脚本:对每个trackingId逐条生成gtag('config', '<id>', {...})命令,gtagConfigJSON.stringify序列化后内嵌。

最终产出的 HTML 结构等价于:

<script async src="https://www.googletagmanager.com/gtag/js?id=GA-TRACKING_ID"></script> <script> window.excludeGtagPaths=[/* 由 exclude 生成的正则 */]; /* 若 anonymize_ip: true,此处还有 gaOptout 代码块 */ if(true /* respectDNT 为 true 时替换为 DNT 判断 */) { window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'GA-TRACKING_ID', {"send_page_view":false, ...}); gtag('config', 'AW-CONVERSION_ID', {"send_page_view":false, ...}); } </script>

浏览器阶段:onRouteUpdate发送 pageview

gatsby-browser.js 监听 Gatsby 的onRouteUpdateAPI:

exports.onRouteUpdate = ({ location }, pluginOptions = {}) => { if (process.env.NODE_ENV !== `production` || typeof gtag !== `function`) { return null } // ... 排除路径检查 const sendPageView = () => { const pagePath = location ? location.pathname + location.search + location.hash : undefined window.gtag(`event`, `page_view`, { page_path: pagePath }) } // 双层 requestAnimationFrame + setTimeout(delayOnRouteUpdate) }

几个值得注意的实现细节:

  • 事件携带完整的page_path(pathname + search + hash),保证带 query/锚点的导航也被正确记录;
  • 发送前会用window.excludeGtagPaths正则测试当前pathname,命中即返回;
  • sendPageView被包裹在两层requestAnimationFrame之后再叠加setTimeout(delayOnRouteUpdate)——源码注释说明这是为了确保react-helmet等对 document 的修改已经完成;在不支持requestAnimationFrame的环境下退化为固定的 32ms 延迟(模拟两次 rAF)再加配置延迟。

自定义事件(Custom Events)

该插件会自动为所有trackingIds中给出的产品在每次 Gatsby 路由变化时发送pageview事件。如需触发自定义事件,可以直接访问全局的window.gtag,向所有产品发送:

window.gtag("event", "click", { ...data })

或者用send_to指定特定产品:

window.gtag("event", "click", { send_to: "AW-CONVERSION_ID", ...data })

无论哪种方式,都要记得对 SSR 做防护:

typeof window !== "undefined" && window.gtag("event", "click", { ...data })

<OutboundLink>组件

为了简化出站链接点击的追踪,插件提供了一个<OutboundLink>组件(实现见 src/index.js,类型定义见 index.d.ts),用法与<a>元素一致:

import React from "react" import { OutboundLink } from "gatsby-plugin-google-gtag" export default () => ( <div> <OutboundLink href="https://www.gatsbyjs.com/plugins/gatsby-plugin-google-gtag/"> Visit the Google Global Site Tag plugin page! </OutboundLink> </div> )

从源码实现看,它比文档描述做了更多细节处理:

  • 先调用用户传入的onClick(如果提供),随后发送event_category: "outbound"event_label: props.hrefclick事件;
  • 重定向判定:只有左键单击、且未附带altKey/ctrlKey/metaKey/shiftKeydefaultPrevented未设置、target_self(或未指定)时才会由组件接管跳转;中键点击、target="_blank"等场景直接放行,不发送 beacon、不阻止默认行为;
  • 可接管跳转的场景下使用transport_type: "beacon",并通过event_callback在事件上报完成后才执行document.location = href,尽量降低跳转导致事件丢失的概率;若当前环境没有window.gtag(如未通过校验或 DNT 被排除),则退化为直接跳转。

组件以React.forwardRef实现并透传全部<a>属性,因此classNamearia-*等属性均可正常使用。

验证与排错

由于插件仅在 production 模式生效,推荐的验证流程是:

gatsby build && gatsby serve

然后在浏览器中打开页面,通过 Google 官方的 Tag Assistant 或 GA4 的 DebugView 确认事件是否上报。如果事件没有触发,可以按以下顺序排查:

  1. trackingIds是否已配置且格式正确(Joi schema 缺失必填项会在构建时直接报错);
  2. 是否误在gatsby develop下测试(开发模式下 SSR 注入与浏览器端onRouteUpdate均被守卫短路);
  3. 当前路径是否命中pluginConfig.exclude的 glob 表达式,或开启了respectDNT而浏览器启用了 DNT;
  4. 自托管origin是否可正常访问/gtag/js路径。

小结

gatsby-plugin-google-gtag通过三个 Gatsby API 协作完成完整链路:gatsby-ssr.js 在onRenderBody中注入 preconnect、gtag 加载脚本与逐 ID 的 config 命令(并强制send_page_view: false防止首次加载重复计数),gatsby-browser.js 在onRouteUpdate中处理排除路径、延迟与 rAF 时序后发送page_view,gatsby-node.js 用 Joi schema 保证选项合法且提供合理默认值,而 src/index.js 提供了带跳转时序优化的<OutboundLink>组件。配合本文完整的参数说明与源码级解释,你可以放心地将 GA4、Google Ads(AW-)及 Marketing Platform(DC-)等产品接入自己的 Gatsby 站点。

【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询