What gets traced
Once enableTracing is on, the browser client records the following spans on its own. You don't write any code for these:
| Span | When |
|---|---|
browser_pageload |
The first load of a page |
browser_navigation |
A client side route change |
browser_fetch |
A fetch() call |
browser_xhr |
An XMLHttpRequest |
On top of these spans, the client measures the five Core Web Vitals for every page load and puts them on the browser_pageload span. See web vitals.
A browser_pageload or browser_navigation span is always the root of its trace. Every browser_fetch and browser_xhr span your page makes while that root is open becomes a child of it.
The plain JavaScript client already opens a browser_navigation span for a client side route change on its own, by watching for history and URL changes. It has no router, so it only knows the URL. A framework package with router support adds the matched route pattern, as described below.
What does not count as a navigation
The plain JavaScript client decides a navigation happened by comparing the path of the URL. Only the path, not the query string and not the hash. So these open no browser_navigation span:
| Change | Example | New span? |
|---|---|---|
| The path changes | /products → /products/12 |
Yes |
| Only the query string changes | /products → /products?page=2 |
No |
| Only the hash changes | /products → /products#reviews |
No |
That's on purpose. A hash change usually just scrolls to a section, and ?page=2 is the same page with a different filter. Counting either as a page view would fill your Pages table with duplicates.
Framework packages override this behaviour. Their router decides what counts as a navigation, and they all open a browser_navigation span when the query string changes. Hash changes depend on the router: SvelteKit opens no span, Vue Router does.
What needs a framework integration
Two things need a framework package on top of @flareapp/js:
Route patterns. On its own, a browser_navigation span only knows the URL it navigated to. A framework's router integration adds the matched route pattern, so navigations to the same route group together on the Pages table instead of becoming one entry for every URL. When you open a single trace, you still see the URL. Flare uses the pattern to group pages, not to name the span. See the React, Vue, or Svelte tracing introduction for how each framework package sets this up.
Component mount spans. Timing how long a component takes to mount is not something a browser API exposes on its own. It needs a framework package that hooks into that framework's component lifecycle. These spans use the browser_component span type. See how component profiling works for what that looks like, then the React, Vue, or Svelte profiling introduction for how each framework package sets it up.
Timing your own code
For anything that isn't covered above, for example a slow client side calculation, write a manual span. See manual spans.