Install guide
Adding a chat assistant to a Ruby on Rails application
Rails keeps the whole install in one layout file. What makes it different from every other framework here is Turbo Drive, which replaces the body element on each navigation rather than reloading the document, so a script sitting in that body is handed to the parser more than once.
The tag
<script src="https://cdn.askably.xyz/w.js" data-key="pk_live_YOUR_KEY" defer></script>Your own key replaces the placeholder. You will find it on the install tab of the assistant.
The origin the page is served from has to be on the allowlist for that assistant, or nothing renders and the browser console says which origin was refused. An apex domain and its www are two different origins to a browser, so list both, along with any staging or preview host you want it to work on.
Where it goes on Ruby on Rails
app/views/layouts/application.html.erb, immediately before the closing body tag.
Any Rails application that renders ERB layouts. An application generated in API only mode has no layout to paste into, so the tag belongs in whatever front end calls it.
Step by step
- 1Open app/views/layouts/application.html.erb.
- 2Paste the tag on its own line immediately before the closing body tag, as literal markup rather than through a tag helper.
- 3If you would rather sidestep the Turbo question entirely, put the same line in the head instead. It defers, so it still runs after the document parses and the launcher appears no later.
- 4Look through app/views/layouts for the other layouts. A generated admin layout does not inherit from application.html.erb, and neither do mailer layouts, which should not have it anyway.
- 5If you have uncommented config/initializers/content_security_policy.rb, add the loader origin to the script source directive and the panel origin to the frame source directive.
- 6Restart, load a page, then click through two links and confirm the launcher survives the Turbo navigations.
What goes wrong on Ruby on Rails
Turbo Drive replaces the body, not the page
On a Turbo navigation the browser never reloads. Turbo fetches the next page and swaps in its body element, which hands any script tag inside that body to the parser again. Without a guard, that would be a second launcher on every click.
The loader refuses to install twice on one page, so what actually happens is nothing at all, which is the correct outcome. If you would rather not lean on that, move the line into the head: Turbo leaves the head alone apart from merging tracked assets, so a head script runs once for the life of the tab.
The policy initializer is generated but commented out
New Rails applications ship config/initializers/content_security_policy.rb with the policy commented out, so most applications have no policy at all and nothing to configure. The day somebody uncomments it, the loader origin has to be listed under the script source directive and the panel origin under the frame source directive.
A policy violation and a refused origin produce similarly shaped console messages and need completely different fixes. Read which one you actually got before editing anything.
Turbo shows you a cached preview first
Turbo keeps a snapshot of pages you have already visited and paints it while it fetches the current version. Right after you add or remove the tag, revisiting a page can flash the previous state for a moment, which reads as a flickering or half installed widget.
Do a full reload once and it settles. Worth knowing before you start editing the layout a second time to fix a problem that was never there.
Origins to allowlist
These are the origins a Ruby on Rails site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.
- http://localhost:3000
- https://yourdomain.com
- https://www.yourdomain.com
How the tag behaves, wherever you put it
The rest of this is the same on every platform, so it is worth reading once rather than on each guide.
| One tag, nothing else | There is no second file, no stylesheet and no package to install. The tag is the whole install. |
|---|---|
| Where it goes | Immediately before the closing body tag. It works in the head too, because it defers, but the body keeps it out of the way of anything that measures render order. |
| data-key is required | Without it the loader stops and writes a warning to the browser console rather than rendering anything. |
| It finds itself | The loader reads the tag it was loaded from, and falls back to the first tag on the page carrying a data-key. Platforms that move or re-inject the tag do not break it. |
| It installs once | A second copy of the tag on the same page is ignored, so a template that renders twice does not produce two launchers. |
| Assets follow the tag | Everything else it needs is fetched from the same origin the tag was served from, so a proxy or a private domain needs no extra configuration. |
| The panel loads late | Only the small launcher is on the page at first. The conversation panel is fetched the first time a visitor opens it, in its own frame. |
| Styles cannot collide | The launcher renders inside a closed shadow root and the panel inside a frame, so nothing on the host page can restyle either, and neither can restyle the host page. |
Set up on Ruby on Rails for a particular trade
The tag is the same everywhere. What is not the same is which of your pages the assistant can read once it is running, and on Ruby on Rails that depends on what kind of site this is. These go one level further than this guide.
Taking it off again
Delete the line from the layout and deploy. If you added the loader origin to the content security policy initializer, take it out again so the policy stays honest about what the page actually loads.
Before you remove it
- Removing the tag stops the widget on that site. It does not delete the assistant, its material, or the enquiries it has already collected.
- If you are moving the widget to a different host rather than retiring it, add the new origin to the allowlist before you remove the old tag, or there is a window where neither works.
Questions
- Head or body on Rails specifically?
- The head is the quieter choice here. Both work, but a head script is parsed once per full document load and never again, which removes Turbo body swapping from the conversation entirely.
- Do I need a turbo:load listener to reinitialise it?
- No. The launcher already on the page keeps working across Turbo navigations, and the loader will not install a second copy. Anything you add on turbo:load is redundant at best and a source of duplicate state at worst.
- Can it read my models?
- No. It answers from what you index: files you upload, or a crawl of your own site. Records that exist only behind a signed in route are not part of that, and every answer cites the sources it used so you can see where it came from.
- Does it work when a proxy serves the app on a different host?
- Yes, but the origin the browser is showing is the one that has to be allowlisted, not the one the application believes it is serving. When those differ, allowlist the public one.
Keep reading
- Install on Next.jsapp/layout.tsx in the App Router, or pages/_document.tsx in the Pages Router. Not a client component that can unmount.
- Install on Reactindex.html at the project root for a Vite app, or public/index.html for Create React App. Immediately before the closing body tag.
- Install on Vueindex.html at the project root, after the div the app mounts into and immediately before the closing body tag.
- Every install guideThe same one line of HTML, and where it goes on each platform.
Try it on your own material
Upload a document or point it at your site, paste one line of HTML, then ask it something only your business could answer.