Compass Web SDK: Integration Guide
Audience: Front-end and site developers integrating a publisher site with the Compass Web SDK.
The Compass Web SDK — published as @arcxp/compass-sdk and exposed in the
browser as the global ArcCompass — is Arc XP’s first-party, client-side library
for collecting reader interaction events (page views, video progress, clicks,
and more) and posting them to the event collector. These events train the
recommendation models.
It ships as a single bundled JavaScript file for <script> inclusion, and also
as an npm ESM module for build-pipeline consumers (React / Next). The target is
a roughly one-hour integration: paste a snippet, call init() once, resolve
consent, and call track() for each event.
Quickstart
<script> (function (w, d) { w.ArcCompass = w.ArcCompass || { q: [] }; ["init", "setConsent", "setUserId", "track", "flush"].forEach(function (m) { w.ArcCompass[m] = w.ArcCompass[m] || function () { w.ArcCompass.q.push([m, [].slice.call(arguments)]); }; }); var s = d.createElement("script"); s.async = true; s.src = "https://arc-rec.app-recommend.aws.arc.pub/arc-rec/v1/compass-sdk.iife.min.js"; d.head.appendChild(s); })(window, document);
window.ArcCompass.init({ // Events collector base path for your org. The SDK appends `/events/batch`. domain: "https://<org-id>-config-prod.api.arc-cdn.net/collect-web/v1", apiKey: "<arc-delivery-token>", }); // Single collect-for-personalization gate: pass true once your CMP reports // consent. Nothing is sent or persisted until then. window.ArcCompass.setConsent(true); window.ArcCompass.track("page_view");</script>The rest of this guide walks through each step.
1. Provision a delivery token
Provision a delivery token through the Arc XP Delivery API — see Provisioning tokens through the Delivery API.
The SDK sends this token as the X-API-Key header on every request.
Use a key scoped to the browser events collection (the collect-web API).
That key can post events but cannot reach the content catalog, so it is safe to
embed in page JavaScript.
2. Add the snippet
Place this block in <head>, before any code that calls ArcCompass.*:
<script> (function (w, d) { w.ArcCompass = w.ArcCompass || { q: [] }; ["init", "setConsent", "setUserId", "track", "flush"].forEach(function (m) { w.ArcCompass[m] = w.ArcCompass[m] || function () { w.ArcCompass.q.push([m, [].slice.call(arguments)]); }; }); var s = d.createElement("script"); s.async = true; s.src = "https://arc-rec.app-recommend.aws.arc.pub/arc-rec/v1/compass-sdk.iife.min.js"; d.head.appendChild(s); })(window, document);</script>The snippet defines a tiny stub on window.ArcCompass so calls made before the
bundle loads queue up and replay in order.
The …/arc-rec/v1/… URL is major-pinned, so you receive backwards-compatible
fixes automatically. For production, add Subresource Integrity (integrity +
crossorigin) as shown in Distribution,
which also covers exact-version pinning, the npm (ESM) install, and the
self-host fallback.
3. Initialize the SDK
ArcCompass.init({ domain: "https://<org-id>-config-prod.api.arc-cdn.net/collect-web/v1", apiKey: "<arc-delivery-token>",});domain is the browser events collector base path for your org: the shared
<org-id>-config-prod.api.arc-cdn.net hostname followed by the collect-web/v1
prefix. The SDK appends /events/batch, so events post to
https://<org-id>-config-prod.api.arc-cdn.net/collect-web/v1/events/batch. Arc
provides the exact base URL during onboarding.
4. Resolve consent
Translate whatever your CMP returns into the SDK’s single yes/no gate:
ArcCompass.setConsent(true); // collect-for-personalization grantedEvents that fired before this call are flushed once consent resolves. Nothing is sent or persisted until then. See Consent & Identity for the full state machine.
5. Add the content and site meta tags
Add these tags to each page’s <head> so the SDK can attribute events to the
right content and Site:
<!-- Required. The content item this page represents; it must match the ID the content was ingested under. --><meta name="arc-compass:item-id" content="ARTICLE-ABC123" />
<!-- Optional. The Site this page belongs to — multi-site tenants only. --><meta name="arc-compass:site-id" content="the-daily" />item-id must be present for automatic page_view capture to fire. You can
override either value for a single event with track(type, { itemId, siteId }).
See Events & Reliability for the full resolution order.
6. Track events
ArcCompass.track("video_progress", { itemId: "VIDEO123", eventValue: 0.75 });page_view is captured automatically on load and on SPA route changes — you do
not need to call track("page_view") yourself unless you disable auto capture
(autoPageView: false). item_id and the optional site_id come from the
meta tags you set above; pass itemId or siteId to track() to override them
for a single event. See Events & Reliability.
7. (Optional) Set a known user ID after login
ArcCompass.setUserId("user-abc-123");// Pass null on logout to revert to the persistent anonymous ID.ArcCompass.setUserId(null);A stable, host-managed ID is what makes personalization work across devices. See Consent & Identity.
Configuration reference
ArcCompass.init(options) accepts the following options. Only domain and
apiKey are required.
| Option | Type | Default | Description |
|---|---|---|---|
domain | string | — (required) | Events collector base path for your org, e.g. https://<org-id>-config-prod.api.arc-cdn.net/collect-web/v1. No trailing slash. The SDK appends /events/batch. |
apiKey | string | — (required) | Arc-provisioned delivery token scoped to the browser events (collect-web) collection. Sent as X-API-Key. |
cookieDomain | string | inferred eTLD+1 (e.g. .host.com) | Cookie Domain attribute for the anonymous-ID cookie. Set explicitly for multi-subdomain sites. |
batch.maxEvents | number | 20 | Flush when the buffer reaches this many events. |
batch.flushIntervalMs | number | 2000 | Flush this many milliseconds after the last flush. |
queue.maxBuffered | number | 500 | Hard cap on in-memory queued events. Oldest are dropped on overflow with a console.warn. |
autoPageView | boolean | true | Fire page_view automatically on load and SPA route changes, reading item_id from the <meta name="arc-compass:item-id"> tag (and the optional site_id from <meta name="arc-compass:site-id">). Set false to call track('page_view', { itemId }) yourself. |
debug | boolean | false | Log lifecycle and transport diagnostics. |
onError | (e: ArcCompassErrorInfo) => void | — | Called when the SDK abandons a batch (a terminal 4xx/429, or a 5xx/network failure that exhausts retries). Use it to forward otherwise-silent data loss to your observability. See Error visibility. |
Error visibility
The SDK is fire-and-forget: track() never throws, and a batch that the
collector rejects (or that never gets through) is dropped rather than surfaced
to the page. To make those drops observable, wire onError to your tooling — it
fires only for terminal transport failures, off the user’s interaction path:
ArcCompass.init({ domain: "https://<org-id>-config-prod.api.arc-cdn.net/collect-web/v1", apiKey: "<collect-web token>", onError: (e) => { // e: { message, reason: "rejected" | "exhausted", status?, droppedEvents, eventTypes, cause? } Sentry.captureException(e.cause ?? new Error(e.message), { extra: e }); // or: datadogRum.addError(e.cause ?? new Error(e.message), e); },});reason: "rejected" is a 4xx/429 the collector refused (fix the payload or
key — retrying won’t help); reason: "exhausted" means repeated 5xx/network
failures used up the retry budget. status is absent for network/CORS errors
(no response). Per-event issues (an unresolved item_id, a coerced
event_value) are logged only under debug, not through onError.
Cookie domain inference
When cookieDomain is omitted, the SDK falls back to the last two labels of
location.hostname (e.g. www.example.com → .example.com). This is correct
for most single-suffix TLDs but cannot handle multi-segment public suffixes
(e.g. .co.uk, .com.au, GitHub Pages) — set cookieDomain explicitly in
those cases.
Browser support
The SDK assumes baseline support for fetch with keepalive: true,
crypto.randomUUID (with a fallback when absent), visibilitychange, and
localStorage / sessionStorage / cookies.
Tested matrix:
- Chrome / Edge / Chromium ≥ 90
- Safari / WebKit ≥ 14
- Firefox ≥ 88
The SDK is browser-only. The IIFE bundle is safe to include in a
server-rendered page — it no-ops on import when window is undefined.