diff --git a/src/components/GoogleAnalytics.tsx b/src/components/GoogleAnalytics.tsx
new file mode 100644
index 00000000..fd12f674
--- /dev/null
+++ b/src/components/GoogleAnalytics.tsx
@@ -0,0 +1,37 @@
+'use client'
+
+import { useEffect } from 'react'
+
+declare global {
+ interface Window {
+ dataLayer: unknown[]
+ gtag: (...args: unknown[]) => void
+ }
+}
+
+function GoogleAnalyticsInit({ id }: { id: string }) {
+ useEffect(() => {
+ if (typeof window.gtag !== 'undefined') return
+
+ window.dataLayer = window.dataLayer || []
+ window.gtag = function gtag() {
+ // biome-ignore lint/complexity/noArguments: gtag API requires arguments object
+ window.dataLayer.push(arguments)
+ }
+ window.gtag('js', new Date())
+ window.gtag('config', id)
+
+ const script = document.createElement('script')
+ script.async = true
+ script.src = `https://www.googletagmanager.com/gtag/js?id=${id}`
+ document.head.appendChild(script)
+ }, [id])
+
+ return null
+}
+
+export default function GoogleAnalytics() {
+ const id = import.meta.env.VITE_GA_MEASUREMENT_ID
+ if (!id) return null
+ return
+}
diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx
index c45a1050..6b37fb56 100644
--- a/src/pages/_layout.tsx
+++ b/src/pages/_layout.tsx
@@ -4,6 +4,7 @@ import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/react'
import type React from 'react'
import { Toaster } from 'sonner'
+import GoogleAnalytics from '../components/GoogleAnalytics'
import PostHogSetup from '../components/PostHogSetup'
export default function Layout(
@@ -29,6 +30,7 @@ export default function Layout(
/>
+
>
)
diff --git a/vocs.config.ts b/vocs.config.ts
index 82c5ae11..9ebdd607 100644
--- a/vocs.config.ts
+++ b/vocs.config.ts
@@ -1,9 +1,6 @@
-import { createElement, Fragment } from 'react'
import { Changelog, defineConfig, McpSource } from 'vocs/config'
import { createFeedbackAdapter } from './src/lib/feedback-adapter'
-const gaMeasurementId = process.env.VITE_GA_MEASUREMENT_ID
-
const baseUrl = (() => {
if (URL.canParse(process.env.VITE_BASE_URL)) return process.env.VITE_BASE_URL
// VERCEL_BRANCH_URL is the stable URL for the branch (e.g., next.docs.tempo.xyz)
@@ -16,21 +13,6 @@ const baseUrl = (() => {
})()
export default defineConfig({
- head: gaMeasurementId
- ? createElement(
- Fragment,
- null,
- createElement('script', {
- async: true,
- src: `https://www.googletagmanager.com/gtag/js?id=${gaMeasurementId}`,
- }),
- createElement('script', {
- dangerouslySetInnerHTML: {
- __html: `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','${gaMeasurementId}');`,
- },
- }),
- )
- : undefined,
changelog: Changelog.github({ prereleases: true, repo: 'tempoxyz/tempo' }),
// TODO: Set back to true once tempoxyz/tempo#tip-1011 dead link is fixed
checkDeadlinks: 'warn',