The voyse object
Everything the data attributes do, your own code can do — and two things it cannot: read the ids the embed minted for this visitor, and tell Voyse that a conversation led to an application.
The embed defines window.voyse once its script has run. It is set at the end
of the script's own execution, before the configuration request settles, so it
exists as soon as the tag has executed. voyse.version is 2.
if (window.voyse) {
window.voyse.open({ ask: "What's the interview process?" });
}
Guard on its presence rather than assuming it. The snippet is async, so your
code may run first, and the script returns without defining anything if it
cannot find its own tag.
voyse.open(options)
Opens the assistant. Every option is optional; with none, it behaves like tapping the launcher.
| Option | Type | Does |
|---|---|---|
ask |
string | Question to send as the first message |
atsId |
string | The role to frame the conversation on — see Tell the assistant which role a page is about |
context |
string | One line about where the question came from, capped at 500 characters |
voyse.open({
ask: "Is this role open to part-time?",
atsId: "4821",
context: "Job detail page, benefits section",
});
With no question and no role, on desktop, it opens whatever the panel was last showing rather than resetting the visitor — the same behaviour as the launcher. With either of them, it opens on that question or that role. On mobile it opens a new tab in every case.
voyse.close()
Closes the desktop panel. On mobile the assistant is a separate tab, so there is nothing for this to close and the call does nothing.
voyse.identify()
Returns the three ids the embed minted for this visitor, or null when
host-side tracking is off:
const ids = voyse.identify();
// { visitorId, sessionId, assistantSessionId } | null
The embed owns these ids, mints them on first load — before any interaction — and hands them to the assistant, so browsing your site, the conversation, and an eventual application stitch into one session rather than three strangers. Use them to correlate your own analytics with what your team sees in the admin.
null means tracking is disabled, which happens when the browser sends Do Not
Track or when the URL carries ?analytics=off.
voyse.track(name, props)
Reports a host-side signal to Voyse. Only these names are accepted; anything else is ignored without error:
| Event | Means |
|---|---|
host_page_view |
A page on your site was viewed |
assistant_embed_loaded |
The embed loaded |
assistant_pill_impression |
The launcher was shown |
assistant_pill_click |
The launcher was tapped |
assistant_open |
The assistant opened |
assistant_close |
The assistant closed |
host_apply_start |
The visitor started an application |
host_apply_complete |
The visitor finished one |
The embed already emits the launcher and open/close events itself. What it
cannot see is your application flow, which is why host_apply_start and
host_apply_complete are the two worth calling by hand:
form.addEventListener("submit", () => {
window.voyse?.track("host_apply_start", { jobId: "4821" });
});
Whatever you put in props is sent. Keys are not filtered; string values
are truncated at 100 characters and that is the whole of it. So pass identifiers
and nothing else — never a name, an email address, or an application answer.
Where the page declares a role, jobId is added for you.
track is silent in three cases, none of which raise: the event name is not in
the table above, the assistant has no analytics token configured, or tracking is
off for this visitor (Do Not Track, or ?analytics=off). Treat it as
best-effort reporting rather than a delivery guarantee.
voyse.markAssistantUsed(meta)
The one call with no attribute equivalent, and the reason the API exists:
voyse.markAssistantUsed({ jobId: "4821", applicationId: "a_88213" });
Call it when an application completes on a visit where the assistant was used.
It sends host_apply_complete with the fact that the assistant was involved,
which is what lets your team see whether conversations turn into applications
rather than only that both happened. Both fields are optional and truncated at
100 characters.
Events coming the other way
The embed posts a same-origin message for its own events, so you can forward them to your own analytics without polling:
window.addEventListener("message", (event) => {
if (event.source !== window || event.origin !== window.location.origin) return;
if (!event.data || event.data.type !== "voyse:analytics") return;
myAnalytics.track(event.data.event, event.data.eventModel);
});
eventModel carries campaign_id, tenant_id, job_id, page_path,
page_type and surface. Check event.source and event.origin as above:
these are ordinary window messages, and anything on the page can post one.