Tag JS API
Once the tag loads it exposes window.axo (window.vibeTag is a permanent alias). There is no pre-load queue: check that window.axo exists, or make calls after the load event. Personalization zones are authored declaratively with data-vt-* attributes.
Install
One deferred script before </head>. See Getting Started for the full install (Shopify, anti-flicker) and Site Speed for the load model.
<script src="https://axoapp.ai/tag.js?site=YOUR_SITE_ID" defer></script>Identify a visitor
// Call after login, checkout, or a form submit.
axo.identify({
email: "customer@example.com",
external_id: "usr_12345",
// any additional traits become profile attributes:
plan: "pro"
});Conversions & cart
// SPA / custom-flow escape hatch – fire the primary goal manually.
// Set the cart before recording the conversion:
axo.setCart([
{ sku: "SKU-1", quantity: 2, price: 24.0 },
{ sku: "SKU-2", quantity: 1, price: 101.0 }
]);
axo.convert(149.00); // optional revenue valueCustom events
Pair a custom event with a custom event conversion goal (Admin → Account → Conversion goals) to optimize for outcomes the tag cannot see on its own.
// Report a business fact only your code knows. A custom_event goal whose
// event_type matches fires exactly like a built-in goal.
axo.event("quote_started", { plan: "pro", seats: 12 });Read session state
axo.getSessionId(); // "sess_…" – current session UUID
axo.getVisitorId(); // "vis_…" – persistent, first-party cookie
axo.getSegment(); // "deliberator", or null before scoring
axo.lastRender(); // RenderSnapshot, or null before personalization
// Fired once the visitor has been scored (detail: { segment_id, confidence }).
window.addEventListener('vt:segment_ready', (e) => console.log(e.detail));Single-page apps & hydrated frameworks
Install the tag once in your root layout. It observes browser navigation through history.pushState / replaceState / popstate, and on every pathname change it records a new pageview, re-checks URL goals, re-attaches form tracking, and re-runs personalization against the freshly mounted DOM. Query-string-only changes do not count as a navigation. Because the tag swaps content in the DOM, a framework re-render that replaces a personalized node restores the original markup in that node – inspect axo.lastRender() when a variant appears to revert, and prefer zones whose container the framework does not re-create on state changes.
Method reference
| Method | Type | Description |
|---|---|---|
| axo.identify(traits) | traits: object | Attach a known identity (email, external_id, arbitrary traits) to the current anonymous session. Merges cross-device sessions. Traits must have string values. No-op in preview, without consent, and on passive-mode sites. |
| axo.convert(value?) | value?: number | Fire a conversion for the primary goal. The escape hatch for SPAs where no goal URL is navigated to. If value is omitted it is read from a [data-vt-revenue] element. No-op in preview or when consent has been denied. |
| axo.event(type, properties?) | type: string, properties?: object | Report a site-defined event (lower_snake_case, 2–64 chars; built-in names like form_submit are reserved). Lands in the event stream and fires any custom_event goal with a matching event_type. Properties are shallow primitives. No-op in preview or when consent has been denied. |
| axo.setCart(items) | items: LineItem[] | Persist cart state so the next convert attaches line_items (powers CAPI content_ids + the co-purchase recommender). |
| axo.getSessionId() | → string | The active session ID (UUID). |
| axo.getVisitorId() | → string | The persistent visitor ID (survives sessions, first-party cookie). |
| axo.getSegment() | → string | null | The current visitor's primary segment ID. |
| axo.whenVisitorReady() | → Promise<string> | Wait for visitor identity resolution before reading or sharing the visitor ID, including cross-domain handoffs. |
| axo.getResumedContext() | → object | Context from a triggered-email token redemption (fire_id, cart resume URL, …) when the visitor lands via a ?vt_token= link. Returns an empty object otherwise. |
| axo.lastRender() | → RenderSnapshot | null | The last personalize pass, per zone (applied / holdout / no_variant / not_found / render_error) – for QA and DevTools. |
Authoring attributes
These data-vt-* attributes are part of the public authoring surface – add them to your markup so the tag can find zones and read commerce context. A data-vt-zone attribute supplies a stable selector; you still need a configured zone and active content in AXO. See Create a zone.
| Attribute | Type | Description |
|---|---|---|
| data-vt-zone | string | Marks an element as a named personalization zone (the DOM slot AXO can swap or fill). |
| data-vt-revenue | number | On a goal page, the conversion revenue to record. |
| data-vt-category | string | Tags the current page/product category for behavioral scoring and reco context. |
| data-vt-line-item | container | Marks a cart/line-item element; on the same element, data-vt-product-id / -sku / -url / -name / -quantity / -price supply its fields (a zero-config alternative to axo.setCart). |
| data-vt-breadcrumb | string | Supplies breadcrumb context for taxonomy and page-type detection. |
Consent
By default the tag runs in implicit-consent mode. To honor a visitor's refusal, set window.vt_consent = false (or the vt_consent cookie to denied) from your CMP, or enable AXO's built-in banner – see Privacy, Consent & Compliance. While consent is denied, behavioral events, identify, convert, and event no-op. Passive-mode sites also block identify.