Overview
The Rayko widget is a single embeddable script that drops a chat bubble onto any HTTPS page. When a visitor clicks the bubble, they can:
- Ask questions in text and get streamed answers grounded in your site’s content.
- Switch to voice and hold a natural spoken conversation about your product, pricing, integrations, or anything else published on your site.
The assistant is grounded by a knowledge base built from a one- click crawl of your site. You do not write Q&A pairs or train a model — the system reads your pages, indexes them, and feeds them to the language model in context.
Quick start
From your Rayko dashboard:
- Create an embed for your site. You will receive a site key that looks like
rk_live_xxxxxxxxxxxxxxxxxxxx. - On the install page, add your production origin (for example
https://your-site.com) to the Allowed origins list. - Open the Knowledge tab and click Crawl now. The crawler will discover and index every public page on your site.
- Copy the script tag from the install page and paste it into the
<head>of your site.
The script tag looks like this:
<script
async
src="https://app.raykolabs.com/widget/rayko.js"
data-site-key="rk_live_your_site_key_here"
data-api-base="https://app.raykolabs.com"
></script>How it works
The widget is split into three pieces that work together:
When you click Crawl now, our indexer discovers URLs from your sitemap, fetches each page, renders any JavaScript-heavy pages with a real browser, extracts the main content as clean Markdown, and stores it against your embed.
The script tag loads a small bundle that mounts a chat bubble inside a Shadow DOM (so your site’s CSS never collides with ours). It then opens a session against the Rayko backend keyed by your site key.
When a visitor sends a message, the backend gives the language model your indexed content as grounding context, streams the answer back, and renders it in the bubble. For voice, the same content grounds the voice model in real-time speech.
Installation
Paste the script tag inside the <head> of every page where you want the widget to appear. If you want it site-wide, put it in your layout template, theme header, or site-wide partial.
Required attributes
| Attribute | Description |
|---|---|
src | The widget bundle URL. Use the absolute URL shown on the install page (https://app.raykolabs.com/widget/rayko.js). |
data-site-key | Your embed’s public site key, e.g. rk_live_xxxxxxxx. Safe to expose publicly — access is controlled by Allowed origins, not by secrecy. |
data-api-base | The base URL of the Rayko API. Always https://app.raykolabs.com unless you were given a different host. |
async | Loads the bundle without blocking page render. Recommended. |
Optional attributes
| Attribute | Description |
|---|---|
data-voice="false" | Disable the voice mode toggle entirely. By default voice is enabled if your plan allows it. |
/embeds/<embed-id>/install. It always uses the absolute URL for the current environment, so copy from there rather than constructing it by hand.Allowed origins
The widget will only load and create sessions for browsers whoseOrigin header matches an entry in your embed’s Allowed origins list. If the list is empty, every request is rejected. This is the primary security boundary on the widget — the site key itself is public.
You can edit allowed origins from the install page in your dashboard. Accepted formats:
https://your-site.com— exact origin.your-site.com—https://is added automatically.your-site.com/*— the/*is decorative; only the origin (host) is actually checked.*.your-site.com— matches any subdomain depth (app.your-site.com,staging.app.your-site.com, etc.). Does not match the apexyour-site.com— add that separately if you need it.
example.com and www.example.com, add both. Browsers send the Origin header as the user is actually browsing, and exact-string matches are strict.Knowledge base
The widget answers from a knowledge base built by crawling your site. Open the Knowledge tab on your embed and click Crawl now to kick it off.
What gets crawled
- URLs are discovered from your
sitemap.xml(the crawler also checksrobots.txtfor additional sitemap hints). - Each page is fetched with a friendly bot user agent (
RaykoBot/1.0). Pages that are JavaScript-rendered are loaded in a real headless browser so the post-hydration content is captured. - The main content is extracted to clean Markdown and stored against your embed.
robots.txtis respected. If youDisallowa path, we will not fetch it.
Excluded paths
By default, these path prefixes are skipped (they tend to add noise without improving answers):
/blog,/blogs,/news,/changelog/legal,/privacy,/terms
If you want one of these indexed anyway, contact support — the exclusion list is configurable per embed.
Soft vs hard recrawl
- Soft (default) — fetches every page; pages whose content has not changed since last crawl are kept as-is.
- Hard — supersedes the previous crawl entirely. Use this after you make material changes to your site or want to force the index to refresh.
Adding content directly
The Knowledge tab also supports pasting Markdown directly or uploading .md files. This is useful for content that does not live on a public URL (price sheets, internal specs, partner-only docs) but should still be answerable.
Voice mode
Voice mode is available if your plan includes it. When enabled, visitors can tap a microphone button in the bubble and hold a spoken conversation with the assistant.
- Requires microphone permission. The browser will prompt the visitor on first activation.
- Each voice session has a configurable cap (default 30 minutes). The session ends automatically when the cap is hit.
- On iOS Safari, the microphone must be activated by an explicit user tap — this is enforced by the platform, not by Rayko. Visitors will see a one-tap prompt to enable voice.
Disabling voice
Add data-voice="false" to the script tag to hide the mic button entirely:
<script
async
src="https://app.raykolabs.com/widget/rayko.js"
data-site-key="rk_live_your_site_key_here"
data-api-base="https://app.raykolabs.com"
data-voice="false"
></script>Playground
Every embed has a shareable playground URL where you (or your team) can test the widget end-to-end before installing it on your site. Find your playground URL on the install page; it looks like:
https://app.raykolabs.com/playground/rk_live_your_site_key_hereAnyone with the link can chat with the assistant (the same as they could on your real site once installed). It is the fastest way to confirm:
- The crawl captured your content.
- The assistant answers from your real pages.
- Voice mode is enabled and working.
https://app.raykolabs.com) must be in your Allowed origins. Add it via the install page.Content Security Policy
If your site sends a Content-Security-Policy header, append these directives so the browser allows the widget to load and talk to the backend:
script-src https://app.raykolabs.com;
connect-src https://app.raykolabs.com wss://app.raykolabs.com;
img-src data:;The install page in your dashboard generates a ready-to-paste CSP snippet that matches your environment exactly.
Troubleshooting
The bubble does not appear
- Open your browser’s DevTools network tab and confirm
rayko.jsreturns200 OK. If it 404s, yoursrcattribute is wrong — copy a fresh snippet from the install page. - Make sure the script tag is in the page’s actual HTML, not injected by a tool that strips
asyncor rewrites attributes. - Check the console for
[rayko] widget boot failed— this message includes the underlying cause.
403 origin_not_allowed
The browser’s Origin header for your page is not in your embed’s allowed list. The response body tells you exactly which origin the server saw:
{
"error": "origin_not_allowed",
"detail": "Origin https://your-site.com is not in allowed_origins for this embed."
}Add that exact origin via the install page’s Allowed origins editor and refresh.
The assistant says “I don’t know” or invents answers
- Confirm your last crawl finished successfully on the Knowledge tab. If the page count is zero, click Hard recrawl.
- If specific pages were missed (single-page apps with collapsed accordions, gated routes, etc.), paste the relevant content as Markdown directly in the Knowledge tab.
- Compare what the assistant returned with the content in the Knowledge tab. If the answer is not present in the source, the model has no grounding for it.
Voice does not start
- Microphone permission was denied. Reset the permission in your browser’s site settings and try again.
- Your plan does not include voice. Check the embed’s config or contact support.
- You added
data-voice="false"to the script tag.
FAQ
Is the site key sensitive?
No. The site key is public by design — it ships in every installed script tag. Access is controlled by the Allowed originslist, not by keeping the key secret.
How big can the widget bundle be?
The widget bundle is around 23 KB gzipped and loads asynchronously, so it never blocks your page render. Voice support is lazy-loaded only when a visitor actually starts a voice session.
Does the widget affect SEO or page speed?
No. The script loads asynchronously and mounts in a Shadow DOM, so it does not interact with your page’s critical render path or DOM. There is no impact on Core Web Vitals beyond the cost of a single async script request.
Will visitor questions be used to train AI models?
No. Conversations are used only to generate the live response and to populate your transcripts. They are not used to train third-party models.
How often should I recrawl?
Whenever you make material changes to public pages — new feature launches, pricing updates, a new FAQ, etc. A soft recrawl is cheap and only re-indexes pages whose content has actually changed.
Can I customize the look of the bubble?
Theming hooks (accent color, greeting text, modality default) are configurable per embed via the dashboard. Deeper customization is planned — reach out if you have specific needs.
Where do conversations live?
Every conversation is saved as a session in your dashboard with the full transcript, visitor metadata (UTM parameters, hashed IP, user agent), and any captured leads.
Still stuck? Email contact@raykolabs.com with your embed ID and the network response from the failing request. We’ll get back to you within a business day.