From fd3ffc8bc2415cafc254960aba5449bf22c6c2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Fri, 18 Sep 2026 18:06:59 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E9=98=B6=E6=AE=B5B=20spec=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E5=A4=8D=E5=AE=A1=E4=BF=AE=E6=AD=A3=E2=80=94=E2=80=94?= =?UTF-8?q?fb+paid=E4=BC=98=E5=85=88=E8=A7=84=E5=88=99(=E5=AE=9E=E6=B5=8B?= =?UTF-8?q?=E4=B8=BB=E5=AF=BC=E6=A8=A1=E5=BC=8F)/=5Fctk=5Fsid=E5=8E=9F?= =?UTF-8?q?=E7=94=9Fsubmit=E6=8D=95=E8=8E=B7/=E4=BA=A7=E5=93=81=E6=AE=B5?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E9=9D=9E=E9=94=9A=E5=AE=9A/=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E8=A1=A5=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Code --- .../specs/2026-09-18-collection-phase-b-design.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/superpowers/specs/2026-09-18-collection-phase-b-design.md b/docs/superpowers/specs/2026-09-18-collection-phase-b-design.md index f8dc064..40acb7f 100644 --- a/docs/superpowers/specs/2026-09-18-collection-phase-b-design.md +++ b/docs/superpowers/specs/2026-09-18-collection-phase-b-design.md @@ -2,7 +2,7 @@ 日期:2026-09-18 分支:m1 -状态:设计已获用户批准(含三轮自审 21 项修正) +状态:设计已获用户批准(四轮自审+独立复审,共 28 项修正) 依据:gpt/14 §5/§6.2;前置阶段A 已上线(2026-09-18,归属冻结/区间停留/清洗三轨制/契约 v2) 实测基础:hesucar.com 载体盘点(2026-09-18 Playwright)——tel/mailto/wa.me 链接、Contact Form 7 v6.1.6 留言表单(Name/Tel/Message→Inquiry Now)、悬浮聊天组件 @@ -43,7 +43,7 @@ ### 1.3 product_view -- 规则:path 匹配 `/product/{slug}/`(pattern 内置默认,init 可覆盖——为未来站点预留,hesucar 用默认)。 +- 规则:path **段匹配** `product/{slug}`(**非锚定**——覆盖 `/{lang}/product/{slug}/` 多语言前缀;实测样本 9 种语言前缀 ar/de/es/fr/it/pt/ro/ru/th,锚定匹配会静默丢失约半数产品页);pattern 内置默认,init 可覆盖——为未来站点预留,hesucar 用默认。 - 属性:`{product_id: slug, inferred: true, rule_version: "v1"}`。多语言同产品无法关联——诚实标注(inferred 降级路径,gpt/14 §5.1)。 - **触发时机**:init 时同步判定 + SPA 切段回调。PageSession 新增 `onSegmentChange(fn)` 钩子——**触发点钉死在 `onRouteChange` 内新段创建之后**(模块级注册表,不在 `close()` 内触发——close 还覆盖 pagehide/重复 init,放在那里会在卸载时重复发 product_view);单点 hook history,business.ts 注册回调判定新段 path,不重复 wrap。 - PV 不双计:服务端 PV 统计已有 event_name 过滤(87261ab)。 @@ -55,21 +55,22 @@ ### 1.5 隐藏字段 `_ctk_sid`(服务端确认契约预留的浏览器侧半边) -- form_start 时向表单注入 ``(**空占位**——不用预生成 ID:若 submit 时更新对 CF7 FormData 不可见,空值=干净缺失,预生成 ID 则阶段C 会收到匹配不到任何事件的孤儿确认,更糟);form_submit 事件触发时更新该字段为当次 submission_id(更新可见性以 CF7 源码核验为准,不可靠则该次对齐缺失)。 +- **submission_id 写入时序(结构性修正)**:`wpcf7submit` 在 AJAX 响应到达后才触发——POST 已发出,届时更新字段必然晚。因此改为:**capture 阶段监听表单原生 `submit` 事件**(document 级 capture 委托,先于 CF7 的 handler 构造 FormData 执行)——原生 submit 时生成当次 submission_id 并写入隐藏字段;wpcf7submit 触发的 form_submit 事件引用同一 ID。 +- form_start 时注入 `` 空占位(提交前字段恒存在;值由上述 submit 捕获填充)。 - 作用:CF7 提交 POST 天然携带,阶段C 的 WP mu-plugin 从 `$_POST['_ctk_sid']` 读取对齐。CF7 忽略未注册字段、正常传输——对现有表单行为无害。 -- known-limitation:无任何交互直接提交的极端场景,submission_id 可能为空(事件与漏斗不受损,仅确认对齐缺失)。 +- known-limitation:`_ctk_sid` 空值仍可能出现(capture submit 未及触发的极端时序),阶段C 按 §5.4 兜底(浏览器侧缺失不影响服务器事实)。 ## 2. Server:契约扩展 - `EVENT_NAMES` +6:contact_click / form_start / form_error / form_submit / form_submit_result / product_view。 - `EVENT_PROP_WHITELIST` 严格枚举(§1 表格所列键;无自由文本字段)。 -- validate_event 新键校验:`channel` ∈ {whatsapp, phone, email};`result_code` ∈ {mail_sent, mail_failed};`error_code` 短枚举(invalid/spam/other);`submission_id` uuid 或空串;`form_id` 格式 `cf7-\d+`;`product_id` slug 格式(复用清洗 `_SAFE_VALUE` 同款正则);`inferred` 布尔;`rule_version` 短 slug。 +- validate_event 新键校验:`channel` ∈ {whatsapp, phone, email};`result_code` ∈ {mail_sent, mail_failed};`error_code` 短枚举(invalid/spam/other);`submission_id` uuid 或空串;`form_id` 格式 `cf7-\d+`;`product_id` slug 格式(**≤100 字符**——独立于清洗 _SAFE_VALUE 的 31 上限,产品 slug 可较长);`field_count` 非负整数(≤99);`inferred` 布尔;`rule_version` 短 slug。 - 幂等沿 uq_site_event;归属走既有 v2 路径,零新机制。 ## 3. D06 归因扩展(attribution.py + constants.py) - **优先级重排**:点击参数决定平台性质——fbclid → **paid_social**(Meta 平台本质),gclid/msclkid/yclid → paid_search;utm_medium 仅在无点击参数时参与判定(label_only 证据)。 -- `CHANNELS` +`paid_social`;utm_medium 规范化映射(写死):paid_search 强化集 {cpc, ppc, paidsearch, paid}、paid_social 判定集 {social, paid_social, social_ads, paidsocial}(需同时有 fb 家族 utm_source)。 +- `CHANNELS` +`paid_social`;utm_medium 规范化映射(写死):**fb 家族 utm_source + 任意付费类 medium(cpc/ppc/paidsearch/paid/social/paid_social/social_ads/paidsocial)→ paid_social,此规则优先于强化集**(实测样本主导模式即 `utm_medium=paid&utm_source=fb`,gpt/14 §6.1 的 28 条 fb/paid——不放本规则则它们仍全落 paid_search,违背本节目的);其余付费 medium(无 fb source)→ paid_search 强化(label_only 证据)。 - **`ATTRIBUTION_RULE_VERSION` bump v1→v2** + 历史重算:`recompute_attribution` 管理命令**已存在**(management/commands/recompute_attribution.py,含 --site 参数与既有幂等测试 test_attribution.py:226 可参照),本任务只需 bump 版本 + 新渠道分支测试 + 线上重算执行。 - fb 家族 utm_source 判定复用既有广告家族归一表(132e2fe 引入的家族映射)。 - admin 中文标签同步:付费社交(渠道徽章/来源分布,grep 全部渠道显示点统一改)。 @@ -83,7 +84,7 @@ ### 4.2 询盘漏斗卡(数据总览) -- 五级:浏览(page_view) → 咨询点击 → 表单开始 → 提交 → 邮件已发(**显示措辞"邮件已发(未验证)"**——客户端声明的诚实边界)。 +- 五级:浏览(page_view) → 咨询点击 → 表单开始 → 提交 → 邮件已发(**显示措辞"邮件已发(未验证)"**——客户端声明的诚实边界)。首级用 page_view 而非上游文档的 product_view:product_view 为 inferred 推导会低漏计,page_view 是全量基线(偏离理由留档)。 - **口径:逐级独立 distinct session 计数**(各级 Count("session", distinct=True)),**非严格嵌套漏斗**——允许跳级真实路径(gpt/14 §5.4"允许直接进入表单");各级数字不嵌套,**UI 不显示级间百分比转化率**(避免嵌套误读),只显示各级计数。 - **全级过滤 `is_bot=False`**(Event.is_bot 既有标记——爬虫浏览/垃圾提交不灌漏斗)。 - 当日/近 7 天切换;新 API `GET /api/admin/funnel-summary?days=N`(site 权限沿既有)。