SDK reference
The same API is available as ESM exports (import { track } from "@3x-engine/sdk"), on the
x3 object of the script-tag build (x3.track(…)), and as queue commands
(x3("track", …)). Every method swallows its own errors – tracking can never break your page.
init(options)
Starts the tracker. Idempotent. Options: npm package.
track(name, props?, options?)
Sends a built-in or custom event attached to the current pageview.
track("download_whitepaper", { topic: "pricing" });
track("checkout_started", { items: 3 }, { flush: true }); // send now, the page may unloadname: lowercase snake_case, 1–40 characters.props: up to 20 keys; values string, number or boolean. Strings of unregistered events must look like identifiers (≤ 80 characters, letters, digits, space and. : / # - _, never e-mail or phone numbers) – anything else is dropped. Register an event schema for enums, ranges or free text.- Built-in events validate their props in the browser and on the server (event catalog).
goal(name, props?)
track + immediate send. Use it for events you define as goals.
funnelStep(funnel, step)
Emits funnel_step {funnel, step}; funnel steps of kind funnel_step match on step.
funnelStep("onboarding", "profile_completed");page(path?)
Manual pageview for routers without the History API. Defaults to the current location.
identify(data)
Links the session to a person – hashed in the browser before sending.
await identify({ email: "jane@example.com", firstName: "Jane", form: "contact", traits: { plan: "pro" } });Fields: email, phone, firstName, lastName, externalId, form, traits (≤ 20,
non-personal). Sent only with consent unless the project sets identify.requireConsent = false.
See Identify and leads.
conversion(definition, options?)
Browser conversion beacon (POST {host}/v1/cb) for a
conversion definition with trigger.kind = "beacon" –
for example a booking confirmed in an embedded calendar. Resolves with the event id, or null when
nothing was sent (opted out, bot, no running tracker).
const eventId = await conversion("booking", {
eventId: pixelEventId, // optional: share it with the browser pixel for dedupe
contact: { email: "jane@example.com" }, // optional: hashed in the browser, never sent raw
});eventId: default a new random id. Pass the id your Meta/LinkedIn pixel used so the platform deduplicates browser and server event.contact:email,phone,firstName,lastName– SHA-256 after provider normalization.- Server guards: publishable key and allowed origin (403), body ≤ 4 KB, 4 beacons per minute and
IP (429), one conversion per session and definition. Definitions without the
beacontrigger answer 404, so server-only conversions (quiz, manual WhatsApp, …) cannot be forged from the browser. The abuse guards (engaged session, no test traffic, daily cap, optional server confirmation) still decide whether it is uploaded.
consent(state)
"granted" or "denied". Granting upgrades the session (sessionStorage id, screen, first touch, ad
cookies); denying removes the stored session id. See Consent.
flush()
Sends everything queued now (sendBeacon). Useful before a navigation you control.
getIds()
const { sessionId, pageviewId, attribution, url, test, consent } = getIds();All null (and false) while the tracker is not running. Send sessionId to your server with form
posts so leads, conversions and server events are attached to the visit.
optOut() / optIn()
Stores or removes the opt-out flag for this browser – the same as opening a URL with
?x3_notrack=1 / =0. While opted out nothing is sent.
Preset helpers
Generic helpers whose stored events are identical to the cpi-website2 engine (see Custom events and presets):
| Helper | Event |
|---|---|
quiz.view(variant?) | quiz_view (once per pageview) |
quiz.answer(variant, question, value) | quiz_answer |
quiz.contact(variant?) | quiz_contact |
quiz.submit(variant?) | quiz_submit + immediate send |
cta(label?, section?) | cta_click |
whatsapp(section?) | whatsapp_click + immediate send |
messaging(app, section?) | messaging_click (telegram, signal, messenger, viber, line, wechat, sms, skype, threema) |
calculator() | calculator_used (once per pageview) |
booking(via) | booking {via} + immediate send |
video.track(element, {id?, format?}) | tracks a <video> without controls |
video.custom(id, {format?, src?}) | returns a tracker for YouTube/Vimeo/custom players (Video) |
bridges.funnelStage(stage, variant?), bridges.quizAnswer(…), bridges.funnelEvent(event) | drop-in replacements for cpi-website2's funnelBeacon hooks |
version
x3.version – the SDK version string.
Debugging
init({ debug: true }) (or data-debug) exposes window.__x3 with the current state (session,
consent, test flag, wire state, queued events) and flushNow(), and logs diagnostics to the
console. The API adds an x-3x-debug response header with the ingest result outside production.