Compass Web SDK: Consent & Identity
Consent and identity are tightly coupled in the Web SDK: no identifier is created, read, or persisted until consent is granted, and the identity the SDK resolves is what personalization is keyed on. This page covers both.
Consent
The SDK is CMP-agnostic. It does not parse IAB TCF / GPP / vendor strings
itself; the host translates whatever its CMP returns into a single yes/no
decision and passes it to setConsent.
Single gate
The Web SDK has one consent purpose — collect-for-personalization — expressed as a plain boolean. In v1 there is no separate analytics-only collection mode and no ephemeral-ID “soft-gate”: consent granted means collect with a stable identifier; not granted means collect nothing.
ArcCompass.setConsent(granted: boolean);State machine
| State | Trigger | Behavior |
|---|---|---|
unknown | Initial; before setConsent | Events queue in memory (subject to the 500-event cap) and wait. Nothing is sent or persisted. |
granted | setConsent(true) | Queue drains; events fire normally; future events flow live under a stable ID. |
denied | setConsent(false) | Queue is dropped; any persistent ID is wiped; future events are dropped at track() time. |
Consent can be revised at any time — calling setConsent again applies the new
decision to subsequent events. Events already in flight when consent changes are
not recalled.
No pre-consent leak
Before setConsent is called, the SDK makes no network request and no
persistent-storage write. Events captured pre-consent buffer in memory and
flush on grant; on denial the buffer is dropped and any persistent ID is wiped.
Mapping a CMP to the gate
The host maps its CMP’s signal to the single boolean, e.g.:
// OneTrustwindow.OptanonWrapper = function () { const groups = OptanonActiveGroups.split(","); ArcCompass.setConsent(groups.includes("C0004")); // personalization group};Identity & sessions
Identity is host-primary. The SDK uses the ID you set via setUserId()
as-is, and generates its own anonymous ID only when you do not set one.
setUserId(userId) — the preferred path
Call this with the ID you already have for the visitor. It may be either:
- a logged-in user ID, or
- your own anonymous / visitor ID (many sites already assign one to signed-out visitors; if you have it, pass it).
A stable, host-managed ID is what makes personalization work across devices: the same ID on a phone and a laptop shares one history. Prefer it over the SDK’s per-device fallback whenever you can.
ArcCompass.setUserId("user-abc-123"); // logged-in or host visitor IDArcCompass.setUserId(null); // revert to the SDK anonymous fallbackThe value is held in memory only — the SDK never writes it to a cookie or
storage. You own its persistence. A blank or whitespace-only string is treated
the same as null.
Anonymous fallback — only when you set no ID
When no host ID is set (and consent is granted), the SDK generates a UUID and writes it to:
- a first-party cookie
arccompass_aidwithDomain=<cookieDomain>; Max-Age=63072000; SameSite=Lax(Secureis added onhttpsorigins), and localStorageunder the same key, as a mirror.
Read priority: cookie → localStorage → generate. If a value is found in one
store but not the other, the SDK writes it back to repair the mirror. This
fallback is per-device and less durable than a host-managed ID, but it makes a
low-effort, out-of-the-box integration work with no identity wiring. A host-set
ID always takes precedence over arccompass_aid.
cookieDomain is inferred from the current host by default; set it explicitly
in init() for multi-subdomain sharing (e.g. .example.com).
getUserId() — keep the recommend read path coherent
The user_id the SDK puts on events must be the same raw value your
recommend read-path query uses. The event collector and the recommendation read
API pseudonymize user_id identically, so personalization silently breaks if
the two paths send different raw values.
getUserId() returns the SDK’s resolved identifier so you can forward the
identical value:
// When calling the recommend API from the browser:const userId = ArcCompass.getUserId();if (userId) { const res = await fetch(`${RECOMMEND_URL}?user_id=${encodeURIComponent(userId)}`, { headers: { "X-API-Key": deliveryToken }, }); // ...render recommendations}It returns:
- the host-set ID when
setUserId()has been called (regardless of consent — it is your value, never persisted by the SDK); - otherwise the persistent anonymous ID once consent is granted;
- otherwise
null— before consent (nothing may be read or written yet, and there is nothing to personalize) or beforeinit().
Session ID
The SDK manages a session ID transparently:
- generated on the first event and stored in
sessionStorage(arccompass_sid) for the tab; - mirrored in a short-TTL cookie (
arccompass_sid, plusarccompass_slsfor the last-activity timestamp) so reloads stay within the same session; - slides on a 30-minute inactivity window — the next
track()after the window expires mints a fresh session ID.
session_id is sent on every event and is used server-side to group a visit’s
interactions into one personalization session. A per-call override via
track(type, { sessionId }) is honored.
Consent gating
There is a single consent gate (see above). There is no ephemeral-ID soft-gate:
before consent is granted the SDK creates and reads no persistent identifier,
and on denial any persistent ID is wiped. Once granted, events carry the stable
identity (host-set ID or the anonymous arccompass_aid) and the SDK-managed
session ID.
Safari / ITP 7-day caveat
Both cookies set from JavaScript and localStorage entries are subject to
Safari’s Intelligent Tracking Prevention 7-day cap on script-writeable storage.
There is no client-only workaround, and this applies to the SDK’s arccompass_aid
fallback. Returning visitors after seven days of no interaction may appear as
new anonymous IDs, splitting their history. A stable host-managed ID passed
to setUserId() (persisted server-side or in a first-party context you control)
is the durable way to avoid this.