Browser, OS, device and language reports tell you what to test and what you can stop supporting. They also hide a few traps. Here is what the numbers count, where they mislead, and how to turn them into a support policy.
A browser or device report answers one question well: which environments carry enough of your traffic to justify testing. It answers a second question badly: who exactly is using them. The difference comes down to what is being counted and how the label was made.
In GhostMetrics these four reports live on the Visitors tab. The tab name suggests people, but the query behind each panel groups rows in the events table by one column and counts them. Every row written by a page load is a pageview, so the count is pageviews with that label over the selected period of 24 hours, 7 days, 30 days or 90 days.
That has three practical consequences.
Each panel also returns at most the top 10 labels. For browser, OS and device that cap never bites, because the tracker can only emit five, six and three distinct labels. It matters for language, which can take any value the browser reports.
Two further limits are worth knowing. The four panels are independent queries, so there is no browser-by-device or OS-by-browser cross-tab. And there is no country filter in the dashboard, so you cannot narrow these panels to one market; use the export for that.
One more place shows the same labels: click a bar in the daily chart and the day drill-down lists that day's devices and browsers, counted as pageviews, with raw counts rather than percentages. It is the quickest way to check whether a deploy shifted your mix.
The labels come from the tracker in the visitor's browser, not from the server. At load, gm.js reads navigator.userAgent and innerWidth and sends three derived strings with the pageview. The parsers are short enough to read in full:
function parseBrowser(ua) {
if (/Edg\//i.test(ua)) return "Edge";
if (/Chrome\//i.test(ua) && !/Chromium/i.test(ua)) return "Chrome";
if (/Firefox\//i.test(ua)) return "Firefox";
if (/Safari\//i.test(ua) && !/Chrome/i.test(ua)) return "Safari";
return "Other";
}
function parseOS(ua) {
if (/iPhone|iPad|iPod/i.test(ua)) return "iOS";
if (/Android/i.test(ua)) return "Android";
if (/Windows/i.test(ua)) return "Windows";
if (/Mac OS/i.test(ua)) return "Mac";
if (/Linux/i.test(ua)) return "Linux";
return "Other";
}
function parseDevice(w) {
if (w < 768) return "mobile";
if (w < 1024) return "tablet";
return "desktop";
}
The first match wins, which is why the order matters: Edge sends a Chrome token, so it is tested first, and Android user agents contain the word Linux, so Android is tested first. The language is not parsed at all: navigator.language is sent as is and stored verbatim, so en-US and en-GB are separate rows. Viewport and screen sizes are stored too but no dashboard panel charts them; they are in the raw export, which is built from the table's live columns.
| Panel | Label source | Possible labels | Where it misleads |
|---|---|---|---|
| Browser | User-agent regex in gm.js | Edge, Chrome, Firefox, Safari, Other | Chromium forks read as Chrome; iOS third-party browsers typically read as Safari |
| OS | User-agent regex in gm.js | iOS, Android, Windows, Mac, Linux, Other | No versions; iPads that request desktop sites typically read as Mac |
| Device | Viewport width at load | mobile, tablet, desktop | Window size, not hardware |
| Language | Browser language setting, stored verbatim | Any value, top 10 shown | Regional variants split; it is a setting, not a location |
A user-agent string is a self-description that browsers have padded with each other's names for decades, so a short regex list gets the family right and the product wrong. Reading the parsers above against typical user agents gives a predictable set of blind spots. The parser rules are exact; the browser behavior described is typical at the time of writing, and user-agent formats change, so confirm any single case against the vendor's current docs.
CriOS/ and FxiOS/ plus Safari, and none of them match the Chrome or Firefox patterns. They land in the Safari rule. For testing purposes that is often right, since iOS browsers have historically all used Apple's engine, though platform rules on alternative engines have been changing in some regions.Edg/ the parser looks for, so it reads as Chrome on Android and Safari on iOS.Browser vendors, led by Chromium, have been trimming the detail in the user-agent string and moving finer detail, such as full versions and device model, behind a separate opt-in mechanism called User-Agent Client Hints. Check the current browser documentation for what each engine sends today, because the rollout has been staged and differs between vendors.
For GhostMetrics the effect is limited, because of what the tracker reads. It never reads navigator.userAgentData, and it keeps only coarse families. It does not depend on versions or device models, which are the details reduction removes. The remaining risk is a browser dropping a token the regexes rely on; those visits would move into Other, so a growing Other slice is the signal to watch. Tools that report versions, models or screen resolutions depend more on this change; check their current docs.
Device type is the most useful split in this report, because it is the one that changes what you build. A site that is 54% mobile deserves a different review order from one that is 15% mobile, regardless of which browser leads.
The cut is a viewport threshold. parseDevice compares the window's inner width to 768 and 1024 when the page loads, and recomputes it for each single-page-app navigation. That means:
Treat "mobile" as "narrow layout" and you will read it correctly: it matches the breakpoints your CSS responds to, which is arguably what you want to test anyway. Treat it as "phone hardware" and it will mislead you at the edges.
The Performance tab carries a Performance by Device table below the Vitals by Page table. It groups rows that carry a vitals beacon by the same device label and shows the average FCP, LCP, CLS and TTFB for each. Four things to keep in mind when reading it:
INP is not captured by GhostMetrics, so responsiveness on slow phones needs another source. Pair the two views: if mobile is your largest device slice and its LCP is well above desktop, fix mobile first. If mobile is a small slice and fast, spend the time elsewhere. Our guide to real-user Core Web Vitals monitoring covers the thresholds and what to do about each metric.
A support decision needs two inputs: how much traffic an environment carries, and how costly it is to support. The report gives you the first. This worked example uses made-up numbers; it is illustrative, not a benchmark. Suppose 90 days of data show 10,000 pageviews:
| Browser slice | Pageviews | Share | Example policy tier |
|---|---|---|---|
| Chrome | 6,200 | 62.0% | Full testing on every release |
| Safari | 2,300 | 23.0% | Full testing on every release |
| Edge | 900 | 9.0% | Smoke test on release |
| Firefox | 450 | 4.5% | Smoke test on release |
| Other | 150 | 1.5% | Best effort; investigate if it grows |
The donut shows only the percentage in its legend, so work backwards from the total in the centre: a 4.5% Firefox slice of a 10,000 total is 450 pageviews. Here is how to reason from that table.
A second reason to be careful with small slices: with a 30-day window and low traffic, a one- or two-point swing can be noise. Prefer the 90-day view for policy and the 24-hour or 7-day view for spotting a regression after a deploy.
Most analytics tools offer these breakdowns; they differ in granularity, in what they count, and in how much of the data survives privacy settings. The comparison below is qualitative; check each tool's current documentation for the exact dimensions and limits.
| Option | What it reports | What it counts | Notes |
|---|---|---|---|
| GhostMetrics | Browser family, OS family, device type by viewport width, browser language | Pageview rows | Coarse labels; vitals split by device; raw export includes screen and viewport size; cookieless |
| GA4 | Device category, browser, OS and more detailed dimensions | Event-based users and sessions | Deeper dimensions and conversion by segment; cookies mean consent in the EU and UK; see GA4 alternatives |
| Cloudflare Web Analytics | Browsers, devices and OS, plus Core Web Vitals | Visits and pageviews | Free and cookieless; no custom events; see our comparison |
| Plausible, Fathom, Umami | Browser, OS and device reports | Visitors or sessions by their own definitions | Cookieless; versions and depth vary by tool |
| Server access logs | Raw user-agent strings for every request | Requests, bots included | No script to block; you parse and filter bots yourself |
GA4 is the stronger choice if you need to see conversion rate by browser or device, or to build audiences on those segments. A cookieless tool is the stronger choice if you want the breakdown without a consent banner; the trade-off is coarser labels. For a broader view, see cookieless analytics compared and how cookieless tools count visitors.
GhostMetrics gives you browser, OS, device and language breakdowns, a Performance by Device table for FCP, LCP, CLS and TTFB, and a day drill-down, with no cookies and no localStorage and no IP addresses stored (they are hashed). The labels are coarse families and the Visitors tab counts pageviews, which this page spells out so you can read it correctly. Install is one script tag in <head>, about 3 KB compressed on the wire.
The free plan is free forever, no card: one website, unlimited pageviews, a real-time dashboard, every view and full history. Raw event export as CSV or JSON is on every plan, including free. Pro is $9.99/mo flat with unlimited websites (fair-use ceiling of 250) and a public shareable dashboard, and it starts with a 30-day free trial that needs a card and charges nothing for 30 days.
Start free, no card See the live demoDisclosure: GhostMetrics is built by Null Agency and we use it on this site, so we are not a neutral party about our own product. User-agent formats, client hints and engine rules are set by browser vendors and change over time; check their current documentation. Competitor tools' dimensions are theirs to document; check their current docs. The worked example numbers are illustrative, not benchmarks.