user.id— optional. A stable ID enables user-based ad controls. Seeuser.context.id— optional. A chat ID enables controls for that conversation. Seecontext.
user.id, keep it stable for at least the whole session, and across sessions wherever your privacy policy allows. Omitting it skips user-based retargeting, campaign repeat limits, per-user abuse limits, and user-linked transcript storage. Contextual matching still works, as does chat pacing when context.id is supplied. We do not generate an ID.
The IDs support these features:
- Frequency capping — limits how often the same user sees the same campaign: by default at most 20 times a day, and not for 24 hours after they click it. Needs a persistent
user.id; a fresh id each session resets these limits. Withcontext.idtoo, a campaign is not shown twice in the same chat within 2 minutes. - Ad pacing — controls how often ads appear within a conversation. Uses
context.id. - Better targeting — DSPs can optimize bids on user-level signals. Needs a persistent
user.id. - Accurate analytics — your dashboard reflects real unique users and conversations.
context.id
The optional chat id: a unique id for the current conversation. If supplied, it must be non-blank and 1–100 characters. Use the same context.id for every request in one chat, and a new one when the user starts a new conversation. Chat repeat checks also need user.id.
Without it you still get ads, but we can’t pace ads or avoid repeats within a conversation. We don’t generate a chat ID for you.
Rules:
- One
context.idper conversation, not per user - Store it in
sessionStorage(browser) or generate it per conversation (server-side) - Reset it when the user starts a new chat
Browser Example
Server-Side Example
user.id
An optional anonymous id for the user. It is yours: send whatever key identifies the person in your own system. It never has to mean anything to us, and it is never matched against another publisher’s ids. Supplied IDs must be non-blank and at most 100 characters. You can omit the entire user block when you have no other user fields to send. Age checks still apply when an age is sent without an ID.
Persistent (recommended):
- Store it in
localStorage, a cookie, or your own user store - Reuse it across sessions so DSPs can build better bidding signals
- Use anonymous UUIDs — never PII (email, name, phone, etc.)
- Generate one UUID when the session starts and reuse it for every request in that session
- Frequency capping and pacing still work within the session; cross-session targeting won’t apply
- Never mint a new id per request: that defeats capping entirely and looks like invalid traffic
Browser Example — Persistent
Browser Example — Per session
Publishers who persist
user.id across sessions see higher fill rates and CPMs than those who don’t. We recommend it where your privacy policy allows.user.extended_ids
user.id names the person only within your app. To name them across publishers, send hashed identifiers in user.extended_ids:
Anything that isn’t a lowercase SHA-256 hex is refused, so an unhashed address never reaches us. Only send these where your privacy policy allows.
Device and location
Identity isn’t the only thing that decides whether a campaign can bid. Senddevice.geo.country, device.type and device.os on every request. Without the user’s country, every campaign that targets a country is skipped, and device-targeted campaigns can’t match without type and os. device.ip and device.user_agent are only fallbacks. See device.
Next steps
Impression Billing
Make sure every ad you show gets counted and paid.
Best Practices
Timeouts, rate limits, errors, and fill rate.
