Account linking connects TRACIO's device-level identification to your own concept of a user. By passing your internal account ID as linkedId, you tell TRACIO which visitor IDs belong to the same authenticated person — across browsers, devices, and sessions.
Every visitor TRACIO sees gets a device-level identifier (see Identification). On its own, that identifier knows nothing about your users — it just recognizes returning devices.
linkedId closes that gap: it is the accountId of the currently authenticated user, sent alongside the normal identification request. When two or more visitor IDs share the same linkedId, TRACIO links them into a single account, powering the dashboard's Connections page, cross-device identity, and account-takeover (ATO) drift detection — see What You Get.
Without linkedId, TRACIO only sees anonymous devices — it has no way to group them by account.
Account linking is an additive parameter on the same integration you already have. No backend code is required.
Add lid to the existing script tag, alongside your public key:
<!-- before --><script src="https://edge.tracio.ai/s.js?k=PUBLIC_KEY" async></script>
<!-- after (only once the user is authenticated) --><script src="https://edge.tracio.ai/s.js?k=PUBLIC_KEY&lid=ACCOUNT_ID" async></script>If you use @tracio/sdk, pass linkedId in the config:
import { Tracio } from "@tracio/sdk"
const tracio = Tracio.init({ publicKey: "5ca175fc...", linkedId: user.id,})linkedId is read once, at the moment the agent loads. If your script tag or Tracio.init() call runs before login, you need to make sure linkedId is included once auth state is known:
lid=ACCOUNT_ID after login.Tracio.init() again with the same publicKey returns the existing instance and ignores the new config — it does not pick up linkedId. Call tracio.destroy() first, then Tracio.init({ publicKey, linkedId: user.id }). Alternatively, defer the first Tracio.init() call until the user's auth state is known.linkedId only after a real login. Never send it for guests or anonymous visitors, and never fall back to a placeholder like "guest" or "anonymous" — a shared placeholder value merges unrelated people into the same account.linkedId is truncated at 256 bytes. Ordinary IDs are far under this; don't pass large tokens (e.g. full JWTs).linkedId is stored alongside your workspace's other event data and is shown back to you in the dashboard as the account identifier on the Connections page — it is not hashed or anonymized for display, since you need to recognize the account.
Internally, TRACIO's cross-device matching (fanout detection, ATO behavioral baselines) uses a separate, environment-scoped one-way hash of linkedId — never the raw value — so matching logic never depends on and never exposes the plaintext value beyond your own dashboard and webhooks.
This is why linkedId should be an opaque internal ID rather than an email address or name (see Rules): it is visible to you as your account identifier, so it shouldn't carry more personal information than you already have.
s.js (or the agent's identification request) includes both k= and lid= parameters.linkedId is integrated, it shows a setup notice; that notice disappears within a few minutes of the first request carrying lid=.Once linkedId is flowing, TRACIO unlocks: