跳转到内容

Web 指标

托管版 Agent Analytics 把 cwv_* 存在 page_view 上。自行托管的 core 把同样的键存在 $web_vitals 事件上。托管版不存储 $web_vitals。

POST /vitals 和 GET /vitals 是托管读取。事件固定为 page_view。

data-track-vitals="true" 打开采集。data-track-vitals="false" 关闭采集。默认安装片段包含 data-track-vitals="true"。省略该属性的片段保持关闭。已经 opt-in 的安装保持原来的开关含义。

在托管版上,每次 flush 合并进同一 session、同一 path 最新的 page_view。后一次 flush 覆盖这些键。随 vitals 发送的 path 是该页开始时捕获的 path。

data-track-performance 仍然把 perf_ttfb 写在 page_view 上,值为 responseStart - requestStart。它不是 cwv_ttfb。

标题数字是页面加载的第 75 百分位 (p75)。方法是 nearest-rank:按值升序排序,用 event id 打破并列,取排名 ceil(0.75 * n)。排名 1 是最小值。结果是一个观测到的值。

指标 Property 单位 定义
LCP cwv_lcp ms,整数 Largest Contentful Paint。页面在 first paint 之前处于 hidden 时省略。
INP cwv_inp ms,整数 Interaction to Next Paint。event 条目按 interactionId 分组。每次交互取最大 duration。INP 是每 50 次交互忽略一次最高值之后最差的那次交互。
CLS cwv_cls 无单位,3 位小数 Cumulative Layout Shift。最大 session window:间隔小于 1 秒,窗口最长 5 秒,排除带 hadRecentInput 的 shift。
FCP cwv_fcp ms,整数 First Contentful Paint。页面在 first paint 之前处于 hidden 时省略。
TTFB cwv_ttfb ms,整数 Time to First Byte。导航的 responseStart - max(activationStart, 0),从 navigation start 起算。

经过 prerender 的页面不会被跟踪。

Core Web Vitals 是 LCP、INP 和 CLS。FCP 和 TTFB 是这次读取里的另外两个指标。定义和阈值遵循 Web Vitals。

值 <= good_max 为 good,> poor_min 为 poor,否则为 needs-improvement。p75 的评级把同一规则用在 p75 上。share 把同一规则用在每一次页面加载上。份额是 0 到 1 的分数,保留 3 位小数。share 的键是 good、needs_improvement 和 poor。评级字符串用连字符 (needs-improvement)。share 的键用下划线 (needs_improvement)。

指标 单位 Good Needs improvement Poor
LCP ms <= 2500 <= 4000 > 4000
INP ms <= 200 <= 500 > 500
CLS 无单位 <= 0.1 <= 0.25 > 0.25
FCP ms <= 1800 <= 3000 > 3000
TTFB ms <= 800 <= 1800 > 1800

cwv_pass 只用 LCP、INP 和 CLS。当 LCP、INP、CLS 的 p75 都是 good 时为 true。INP 的 n 为 0 时,只根据 LCP 和 CLS 判断。LCP 的 n 为 0 或 CLS 的 n 为 0 时,cwv_pass 为 null。

CLS 和 INP 只在 Chromium 中采集。其他浏览器上该键不存在。不会存成 0。

浏览器报告了对应条目时才写入 LCP、FCP 和 TTFB。浏览器不报告该条目时省略该键。省略的键不是 0。

n 是该分组里包含该指标的 page_view 行数。skipped 是该分组里不包含该指标的 page_view 行数。

缺失的 vital 计入 skipped,不是 0。路由切换后的浏览可能没有 LCP 和 FCP。非 Chromium 浏览器没有 CLS 和 INP。没有交互的页面没有 INP。这次读取没有最小 n。

vitals 开关打开时,跟踪器可以发送三个 target 属性:

Property Selector
cwv_lcp_target LCP 元素
cwv_inp_target INP 交互目标
cwv_cls_target CLS 最大 shift 目标

每个值都是 CSS selector,会 trim,最长 200 个字符。这些字段只包含 selector:没有文本内容,也没有 URL。

top_poor_targets 列出该指标被评为 poor 的加载里,按 count 取最多 5 个 selector。每项是 { target, count }。FCP 和 TTFB 没有 target 字段,所以 top_poor_targets 是 []。

Pro。免费账户收到 403,error 为 PRO_REQUIRED。该 403 不计为读取。一次成功响应计为一次计量读取。403 的响应体是标准错误对象:error、message,以及调用方可以看到账单时的 payment。

POST /vitals 的 JSON body,或 GET /vitals 上同名的 query 参数:

字段 必填 取值
project 是 项目名
days 否 整数天数窗口
date_from 否 YYYY-MM-DD
date_to 否 YYYY-MM-DD
group_by 否 device 或 path
limit 否 默认 10,最大 20。group_by 为 path 时使用。

事件是 page_view。/query 和 /compare 没有变化。

省略 group_by:一行,group 为 null。group_by 为 device:group 为 mobile、tablet 或 desktop。group_by 为 path:按 n 取前 limit 个 path,按最差的 LCP p75 排序。group 是 pathname。

百分位是 nearest-rank。样本上限为 200,000 个事件。达到上限时响应仍是 200,approximate 为 true,并且带 caps。否则 approximate 为 false,省略 caps。

{
"project": "my-site",
"date_from": "2026-11-06",
"date_to": "2026-11-12",
"event": "page_view",
"group_by": null,
"percentile": "p75",
"percentile_method": "nearest_rank",
"approximate": false,
"thresholds": {
"lcp": { "unit": "ms", "good_max": 2500, "poor_min": 4000 },
"inp": { "unit": "ms", "good_max": 200, "poor_min": 500 },
"cls": { "unit": "unitless", "good_max": 0.1, "poor_min": 0.25 },
"fcp": { "unit": "ms", "good_max": 1800, "poor_min": 3000 },
"ttfb": { "unit": "ms", "good_max": 800, "poor_min": 1800 }
},
"rows": [
{
"group": null,
"cwv_pass": true,
"metrics": {
"lcp": {
"p75": 2100,
"rating": "good",
"n": 400,
"skipped": 20,
"share": { "good": 0.8, "needs_improvement": 0.15, "poor": 0.05 },
"top_poor_targets": [{ "target": "img.hero", "count": 4 }]
},
"inp": {
"p75": 180,
"rating": "good",
"n": 360,
"skipped": 60,
"share": { "good": 0.75, "needs_improvement": 0.2, "poor": 0.05 },
"top_poor_targets": [{ "target": "button.buy", "count": 3 }]
},
"cls": {
"p75": 0.08,
"rating": "good",
"n": 390,
"skipped": 30,
"share": { "good": 0.82, "needs_improvement": 0.12, "poor": 0.06 },
"top_poor_targets": [{ "target": "#main > .banner", "count": 2 }]
},
"fcp": {
"p75": 1600,
"rating": "good",
"n": 400,
"skipped": 20,
"share": { "good": 0.84, "needs_improvement": 0.12, "poor": 0.04 },
"top_poor_targets": []
},
"ttfb": {
"p75": 700,
"rating": "good",
"n": 400,
"skipped": 20,
"share": { "good": 0.78, "needs_improvement": 0.16, "poor": 0.06 },
"top_poor_targets": []
}
}
}
]
}

n 为 0 时 p75 和 rating 为 null。rating 为 good、needs-improvement、poor 或 null。

托管 MCP 工具是 web_vitals。参数与 /vitals 相同:project、days、date_from、date_to、group_by、limit。工具描述包含阈值。p75 是标题数字。文本结果按每个指标打印带单位的 p75、评级、good / needs-improvement / poor 份额,以及 n。

query 和 compare 仍然接受 cwv_* 作为数值属性。在托管版上,事件是 page_view。

vitals 在 @agent-analytics/cli@0.5.41。它调用托管的 /vitals 读取。

终端窗口
npx --yes @agent-analytics/cli@0.5.41 vitals <project> [--days N] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--by device|path] [--limit N] [--json]

--from 和 --to 对应 date_from 和 date_to。--by 对应 group_by。--limit 默认 10,最大 20。--json 打印 API 响应体。

2026-11-13,CLS 和 INP 原地更改(tracker 0.2.5)。

该日期之前,CLS 是不含 hadRecentInput 的 layout-shift 值之和;当已有其他 vital 且不支持 layout-shift 时会存成 0。INP 是每个带 interactionId 的 event 条目的百分位,因此一次交互可能贡献多个 duration。

从 2026-11-13 起,CLS 是最大 session window,不支持 layout-shift 时省略该键。INP 是按 interactionId 分组后、每 50 次忽略一次最高交互的最差交互。cwv_fcp、cwv_ttfb 和三个 target 键从这一天开始。

跨越 2026-11-13 的窗口会混合两种定义。各指标的 n 在该日期两侧可以不同。