[{"data":1,"prerenderedAt":1012},["ShallowReactive",2],{"content:\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons":3,"surroundings:\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons":1003},{"id":4,"title":5,"body":6,"description":982,"extension":983,"meta":984,"navigation":996,"path":997,"seo":998,"stem":1001,"__hash__":1002},"content\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons\u002Findex.md","Computing p75 from Raw RUM Beacons",{"type":7,"value":8,"toc":967},"minimark",[9,14,29,32,183,188,225,229,243,249,255,261,356,360,365,375,520,523,527,574,577,581,638,641,645,681,684,807,811,814,818,821,825,828,867,870,874,898,907,916,925,929,952,957,960,963],[10,11,13],"h1",{"id":12},"how-to-compute-p75-correctly-from-raw-rum-beacons","How to Compute p75 Correctly from Raw RUM Beacons",[15,16,17,18,23,24,28],"p",{},"This guide covers the aggregation side of ",[19,20,22],"a",{"href":21},"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002F","RUM Beacons & Field Data Collection",", part of ",[19,25,27],{"href":26},"\u002Fcore-web-vitals-measurement\u002F","Core Web Vitals & Measurement",". Collecting beacons is the easy half. Turning them into a p75 that you can defend in a performance review — and that behaves like the assessed Core Web Vitals number — requires decisions most dashboards make implicitly and often wrongly.",[15,30,31],{},"The four that matter most: what one row represents (a page view, not a beacon), which value per page view counts (the final one), how the percentile is computed (and over which population), and which segments get their own p75 rather than being averaged together. Getting any one wrong produces numbers that drift from reality by hundreds of milliseconds, and teams then argue about whether a release helped.",[15,33,34],{},[35,36,42,43,42,50,42,54,42,57,42,75,42,83,42,89,42,97,42,104,42,109,42,113,42,116,42,120,42,123,42,126,42,132,42,136,42,139,42,142,42,145,42,149,42,152,42,155,42,159,42,162,42,171,42,175,42,179,42],"svg",{"viewBox":37,"width":38,"role":39,"ariaLabel":40,"style":41},"0 0 760 149","100%","img","Pipeline from raw beacons through deduplication, final-value selection and segmentation to a percentile per segment.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[44,45],"rect",{"className":46,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],"svg-canvas","0","#ffffff",[51,52,53],"title",{},"From raw beacons to a trustworthy p75",[55,56,40],"desc",{},[58,59,60],"defs",{},[61,62,69],"marker",{"id":63,"viewBox":64,"refX":65,"refY":66,"markerWidth":67,"markerHeight":67,"orient":68},"fa088c80d3","0 0 10 10","9","5","7","auto-start-reverse",[70,71],"path",{"d":72,"fill":73,"style":74},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[44,76],{"x":77,"y":77,"width":78,"height":79,"rx":80,"fill":81,"stroke":73,"style":82},"1","758","147","10","none","stroke-opacity:0.18",[84,85,53],"text",{"x":86,"y":87,"fill":73,"style":88},"28.0","34.0","font-size:16px;font-weight:700",[44,90],{"x":86,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[84,98,103],{"x":99,"y":100,"fill":73,"style":101,"textAnchor":102},"82.4","78.0","font-size:13px;font-weight:700","middle","Raw beacons",[84,105,108],{"x":99,"y":106,"fill":73,"style":107,"textAnchor":102},"96.0","font-size:12px","many per page",[84,110,112],{"x":99,"y":111,"fill":73,"style":107,"textAnchor":102},"112.0","view",[44,114],{"x":115,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"176.8",[84,117,119],{"x":118,"y":100,"fill":73,"style":101,"textAnchor":102},"231.2","Deduplicate",[84,121,122],{"x":118,"y":106,"fill":73,"style":107,"textAnchor":102},"one row per page",[84,124,125],{"x":118,"y":111,"fill":73,"style":107,"textAnchor":102},"view + metric",[44,127],{"x":128,"y":91,"width":92,"height":93,"rx":94,"fill":129,"stroke":130,"style":131},"325.6","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[84,133,135],{"x":134,"y":100,"fill":73,"style":101,"textAnchor":102},"380.0","Final value",[84,137,138],{"x":134,"y":106,"fill":73,"style":107,"textAnchor":102},"last reported",[84,140,141],{"x":134,"y":111,"fill":73,"style":107,"textAnchor":102},"value",[44,143],{"x":144,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"474.4",[84,146,148],{"x":147,"y":100,"fill":73,"style":101,"textAnchor":102},"528.8","Segment",[84,150,151],{"x":147,"y":106,"fill":73,"style":107,"textAnchor":102},"device, template",[44,153],{"x":154,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"623.2",[84,156,158],{"x":157,"y":100,"fill":73,"style":101,"textAnchor":102},"677.6","Percentile",[84,160,161],{"x":157,"y":106,"fill":73,"style":107,"textAnchor":102},"p75 per segment",[163,164],"line",{"x1":165,"y1":166,"x2":167,"y2":166,"stroke":73,"strokeWidth":168,"style":169,"markerEnd":170},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fa088c80d3)",[163,172],{"x1":173,"y1":166,"x2":174,"y2":166,"stroke":73,"strokeWidth":168,"style":169,"markerEnd":170},"285.6","323.6",[163,176],{"x1":177,"y1":166,"x2":178,"y2":166,"stroke":73,"strokeWidth":168,"style":169,"markerEnd":170},"434.4","472.4",[163,180],{"x1":181,"y1":166,"x2":182,"y2":166,"stroke":73,"strokeWidth":168,"style":169,"markerEnd":170},"583.2","621.2",[184,185,187],"h2",{"id":186},"rapid-diagnosis","Rapid Diagnosis",[189,190,191,207,213,219],"ul",{},[192,193,194,42,198,202,203,206],"li",{},[195,196,197],"strong",{},"Count rows per page view.",[199,200,201],"code",{},"SELECT page_view_id, metric, COUNT(*) ... HAVING COUNT(*) > 1",". Duplicates mean ",[199,204,205],{},"reportAllChanges"," or retries are inflating counts.",[192,208,209,212],{},[195,210,211],{},"Check which value is used."," If CLS or INP is reported incrementally, using the first or an average of reported values understates the final value.",[192,214,215,218],{},[195,216,217],{},"Check the percentile function."," Approximate quantile functions are fine at scale; averaging per-day percentiles is not.",[192,220,221,224],{},[195,222,223],{},"Check the population."," Are desktop and mobile mixed? Are bots excluded? Are prerendered or bfcache-restored page views treated consistently?",[184,226,228],{"id":227},"root-cause-analysis","Root Cause Analysis",[15,230,231,234,235,238,239,242],{},[195,232,233],{},"1. Beacons are not page views."," With ",[199,236,237],{},"reportAllChanges: true",", the ",[199,240,241],{},"web-vitals"," library reports CLS and INP every time they change. Each report is a beacon; only the last one per page view is the final value.",[15,244,245,248],{},[195,246,247],{},"2. Averaging percentiles."," A weekly p75 computed as the average of seven daily p75s is not the weekly p75. Percentiles do not average; compute them over the pooled data.",[15,250,251,254],{},[195,252,253],{},"3. Mixing populations."," Desktop and mobile distributions differ so much that a pooled p75 describes neither. Core Web Vitals are assessed per form factor for this reason.",[15,256,257,260],{},[195,258,259],{},"4. Inconsistent handling of special navigations."," Prerendered pages report near-zero LCP; bfcache restores report a fresh set of metrics. Including or excluding them inconsistently between periods creates false trends.",[15,262,263],{},[35,264,42,267,42,270,42,273,42,275,42,278,42,280,42,288,42,295,42,302,42,307,42,311,42,316,42,320,42,324,42,328,42,332,42,336,42,340,42,344,42,350,42],{"viewBox":265,"width":38,"role":39,"ariaLabel":266,"style":41},"0 0 760 242","Bar chart showing the reported p75 INP for the same data under correct modelling and three common mistakes.",[44,268],{"className":269,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,271,272],{},"How modelling mistakes move a p75 INP",[55,274,266],{},[44,276],{"x":77,"y":77,"width":78,"height":277,"rx":80,"fill":81,"stroke":73,"style":82},"240",[84,279,272],{"x":86,"y":87,"fill":73,"style":88},[163,281],{"x1":282,"y1":283,"x2":282,"y2":284,"stroke":130,"strokeWidth":168,"strokeDashArray":285,"style":287},"597.5","72.0","194.0",[286,286],"4","stroke-opacity:0.9",[84,289,294],{"x":290,"y":291,"fill":73,"style":292,"textAnchor":293},"193.8","92.0","font-size:13px","end","Correct (final value per view)",[44,296],{"x":297,"y":100,"width":298,"height":299,"rx":300,"fill":73,"stroke":73,"style":301},"205.8","462.1","19","3","fill-opacity:0.7;stroke-opacity:0.4",[84,303,306],{"x":304,"y":291,"fill":73,"style":305},"674.0","font-size:12px;font-weight:600","236ms",[84,308,310],{"x":290,"y":309,"fill":73,"style":292,"textAnchor":293},"123.0","All beacons counted",[44,312],{"x":297,"y":313,"width":314,"height":299,"rx":300,"fill":129,"stroke":130,"style":315},"109.0","368.2","fill-opacity:0.7;stroke-opacity:0.9",[84,317,319],{"x":318,"y":309,"fill":73,"style":305},"580.0","188ms",[84,321,323],{"x":290,"y":322,"fill":73,"style":292,"textAnchor":293},"154.0","First reported value",[44,325],{"x":297,"y":326,"width":327,"height":299,"rx":300,"fill":129,"stroke":130,"style":315},"140.0","295.7",[84,329,331],{"x":330,"y":322,"fill":73,"style":305},"507.5","151ms",[84,333,335],{"x":290,"y":334,"fill":73,"style":292,"textAnchor":293},"185.0","Mobile + desktop pooled",[44,337],{"x":297,"y":338,"width":339,"height":299,"rx":300,"fill":129,"stroke":130,"style":315},"171.0","340.7",[84,341,343],{"x":342,"y":334,"fill":73,"style":305},"552.6","174ms",[84,345,349],{"x":282,"y":346,"fill":347,"style":348,"textAnchor":102},"68.0","#8a6608","font-size:12px;font-weight:700","200ms INP",[84,351,355],{"x":86,"y":352,"fill":353,"style":354},"220.0","#51617a","font-size:12.5px","Each mistake flatters the number — the page appears to pass while the correctly modelled p75 fails.",[184,357,359],{"id":358},"step-by-step-resolution","Step-by-Step Resolution",[361,362,364],"h3",{"id":363},"_1-give-every-beacon-a-page-view-id-and-a-metric-id","1. Give every beacon a page-view id and a metric id",[15,366,367,368,370,371,374],{},"The ",[199,369,241],{}," library provides ",[199,372,373],{},"metric.id",", unique per metric per page view; add your own page-view id for joins with other events.",[376,377,382],"pre",{"className":378,"code":379,"language":380,"meta":381,"style":381},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","import { onLCP, onINP, onCLS } from 'web-vitals';\nconst pageViewId = crypto.randomUUID();\nconst send = (m) => queue({ pv: pageViewId, id: m.id, name: m.name, value: m.value,\n                           delta: m.delta, nav: m.navigationType, ts: Date.now() });\nonLCP(send); onINP(send, { reportAllChanges: true }); onCLS(send, { reportAllChanges: true });\n\u002F\u002F trade-off: reportAllChanges improves delivery for long visits (you get a\n\u002F\u002F value even if the final beacon is lost) but multiplies beacons. Deduplicate\n\u002F\u002F on ingest, as below, or the counts are meaningless.\n","javascript","",[199,383,384,406,429,458,470,501,508,514],{"__ignoreMap":381},[385,386,388,392,396,399,403],"span",{"class":163,"line":387},1,[385,389,391],{"class":390},"sPARh","import",[385,393,395],{"class":394},"saISM"," { onLCP, onINP, onCLS } ",[385,397,398],{"class":390},"from",[385,400,402],{"class":401},"sZ8jY"," 'web-vitals'",[385,404,405],{"class":394},";\n",[385,407,409,412,416,419,422,426],{"class":163,"line":408},2,[385,410,411],{"class":390},"const",[385,413,415],{"class":414},"sPXB4"," pageViewId",[385,417,418],{"class":390}," =",[385,420,421],{"class":394}," crypto.",[385,423,425],{"class":424},"smZ65","randomUUID",[385,427,428],{"class":394},"();\n",[385,430,432,434,437,439,442,446,449,452,455],{"class":163,"line":431},3,[385,433,411],{"class":390},[385,435,436],{"class":424}," send",[385,438,418],{"class":390},[385,440,441],{"class":394}," (",[385,443,445],{"class":444},"sQw3B","m",[385,447,448],{"class":394},") ",[385,450,451],{"class":390},"=>",[385,453,454],{"class":424}," queue",[385,456,457],{"class":394},"({ pv: pageViewId, id: m.id, name: m.name, value: m.value,\n",[385,459,461,464,467],{"class":163,"line":460},4,[385,462,463],{"class":394},"                           delta: m.delta, nav: m.navigationType, ts: Date.",[385,465,466],{"class":424},"now",[385,468,469],{"class":394},"() });\n",[385,471,473,476,479,482,485,488,491,494,496,498],{"class":163,"line":472},5,[385,474,475],{"class":424},"onLCP",[385,477,478],{"class":394},"(send); ",[385,480,481],{"class":424},"onINP",[385,483,484],{"class":394},"(send, { reportAllChanges: ",[385,486,487],{"class":414},"true",[385,489,490],{"class":394}," }); ",[385,492,493],{"class":424},"onCLS",[385,495,484],{"class":394},[385,497,487],{"class":414},[385,499,500],{"class":394}," });\n",[385,502,504],{"class":163,"line":503},6,[385,505,507],{"class":506},"sjfSM","\u002F\u002F trade-off: reportAllChanges improves delivery for long visits (you get a\n",[385,509,511],{"class":163,"line":510},7,[385,512,513],{"class":506},"\u002F\u002F value even if the final beacon is lost) but multiplies beacons. Deduplicate\n",[385,515,517],{"class":163,"line":516},8,[385,518,519],{"class":506},"\u002F\u002F on ingest, as below, or the counts are meaningless.\n",[15,521,522],{},"Expected outcome: every row can be attributed to exactly one page view and one metric instance.",[361,524,526],{"id":525},"_2-keep-only-the-final-value-per-metric-instance","2. Keep only the final value per metric instance",[376,528,532],{"className":529,"code":530,"language":531,"meta":381,"style":381},"language-sql shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","CREATE OR REPLACE VIEW rum.final AS\nSELECT * EXCEPT(rn) FROM (\n  SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY ts DESC) AS rn\n  FROM rum.raw\n) WHERE rn = 1;\n-- trade-off: \"latest timestamp wins\" assumes client clocks are monotonic within\n-- a page view, which holds for Date.now() in practice. If you send deltas\n-- instead, SUM(delta) per id reconstructs the final value without ordering.\n","sql",[199,533,534,539,544,549,554,559,564,569],{"__ignoreMap":381},[385,535,536],{"class":163,"line":387},[385,537,538],{},"CREATE OR REPLACE VIEW rum.final AS\n",[385,540,541],{"class":163,"line":408},[385,542,543],{},"SELECT * EXCEPT(rn) FROM (\n",[385,545,546],{"class":163,"line":431},[385,547,548],{},"  SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY ts DESC) AS rn\n",[385,550,551],{"class":163,"line":460},[385,552,553],{},"  FROM rum.raw\n",[385,555,556],{"class":163,"line":472},[385,557,558],{},") WHERE rn = 1;\n",[385,560,561],{"class":163,"line":503},[385,562,563],{},"-- trade-off: \"latest timestamp wins\" assumes client clocks are monotonic within\n",[385,565,566],{"class":163,"line":510},[385,567,568],{},"-- a page view, which holds for Date.now() in practice. If you send deltas\n",[385,570,571],{"class":163,"line":516},[385,572,573],{},"-- instead, SUM(delta) per id reconstructs the final value without ordering.\n",[15,575,576],{},"Expected outcome: one row per metric per page view, carrying its final value.",[361,578,580],{"id":579},"_3-compute-percentiles-over-pooled-segmented-data","3. Compute percentiles over pooled, segmented data",[376,582,584],{"className":529,"code":583,"language":531,"meta":381,"style":381},"SELECT device, template, name AS metric,\n       APPROX_QUANTILES(value, 100)[OFFSET(75)] AS p75,\n       COUNT(*) AS page_views\nFROM rum.final\nWHERE ts >= UNIX_MILLIS(TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 28 DAY))\n  AND nav IN ('navigate', 'reload')           -- see step 4 for the others\nGROUP BY 1, 2, 3\nHAVING page_views >= 500;\n-- trade-off: the 500-row floor hides small segments whose p75 would be noise.\n-- Report them in an \"other\" bucket rather than silently dropping traffic.\n",[199,585,586,591,596,601,606,611,616,621,626,632],{"__ignoreMap":381},[385,587,588],{"class":163,"line":387},[385,589,590],{},"SELECT device, template, name AS metric,\n",[385,592,593],{"class":163,"line":408},[385,594,595],{},"       APPROX_QUANTILES(value, 100)[OFFSET(75)] AS p75,\n",[385,597,598],{"class":163,"line":431},[385,599,600],{},"       COUNT(*) AS page_views\n",[385,602,603],{"class":163,"line":460},[385,604,605],{},"FROM rum.final\n",[385,607,608],{"class":163,"line":472},[385,609,610],{},"WHERE ts >= UNIX_MILLIS(TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 28 DAY))\n",[385,612,613],{"class":163,"line":503},[385,614,615],{},"  AND nav IN ('navigate', 'reload')           -- see step 4 for the others\n",[385,617,618],{"class":163,"line":510},[385,619,620],{},"GROUP BY 1, 2, 3\n",[385,622,623],{"class":163,"line":516},[385,624,625],{},"HAVING page_views >= 500;\n",[385,627,629],{"class":163,"line":628},9,[385,630,631],{},"-- trade-off: the 500-row floor hides small segments whose p75 would be noise.\n",[385,633,635],{"class":163,"line":634},10,[385,636,637],{},"-- Report them in an \"other\" bucket rather than silently dropping traffic.\n",[15,639,640],{},"Expected outcome: p75 values per device and template over a 28-day window, comparable in spirit with CrUX's assessment.",[361,642,644],{"id":643},"_4-decide-and-document-how-special-navigations-count","4. Decide and document how special navigations count",[15,646,367,647,649,650,653,654,657,658,657,661,657,664,657,667,670,671,674,675,677,678,680],{},[199,648,241],{}," library reports ",[199,651,652],{},"navigationType"," as ",[199,655,656],{},"navigate",", ",[199,659,660],{},"reload",[199,662,663],{},"back-forward",[199,665,666],{},"back-forward-cache",[199,668,669],{},"prerender"," or ",[199,672,673],{},"restore",". Report the main p75 over ",[199,676,656],{}," and ",[199,679,660],{},", and break out bfcache restores and prerenders separately — they are genuinely fast experiences, but mixing them in hides changes to normal loads.",[15,682,683],{},"Expected outcome: trends that move only when real load performance moves.",[15,685,686],{},[35,687,42,690,42,693,42,696,42,698,42,701,42,703,42,708,42,714,42,718,42,722,42,725,42,729,42,733,42,736,42,738,42,741,42,743,42,746,42,749,42,752,42,754,42,756,42,758,42,761,42,764,42,767,42,769,42,772,42,774,42,777,42,780,42,783,42,785,42,787,42,789,42,792,42,795,42,798,42,800,42,802,42,804,42],{"viewBox":688,"width":38,"role":39,"ariaLabel":689,"style":41},"0 0 760 258","How to treat each web-vitals navigation type when computing the headline p75.",[44,691],{"className":692,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,694,695],{},"Handling each navigation type",[55,697,689],{},[44,699],{"x":77,"y":77,"width":78,"height":700,"rx":80,"fill":81,"stroke":73,"style":82},"256",[84,702,695],{"x":86,"y":87,"fill":73,"style":88},[44,704],{"x":86,"y":91,"width":705,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},"135.3","30.0","fill-opacity:0.06;stroke-opacity:0.4",[84,709,652],{"x":710,"y":711,"fill":73,"style":712,"textAnchor":713},"38.0","75.5","font-size:12.5px;font-weight:700","start",[44,715],{"x":716,"y":91,"width":717,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},"163.3","284.4",[84,719,721],{"x":720,"y":711,"fill":73,"style":712,"textAnchor":102},"305.5","In headline p75?",[44,723],{"x":724,"y":91,"width":717,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},"447.6",[84,726,728],{"x":727,"y":711,"fill":73,"style":712,"textAnchor":102},"589.8","Why",[44,730],{"x":86,"y":731,"width":705,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},"86.0","stroke-opacity:0.35",[84,734,656],{"x":710,"y":735,"fill":73,"style":712,"textAnchor":713},"105.5",[44,737],{"x":716,"y":731,"width":717,"height":706,"rx":48,"fill":95,"stroke":95,"style":96},[84,739,740],{"x":720,"y":735,"fill":73,"style":107,"textAnchor":102},"yes",[44,742],{"x":724,"y":731,"width":717,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},[84,744,745],{"x":727,"y":735,"fill":73,"style":107,"textAnchor":102},"Standard page loads",[44,747],{"x":86,"y":748,"width":705,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},"116.0",[84,750,660],{"x":710,"y":751,"fill":73,"style":712,"textAnchor":713},"135.5",[44,753],{"x":716,"y":748,"width":717,"height":706,"rx":48,"fill":95,"stroke":95,"style":96},[84,755,740],{"x":720,"y":751,"fill":73,"style":107,"textAnchor":102},[44,757],{"x":724,"y":748,"width":717,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},[84,759,760],{"x":727,"y":751,"fill":73,"style":107,"textAnchor":102},"Real loads users wait for",[44,762],{"x":86,"y":763,"width":705,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},"146.0",[84,765,666],{"x":710,"y":766,"fill":73,"style":712,"textAnchor":713},"165.5",[44,768],{"x":716,"y":763,"width":717,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},[84,770,771],{"x":720,"y":766,"fill":73,"style":107,"textAnchor":102},"separate series",[44,773],{"x":724,"y":763,"width":717,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},[84,775,776],{"x":727,"y":766,"fill":73,"style":107,"textAnchor":102},"Near-instant; would mask regressions",[44,778],{"x":86,"y":779,"width":705,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},"176.0",[84,781,669],{"x":710,"y":782,"fill":73,"style":712,"textAnchor":713},"195.5",[44,784],{"x":716,"y":779,"width":717,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},[84,786,771],{"x":720,"y":782,"fill":73,"style":107,"textAnchor":102},[44,788],{"x":724,"y":779,"width":717,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},[84,790,791],{"x":727,"y":782,"fill":73,"style":107,"textAnchor":102},"LCP from activation can be ~0",[44,793],{"x":86,"y":794,"width":705,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},"206.0",[84,796,673],{"x":710,"y":797,"fill":73,"style":712,"textAnchor":713},"225.5",[44,799],{"x":716,"y":794,"width":717,"height":706,"rx":48,"fill":73,"stroke":73,"style":707},[84,801,771],{"x":720,"y":797,"fill":73,"style":107,"textAnchor":102},[44,803],{"x":724,"y":794,"width":717,"height":706,"rx":48,"fill":81,"stroke":73,"style":732},[84,805,806],{"x":727,"y":797,"fill":73,"style":107,"textAnchor":102},"Discarded tab restored",[184,808,810],{"id":809},"verification","Verification",[15,812,813],{},"Cross-check your pipeline against an independent computation: export one day of raw beacons, compute the final value per metric id and the p75 in a notebook, and compare with the dashboard. They should match exactly (or within approximate-quantile error). Then compare your origin-level mobile p75 with CrUX's: they will not match exactly — CrUX is Chrome-only and opt-in — but a large and persistent gap usually reveals a modelling bug rather than a population difference.",[184,815,817],{"id":816},"confidence-intervals-is-the-change-real","Confidence Intervals: Is the Change Real?",[15,819,820],{},"A p75 computed from a sample has uncertainty, and week-over-week changes of a few percent are often noise. For a quick estimate, bootstrap: resample page views with replacement a few hundred times, compute p75 for each resample, and take the 2.5th and 97.5th percentiles of those values as a 95% interval. If the intervals for \"before\" and \"after\" overlap substantially, do not claim an improvement. For high-traffic templates intervals are narrow and small changes are detectable; for low-traffic ones, compare over longer windows. Displaying the interval on dashboards prevents a great deal of arguing over noise.",[184,822,824],{"id":823},"a-reconciliation-checklist","A Reconciliation Checklist",[15,826,827],{},"When your RUM p75 and another source disagree, work through these in order before assuming either is wrong:",[829,830,831,837,843,849,855,861],"ol",{},[192,832,833,836],{},[195,834,835],{},"Population:"," same browsers, same form factor, bots excluded in both?",[192,838,839,842],{},[195,840,841],{},"Window:"," same date range, same 28-day versus calendar-week definition?",[192,844,845,848],{},[195,846,847],{},"Unit:"," one value per page view in both, final values only?",[192,850,851,854],{},[195,852,853],{},"Navigation types:"," prerender and bfcache treated the same way?",[192,856,857,860],{},[195,858,859],{},"Sampling:"," weights applied if rates differ by segment?",[192,862,863,866],{},[195,864,865],{},"Percentile method:"," exact or approximate, and pooled rather than averaged?",[15,868,869],{},"Most disagreements resolve at steps 1 or 3. Writing the answers down for your pipeline once makes every future comparison faster.",[184,871,873],{"id":872},"faq","FAQ",[875,876,879,883],"details",{"className":877},[878],"faq-item",[880,881,882],"summary",{},"Should I use the delta or the value field from web-vitals?",[15,884,885,887,888,891,892,894,895,897],{},[199,886,141],{}," is the current total for the metric; ",[199,889,890],{},"delta"," is the change since the last report. If you keep the latest report per metric id, use ",[199,893,141],{},". If your pipeline can only append, summing ",[199,896,890],{}," per id gives the same final value without needing ordering — useful for streaming aggregation.",[875,899,901,904],{"className":900},[878],[880,902,903],{},"Is the median ever the better statistic?",[15,905,906],{},"For tracking typical experience and detecting broad regressions, the median is more stable and responds to changes that affect everyone. For the Core Web Vitals pass\u002Ffail question, p75 is the defined statistic. Many teams chart both: the median for \"did everything get slower?\" and p75 for \"are we passing?\".",[875,908,910,913],{"className":909},[878],[880,911,912],{},"How should CLS zeros be handled?",[15,914,915],{},"Keep them. A large share of page views with CLS of exactly zero is common and legitimate; excluding them shifts the p75 upward and misrepresents the experience. Make sure your beacon sends CLS even when it is zero — some custom implementations only send when a shift occurs.",[875,917,919,922],{"className":918},[878],[880,920,921],{},"Should INP be computed from every interaction or from the per-page value?",[15,923,924],{},"From the per-page value. INP is defined per page visit as the worst interaction (ignoring one outlier per 50), so each page view contributes exactly one INP number, and the p75 is taken across page views. Computing a percentile over all individual interactions answers a different question — how fast a typical interaction is — which is useful for diagnosis but will be much lower than the assessed INP and should be labelled differently.",[184,926,928],{"id":927},"related","Related",[189,930,931,938,945],{},[192,932,933,937],{},[19,934,936],{"href":935},"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fsampling-rum-data-without-biasing-p75\u002F","Sampling RUM data without biasing p75"," — weighting sampled beacons in these queries.",[192,939,940,944],{},[19,941,943],{"href":942},"\u002Fcore-web-vitals-measurement\u002Funderstanding-core-web-vitals-thresholds\u002Fwhy-core-web-vitals-use-the-75th-percentile\u002F","Why Core Web Vitals use the 75th percentile"," — what the statistic is meant to represent.",[192,946,947,951],{},[19,948,950],{"href":949},"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fsegmenting-rum-by-device-and-connection\u002F","Segmenting RUM by device and connection"," — choosing the segments.",[953,954,956],"script",{"type":955},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Compute p75 Correctly from Raw RUM Beacons\",\n  \"description\": \"The data-modelling and SQL details that make your own p75 numbers trustworthy and comparable with Core Web Vitals assessments.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Give every beacon a page-view id and a metric id\",\n      \"text\": \"The web-vitals library provides metric.id, unique per metric per page view; add your own page-view id for joins with other events.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Keep only the final value per metric instance\",\n      \"text\": \"Expected outcome: one row per metric per page view, carrying its final value.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Compute percentiles over pooled, segmented data\",\n      \"text\": \"Expected outcome: p75 values per device and template over a 28-day window, comparable in spirit with CrUX's assessment.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Decide and document how special navigations count\",\n      \"text\": \"The web-vitals library reports navigationType as navigate, reload, back-forward, back-forward-cache, prerender or restore.\"\n    }\n  ]\n}\n",[953,958,959],{"type":955},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Compute p75 Correctly from Raw RUM Beacons\",\n  \"description\": \"The data-modelling and SQL details that make your own p75 numbers trustworthy and comparable with Core Web Vitals assessments.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons\u002F\"\n  }\n}\n",[953,961,962],{"type":955},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Core Web Vitals & Measurement\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"RUM Beacons & Field Data Collection\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Computing p75 from Raw RUM Beacons\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons\u002F\"\n    }\n  ]\n}\n",[964,965,966],"style",{},"html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":381,"searchDepth":408,"depth":408,"links":968},[969,970,971,977,978,979,980,981],{"id":186,"depth":408,"text":187},{"id":227,"depth":408,"text":228},{"id":358,"depth":408,"text":359,"children":972},[973,974,975,976],{"id":363,"depth":431,"text":364},{"id":525,"depth":431,"text":526},{"id":579,"depth":431,"text":580},{"id":643,"depth":431,"text":644},{"id":809,"depth":408,"text":810},{"id":816,"depth":408,"text":817},{"id":823,"depth":408,"text":824},{"id":872,"depth":408,"text":873},{"id":927,"depth":408,"text":928},"The data-modelling and SQL details that make your own p75 numbers trustworthy and comparable with Core Web Vitals assessments.","md",{"slug":985,"type":986,"breadcrumb":987,"datePublished":995,"dateModified":995},"computing-p75-from-raw-rum-beacons","article",[988,991,992,993],{"name":989,"url":990},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":994},"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons\u002F","2026-10-06",true,"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons",{"title":999,"description":1000},"Computing p75 Core Web Vitals from Raw RUM Beacons","Compute LCP, INP and CLS p75 correctly from raw beacons: one value per page view, the right percentile definition, deduplication, and per-segment breakdowns.","core-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcomputing-p75-from-raw-rum-beacons\u002Findex","iXnbWb-0Nzt3l3Wce2XVk7PnBwSyzjhhRLNUQCH78a8",[1004,1008],{"title":1005,"path":1006,"stem":1007},"Attributing INP to a Component","\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fattributing-inp-to-a-component-with-the-attribution-build","core-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fattributing-inp-to-a-component-with-the-attribution-build\u002Findex",{"title":1009,"path":1010,"stem":1011},"CrUX vs Your Own RUM","\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcrux-vs-your-own-rum-why-the-numbers-differ","core-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fcrux-vs-your-own-rum-why-the-numbers-differ\u002Findex",1791308076854]