時隔一年後再度嘗試,發現可以在 React Router v7 的 Framework 模式順利以原生 script 標籤啟動 Google Analytics (gtag) 了 去年到底是發生了什麼呢。總之紀錄並分享一下做法。
順帶確認了可以在 clientAction 中派送 GA 事件——終於,我們可以優雅地滿足那些「我需要在購買成功、api 呼叫成功後派送 XX 成功的 GA 事件 🥺」需求了。
安裝方式
步驟:
- 以環境變數
VITE_GA_TRACKING_ID傳遞 GA 的啟動碼 - 開啟
<你的專案>/app/root.tsx並在function Layout貼上 gtag.js 提供的範例(如下);我追加了一行官方文件沒有列出的參數debug_mode(開啟後,可以在 GA 後台透過 Admin > DebugView 即時查看被派送的事件)
<> <script async src={`https://www.googletagmanager.com/gtag/js?id=${import.meta.env.VITE_GA_TRACKING_ID}`} /> <script async dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${import.meta.env.VITE_GA_TRACKING_ID}', { debug_mode: ${import.meta.env.DEV ? "true" : "false"}, }); `, }} /></>新增 script 後的 function Layout 會長得像這樣:
export function Layout({ children }: { children: React.ReactNode }) { return ( <html lang="zh-Hant"> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <Meta /> <Links /> </head> <body className="bg-gray-1"> {children} <ScrollRestoration /> <Scripts /> <script async src={`https://www.googletagmanager.com/gtag/js?id=${import.meta.env.VITE_GA_TRACKING_ID}`} /> <script async dangerouslySetInnerHTML={{ __html: ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${import.meta.env.VITE_GA_TRACKING_ID}', { debug_mode: ${import.meta.env.DEV ? "true" : "false"}, }); `, }} /> </body> </html> );}完成。就這樣。你可以在整個 React Router v7 app 中透過 gtag('event', '<event_name>', {<event_params>}) 派送 GA 事件了。
在 clientAction 派送 GA 事件
在 clientAction 派送事件的話,可以避免重整畫面造成的重複派送,也能運用 action 回傳的資料。可參考以下範例。
import { type ActionFunctionArgs, type ClientActionFunctionArgs, Form, redirect } from 'react-router';
export async function loader() { return null;}
export async function action({ request }: ActionFunctionArgs) { const form = await request.formData(); const test = form.get('test') as string; // do something... const result = await db.doSomething({ ...test }); return { test, result };}
export async function clientAction({ serverAction }: ClientActionFunctionArgs) { const data = await serverAction<typeof action>(); window.gtag('event', 'some_ga_event', { ...data }); return redirect('/test-b');}
export default function TestA() { return ( <Form method="post"> <input type="text" name="test" /> <button type="submit">Submit</button> </Form> );}這段程式碼在做的事情是:
- 當使用者送出表單後,在
action階段進行一些處理 - 接下來,透過
clientAction的serverAction參數取得action階段取得的資料——這些資料會成為 GA 事件的參數 - 透過
window.gtag('event', 'some_ga_event', { ...data })派送事件 - 將使用者導向路由
/test-b