Self-declared
const { setUser } = useTraceItX();
setUser({ id: 'u_1042', email: 'jane@example.com', displayName: 'Jane' });
setUser(null); // on sign-out
This is an unauthenticated claim. Anyone who can open a console can call it with any values. It is genuinely useful — most reports come from your own QA and beta users — but it is not evidence.
Verified
To make it evidence, the SDK presents a token your backend signed. Stand up an
endpoint with @traceitx/identity
and point the provider’s identity prop at it:
<TraceItXProvider
config={{ apiKey: 'txx_live_…' }}
identity={{ endpoint: '/api/traceitx-identity', key: user?.id }}
>
Unlike config, which is frozen at mount, identity is live. The SDK mints a
token when key changes — a sign-in or an account switch — and signs out when
it becomes null or undefined. A re-render does not re-mint.
| Prop | What it does |
|---|---|
endpoint | URL of your identity endpoint. It must answer with { token } JSON. |
key | Your signed-in user’s id. Change it to re-mint; drop it to sign out. |
headers | Called on every mint; return auth headers. A rotating access token is never captured stale. |
credentials | Fetch credentials mode. Default 'same-origin'; use 'include' only for a cookie-based cross-origin endpoint. |
fetch | Replace the request entirely. |
The server verifies the token and resolves the person itself, rather than trusting anything the client asserted. Recognition never blocks a report: if the endpoint fails or times out, the report goes out anonymous.
By hand
If you already have a token source, setIdentityToken on the hook takes a JWT
string, a provider function the SDK re-asks as the token nears expiry, or
null on sign-out:
const { setIdentityToken } = useTraceItX();
useEffect(() => {
setIdentityToken(async () => {
const res = await fetch('/api/traceitx-identity');
return res.ok ? ((await res.json()).token ?? null) : null;
});
}, []);
useTraceItX() returns a freshly bound setIdentityToken on every render, so do
not put it in a dependency array; the effect would re-run each render and
re-mint every time. The identity prop holds these rules for you.
The three tiers
A webhook receiver sees data.reporter, resolved server-side:
tier | Meaning |
|---|---|
verified | A valid identity token was presented. This is proof. |
self_declared | setUser was called; nothing was verified. |
anonymous | No person was resolved at all. |
Use data.reporter, not data.report.reporter.user. The latter is whatever
the app passed to setUser — an unauthenticated claim in every case, even when
a valid token was also presented.
And anonymous does not mean “unverified” — it means nobody was resolved.
Treat the three as distinct states, not a confidence gradient. See
Webhooks.
What actually reaches the report
Whatever you pass to setUser is projected down to id, email and
displayName. Extra keys are dropped rather than carried, so passing a whole
user object does not quietly ship your internal fields.