Start journeys from your site, record analytics events, and credit purchases to the journey that earned them.
Every event goes through one call, track(eventName, props?, opts?), to one
endpoint. What happens to it depends on opts.trigger:
The event name must match the event configured on the journey's Event Trigger node, exactly.
A journey listening for add_to_cart will never fire for addToCart. Agree the
names once with whoever builds the journey, then keep them stable.
Add data-xenia="<event>&<interaction>" to any element. Elements added to the page
later are picked up too, and every attribute fire is a journey trigger.
<button data-xenia="signup&click">Sign up</button>
<section data-xenia="pricing&view-port">Pricing</section>
<div data-xenia="landing&page-load"></div>In React, <XeniaTrack> does the same without the attribute:
import { XeniaTrack } from "@xenia-martech/sdk-js/client/react";
<XeniaTrack event="signup" on="click" as="button" props={{ placement: "footer" }}>
Sign up
</XeniaTrack>;// Browser
xenia.track("add_to_cart", { productId: "p1", price: 49.99 }, { trigger: true });
// Server
await xenia.track("add_to_cart", {
trigger: true,
identity: { userId: "c1" },
properties: { productId: "p1", price: 49.99 },
});Every browser event carries the visitor's identity, UTM parameters, journey, and the
page's url, path and query automatically. On the server, bind those once per
request (see Server-side).
With the default trigger: false, track() records a fact for analytics and
reporting.
track("ctaClick", { productId, label: "Buy now" });
track("pageView", { referrer: document.referrer });consent({ analytics: true }) is called.
Earlier events are queued and flush once consent is given.respectDnt: false.pageView, ctaClick, formSubmitted, and
more) autocompletes in TypeScript. Other names are recorded as custom events.An analytics event needs at least one way to know who it belongs to: the
visitor id, a userId, email or phone, or a utm_id. An event with none is
dropped.
In the browser the visitor id is resolved for you, so anonymous events still count. Once you know who the visitor is, tell Xenia:
xenia.identify("<your customer id>");identify() keeps the id locally and links the visitor to that customer in the
background. For a customer id of your own, pass it as identity.userId. There is
no customerId field on events.
xenia.consent({ analytics: true, marketing: false, personalization: false });The browser client also writes the consent to a xenia_consent cookie, so your
server can read it with getConsent() or, in Next.js, consentFromNext().
A purchase is a track() whose name is a recognized conversion name, such as
purchase or order_complete. For it to be recorded and credited correctly,
include all of these:
In the browser, utm_id is captured from the landing URL and added for you. On the
server, pass it yourself, since there is no URL to read it from.
await xenia.track("purchase", {
trigger: true,
eventId: "ord-1001",
identity: { email: "buyer@example.com" },
consent: { analytics: true },
properties: {
customEventName: "purchase",
orderId: "1001",
orderValue: 120,
currency: "USD",
utm_id: "<from the journey link>",
},
});eventId is capped at 26 characters. Longer keys are folded into a stable 26
character digest, so the same order still produces the same id. Omit it and the SDK
generates one with generateUlid().
Wrap server-side track() calls in try/catch. A slow or unreachable Xenia
should never break your checkout.
A purchase recorded on your server is only credited to a journey the shopper
entered in the browser if both use the same visitor id. The browser SDK writes it
to the xenia_vid cookie for this reason. Read it back when you create the server
client:
const xenia = createXeniaServer({
...config,
visitorId: getVisitorId(request.headers.get("cookie")) ?? undefined,
});A fully server-rendered app with no browser SDK has nobody writing that cookie.
Create one on first use and reuse it for the whole session, or use
xeniaProxy() in Next.js, which does it for you.
On the server, track() returns how the event was handled: accepted and
rejected counts, how many were sampled, deduped or shed, and per event in
results, whether it was accepted, why not if rejected, and whether it triggered
a journey.