Every report carries a single chronological chain, captured automatically. You only write code when you want to add something of your own.
{
"t": 1765800000123,
"seq": 42,
"kind": "network",
"level": "error",
"message": "POST /api/cart",
"data": {
"reqId": 17,
"status": 500
}
}
Kinds
| Kind | Recorded when |
|---|---|
navigation | A route change. See Screen tracking. |
tap | The user interacts with a control. |
console | Your app logs. See Console & network. |
network | A request completes. |
lifecycle | The tab is hidden or restored (visibilitychange). |
error | An uncaught error fires. See Crash reporting. |
custom | You called addBreadcrumb. |
Which kinds are recorded at all is configurable per app on the server — see Server config.
How a tap is labelled
This is the part worth understanding, because you control the output.
A pointerdown is captured, then the SDK climbs at most five ancestors looking
for the nearest interactive element — button, a, input, select,
textarea, summary, label, or anything with role="button" or
role="link". From that element it takes the first of:
aria-label- Visible text, whitespace-collapsed, capped at 48 characters
tag#id- The tag name alone
So aria-label is the lever. A button whose only content is an icon lands in
the trail as tap button unless you label it, and “the user clicked something”
is the crumb that wastes a triager’s time.
There are no component names here. Reports carry DOM-level context — tag,
id, role, aria-label — not framework component names. That is the same on
@traceitx/react, which shares this capture core.
An element that intersects the sensitive mask set is
labelled [masked] and no text is read out of its subtree at all.
Adding your own
traceitx.addBreadcrumb({
message: 'Coupon applied',
kind: 'custom',
level: 'info',
data: { code: 'SUMMER25', discount: 0.25 },
});
addBreadcrumb never throws. An unknown kind coerces to custom and an
invalid level is dropped rather than passed through — instrumentation must not
be able to break the app it is instrumenting.
Put identifiers in data, not in message. data survives as structured fields
an agent can filter on; message is prose, and prose is what gets truncated
first.
The shared clock
t is absolute epoch milliseconds, on the same clock as the session replay —
that is what lets a viewer line a crumb up against the frame that was on screen
when it fired. seq is a monotonic per-session counter breaking ties inside the
same millisecond, so ordering stays stable at high event rates.
Limits
Caps and trimming behaviour — the entry cap, the byte budget, and the trim markers that record what was dropped — are in Errors & limits.