Frontend tracing
Trace what happens in the browser before a request reaches your backend: route navigations, data loading, caught errors and the first page load, in the same OpenTelemetry trace as your API.
Frontend tracing records what happens in the browser before a request reaches your backend. Each click becomes one trace: a span for the navigation, spans for the data it loads, the fetch and XHR requests those make, and your backend’s spans behind them. With server rendering, the first page load also joins the server render’s trace. The same SDK records each session for session replay, and every trace links to the recording of the session it came from.
The guides below set this up per framework with @maple-dev/browser 0.14.0 or later. Here’s one navigation where every API call is fast and the page is still slow:
Each API call takes about 120ms, so the backend looks healthy. The loader makes three of them one after another, each with about 60ms of network on top, and React needs another 250ms to render the result.
acme-web rows come from the browser, the acme-api rows from the backend. They are
one trace because every fetch sent a traceparent header.
Choose your framework
Each guide installs the SDK, connects browser traces to your backend, and wires navigations, data loading and errors into the framework’s own hooks.
- TanStack Router & Start Router events, loaders, TanStack Start SSR
- React Router Instrumentation API, data and framework mode
- Next.js App Router navigations, error.tsx, first load
- Vue & Nuxt Vue Router guards, errorHandler, Nitro
- SvelteKit Navigation hooks, load, built-in server tracing
- Angular Router events, resolvers, ErrorHandler, SSR
- Astro Page loads, view transitions, islands
- Other frameworks Any router, SPA or multi-page app
Quick setup with a coding agent
Copy this prompt into Claude Code, Codex, Cursor or another agent that can run shell commands. It installs the maple-frontend-tracing skill, which detects your framework and follows the matching guide.
Set up Maple frontend tracing in this project.
Install the skill with `npx skills add MapleTechLabs/maple/skills --skill maple-frontend-tracing -y`, then follow it.
My Maple public ingest key is maple_pk_... and my organization is in the US region.
Use your public key from Settings → Ingestion. Without one, the agent uses a placeholder you can replace later. EU organizations should say EU region.
What you get
- Navigation spans.
pageloadfor the first route,navigatefor each one after it, named after the route template (navigate /projects/:id). The concrete path is theurl.pathattribute. A navigation cut short by another click ends withmaple..navigation. interrupted: true - Data-loading spans. Loaders,
loadfunctions or resolvers under the navigation, with their requests under them. - Backend spans in the same trace. Requests carry a W3C
traceparentheader: same-origin automatically, cross-origin for the URLs you list intracing..propagateTraceHeaderCorsUrls - Caught errors. Errors the framework’s error boundaries catch are reported once, next to uncaught errors, on the Errors page.
- Server render joined. The
pageloadspan becomes a child of the server’s span when the HTML response carries aServer-entry or aTiming: traceparent;desc="…" <meta name="traceparent">tag. The server needs OpenTelemetry to write either; each guide shows where. - Session replay. Every span carries the session id, so a trace links to the recording.
Limits
Detailed instructions for each of these are in the guide for your framework.
- Requests after an
awaitcan start their own trace. In the browser, a request inside a data-loading function only joins the navigation’s trace if it starts before the function’s firstawait. Start independent requests together withPromise.all; for a request that depends on an earlier one, the guides show the extra line that keeps it in the trace. - Your API must allow the
traceparentheader. For an API on another origin, addtraceparenttoAccess-Control-Allow-Headersin its CORS configuration, or the browser blocks the request. - Don’t let a CDN cache server-rendered HTML that carries the trace context. Every visitor served the cached page would join the same server trace. Only add the
Server-Timingheader or meta tag to responses rendered for one request.
Browser and server clocks also differ, so a server span can appear to start slightly before the browser request that caused it. Durations are exact.
Related
- Browser SDK reference: every option, including sampling, consent, masking and URL redaction.
- Instrument your application: backend guides, so browser traces continue into your services.