Docs

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 unload
  • name: 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 beacon trigger 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):

HelperEvent
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.