ping属性是浏览器原生的轻量级点击追踪机制,仅在href合法、用户真实点击且目标支持text/ping时触发一次性post请求,发送固定字符串“ping”,不支持参数,safari完全不支持,chrome限制第三方上下文。

ping 属性根本不会在所有浏览器里发请求
Chrome 和 Firefox 会尝试发,Safari 完全不支持(截至 2026 年 5 月仍无实现计划),Edge 虽支持但默认受限于第三方上下文。你写上 ping 属性,不代表请求一定发出——它像一个条件极苛刻的自动触发器,缺一不可。
常见失效表现:Network 面板里压根看不到请求、控制台零报错、后端日志收不到任何 text/ping 流量。这不是 bug,是规范行为。
- 必须用合法
href:不能是javascript:void(0)、#、空字符串或伪协议 - 必须用户真实点击:
link.click()、@click.prevent拦截后再router.push,全部绕过ping - 必须目标服务响应头含
Access-Control-Allow-Origin(哪怕只是*),否则静默丢弃 - HTTP 环境下 Chrome 94+ 直接禁用,不警告、不记录——只在 HTTPS 页面生效
ping 发出去的请求到底长什么样
它不是 fetch,不是 XHR,也不是你熟悉的表单提交。浏览器发的是一个极简 POST,固定内容、固定头、零自定义空间。
- 请求方法:
POST -
Content-Type头一定是text/ping(注意不是text/pingback,后者是 WordPress 协议) - 请求体只有字符串:
PING(全大写,无换行,无 JSON,无 query) - 带两个关键头:
PING-FROM(当前页完整 URL)、PING-TO(href值) - 同源时自动携带 Cookie;跨域时不带,但
PING-FROM仍完整暴露当前页地址(含 query 和 hash)
这意味着你没法塞 utm_source、用户 ID 或事件上下文——它只适合“这个 banner 被点了几次”,不适合“谁在什么状态下点了哪条推广链接”。
后端怎么安全接收 ping 请求
别直接写个 POST /ping 就完事。攻击者能伪造 PING-FROM 头,也能批量生成恶意链接诱导点击,你的 endpoint 很可能变成 DDoS 中转站或 SSRF 入口。
- 必须校验
Content-Type: text/ping,拒绝text/pingback、application/json等变体 - 必须解析并白名单校验
PING-FROM值:禁止内网地址(如http://192.168.1.1)、禁止非 HTTP(S) 协议 - 必须限速:单 IP 每分钟 ≤ 3 次,超限返回
429 Too Many Requests,且不返回 body - 建议记录
PING-FROM和PING-TO到独立日志,和主业务流量隔离,便于审计
企业内网页面若嵌了外部广告,而广告链接带 ping 指向第三方,PING-FROM 会直接泄露内网路径,这是真实发生过的信息泄漏面。
什么时候该放弃 ping,改用 sendBeacon
只要你需要以下任意一项,就别碰 ping:传参数、要成功率保障、兼容 Safari、需错误回调、埋点不可丢。
navigator.sendBeacon() 是更可控的选择,虽然要写 JS,但它允许你:
- 发送任意格式 payload(
new Blob([jsonStr], {type: 'application/json'})) - 在
beforeunload或visibilitychange时仍尽力发出 - 配合重试逻辑(比如失败后存 localStorage,下次启动再补发)
- 统一走业务鉴权流程,不额外开新 endpoint
真正上线后发现 ping 没数据?先查是不是 HTTPS、是不是 Safari 用户、是不是后端漏了 CORS 响应头——而不是怀疑代码写错了。它的限制不是缺陷,而是设计前提。











