Install the assistant on your site
By the end of this page a launcher appears on your site, and tapping it opens your assistant with the page's context already in hand.
What you need
The assistant's id, and the snippet built around it. Both are in the admin, on the assistant's own page under Add to your site — copy the snippet from there rather than assembling it here, since it carries the id for the assistant you are installing. Your talent team can send it to you: for them the same step is Put your assistant in front of candidates.
If your careers site is a Voyse careers site, stop here. The assistant is already on it, switched on from Integrations in the Careers admin, and pasting the snippet as well would put two launchers on the page.
Install
Paste the snippet before </body> on every page you want the assistant on:
<script
src="https://assistant.voyse.io/embed.js"
data-assistant-id="0f3c81a2b47e5d6091ac4472"
async
></script>
That is the whole installation. The tag names the assistant and nothing else — message, position, shape, theme and the job URL pattern all arrive at runtime from the assistant's settings, so your team can change how it looks and behaves without you re-pasting anything.
Three things about the tag itself are load-bearing:
- It must be a real
<script src>element. The script readsdocument.currentScriptto find its own origin, and returns without doing anything if it cannot. Copying the file into your own bundle, or injecting it in a way that losescurrentScript, gives you a silent no-op. - The origin in
srcis where everything else is fetched from. The configuration request and the assistant panel are both built from it. asyncis right. Nothing on your page waits for the assistant, and nothing in the script needs to run before your own code.
Including the snippet twice is harmless: the first copy sets
data-voyse-embed-loaded="1" on <html> and any later copy returns
immediately.
What happens on load
- The script requests
/api/embed-configfrom its own origin, passing the assistant id and your page's host. - Until that request settles it paints nothing. A launcher never appears with default styling that then changes under the visitor — if the request hangs, the script gives up after eight seconds and stays silent.
- On success it caches the configuration in
sessionStorageand renders the launcher.
Each of those requests is also the installation heartbeat — it stamps when the snippet was first and last seen, and on which host, which is what tells your team it is live.
What the visitor gets
Which depends on their device, and you cannot override it:
| Desktop | Mobile | |
|---|---|---|
| Opening | An iframe panel over your page | A new browser tab |
| Placement | Centred overlay, docked in the launcher's corner, or a sheet rising from the base — whichever the assistant's settings say | Full tab |
| Context | Passed into the iframe | Passed as query parameters |
Mobile is anything matching both (pointer: coarse) and (max-width: 767px),
with a user-agent check as the fallback. A tablet with a mouse gets the desktop
panel.
Content Security Policy
If your site sends a CSP, the embed needs four allowances:
| Directive | Why |
|---|---|
script-src https://assistant.voyse.io |
The snippet itself |
connect-src https://assistant.voyse.io |
The configuration request |
frame-src https://assistant.voyse.io |
The desktop panel |
img-src https://res.cloudinary.com |
The Voyse mark on the launcher, unless the assistant is set to the plain chat icon, which is drawn inline |
Analytics adds a fifth: the configuration response names the API origin the
script sends events to, and connect-src has to include it. Read it from the
apiUrl field of the response rather than assuming — it differs between
environments.
The script injects a <style> element and a JSON <script>, so a policy with
no 'unsafe-inline' would strip the launcher's styling. Rather than loosening
the policy, put a nonce on the snippet: the script reads its own tag's
nonce and applies it to everything it inserts, which is what makes it work under
'strict-dynamic' or a nonce-matched style-src.
Check it worked
Load a page carrying the snippet and confirm, in this order:
document.documentElement.dataset.voyseEmbedLoadedis"1". If it is not, the tag is not executing — check for a 404 on the script and fordocument.currentScriptbeing lost.- The request to
/api/embed-configreturns 200. A 404 means the assistant id is wrong or the assistant is not active. - The launcher renders, and tapping it opens the assistant.
If the request succeeds and no launcher appears, check the render field in the
response: false means the account is suspended, and the script renders nothing
by design.
Then
The snippet on its own gives you a launcher. The rest of this stage is about making the assistant aware of the page it is sitting on, and letting your own markup open it: Open the assistant from your own page, then Tell the assistant which role a page is about.