Skip to content

feat: migrate managed analytics to GA4 - #9

Merged
xiongxz merged 2 commits into
mainfrom
codex/ga4-analytics-templates
Sep 7, 2026
Merged

feat: migrate managed analytics to GA4#9
xiongxz merged 2 commits into
mainfrom
codex/ga4-analytics-templates

Conversation

@xiongxz

@xiongxz xiongxz commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • replace the managed browser analytics integration in all 14 template projects with GA4 gtag.js
  • prefer runtime gaMeasurementId, with framework-specific environment fallbacks for standalone production builds
  • track sanitized initial and SPA page views, preserve helper compatibility, and map conversion helpers to recommended GA4 event names
  • remove replay support, browser/server legacy SDK dependencies, and ai-pdf server-side analytics calls
  • update environment examples, analytics documentation, lockfiles, and the repository analytics contract check

Verification

  • node scripts/check-analytics.mjs (14 templates)
  • npm run validate --prefix scripts (14 templates)
  • npm test --prefix scripts (23/23)
  • npm test --prefix ai-pdf-chatbot (18/18)
  • npm test --prefix landing (7/7)
  • all available template typechecks
  • production builds for all 14 template projects
  • git grep -in posthog returns no matches

Known baseline issue

npm test --prefix insight-flow-agent-chat reports one suite import failure because the existing src/lib/insforge.ts reads window in the Node test environment. The same command and error were reproduced from clean origin/main; this PR does not modify that file. The other 7 assertions pass.

@xiongxz

xiongxz commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator Author

Review(首轮,head d6ebb73

结论:无 P1;一条跨仓 P2(SPA page_view 双计,需与平台侧二选一),其余 P3。 本地:node scripts/check-analytics.mjs 14/14、scripts vitest 23/23;14 份 analytics.ts 两两 diff 一致(Next 版与 Vite 版仅分号和 env 读法差异)。

P2(跨仓)— SPA 路由切换 page_view 双计

平台通过 Admin API 建的 Web Data Stream,增强衡量默认开启且 pageChangesEnabled 默认为开(history pushState/replaceState/popstate 自动发 page_view)。本 PR 的 installNavigationTracking 又在同样的三个钩子上手动发 page_viewgtag('config', id, {send_page_view:false}) 只压掉 config 那一次初始 page_view,压不掉增强衡量的 history page_view。结果每次前端路由切换两条 page_view。

两个修法只能留一个:平台侧 ensureWebStream 后关掉 pageChangesEnabled(我在 insforge-platform#86 建议的做法,模板不用动);或者模板侧删掉手动 SPA 上报、只保留初始 page_view 并把 page_location 交给增强衡量。建议前者:增强衡量的自动 page_view 会带完整 page_location(含 query),和本 PR 精心做的去 query/fragment 脱敏相冲突。

P3

  • P3-1 别名表把普通表单升格成转化事件EVENT_ALIASES.form_submitted → generate_leadformSubmitted() 也直接 track('generate_lead'),而平台把 generate_lead 注册为 Key Event。当前 14 个模板里没有调用者(只有 ai-pdf 用 loginCompleted/signUpCompleted),所以今天无害;但 ANALYTICS.md 写着 "Legacy event names ... are mapped",模板作者用 formSubmitted 上报搜索框/待办新增这类表单,就会灌进转化。建议 form_submitted 保持普通 form_submit,单独给一个 leadSubmitted() 语义 helper 才发 generate_lead
  • P3-2 page_title 取值时机:pushState 后 queueMicrotask(trackPageView),Next app router 更新 document.title 在导航完成之后,多数情况下拿到的是上一页标题。用 requestAnimationFrame/setTimeout(0) 或干脆不发 page_title(增强衡量会自己带)。
  • P3-3 大陆可达性googletagmanager.com 在大陆不可达,事件会永远堆在 dataLayer 里(无害但为 0)。若目标用户在国内,这是产品决定而不是实现问题,只希望有意识。
  • P3-4 content/query/name 的 PII 键规则会误杀(^|_)(name|content|query)(_|$) 会丢掉 content_typequery_lengthtemplate_name 这类无 PII 的键。可以接受(宁可漏报),但 ANALYTICS.md 里列一下被拦的键名,省得模板作者以为没上报是 bug。

已核实

  • lockfile 变更只有 posthog 依赖树移除(posthog-js@posthog/*fflatepreactweb-vitals* 等)和 @tailwindcss/oxide-wasm32-wasi 子依赖重解析,没有夹带其他升级。
  • .well-known/insforge-runtime-config.js 的同步加载顺序、Next 的 DOMContentLoaded 兜底、Vite 的 vite-ignore 都保留;check-analytics.mjs 仍钉住这些。
  • ai-pdf-chatbot 六个 route 的 posthog-node 调用与 lib/posthog-server.ts 一起删干净,无残留 import;两个客户端组件改走 analytics.track
  • identify 只收不透明 user id 且拒绝邮箱形态;purchasetransaction_id/value/currency,符合 GA4 推荐事件最小字段。
  • Known baseline issue(insight-flow-agent-chat 的 window 读取)确认在 main 上同样存在。

@xiongxz

xiongxz commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

已在 d50b9bd 处理本轮 review:

  • P2 双计由 platform #86 统一解决:Provisioning 关闭 GA4 pageChangesEnabled;模板继续手工发送去 query/fragment 的 SPA page_view。
  • 普通 formSubmitted 和 legacy form_submitted 现在上报 form_submit,不再误记为 Key Event;新增显式 leadSubmitted helper 才发送 generate_lead。14 个模板及契约检查全部同步。
  • SPA 路由上报从 queueMicrotask 改为 requestAnimationFrame,并保留 setTimeout fallback,让目标页 title 有机会先完成渲染。
  • ANALYTICS.md 明确列出 name/content/query 分词规则可能误杀的安全字段,这是有意识的 privacy-first 取舍。
  • 文档补充 googletagmanager.com 在中国大陆可能不可达、事件为 0 的产品风险。

验收:14/14 analytics contract、scripts vitest 23/23、Next.js 与 Vite 代表模板生产构建均通过。

@xiongxz

xiongxz commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Review 二轮(head d50b9bd

结论:LGTM,可合。 首轮唯一的 P2(SPA page_view 双计)已由 platform#86 在建流时关掉 pageChangesEnabled 解决,模板保留脱敏后的手工 SPA page_view 是正确的一侧;四条 P3 全部落地。

复核:

  • P3-1 form_submitted → form_submitformSubmitted() 发普通 form_submit,新增 leadSubmitted() 才发 generate_leadcheck-analytics.mjs 用三条字面量断言把这个语义钉死,ANALYTICS.md 写明 generate_lead 是 Key Event。
  • P3-2 SPA 上报改 requestAnimationFrame(无 rAF 时 setTimeout 0),契约检查同步。rAF 在后台标签页会被挂起,那种情况下 page_view 会延迟到标签页可见时才发,可接受。
  • P3-3/P3-4 文档补了大陆可达性与 name/content/query 分词误杀说明。

本地:node scripts/check-analytics.mjs 14/14、scripts vitest 23/23;14 份 helper 两两 diff 零差异(8 份 Next 版含 todo、6 份 Vite 版,两组之间只有分号/env 读法)。

三个 PR 合并顺序:platform#86 → lex-insforge#5 → 本 PR(模板依赖平台关掉增强衡量的 history page_view,否则先上模板会短暂双计)。

@xiongxz
xiongxz merged commit 643b9d7 into main Sep 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant