Interpret Web Vitals, flag performance impact, and session data in the Flaggr analytics dashboard
Last updated October 25, 2026
Analytics Dashboard
The analytics dashboard shows real-user performance data from browser analytics, split by the flag variants each event carried, plus first-party admin analytics for the Flaggr console workflow. Navigate to Console > [Project] > Analytics to access it. Its tabs are Overview, Heatmap (pages by browser), Browsers, Versions, Pages, Flags, Errors, Performance and Mobile.
Admin Analytics Tools
The Overview tab's More analytics panel links to two first-party console analytics pages (and to the project's health heatmap):
| Tool | Route | What it shows |
|---|---|---|
| Admin Funnel | /console/[slug]/analytics/admin-funnel | Users moving from flags index to flag detail to toggle or targeting-rule activation |
| Adoption Cohorts | /console/[slug]/analytics/adoption-cohorts | Weekly projects that create flags and return to view them |
These pages use admin events collected by the Flaggr console itself. See Admin Analytics for event definitions, test data generation, and API details.
Site, Filters and Range
Pick the Site in the header; a project without Sites reads the events stored under its own ID. The page, device (desktop, mobile or tablet) and traffic filters narrow the KPI row and the Overview, Heatmap, Browsers, Versions, Pages and Flags tabs, and the traffic filter limits them to one flag variant. Errors and Performance show all traffic, and the Mobile tab has no filters. The range comes from the console's time picker: 24 hours, 7 days or 30 days (90 days shows the last 30 days, the longest range the analytics routes read). Live feed opens the latest events (see Live Event Feed).
KPI Row
The top row, above every tab except Mobile, shows four figures for the selected range and filters:
| KPI | What it shows |
|---|---|
| Total sessions | Sessions in the range, with their page views and the change against the previous period |
| Error rate | Share of sessions with a JavaScript error, and the browser that drives most of the error sessions |
| LCP p75 | 75th-percentile Largest Contentful Paint, and the share of page loads rated good |
| Flags on this traffic | Flags whose values the events carried, and how many show degraded real-user impact |
The figures leave out events sent from an origin other than the Site's domain. When there were any, a quiet line under the KPIs (and under a browser drilldown's KPIs) says how many, for example "3 events from other origins were hidden — check the Site's domain (shop.example)." Check that the Site's domain covers the pages the script runs on (see Trust marks).
Querying via API
Access is checked against the project that owns siteId. A projectId query parameter that names a different project is ignored; it never grants access to another project's site.
Site ids are generated by Flaggr (site_…) when you create a site; use the returned id as the analytics script's data-site-id, and as siteId in these queries and in mobile batches. The optional slug is a label that must be unique within the service. Reserved slugs (default, flaggr-marketing, flaggr-showcase, project ids) are refused with 400, and a duplicate slug returns 409. The site's serviceId must belong to its projectId (404 otherwise). Sites created earlier keep their ids. A project id used as siteId always reads that project's own events.
A site created before site ids were server-generated whose id belongs to other data (another project's id, a reserved or showcase id) is skipped in flag exposure, audience, rollout RUM checks and alert impact. Its health, guardrails and new flag links answer 409 SITE_ID_NOT_OWNED; a site on another project's service answers 409 (SITE_SERVICE_MISMATCH on guardrails, SITE_SERVICE_NOT_IN_PROJECT on health and links). Delete it and create the site again. Site health needs read on the site's service and environment (production when unset).
curl "https://flaggr.dev/api/analytics/overview?siteId=proj_abc123&range=24h" \
-H "Authorization: Bearer <token>"Response:
{
"visitors": 1842,
"pageviews": 5231,
"avgSessionDuration": 124500,
"bounceRate": 34,
"excluded": { "untrustedEvents": 12, "untrustedSessions": 3 },
"range": "24h"
}Web Vitals
The Overview's Web vitals scorecards show the p75 of real-user samples for LCP, CLS, INP and TTFB, rated against Google's thresholds, with the share of good, needs-improvement and poor samples and the change against the previous period (when that period had at least 20 sessions and 20 samples of the vital). The Performance tab's Vitals over time charts the hourly p75 of LCP, CLS, INP, FCP or TTFB, with the good threshold as a dashed line.
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| LCP | ≤ 2500ms | ≤ 4000ms | > 4000ms |
| CLS | ≤ 0.1 | ≤ 0.25 | > 0.25 |
| INP | ≤ 200ms | ≤ 500ms | > 500ms |
| TTFB | ≤ 800ms | ≤ 1800ms | > 1800ms |
| FCP | ≤ 1800ms | ≤ 3000ms | > 3000ms |
A browser sends a vital only where it can measure it: Firefox and Safari send no CLS. LCP carries the element that painted it (elementSelector: its tag, #id and first two classes), and TTFB the document's Server-Timing spans. See Browser Analytics for when each vital is sent.
To compare variants, use the Flags tab (see Flags Tab) or the API's flagKey view below.
Querying vitals via API
# All vitals
curl "https://flaggr.dev/api/analytics/vitals?siteId=proj_abc123&range=7d" \
-H "Authorization: Bearer <token>"
# Vitals filtered by flag
curl "https://flaggr.dev/api/analytics/vitals?siteId=proj_abc123&range=7d&flagKey=new-checkout" \
-H "Authorization: Bearer <token>"Response:
{
"vitals": [
{ "metric": "lcp", "p50": 1200, "p75": 1850, "p95": 3200, "count": 4521 },
{ "metric": "cls", "p50": 0.03, "p75": 0.08, "p95": 0.18, "count": 4521 },
{ "metric": "inp", "p50": 85, "p75": 145, "p95": 320, "count": 3890 }
],
"range": "7d"
}Pre-aggregated data
Every hour a job recomputes the last 3 hours of the analytics_vitals_hourly rollup: percentiles per metric for all traffic, per browser, per browser version and per flag set. Ranges other than 1 hour read the rollup when it has rows for the window, else the raw events. The per-flag view (flagKey) reads only the rollup. The rollup holds only trusted events, so a member's includeUntrusted=1 reads the raw events instead.
Flags Tab
Flag impact on browser experience compares treatment and control for every flag with exposure in the range, sorted by real-user health: the treatment's share, exposed sessions, and the change in LCP p75, CLS, INP and error rate against control. Each cohort needs at least 20 sessions. Degraded segments lists flag, browser and page combinations that breach a guardrail. Select a flag to see its sessions by browser and every variant seen on browser traffic. Variant and funnel analysis shows evaluation outcomes per variant and conversion funnels for the most-exposed flags.
Querying flag impact via API
curl "https://flaggr.dev/api/analytics/flag-impact?siteId=proj_abc123&range=24h" \
-H "Authorization: Bearer <token>"Response:
{
"impact": [
{
"flagKey": "new-checkout",
"variants": [
{ "variant": "control", "pageviews": 2100, "sessions": 820, "lcpP75": 1900, "avgCls": 0.05 },
{ "variant": "v2", "pageviews": 2050, "sessions": 810, "lcpP75": 1650, "avgCls": 0.04 }
]
}
],
"range": "24h"
}In this example, the v2 variant shows a 13% improvement in LCP p75 and a 20% improvement in CLS compared to control.
Variant Statistics
For detailed per-variant analytics on a specific flag, use the variant stats endpoint. It and the funnel analysis below read recorded evaluations and outcome events, not browser analytics (see Conversion Rates by Variant):
curl "https://flaggr.dev/api/analytics/flags/new-checkout/variants?projectId=proj_abc123&environment=production&period=7d" \
-H "Authorization: Bearer <token>"Response:
{
"flagKey": "new-checkout",
"environment": "production",
"period": "7d",
"variants": [
{
"variant": "control",
"evaluations": 12500,
"conversions": 625,
"conversionRate": 0.05,
"avgEventValue": 42.50,
"latencyP50": 3.2,
"latencyP99": 18.5
},
{
"variant": "v2",
"evaluations": 12300,
"conversions": 738,
"conversionRate": 0.06,
"avgEventValue": 45.20,
"latencyP50": 3.1,
"latencyP99": 17.8
}
],
"totalEvaluations": 24800,
"totalConversions": 1363,
"overallConversionRate": 0.055
}Funnel Analysis
Analyze multi-step conversion funnels segmented by flag variant:
curl "https://flaggr.dev/api/analytics/funnel?projectId=proj_abc123&flagKey=new-checkout&steps=page_view,add_to_cart,checkout,purchase&environment=production&period=7d" \
-H "Authorization: Bearer <token>"Response:
{
"flagKey": "new-checkout",
"steps": ["page_view", "add_to_cart", "checkout", "purchase"],
"funnelSteps": [
{ "step": "page_view", "stepIndex": 0, "totalUsers": 5000, "byVariant": { "control": 2500, "v2": 2500 }, "dropOffRate": 0 },
{ "step": "add_to_cart", "stepIndex": 1, "totalUsers": 1200, "byVariant": { "control": 550, "v2": 650 }, "dropOffRate": 0.76 },
{ "step": "checkout", "stepIndex": 2, "totalUsers": 800, "byVariant": { "control": 350, "v2": 450 }, "dropOffRate": 0.33 },
{ "step": "purchase", "stepIndex": 3, "totalUsers": 600, "byVariant": { "control": 250, "v2": 350 }, "dropOffRate": 0.25 }
],
"overallConversionRate": 0.12
}Live Event Feed
Live feed in the header opens the Site's latest 50 events, refreshed every 5 seconds while it is open. Filter it to page views, vitals, errors or mobile events. Each entry shows:
- The event type and a label (for example
LCP 1650orBrowser error) - The time
- The page
- The browser and country
- How many flags the event carried (hover for their values)
Like the API, the feed leaves out events from other origins.
Querying recent events via API
curl "https://flaggr.dev/api/analytics/events?siteId=proj_abc123&limit=50" \
-H "Authorization: Bearer <token>"Response:
{
"events": [
{
"id": 12345,
"type": "webvital",
"url": "https://example.com/checkout",
"timestamp": "2026-03-20T10:30:00.000Z",
"country": "US",
"browser": "Chrome",
"flags": { "new-checkout": "v2" },
"data": { "metric": "lcp", "value": 1650, "rating": "good", "_src": "worker", "_c": "3f9a1c0b7e42" }
}
]
}url is the page's full URL as the ingest stored it, after scrubbing, and data carries the ingest's trust marks (see Events for every field).
Mobile Tab
The Mobile tab summarizes the events your iOS and Android apps send to POST /api/ingest/mobile-events: events, active installs, searches, scan completion, top events and platforms. Apps send no Origin, so their events are stored as untrusted: the tab still counts them all, but rollout guardrails ignore them. With no events, the tab shows what to send for the ID it reads:
- A Site with a generated
site_…ID: send that ID assiteId. No key is needed. - A Site whose ID isn't a generated one (a reserved ID such as
flaggr-marketing, a Site whose ID is its project's ID, or an older slug or UUID ID): the endpoint can refuse it without a key. Send it assiteIdwith the project's SDK key or a project API token asAuthorization: Bearer, or use Create a Site and send the new Site'ssite_…ID. - No Site (the project has none, or
?siteId=names the project or an ID that isn't one of its Sites): the tab reads the project's ID. The endpoint takes that ID only with the project's SDK key or a project API token asAuthorization: Bearer. A project without Sites gets a Create a Site link to the service's Sites tab; a project with Sites can pick one in the header.
Demo Mode
When demo mode is enabled on a project, Flaggr seeds ~24 hours of synthetic analytics data with realistic distributions. This lets you explore the full dashboard without waiting for production traffic. Demo data includes:
- Page views across multiple URLs
- Web Vitals with natural variance (mostly good, some needs-improvement)
- Sessions with varying durations
- Flag variants showing measurable impact differences
Next Steps
- Browser Analytics — Install and configure the analytics script
- Admin Analytics — Measure console activation funnels and adoption cohorts
- Analytics API Reference — Full endpoint reference
- Analytics & A/B Testing — Use analytics to measure experiment outcomes