fastmon Docs

Analytics

Traffic, visitors, errors, and the Experience Score. The field-data dashboards on top of your beacons.

Analytics shows who is on your site, where they come from, which pages and errors they see, and how their visits unfold.

The dashboard

The main Analytics view for a site shows, from top to bottom:

  • Live line: the visitors on the site right now. "Watch live" opens a ticker of the newest events: the orders with their value by default, the whole purchase, or every event. Each row opens its visitor.
  • Headline tiles: Visitors, Pageviews, Pageviews per visitor, and on a shop Orders and Conversion, each with a sparkline over the whole range. The change compares against the same weekdays and hours, the fewest whole weeks earlier that cover the window.
  • Trend chart: the selected tile over the range (?metric=). Orders show as a line or as three lanes, cart, checkout reached, and ordered, each on its own scale.
  • Bots beside the chart type splits the pageviews chart into humans and bots, each bot, or bot type. The tiles and cards keep the page's bot filter.
  • Breakdown: cards for Pages, Page types, Sources, Locations, Devices, Traffic quality, Campaigns, and Access. A menu picks a card's dimension, the card pages through its rows, and a click on a row filters the page.
  • All values of a card open from its title in a pop-up with a search, a second dimension, sortable columns, and a CSV download.
  • Visitor paths: the checkout funnel and the buyer comparison in one card, visit depth, and visitor lists that open the Visitors page.
  • Active hours: pageviews by time of day and by weekday as bars. The heatmap is one toggle away.

Line charts draw each bucket at its end. The running bucket of a count, an hour or longer, is dashed towards a projection of the full bucket once a third of it has passed. Release markers are a thin purple line, tracker releases blue.

See Privacy for what a "visitor" means here.

Shopfloor

The Shopfloor, under Analytics at /shopfloor, draws your shop from above as it happens.

  • Zones are your platform's page type groups: Home, Category (PLP), Search, Product (PDP), Checkout, Account, Content, and Other. Each is tinted by how fast its pages are.
  • Every visitor is a dot in the zone of the page they are on. A tab in the background is drawn faint, and a buyer runs to the exit, where the order counts at once.
  • The window is 5, 15, 30, or 60 minutes. Under the headline stand today's visitors, orders, and Conversion Rate from your midnight, each beside the same weekday last week. Orders count up to the second and say so ("as of 14:32"), and last week runs to the same clock time.
  • A click on a zone zooms into it: its page types, and its top 10 URLs of the last 30 minutes with Pageviews and LCP.
  • For a wall screen, ?window=60&sound=1&kiosk=1 sets the window, the ka-ching per order, and kiosk mode. Sound is off by default.
  • Filters are country, device, page type, and traffic. A filter from another page stays as a muted chip marked "not applied here".
  • It needs store_stitch. A site without it shows nobody and says so.

The API is POST /analytics/live and POST /analytics/live-summary.

Partnerfloor

A partner organization finds the Partnerfloor under Partner in the sidebar. Every live client is one zone.

  • Size and colour: a zone grows with the client's share of your traffic in the last hour and is coloured by its LCP p75.
  • Each zone shows its people, cart and checkout, today's orders, and the change against last week.
  • A click opens the client's Shopfloor in place.
  • Controls: the only filter is the traffic class. Window, pause, kiosk mode, and sound work as on the Shopfloor.
  • Live means an active, approved organization with an activated, active site on an active production application.

The API is POST /organizations/{org_id}/partner/live, polled at meta.next_poll_ms. It needs direct membership in the partner organization with partner:read and analytics:read. It takes only bot_class, and data_total, client_count, and site_count cover listed clients only.

Time range

The range pill in the header sets the window for every chart on the page.

  • Zoom: minus doubles the window, plus halves it, also on the - and + keys. A live window keeps its end at now.
  • Drag across a trend chart to zoom into that stretch. The charts reload at the resolution it gets.
  • Jump to now: while the window lies in the past, a button moves it to the present at the same length.
  • Date and time are fields that apply at once. The expression field shows the current range, such as now-7d, and also takes a past window (7d-3d) or a clock range (14:00-16:30).
  • The timeline at the top of the picker shows the window on the days around it. Drag it, pull an edge, or scroll to zoom.

Resolution

The picker and the command palette offer each bucket width with the number of buckets it gives. A width needs 4 to 1500 buckets over the window.

WidthFitsOn a longer window
Minute25 hourscropped to the last 25 hours
5 minutes5 dayscropped to the last 5 days
15 minutes15 dayscropped to the last 15 days
Hour, 6 hours, day, week, month4 to 1500 bucketsnot offered

Auto picks the smallest width with at most 300 buckets, and days from 28 days on. The last 24 hours get 5-minute buckets, 48 hours 15-minute buckets, and 7 days hourly ones.

Buckets of 6 hours and longer start on your clock: 6-hour buckets at 00, 06, 12, and 18 local time, a day at midnight, a week on Monday. A day across a clock change is 23 or 25 hours long.

Filtering

A filter bar sits next to the time picker on every analytics page. Type a dimension and value, for example country = DE, and press Enter to add a filter chip. The value field suggests the real values of the time range with their pageviews.

The dimension picker lists Page, Country, and Device first, then browser, OS, connection, viewport, referrer, UTM fields, click-ID label, domain, navigation type, protocol, and the checkout stage. Empty values such as "Direct / none" cannot be filtered yet.

Filters live in the URL, so they survive a reload, are shareable, and carry across navigation between views. Multiple chips combine with AND; a comma inside one value means "any of". Click a chip to edit it; its X removes it. The "Filter" button carries a badge with the active count.

Every page starts without bot traffic, so the numbers describe real visitors unless you say otherwise. The filter menu's Traffic control switches between No bots, Bots only, and All, and the page header says which is in force next to the period. The scope is not counted as a filter and survives "Clear all".

Every chip also has an on/off switch. Switched off, the chip keeps its values and stays in place, drawn struck through, and the query runs without it. A switched-off filter narrows nothing and is not counted in the badge, and clicking the same country on the map switches it back on instead of adding a second one. The state travels in the URL, so a shared link opens with the same filters on and off.

The Explorer

The Explorer groups pageviews by any dimension and charts the metrics, or shows the raw rows. Maximize gives it the whole window, sidebar included. "Show all" and the per-row links from the dashboard panels carry the page's filters into it, including exclusions, metric ranges, and the bot switches, and it opens with the numbers the page is about (pageviews and visitors, plus LCP p75 on pages). Clicking a group opens its pageviews in place, and the bar above steps to the next group or back to all.

The beacon rows show the page's HTTP status, and HTTP status >= 400 in the filter lists the pageviews of error pages. Firefox, Safari, and soft navigations report no status, so their rows show a dash and never match. Grouped by HTTP status, they form the "Not reported" group. The group-by picker has a search field.

An Events page sits beside the table, one row per checkout event, filterable by type and opening the visitor a row belongs to. A column says whether the row came from a pageview or from the Shopify pixel.

A pageview opens in a detail with fixed places. Eight facts and six vital tiles sit at the top, and nine collapsible sections below each show a one-line summary. The field search opens the section that holds a value, for example ttfb, and a shared link reopens the same sections.

Results copy as Markdown or download as CSV, with raw values and the unit in the header.

Navigating with the command palette

Cmd/Ctrl+K opens a command menu for the whole app: pages, organizations, sites, time range, resolution, and filters. Enter or → opens a category, ← or Backspace steps back, and Esc closes.

Typing searches across every organization you can reach: your own memberships, the client organizations of any agency you belong to, and the applications and domains inside them. Each hit says which organization it lives in. Applications lead the results, prod before dev among equally good matches, and picking one sets the application filter on the page you are on. Inactive sites and applications are listed and flagged.

Typing a group ("network") lists every page under it, and "API" finds Fetch/XHR.

The same search is available from a script as GET /search.

Error Analytics

Errors is a group in the sidebar with four pages: JavaScript errors, Failed resources, Network Error Logging, and Content Security Policy. Each has its own address, headline, chart, and list. On JavaScript errors:

  • Affected pageviews over time: pageviews with at least one JavaScript error, as a share of all pageviews or, under "Absolute", as a count. Top 5 adds the five errors that reached the most pageviews as lines, and the legend links to each. Dragging across the chart zooms in.
  • An error's own page has the same share and count switch.
  • The list filters by origin: All, First-party (your own hosts), or Third-party. The choice stays in the link, and the chart and error rate still count every error.
  • The list is one row per fault. A row counts every variant of a throw site and says how many signatures it stands for. On the API this is group_variants on POST /analytics/error-types.
  • A row leads with what broke, in a sentence: what happened, whose code it is, the file it was thrown from, how often it occurred and when it last did, to the minute. Each row carries a spark line and a "New" or "Rising" badge, and the list sorts by most frequent, new, rising, or last seen.
  • Ranked by the pageviews an error reached, not by how often it fired. A single visit stuck in a loop is marked as a loop instead of topping the list, and "Most frequent" is still an ordering you can pick.
  • Every error has its own page at /org/<org>/errors/<fingerprint>, which is also its share link. Existing ?error= links redirect there.
  • Pages with the most errors: ranked by how many errors a page threw, not by its error rate.
  • Error origin: how pageviews with an error split between your own hosts and foreign ones. The third bar holds pageviews without an error plus errors with no host to attribute them to.

What broke, and where

An error says what broke in a sentence, even where the site keeps no error messages. The tracker recognizes the browser's wording and sends its shape rather than the text, so a row reads "uc.setServiceAlias was called, but uc does not exist at this point" instead of showing a stack alone.

"Resolve this stack" reads the minified file your visitors actually ran. Each frame comes back with the method it is in, the enclosing module, and the code at that column, syntax-colored and scrolled to the failing call. No source map and no setup on your side. The throwing line is marked.

  • A run of frames in the same vendor bundle folds into one row naming the library. When every frame is a library, the panel says so: the call that made the mistake was cut off at five frames.
  • A frame that only passes the error on is marked as a rethrow, and the cause sits further down.
  • A frame that cannot be read says why: no path was stored, the file sits on somebody else's host, the file is the fastmon tracker, or you deployed again under the same name and the position is gone.
  • The endpoint is POST /analytics/error-types/symbolicate. The same panel sits in the Explorer's row drawer: open a pageview, expand its errors, and the stack resolves there too.

"Where it happens" is the breakdown grid the metric pages carry: page, page type, domain, country, device, browser, OS, connection, navigation, caches, bots, and network. Bots and network are among them, so you can see whether an error reaches real visitors or only crawlers.

An error without message or stack says why: messages or frames switched off, a third-party script without the CORS opt-in, or nothing sent. The chart and the breakdown work either way.

"AI prompt" hands the whole case to an assistant: what broke, the numbers, the resolved stack with the code at the throw site, where it happens, and sample occurrences. It also says what your site does not collect.

Which API calls fail alongside it. POST /analytics/error-types/correlated-requests ranks the fetch/XHR endpoints that fail in the same pageviews, each against its failure share in pageviews without that error. It says endpoints occur together, never that one caused the other.

An error signature is a filter like any other. Every error row links into the Explorer scoped to the pageviews that carried it, and "Error signature" is in the filter list. filters.error_fingerprint_kind says which list the key came from (error or failed_resource).

Your own subdomains count as yours. First party means the same registrable domain as the page, in the error rate, the error origin, the Fetch/XHR split, and the resource list alike.

ScriptError is an error in a cross-origin script loaded without CORS, whose details the browser hides. Load it with crossorigin="anonymous" from a host that sends Access-Control-Allow-Origin. See Tracker → What counts as an error. Where ScriptError is present, the error-types response lists own_subdomain_hosts, usually where the header is missing.

How much detail you see depends on the site's tracker settings: error type, count, and message shape arrive always. The error message needs collect_error_messages, and full stack frames need collect_error_frames.

Failed resource loads

A failed <img>, <script>, or <link> is its own signal, with its own tab, its own rate (failed_resource_rate), and its own curve beside the error rate. It is split into two buckets:

  • Your own hosts: the actionable half. A broken image path, a bundle that 404s after a deploy.
  • Foreign hosts: mostly ad blockers and tracking protection.

Ownership is the registrable-domain rule above. The list groups by host, each with its share of all failed loads, and opening a host shows the individual resources under it. A second view ranks pages by the share of their pageviews that lost a resource.

Hiding a host narrows the totals too: host and exclude_hosts do, ownership does not.

Opening a resource drills into it the way opening an error signature does: the file, a time series, breakdowns over page, browser, device, OS, and country, the visitors affected, and sample beacons. Pass the row's fingerprint to POST /analytics/failed-resources/detail. The error drill-down refuses a resource key.

Failed resources is a filter and a metric of its own, so >= 1 scopes any view to pageviews where something did not load. In the pageview drill-down the failed loads have their own block, separate from the JavaScript errors.

The path is often empty, because it needs collect_error_frames.

Ad-blocked requests to known tracker hosts stay visible as a subset of the foreign bucket, reported as blocked_count: read it as "N excluded as ad-blocked", not as a failure.

The list endpoint is POST /analytics/failed-resources. The error-types endpoint refuses error_type: ["ResourceLoadError"] with a 400 pointing here.

Visitors

The Visitors page lists distinct visitors with start time, duration, page count, country, device, average LCP, and errors. Three columns read the visit at a glance:

  • Outcome: ordered, left the checkout, cart, browsed, or bounced.
  • Source: where the visitor came in, such as Google search, a newsletter, or direct.
  • Journey: one block per page, its width the time spent there and its colour the page type. A red mark flags errors, a check an order.

The summary above the list covers the whole period: visitors, pageviews per visitor, and the share with a JavaScript error, slow visitors (average LCP over 4 s), and buyers. Segment chips (with errors, slow, ordered, reached checkout, cart activity, one page only) set the behavior filters, and each shows how many visitors it lists. "Adjust behavior" opens every filter: pages, errors, duration, LCP, page type, and funnel stage. Orders, checkout, and cart show only on a shop.

A visitor opens in a dialog wherever it is linked: in this list, on NEL and CSP reports, in the Explorer, and on checkout events. On a phone it is a sheet from the bottom, and ?visitor= links to it.

  • The journey shows every pageview in order with Web Vitals, errors, page type, and on shops the checkout stage and cart actions. Checkout events and NEL and CSP reports sit between them, abandoned loads only once you switch them on.
  • The entry and every return from outside show on the timeline and before that page, with any campaign. See arrival.
  • Without pageviews in the period, it lists the visitor's reports and events alone.
  • A click on a page opens its full detail, and "Open in Explorer" lists all of the visitor's pageviews there.
  • Refresh picks up new pages of a visit still going on. The live switch does it every 7 seconds.

A visitor is counted by stitch or session, as count_visitors_by sets. The Minimal preset stores neither and leaves the list empty. See Visitors and sessions.

Fetch/XHR and Server-Timing

The Fetch/XHR view has an aggregate waterfall (per-endpoint start offsets, duration histograms and percentiles, a status-error distribution) plus a per-beacon detail. The Server-Timing view breaks out the metrics your backend reports. Both read fields the tracker adds to each beacon (see the beacon).

An expanded endpoint shows its own p75 or p95 over time with its calls and release markers, and stays in the URL. A page with more than 24 API endpoints keeps 24 of them named, and the rest sum into a nameless other row. Ad-blocked calls in that row do not count as failures.

The Fetch/XHR error rate counts failures on your own hosts, by the same registrable-domain rule as the error rate. Failures on foreign hosts are reported beside it as their own number, mostly the visitor's ad blocker. The panel's 1P/3P filter follows the same rule.

To emit the header and see how fastmon splits it, read Server-Timing headers.

Experience Score

The Experience Score panel breaks the score down by segment (all visitors, desktop, mobile, and slow connections), each with its grade, numeric score, and the per-metric values behind it.

API

Every panel maps to an endpoint under /organizations/{org_id}/analytics/…, most of them to the query endpoint. Others serve histograms, errors, visitors, Fetch/XHR, Server-Timing, LoAF, the checkout funnel, and the Experience Score.

FieldWhat it does
granularityminute, five_minutes, fifteen_minutes, hour, six_hours, day, week, month, or auto by the rule above. Widths under an hour allow at most 1500 buckets, a longer request is a 422.
timezoneAn IANA name such as Europe/Berlin. Buckets of 6 hours and longer start at its boundaries, timestamps stay UTC. Weeks start on Monday either way.
meta.granularity_optionsThe widths with 4 to 1500 buckets over the window.
sample_countThe pageviews behind a row, unweighted under sampling. beacons is its deprecated twin.
url_path, url_key, url_key_setGroup or filter by the URL without its query, by each query key, or by the set of keys. A pageview counts once per key, and meta.pageviews is the denominator.
url_param + url_param_keyGroup by the value of one query key. A key the application does not store answers 422 naming collection.query_values_for.
"" as a text filterSelects the rows without a value: referrer_source: "" answers direct visits. exclude: {utm_campaign: [""]} keeps the pageviews with a campaign.

Only a window of at most 6 hours that ends within 10 minutes of now reads live beacons. Every other window reads the finalized pageviews.

What's next

On this page