GA4 完整整合指南:從基礎設定到 Vue Composable 封裝
Google Analytics 4(GA4)是 Google 推出的新一代網站分析工具,採用以「事件」為核心的資料模型,取代了傳統 Universal Analytics 的「工作階段」概念。本篇將完整介紹如何在前端專案中整合 GA4,從基礎設定到進階的 Vue Composable 封裝。
一、 GA4 核心概念
1.1 事件驅動架構
GA4 的資料模型以「事件(Event)」為核心:
- 自動收集事件:頁面瀏覽、首次造訪、工作階段開始等
- 加強型評估事件:捲動、外連點擊、網站搜尋、影片互動等
- 建議事件:Google 定義的標準事件,如
login、purchase - 自訂事件:開發者自行定義的事件
1.2 gtag.js API 架構
gtag() 是 Google Tag 的核心函式,支援以下指令:
| 指令 | 用途 | 範例 |
|---|---|---|
config | 配置目標(GA4 資源) | gtag('config', 'G-XXXXXXXXXX') |
set | 設定全域參數 | gtag('set', { currency: 'TWD' }) |
event | 傳送事件 | gtag('event', 'login', { method: 'Google' }) |
consent | 管理使用者同意權 | gtag('consent', 'update', {...}) |
get | 取得參數值 | gtag('get', 'G-XXXXXXXXXX', 'client_id', callback) |
二、 基礎設定
2.1 安裝 Google Tag
在 HTML <head> 中加入以下程式碼:
<!-- Google tag (gtag.js) -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-XXXXXXXXXX");
</script>IMPORTANT
將 G-XXXXXXXXXX 替換為你的 GA4 測量 ID(Measurement ID),可在 GA4 管理介面的「資料串流」中找到。
2.2 在 VitePress 中整合
VitePress 透過 config.ts 的 head 設定注入標籤:
// .vitepress/config.ts
export default defineConfig({
head: [
[
"script",
{
async: "",
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');`,
],
],
});2.3 在 Vue / Nuxt 中整合
對於 SPA(Single Page Application,單頁應用程式)框架,需要處理路由變化時的頁面瀏覽追蹤:
// plugins/ga4.ts (Nuxt 3 範例)
export default defineNuxtPlugin((nuxtApp) => {
const config = useRuntimeConfig();
const measurementId = config.public.ga4MeasurementId;
if (!measurementId) return;
// 注入 gtag.js
useHead({
script: [
{
src: `https://www.googletagmanager.com/gtag/js?id=${measurementId}`,
async: true,
},
{
innerHTML: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${measurementId}', { send_page_view: false });
`,
},
],
});
// 監聽路由變化
const router = useRouter();
router.afterEach((to) => {
window.gtag?.("event", "page_view", {
page_path: to.fullPath,
page_title: document.title,
});
});
});TIP
設定 send_page_view: false 可避免初始頁面重複計算,改由路由監聽統一處理。
三、 事件追蹤
3.1 基本語法
gtag('event', '<事件名稱>', {
// 事件參數
<參數名稱>: <參數值>,
})3.2 建議事件範例
Google 定義了一系列建議事件,使用這些事件可獲得更好的報表支援:
// 登入事件
gtag("event", "login", {
method: "Google",
});
// 註冊事件
gtag("event", "sign_up", {
method: "Email",
});
// 分享事件
gtag("event", "share", {
method: "Twitter",
content_type: "article",
item_id: "article_123",
});
// 搜尋事件
gtag("event", "search", {
search_term: "Vue composable",
});3.3 自訂事件
// 自訂事件:影片播放
gtag("event", "video_play", {
video_title: "教學影片第一集",
video_duration: 300,
video_provider: "YouTube",
});
// 自訂事件:表單提交
gtag("event", "form_submit", {
form_name: "contact_form",
form_destination: "/thank-you",
});3.4 參數範圍與優先序
gtag 的參數可以在三個層級設定:
優先序:event > config > set
// 全域設定(最低優先)
gtag("set", { currency: "USD" });
// 目標設定
gtag("config", "G-XXXXXXXXXX", { currency: "EUR" });
// 事件設定(最高優先)
gtag("event", "purchase", {
currency: "TWD", // 此事件會使用 TWD
value: 1000,
});四、 使用者屬性
使用者屬性(User Properties)可用於區隔使用者群組,每個專案最多可設定 25 個自訂屬性。
4.1 設定使用者屬性
gtag("set", "user_properties", {
membership_level: "gold",
favorite_category: "electronics",
account_type: "premium",
});4.2 保留名稱
以下名稱為系統保留,不可使用:
first_open_timefirst_visit_timelast_deep_link_referreruser_idfirst_open_after_install
此外,屬性名稱不可以以下前綴開頭:
google_ga_firebase_
4.3 設定 User ID
若有會員系統,可設定 User ID 進行跨裝置追蹤:
gtag("config", "G-XXXXXXXXXX", {
user_id: "USER_12345",
});WARNING
User ID 必須是不可識別個人身份的 ID(如會員編號),絕對不可使用 Email 或電話號碼。
五、 電商追蹤
GA4 提供完整的電商追蹤事件,涵蓋使用者的整個購物流程。
5.1 電商事件流程
5.2 商品資料結構
const items = [
{
item_id: "SKU_12345",
item_name: "Vue 3 實戰指南",
affiliation: "Hirimu 書店",
coupon: "SUMMER_SALE",
discount: 50,
index: 0,
item_brand: "Hirimu",
item_category: "程式設計",
item_category2: "前端開發",
item_variant: "電子書",
price: 450,
quantity: 1,
},
];5.3 加入購物車事件
gtag("event", "add_to_cart", {
currency: "TWD",
value: 450,
items: [
{
item_id: "SKU_12345",
item_name: "Vue 3 實戰指南",
price: 450,
quantity: 1,
},
],
});5.4 購買完成事件
gtag("event", "purchase", {
transaction_id: "T_12345",
value: 850,
tax: 42.5,
shipping: 60,
currency: "TWD",
coupon: "SUMMER_SALE",
items: [
{
item_id: "SKU_12345",
item_name: "Vue 3 實戰指南",
price: 450,
quantity: 1,
},
{
item_id: "SKU_12346",
item_name: "TypeScript 入門",
price: 400,
quantity: 1,
},
],
});六、 Debug 模式
6.1 啟用 Debug 模式
在 config 中加入 debug_mode 參數:
gtag("config", "G-XXXXXXXXXX", {
debug_mode: true,
});或針對單一事件啟用:
gtag("event", "test_event", {
debug_mode: true,
// 其他參數...
});6.2 使用 DebugView
- 開啟 GA4 管理介面
- 前往「設定」→「DebugView」
- 可即時查看來自啟用 debug_mode 裝置的事件
6.3 Chrome 擴充功能
安裝 Google Analytics Debugger 擴充功能,可在 Console 中查看詳細的追蹤資訊。
七、 Vue Composable 封裝
將 GA4 功能封裝為 Vue Composable,提供類型安全與更好的開發體驗。
7.1 類型定義
// types/useGA4.ts
export interface GA4Config {
measurementId: string;
debug?: boolean;
}
export interface EventParams {
[key: string]: string | number | boolean | undefined;
}
export interface EcommerceItem {
item_id: string;
item_name: string;
price?: number;
quantity?: number;
item_brand?: string;
item_category?: string;
item_variant?: string;
coupon?: string;
discount?: number;
index?: number;
}
export interface PurchaseParams {
transaction_id: string;
value: number;
currency: string;
tax?: number;
shipping?: number;
coupon?: string;
items: EcommerceItem[];
}
export interface UseGA4Return {
isReady: Ref<boolean>;
trackEvent: (eventName: string, params?: EventParams) => void;
trackPageView: (pagePath: string, pageTitle?: string) => void;
setUserProperties: (properties: Record<string, string | number>) => void;
setUserId: (userId: string | null) => void;
trackPurchase: (params: PurchaseParams) => void;
trackAddToCart: (item: EcommerceItem, currency?: string) => void;
}7.2 完整實作
// composables/useGA4.ts
import { ref, onMounted } from "vue";
import type {
GA4Config,
EventParams,
PurchaseParams,
EcommerceItem,
UseGA4Return,
} from "@/types/useGA4";
// 擴展 Window 類型
declare global {
interface Window {
gtag?: (...args: unknown[]) => void;
dataLayer?: unknown[];
}
}
export function useGA4(config: GA4Config): UseGA4Return {
const isReady = ref(false);
const { measurementId, debug = false } = config;
// 初始化 gtag
function initGtag() {
if (typeof window === "undefined") return;
// 建立 dataLayer
window.dataLayer = window.dataLayer || [];
window.gtag = function gtag() {
window.dataLayer!.push(arguments);
};
// 載入 gtag.js
const script = document.createElement("script");
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
script.onload = () => {
isReady.value = true;
};
document.head.appendChild(script);
// 初始化配置
window.gtag("js", new Date());
window.gtag("config", measurementId, {
debug_mode: debug,
send_page_view: false, // 由 trackPageView 手動控制
});
}
// 追蹤自訂事件
function trackEvent(eventName: string, params: EventParams = {}) {
if (!window.gtag) {
console.warn("[GA4] gtag 尚未初始化");
return;
}
const eventParams = debug ? { ...params, debug_mode: true } : params;
window.gtag("event", eventName, eventParams);
if (debug) {
console.log("[GA4] Event:", eventName, eventParams);
}
}
// 追蹤頁面瀏覽
function trackPageView(pagePath: string, pageTitle?: string) {
trackEvent("page_view", {
page_path: pagePath,
page_title: pageTitle || document.title,
});
}
// 設定使用者屬性
function setUserProperties(properties: Record<string, string | number>) {
if (!window.gtag) return;
window.gtag("set", "user_properties", properties);
if (debug) {
console.log("[GA4] User Properties:", properties);
}
}
// 設定 User ID
function setUserId(userId: string | null) {
if (!window.gtag) return;
window.gtag("config", measurementId, {
user_id: userId,
});
if (debug) {
console.log("[GA4] User ID:", userId);
}
}
// 追蹤購買事件
function trackPurchase(params: PurchaseParams) {
trackEvent("purchase", params as unknown as EventParams);
}
// 追蹤加入購物車
function trackAddToCart(item: EcommerceItem, currency = "TWD") {
const value = (item.price || 0) * (item.quantity || 1);
trackEvent("add_to_cart", {
currency,
value,
items: [item],
} as unknown as EventParams);
}
onMounted(() => {
initGtag();
});
return {
isReady,
trackEvent,
trackPageView,
setUserProperties,
setUserId,
trackPurchase,
trackAddToCart,
};
}7.3 元件中使用
<script setup lang="ts">
import { useGA4 } from "@/composables/useGA4";
import { useRouter } from "vue-router";
const { trackEvent, trackPageView, setUserId } = useGA4({
measurementId: "G-XXXXXXXXXX",
debug: import.meta.env.DEV,
});
const router = useRouter();
// 路由變化時追蹤頁面
router.afterEach((to) => {
trackPageView(to.fullPath);
});
// 使用者登入後設定 ID
function onLogin(userId: string) {
setUserId(userId);
trackEvent("login", { method: "email" });
}
// 按鈕點擊追蹤
function onCtaClick() {
trackEvent("cta_click", {
button_text: "立即購買",
button_location: "hero_section",
});
}
</script>
<template>
<button @click="onCtaClick">立即購買</button>
</template>7.4 全域提供
// plugins/ga4.ts (Vue 3)
import { useGA4 } from "@/composables/useGA4";
import type { App, InjectionKey } from "vue";
import type { UseGA4Return } from "@/types/useGA4";
export const GA4_KEY: InjectionKey<UseGA4Return> = Symbol("ga4");
export function setupGA4(app: App, measurementId: string) {
const ga4 = useGA4({
measurementId,
debug: import.meta.env.DEV,
});
app.provide(GA4_KEY, ga4);
}
// 在子元件中使用
// const ga4 = inject(GA4_KEY)八、 技術實務與相容性
8.1 瀏覽器支援
GA4(gtag.js)支援所有現代瀏覽器。對於不支援 JavaScript 的環境,可使用 Measurement Protocol 進行伺服器端追蹤。
8.2 Cookie 與隱私
// 預設拒絕追蹤(GDPR 合規)
gtag("consent", "default", {
analytics_storage: "denied",
ad_storage: "denied",
});
// 使用者同意後更新
gtag("consent", "update", {
analytics_storage: "granted",
ad_storage: "granted",
});8.3 效能考量
// 避免阻塞載入
gtag("config", "G-XXXXXXXXXX", {
transport_type: "beacon", // 使用 navigator.sendBeacon
});8.4 錯誤處理
function safeTrackEvent(eventName: string, params?: EventParams) {
try {
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", eventName, params);
}
} catch (error) {
console.error("[GA4] 追蹤事件時發生錯誤:", error);
}
}總結
| 概念 | 說明 |
|---|---|
gtag() | Google Tag 核心 API 函式 |
config | 配置 GA4 測量 ID |
event | 傳送事件資料 |
set | 設定全域參數 |
| User Properties | 使用者屬性區隔 |
| Ecommerce Events | 電商追蹤事件 |
| Debug Mode | 即時偵錯模式 |
TIP
最佳實踐:
- 在開發環境中啟用
debug_mode進行測試 - 使用建議事件名稱以獲得更好的報表支援
- 將 GA4 封裝為 Composable 提供類型安全
- 實作 Consent Mode 以符合隱私法規
進階挑戰
- 實作一個自動追蹤所有連結點擊的 Vue 指令(
v-track-click) - 結合 Measurement Protocol 實作伺服器端追蹤
- 建立一個 A/B 測試框架,將實驗資料傳送至 GA4