feat: add cloud gtm injection (#8311)

## Summary

Add GTM injection for cloud distribution builds and push SPA page view +
signup events.

## Changes

- **What**: Inject GTM script into head-prepend and noscript iframe into
body-prepend for cloud builds
- **What**: Push `page_view` to `dataLayer` on cloud route changes
(page_location + page_title)
- **What**: Push `sign_up` to `dataLayer` after successful account
creation (email/google/github)
- **Dependencies**: None

## Review Focus

- Placement order for head-prepend/body-prepend and cloud-only gating
- Route-change page_view payload shape
- Signup event emission only for new users

## Screenshots (if applicable)

<img width="1512" height="860" alt="Screenshot 2026-01-26 at 11 38
11 AM"
src="https://github.com/user-attachments/assets/03fb61db-5ca4-4432-9704-bbdcc4c6c1b7"
/>

<img width="1512" height="862" alt="Screenshot 2026-01-26 at 11 38
26 AM"
src="https://github.com/user-attachments/assets/6e46c855-a552-4e52-9800-17898a512d4d"
/>
This commit is contained in:
Benjamin Lu
2026-01-27 12:44:15 -08:00
committed by GitHub
parent 75fd4f0e67
commit 788f50834c
9 changed files with 276 additions and 2 deletions

View File

@@ -9,6 +9,7 @@ import type { RouteLocationNormalized } from 'vue-router'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { isCloud } from '@/platform/distribution/types'
import { pushDataLayerEvent } from '@/platform/telemetry/gtm'
import { useDialogService } from '@/services/dialogService'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
import { useUserStore } from '@/stores/userStore'
@@ -36,6 +37,16 @@ function getBasePath(): string {
const basePath = getBasePath()
function pushPageView(): void {
if (!isCloud || typeof window === 'undefined') return
pushDataLayerEvent({
event: 'page_view',
page_location: window.location.href,
page_title: document.title
})
}
const router = createRouter({
history: isFileProtocol
? createWebHashHistory()
@@ -93,6 +104,10 @@ installPreservedQueryTracker(router, [
}
])
router.afterEach(() => {
pushPageView()
})
if (isCloud) {
const { flags } = useFeatureFlags()
const PUBLIC_ROUTE_NAMES = new Set([