> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aiaxoniq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Real user monitoring

> Install the aiAxonIQ browser agent, what it collects and deliberately does not, and what the RUM section's five tabs show — sessions, Core Web Vitals, errors and resource timing.

Real user monitoring (RUM) measures your site as your users' browsers
experienced it: page views, sessions, Core Web Vitals, JavaScript errors and how
long each asset took to load. It is measured in the browser, so it sees what no
server-side trace can — a slow network, a heavy bundle, a script that threw
before any request was made.

<Info>
  **Plan entitlement.** RUM data is served only to organizations whose plan
  includes the `rum` feature. Without it, the RUM tabs show **Not included in
  this plan** with the reason, instead of an error. The install snippet itself
  is available whatever your plan, so you can install first.
</Info>

## How browser telemetry arrives

There is no OpenTelemetry step for the browser. A small aiAxonIQ browser agent,
loaded by a snippet in your pages, sends beacons straight to the `/rum` path on
the same host that serves your dashboard — for aiAxonIQ Cloud,
`https://app.aiaxoniq.com/rum`. The agent's own code is served from that host
too, under `/rum-agent/`.

The beacons are authenticated by a **Browser project's agent key**, which is
written into the snippet. That key is public by design — it ships in your page
source, where anyone can read it — so it is not treated as a secret:

* Each project's ingest is **rate-limited** per project. That is the control
  that refuses traffic.
* A project can carry a list of allowed page origins. That list stops another
  site pasting your snippet and polluting your numbers; it is a data-quality
  control, **not** an authentication boundary, because anything that is not a
  browser can simply omit the origin.

### What the agent collects

| Collected                                                                              | Not collected                                                                                                            |
| :------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
| Page views, and Core Web Vitals as each page finishes loading                          | **Session replay** — switched off, both in the snippet and by the server, until its masking has been verified end to end |
| JavaScript errors with their stack, frame URLs stripped of query strings               | **Automatic console capture** — switched off the same way                                                                |
| XHR and `fetch` timings, with query strings stripped and no request or response bodies | **User actions** (clicks and similar) — switched off in the snippet                                                      |
| Static asset timings from the browser's Resource Timing API                            |                                                                                                                          |
| A per-session page-load trace, for the session detail                                  |                                                                                                                          |

<Note>
  **Why replay is off at the server, not only in the snippet.** A snippet is text
  on your page, and anyone can edit it. The server tells the agent which
  features it may run, and it denies session replay and console capture
  regardless of what the page asks for.
</Note>

## Install the snippet

The dashboard's **Add APM project** dialog does not offer the Browser type, so
a Browser project is created and its snippet fetched through the API. You need a
session token — see [Authentication](/get-started/authentication) — and the
**Editor** role or above to create a project.

<Steps>
  <Step title="Find your organization id">
    Every call names your organization as `tenantId`:

    ```bash theme={null}
    TENANT_ID=$(curl -s -H "Authorization: Bearer $SESSION_TOKEN" \
      https://app.aiaxoniq.com/auth/me | jq -r .user.tenantId)
    ```
  </Step>

  <Step title="Create a Browser project">
    ```bash theme={null}
    curl -s -X POST -H "Authorization: Bearer $SESSION_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"name": "storefront-web", "type": "Browser"}' \
      "https://app.aiaxoniq.com/api/projects?tenantId=$TENANT_ID"
    ```

    The response is the new project (`201`); its `_id` is the project id.
    Creating the same name and type again returns the existing project (`200`)
    rather than a second one.
    If you already have a Browser project, list it instead:

    ```bash theme={null}
    curl -s -H "Authorization: Bearer $SESSION_TOKEN" \
      "https://app.aiaxoniq.com/api/projects?tenantId=$TENANT_ID" |
      jq -r '.[] | select(.type == "Browser") | "\(._id)  \(.name)"'
    ```
  </Step>

  <Step title="Fetch the snippet">
    ```bash theme={null}
    curl -s -H "Authorization: Bearer $SESSION_TOKEN" \
      "https://app.aiaxoniq.com/api/projects/$PROJECT_ID/rum-snippet?tenantId=$TENANT_ID"
    ```

    The response is two `<script>` elements: a configuration block carrying the
    project's agent key and id, then the agent loader.
  </Step>

  <Step title="Paste it into every page">
    Put the snippet in the `<head>` of every page you want measured. Paste it
    exactly as returned: the beacon address and the address
    the agent loads its code from must both point at the host that issued it.
  </Step>
</Steps>

**Expected result.** Load a page. In the browser's network tab you should see
the loader fetched from `/rum-agent/…` and beacons sent to `/rum/…` answered
with a success status. Once the first page load has reported, **RUM →
Overview** shows a non-zero **Sessions** and **Page views** count.

To see original file names and line numbers in error stacks, also upload your
source maps — see [Source maps for browser errors](/guides/rum/source-maps).

<Warning>
  **Do not rotate the project's agent key casually.** The snippet already on
  your pages carries the current key; replacing it stops every page that has not
  been updated from reporting.
</Warning>

## What the RUM section shows

The RUM section shows every browser that reported to your organization in the
selected time range. It has no per-project filter.

<AccordionGroup>
  <Accordion title="Overview" icon="gauge">
    **Sessions**, **Page views** and **Users** for the window, then the Core Web
    Vitals. **Users** counts distinct user ids the agent reported; visitors
    without a user id are not counted. **Page views** are navigations the agent
    recorded, not server-side requests.
  </Accordion>

  <Accordion title="Web vitals" icon="chart-line">
    LCP, FID, CLS, TTFB and INP at the 75th percentile, each judged good, needs
    improvement or poor against published thresholds — for example LCP good at
    2500 ms or less and poor above 4000 ms, CLS good at 0.1 or less and poor
    above 0.25, INP good at 200 ms or less and poor above 500 ms. The thresholds
    are returned with every verdict, so the page shows what each was judged
    against. Below the cards, a per-page table gives views and p75 LCP, CLS and
    INP for up to 50 pages, so one slow route stands out from a fast
    average.

    A vital with no samples in the window is marked as not measured rather than
    shown as zero — a zero LCP would claim the page is fast when nothing was
    measured. INP, for example, is not reported by every browser.
  </Accordion>

  <Accordion title="Sessions" icon="users">
    One row per session that **started** in the window: user, start, duration,
    views, errors, entry page, browser, device and country. Expand a row for its
    referrer and campaign parameters, the client build, and its page-load
    waterfall.
  </Accordion>

  <Accordion title="Errors" icon="triangle-exclamation">
    JavaScript errors grouped by a fingerprint computed from the stack, so a
    rebuild that only changes a bundle hash does not create a new group. Each row
    shows occurrences, affected sessions and users, the page and the last time
    it was seen. Expand a row for the stack, with each frame marked
    **Symbolicated** or **Not symbolicated** depending on whether a matching
    source map is uploaded.
  </Accordion>

  <Accordion title="Resources" icon="file-arrow-down">
    Asset timings grouped by host and type, slowest first: requests, average
    duration, time to first byte and bytes transferred.
  </Accordion>
</AccordionGroup>

<Note>
  **At the time of writing, no browser has been verified reporting to a deployed
  aiAxonIQ environment.** The pipeline has been exercised in a real browser against the
  snippet this page describes, and the RUM section is available so that you can
  install it — but treat your first installation as the check, and use the
  expected result above to confirm it.
</Note>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Overview says Nothing has reported in this window">
    **No browser telemetry yet** means no page views and no sessions arrived in
    the window. That is what an un-instrumented site looks like, and waiting will
    not change it. Check that the snippet is in the page's `<head>`, then load a
    page and watch the network tab: the loader should come from `/rum-agent/…`
    and the beacons should go to `/rum/…`.
  </Accordion>

  <Accordion title="The loader loads but no beacons are sent">
    The snippet was probably edited or assembled by hand. The agent fetches the
    rest of its code from the address in the snippet's configuration; if that
    address is missing or points at your own site, the agent fails to load its
    code and sends nothing. Replace the snippet with a fresh copy from the
    `rum-snippet` call.
  </Accordion>

  <Accordion title="Beacons are refused with 403">
    The response body says which of three reasons applies. **Unknown agent key**
    means the key in the snippet is not a current project key — the project was
    deleted, or its key was replaced after the snippet was pasted; fetch the
    snippet again. **Origin not allowed for this project** means the project has
    a list of allowed origins and the page is not on it. **No agent key
    supplied** means the snippet's configuration block is missing or was edited.
    A burst of refusals under heavy load can also be the per-project rate limit.
  </Accordion>

  <Accordion title="Not included in this plan">
    Your organization's plan does not include RUM. The snippet can still be
    installed; the data becomes visible when the plan includes the `rum`
    feature.
  </Accordion>

  <Accordion title="A vital shows as not measured">
    No browser reported that vital in the window. Some browsers do not report
    every vital, and a page that is closed before it finishes loading reports
    none.
  </Accordion>

  <Accordion title="Resources shows zeros or leaves assets out">
    A cross-origin asset served without a `Timing-Allow-Origin` header reports
    zeros to the browser, and those entries are excluded from the averages. Add
    the header on the asset's host if you control it.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Source maps for browser errors" icon="file-code" href="/guides/rum/source-maps">
    Show original file and line numbers in stacks.
  </Card>

  <Card title="APM" icon="chart-line" href="/guides/apm/overview">
    The server side of the same requests.
  </Card>
</CardGroup>
