const m = document.cookie.match(/_ga=GA\d\.\d\.(\d+\.\d+)/);
const cid = m && m[1];
fetch('/api/order', { method: 'POST', body: JSON.stringify({ cid, orderId }) });
// 服务端 POST /mp/collect?measurement_id=G-XXX&api_secret=YYY 时带上 client_id

订单在服务端完成后用 Measurement Protocol 补一条 purchase,GA4 里能收到事件,来源渠道整列却是 direct,和客户端那条对不上。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:Measurement Protocol 的请求必须带 client_id 或 user_id,缺了它服务端只能新建一个匿名身份,拿不到浏览器里的 _ga 会话和来源。事件进了库,归属是空的。

「Measurement Protocol client_id」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。

处理上按这个顺序:前端把 _ga cookie 里的 client_id 取出来,随下单请求一起提交到服务端;服务端补发时把 client_id 和 session_id 一起带上,别只传事件名和金额;用调试视图核对补发事件的来源和会话是否与前端一致。

确认没问题再收工,补发的 purchase 在报表里归到与前端相同的来源,direct 一行不再凭空多出订单。

作者 9823189