mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-14 17:37:46 +00:00
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:
@@ -6,6 +6,7 @@ import {
|
||||
useFirebaseAuthStore
|
||||
} from '@/stores/firebaseAuthStore'
|
||||
import type { TierKey } from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
import { startSubscriptionPurchaseTracking } from '@/platform/cloud/subscription/utils/subscriptionPurchaseTracker'
|
||||
import type { BillingCycle } from './subscriptionTierRank'
|
||||
|
||||
type CheckoutTier = TierKey | `${TierKey}-yearly`
|
||||
@@ -78,6 +79,7 @@ export async function performSubscriptionCheckout(
|
||||
const data = await response.json()
|
||||
|
||||
if (data.checkout_url) {
|
||||
startSubscriptionPurchaseTracking(tierKey, currentBillingCycle)
|
||||
if (openInNewTab) {
|
||||
window.open(data.checkout_url, '_blank')
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import type { TierKey } from '@/platform/cloud/subscription/constants/tierPricing'
|
||||
import type { BillingCycle } from './subscriptionTierRank'
|
||||
|
||||
type PendingSubscriptionPurchase = {
|
||||
tierKey: TierKey
|
||||
billingCycle: BillingCycle
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'pending_subscription_purchase'
|
||||
const MAX_AGE_MS = 24 * 60 * 60 * 1000 // 24 hours
|
||||
const VALID_TIERS: TierKey[] = ['standard', 'creator', 'pro', 'founder']
|
||||
const VALID_CYCLES: BillingCycle[] = ['monthly', 'yearly']
|
||||
|
||||
const safeRemove = (): void => {
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEY)
|
||||
} catch {
|
||||
// Ignore storage errors (e.g. private browsing mode)
|
||||
}
|
||||
}
|
||||
|
||||
export function startSubscriptionPurchaseTracking(
|
||||
tierKey: TierKey,
|
||||
billingCycle: BillingCycle
|
||||
): void {
|
||||
if (typeof window === 'undefined') return
|
||||
try {
|
||||
const payload: PendingSubscriptionPurchase = {
|
||||
tierKey,
|
||||
billingCycle,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload))
|
||||
} catch {
|
||||
// Ignore storage errors (e.g. private browsing mode)
|
||||
}
|
||||
}
|
||||
|
||||
export function getPendingSubscriptionPurchase(): PendingSubscriptionPurchase | null {
|
||||
if (typeof window === 'undefined') return null
|
||||
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY)
|
||||
if (!raw) return null
|
||||
|
||||
const parsed = JSON.parse(raw) as PendingSubscriptionPurchase
|
||||
if (!parsed || typeof parsed !== 'object') {
|
||||
safeRemove()
|
||||
return null
|
||||
}
|
||||
|
||||
const { tierKey, billingCycle, timestamp } = parsed
|
||||
if (
|
||||
!VALID_TIERS.includes(tierKey) ||
|
||||
!VALID_CYCLES.includes(billingCycle) ||
|
||||
typeof timestamp !== 'number'
|
||||
) {
|
||||
safeRemove()
|
||||
return null
|
||||
}
|
||||
|
||||
if (Date.now() - timestamp > MAX_AGE_MS) {
|
||||
safeRemove()
|
||||
return null
|
||||
}
|
||||
|
||||
return parsed
|
||||
} catch {
|
||||
safeRemove()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function clearPendingSubscriptionPurchase(): void {
|
||||
if (typeof window === 'undefined') return
|
||||
safeRemove()
|
||||
}
|
||||
Reference in New Issue
Block a user