TapCub 正式上线:统计、分析、客服一个平台免费用
数据分析

服务端埋点:哪些事件该从服务端发,哪些不该

服务端埋点适合做什么、不适合做什么,怎样在浏览器和服务端之间分配事件,以及如何在不重复计数的前提下保留会话和来源。

陈屿 发布于 2026 年 11 月 3 日 5 分钟阅读 数据分析
示例埋点方案。行为从浏览器发,结果从服务端发,不要两边都发。示例数据

服务端埋点常被宣传成找回丢失数据的办法。更准确的理解是:它是某些事件该去的地方,也就是你的服务器本来就知道的那些已确认结果。本文区分这个词的两种含义,给出浏览器和服务端之间的混合分配,并讲清怎样保留来源和会话、又不重复计数。

读完你会知道

  • 行为从浏览器发,已确认的结果从服务端发,同一个事件不要两边都发
  • 服务端埋点不会改变同意义务,也不是绕开拦截的手段
  • 把浏览器里的来源和会话传给服务端,并给服务端事件一个唯一标识

服务端埋点的两种含义

「服务端埋点」指的是两种不同的做法:

  1. 服务端标记(server-side tagging)。浏览器照样发数据,只是不直接发给各个厂商,而是先发到你自己控制的服务器,再由它转发。Google 跟踪代码管理器的服务器容器就是这样工作的(Google:服务端标记)。
  2. 后端事件。你的应用服务器自己发送它直接知道的事件:订单已支付、订阅已续费、通过 API 创建了账户。

两者都把工作从浏览器挪走了,但解决的问题不同。本文主要讲第二种,可靠性的提升也主要在这里。

适合做什么,不适合做什么

服务端埋点适合:

  • 已确认的结果。付款、续费、退款、注册都发生在服务端。从服务端发,就不会因为「感谢页」没加载而丢失,也不会因刷新而重复;见收入埋点。
  • 没有浏览器参与的事件。API 调用、后台任务、回调、发出的邮件。
  • 数据可控。你能精确决定哪些字段离开你的系统,这和第一方数据策略一致。

它不是绕开同意或广告拦截的办法。同意的要求取决于你收集什么、为什么收集,与请求从哪里发出无关。论坛上对「服务端埋点能找回丢失数据」的说法多有质疑,对这种说法要谨慎。服务端事件本身也看不到浏览器里的行为:滚动、点击、页面浏览和会话属于浏览器。

在浏览器和服务端之间分配事件

混合方案让每个事件从最清楚它的地方发出。示例是一个 SaaS 产品的典型分配。经验法则:行为从浏览器发,结果从服务端发,同一个事件永远不要两边都发。

app.tapcub.com/settings/tracking-plan

每个事件从哪里发

SaaS 示例方案
事件浏览器服务端原因
页面浏览、会话是否只有浏览器看得到页面跳转
点击、滚动、开始填表是否页面上的行为
signup_completed否是账户在服务端创建后才存在
purchase、refund否是付款由支付渠道确认
feature_used(产品内)是都可以看动作在哪边最容易观察
subscription_renewed否是没有浏览器参与
示例数据
示例埋点方案。行为从浏览器发,结果从服务端发,不要两边都发。

前端埋点和服务端埋点对比

下表对比两者在决定事件归属时最常考虑的几点。整体上谈不上哪个更好,每个事件的答案不一样。

前端(浏览器)服务端
能看到页面浏览、点击、会话能不能,除非从浏览器传过来
付款和注册的可靠性页面提前关闭会丢,刷新会重复确认时只发一次
来源和 UTM自动获得必须从浏览器传过来
受拦截插件影响会后端事件不会
同意要求适用同样适用
工作量脚本标签加事件每个事件写后端代码

按事件选择,而不是按公司选择。

让服务端事件带上来源和会话

服务端事件本身没有来源页、没有 UTM 参数、也没有会话。如果不把它们传过去,从服务端发的注册看起来就像凭空出现,所有归因报表都会把它算成直接访问。

办法是在浏览器里拿到来源,随表单或订单发给后端,再放进服务端事件。示例展示了在 TapCub 里的做法:浏览器端调用 getAttribution(),服务端事件里原样放进 context.campaign。同时带上访客或会话标识,让服务端事件并入浏览器会话;再用你的用户 ID 调用 identify,之后两边的事件就都归到同一个人。

signup.js浏览器 → 服务端
// 浏览器:脚本标签带 data-attribution
const source = tapcub.getAttribution();
await fetch("/api/signup", {
  method: "POST",
  body: JSON.stringify({ email, password, source })
});

// 服务端:账户创建之后
await track({
  type: "track_signup",
  event: "signed_up",
  login_id: user.id,
  insert_id: "signup_" + user.id,
  time: Date.now(),
  context: { campaign: body.source }
});

避免重复计数

  • 每个事件只有一个来源。浏览器发了 signup_completed,服务端就不要再发。在埋点方案里逐个事件定好。
  • 给服务端事件一个 ID。用订单号或记录 ID 作事件 ID,请求重试时会被忽略,而不是算两次。
  • 发真实时间。用动作发生的时间(毫秒),而不是任务执行的时间,排队或批量发送的事件尤其要注意。
  • 页面浏览留在浏览器。服务端也发页面浏览,流量会翻倍。

TapCub 里的服务端埋点

TapCub 通过 track 接口接收服务端发来的行为事件,用绑定项目的密钥鉴权。每个事件可以带 insert_id(更新和覆盖时必填)、毫秒级 time(与服务器时钟相差超过 72 小时会被改为当前时间并给出警告)和 session_id;没有会话 ID 的事件不计入会话指标。未经哈希的邮箱或手机号会先哈希再存储(见文档服务端事件)。

归因方面,浏览器脚本开启 data-attribution 后可调用 tapcub.getAttribution();把结果原样放进 context.campaign,来源、媒介、活动、点击 ID 和落地页就会保留在这个人身上。没有传来源、但事件带了 IP 和 User-Agent 时,TapCub 会在 7 天内(严格模式下仅当天)寻找同一网络、同一浏览器的访问,并把结果标记为推断。人的页面浏览应留在浏览器脚本上,TapCub 也不会尝试绕过拦截插件或「请勿追踪」(见文档 CSP 与拦截插件)。来自服务器日志的机器人流量走另一个接口,见 AI 爬虫台账。

常见问题

什么是服务端埋点?

从服务器而不是(或者同时也从)访客浏览器发送统计事件:要么把浏览器数据经过你自己的服务器转发,要么由后端直接发送它知道的事件。

服务端埋点比前端埋点好吗?

整体上没有谁更好。服务端对已确认的结果更可靠;前端是看到页面浏览、点击、会话这些浏览器行为的必经之路。

服务端埋点能绕过广告拦截和同意吗?

不应该这样用。同意规则针对的是你收集什么,不管数据从哪里发出。

服务端事件怎么保留归因?

在浏览器里拿到来源,随表单或订单发给后端,再连同访客或会话 ID 一起放进服务端事件。

怎样避免一个事件被算两次?

每个事件只从一边发送,并给服务端事件一个唯一标识(比如订单号),重试就会被忽略。

这篇文章对你有帮助吗?

我们会根据反馈修改和补充这篇内容。

陈屿

技术工程师

专注统计代码、SDK 与接口集成文档,从接入验证到问题排查,帮助开发者更顺畅地完成实施。

从服务端发送事件

带事件 ID、会话关联和浏览器归因透传的服务端事件接口,页面浏览仍由浏览器脚本采集。

看清数据,找到增长。

每一次点击,都有数据依据。装好一行代码,1 分钟看到第一批数据。

无需信用卡 · 统计与客服都有免费版 · 统计无 Cookie