---
title: Performance Reports
published: true
index: 0
---

# Shopify Performance Report Workflow

## Select routes and methods

Use the configured routes when supplied. Otherwise measure the homepage and the first available populated collection and product page. Add a high-traffic landing page when target evidence identifies one. Use the exact configured origin and record redirects, locale, market, consent state, timestamp, cache state, device profile, network profile, and tool version.

Measure mobile and desktop with stable profiles. Run at least three comparable cold-load lab samples per route and viewport, return the median, and preserve sample variance in Data detail. Keep field and lab values separate: use `method` values such as `field` and `lab`, never blend them into one number. Use field data to prioritize real-user problems and lab traces to diagnose them.

## Measure every Check

Persist metric IDs and the route/viewport/device/network/cache/method/tool/version/unit/window matrix before measurement. Reuse compatible prior conditions and explain changes; never substitute a page or warm cache to improve comparison. Record uncontrolled actual conditions.

Retain every raw lab sample's route/state/dimensions, native value and timestamp. Compute medians from comparable samples; explain slow/failed exclusions or unstable runs and safely repeat when needed. Field evidence retains source, page/origin scope, window, percentile and supported dimensions; origin values are not page-specific.

Record each metric cell as measured, verified not applicable or precisely unavailable. One timing API proves no other metrics; missing timing, telemetry or transfer capture is not zero. Supported measured zeros remain valid. Preserve units/normalization in detail/evidence; optional source ownership cannot block browser-supported measurement.

- **Page size:** total transferred bytes for the document and its loaded subresources. Do not substitute uncompressed resource size.
- **TTFB:** navigation request start to first response byte for the HTML document.
- **FCP, LCP, and CLS:** use the browser or field source's native metric and preserve its scope.
- **INP:** use real-user field data or a browser interaction measurement that can observe INP. Lighthouse cannot measure INP; do not report TBT as INP. Mark the Check blocked when no responsible INP source is available.
- **Asset count:** unique non-document image, stylesheet, font, media, and other asset requests transferred for the tested state.
- **Script count:** unique JavaScript resource requests loaded for the tested state, including first- and third-party scripts. Record ownership in detail when known.

The current Core Web Vitals are LCP, INP, and CLS. For field data, interpret their 75th-percentile values using the current good thresholds: LCP at or below 2,500 ms, INP at or below 200 ms, and CLS at or below 0.1. Use Shopify's [performance reference](https://shopify.dev/docs/storefronts/themes/best-practices/performance/index) and Google's [Core Web Vitals threshold method](https://web.dev/articles/defining-core-web-vitals-thresholds) as maintained sources. Do not apply the Shopify Theme Store Lighthouse submission score to a merchant storefront.

## Diagnose actionable leaks

Data remain visible whether the Check completes or fails. A poor or regressed number selects what to investigate but does not prove a cause. Trace slow TTFB to server or Liquid work; render delays to CSS, fonts, images, and resource discovery; layout shifts to the exact moving element and space owner; interaction delay to the responsible main-thread task; and page weight or counts to specific assets, scripts, apps, pixels, and initiators.

Fail a Check and create one Issue only when the measured problem and target-bound evidence support one concrete cause, owner, recommendation, and comparable retest. Keep independent causes separate. If the metric is available but no cause qualifies, complete the Check with Data and no Issue. If the metric itself is unavailable, block only that Check and state the exact missing capability or evidence.

## Report and complete

Link claimed causes to exact trace elements/resources/tasks under repeated conditions; a large file or long task alone is only a lead. Retest prior Issues on the same route/state/dependency before claiming resolution. Changed profiles, unstable candidates or missing diagnosis prove no improvement. Measurements without supported actions remain Completed/Data, not invented Pass/Fail outcomes.

Follow [Glue JSON output](../core/glue-output.md): save/validate complete JSON and references, then summarize in chat; Glue receives its bare object and handles storage/rendering. Raw evidence supports, not replaces, the report. Omit missing measurements rather than emitting zero. Retain valid route/viewport/window cells as Completed/Data or Fail with a qualifying Issue. Label partial scope and each missing cell/unblock action in detail/artifacts; keep `limitationIds` empty. Use Blocked with reciprocal Limitations only without valid measurements or an independently supported Issue. Never discard valid cells, attach Data to Blocked or imply unmeasured cells were tested.

Record one terminal `Completed`, `Fail`, `Blocked`, or `Not applicable` outcome for every selected Check. Completed measurements reference their Data; failed Checks reference one concrete Issue; blocked Checks reference precise Limitations. Do not generate a Summary or Findings. The report is complete when every selected Check has one terminal outcome and every safely measurable metric is returned as normalized Data with exact dimensions.
