Why this matters
Browser-specific bugs are the second-loudest support category after payment failures, and the hardest to reproduce on the dev laptop running the latest Chrome. The user emails “I clicked checkout and nothing happened” — you can’t repro, you close the ticket, they churn.
The actual cause is almost always: Safari 14.0 doesn’t support Array.prototype.at(), or some random old Chromium WebView used by an in-app browser is missing Promise.allSettled. Sentry shows you browser as a tag; segmenting by it is a manual filter you forget to apply.
Agentry’s HogQL can group errors by properties.$browser_version in one query. The bugs concentrated in one engine pop out instantly.
What you get
- A per-fingerprint browser distribution (what % of events came from which browser/version)
- Top 5 errors that are >80% concentrated in one browser version (= polyfill / compat issue)
- A “minimum browser version to support” suggestion based on your actual user mix
Walk through it
Split client-side errors by browser. Are any fingerprints concentrated in one browser version?
Let me pull the browser distribution per fingerprint.
agentry_analytics_query {
project_id: "default",
hogql: "SELECT properties.fingerprint AS fp, properties.$browser AS browser, properties.$browser_version AS ver, count() AS cnt FROM events WHERE event = '$exception' AND properties.$lib = 'web' AND timestamp >= now() - INTERVAL 14 DAY GROUP BY fp, browser, ver HAVING cnt > 10 ORDER BY fp, cnt DESC"
}
{
"rows": [
{ "fp": "f_c4a1", "browser": "Safari", "ver": "14.0", "cnt": 88 },
{ "fp": "f_c4a1", "browser": "Safari", "ver": "14.1", "cnt": 12 },
{ "fp": "f_c4a1", "browser": "Chrome", "ver": "120", "cnt": 2 },
{ "fp": "f_98d2", "browser": "Chrome WebView", "ver": "90", "cnt": 64 },
{ "fp": "f_98d2", "browser": "Chrome", "ver": "121", "cnt": 1 },
{ "fp": "f_4e21", "browser": "Chrome", "ver": "121", "cnt": 410 },
{ "fp": "f_4e21", "browser": "Safari", "ver": "17.4", "cnt": 188 },
{ "fp": "f_4e21", "browser": "Firefox", "ver": "124", "cnt": 91 }
]
}
Two fingerprints are heavily browser-concentrated:
f_c4a1— 97% Safari 14.x (100 / 102 events). Likely a missing polyfill.f_98d2— 98% Chrome WebView 90 (64 / 65 events). In-app browser inside some mobile app.
f_4e21 is well-distributed — that’s a real bug affecting everyone, separate workstream.
agentry_get_case { case_id: "f_c4a1" }
{
"id": "f_c4a1",
"error_type": "TypeError",
"message": "undefined is not a function (evaluating 'arr.at(-1)')",
"stack_top": "dist/app.js:bundled — fn name unknown"
}
Confirmed: Array.prototype.at() isn’t supported on Safari 14 (added in 15.4). The fix is either a polyfill (core-js/features/array/at) or swap arr.at(-1) for arr[arr.length - 1]. Affects ~100 Safari users in 14 days.
f_98d2 is harder — Chrome WebView 90 is old enough that it might be a custom browser embedded in a partner’s mobile app. Recommend checking your traffic source.
Should I check overall user-mix by browser so we can decide whether to drop Safari 14 support?
The output
Browser-concentrated errors (14d, client-side only)
f_c4a1 TypeError: undefined is not a function (evaluating 'arr.at(-1)')
97% Safari 14.x (100 events / 102 total)
3% other (2 events)
↗ Polyfill `Array.prototype.at` OR replace with `arr[arr.length - 1]`
f_98d2 ReferenceError: globalThis is not defined
98% Chrome WebView 90 (64 events / 65 total)
2% other (1 event)
↗ Old in-app browser. Check who's embedding you (referrer logs)
User-mix context (last 14d, all events):
Chrome 120+ 62%
Safari 16+ 21%
Safari 14-15 4% ← f_c4a1 users
Firefox 120+ 9%
Chrome WebView 1% ← f_98d2 users
Other 3%
If we drop Safari < 16, we lose ~4% of traffic but kill f_c4a1
and 3 other latent compat bugs.
Setting it up
If you’re already capturing client-side errors via raw fetch, the User-Agent of the browser is auto-attached by the server. To make the slice richer (especially for HogQL), also send $browser / $browser_version in properties — the PostHog-shaped alias /v1/track/ does this automatically when called from posthog-js, but if you’re rolling your own you can parse and send:
// In your browser-side error handler
window.addEventListener("error", async (ev) => {
await fetch(`https://api.agentry.sh/v1/logs/${PROJECT_ID}/`, {
method: "POST",
headers: {
"Authorization": `Bearer ${AGENTRY_DSN}`,
"Content-Type": "application/json",
"User-Agent": "myapp-web/1.0", // REQUIRED — Cloudflare 403s default UAs
},
body: JSON.stringify({
message: ev.message,
stack: ev.error?.stack,
url: window.location.href,
user_agent: navigator.userAgent,
tags: {
$lib: "web",
// Optionally pre-parse for cleaner HogQL queries:
// $browser: parsedUa.browser,
// $browser_version: parsedUa.major,
},
}),
});
});
The server parses user_agent into $browser / $browser_version for you, so you don’t strictly need to pre-parse — but doing so means HogQL queries work without JSONExtract gymnastics.
Variations
- “Same query but only for users on our paid plans — do enterprise customers have a different browser mix?”
- “Which OS versions are concentrating errors? iPhone 14.x = old iOS, Android 9 = old Chrome WebView.”
- “Find errors that only happen on mobile (any browser, screen width < 768).”
- “Are there errors only on Cypress/Playwright user agents? Probably a flaky test, not a real bug.”