Install guide
Installing a chat assistant on a Drupal site
Drupal is the one platform in this family where the obvious route is the wrong one. A custom block looks like the place for a snippet of markup, and it is the place where your tag is most likely to be filtered out before a visitor ever sees it. There are three routes that do work, and which one suits you depends on whether you deploy code.
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 Drupal
A small custom module attaching a library, an asset injection contributed module, or html.html.twig in a custom theme. Not a custom block.
Any Drupal site where you can add a module or edit your own theme, with a role that has the site configuration permission. There is nothing to buy, and no dependency beyond the route you pick.
Step by step
- 1Pick a route first. If your site is deployed from code, write a small custom module. If you administer entirely through the browser, install a contributed asset injection module. If you already maintain a custom theme, a template override is the least new machinery.
- 2Module route: declare the loader as an external script in your module's library definition, with defer and the data-key attribute set on it, then attach that library from a hook that runs on every page.
- 3Asset injection route: add a new asset through that module's admin screen, paste the tag, scope it to the footer, and leave the path conditions empty so it runs everywhere.
- 4Theme route: copy html.html.twig out of your base theme into your own theme and add the tag immediately before the closing body tag. Copy it, never edit the original in place.
- 5Rebuild the cache. Drupal serves rendered pages from several cache layers, so until you do this the site keeps returning markup that predates your change.
- 6Check the result in a private window, signed out. Anonymous visitors are served from a different cache than you are as an administrator, and testing while logged in hides the most common failure.
What goes wrong on Drupal
A custom block is filtered, which is why it looks like nothing happened
Block bodies pass through a text format on the way out, and the restricted formats you hand to editors do not include a script element in their allowed tag list. The tag is dropped on render, and the rich text editor may well have stripped it on save before it ever reached the database. Either way you see a saved block, an empty spot on the page, and no error to explain it.
The unrestricted format lets more through, but it is a format you grant to almost nobody by design, and routing a sitewide script through a content field means one editor with good intentions can delete your widget while tidying up a block. Use one of the three routes above instead.
It works for you and not for anyone else
Drupal caches aggressively and separately: a render cache for fragments, a dynamic cache for authenticated responses, and a plain page cache for anonymous traffic, often with a reverse proxy in front of all three. An administrator gets a freshly assembled page and sees the widget straight away. A signed-out visitor gets a stored copy from before your change and sees nothing.
Rebuild the cache after every attempt, and always confirm in a private window. If the tag is in the anonymous page source and the launcher is still missing, the problem has moved to the allowlist and the console will name the refused origin.
Editing a contributed theme in place does not survive an update
It is tempting to open the template inside the theme you downloaded and add one line. The next dependency update replaces that theme's files and your line is gone, with no record that it was ever there.
Create your own theme that inherits from it and put the overridden template there. The same rule applies to contributed modules: extend them, do not patch them in the folder where an update will land.
Origins to allowlist
These are the origins a Drupal site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.
- https://yourdomain.com
- https://www.yourdomain.com
- https://dev.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 Drupal 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 Drupal that depends on what kind of site this is. These go one level further than this guide.
- For a universityEach department runs its own site, material and allowlist entry. Course requirements sit in fields and tabs that a plain crawl never assembles.
- For a medical practiceBlocks strip the tag and a supplier managed install may leave no route at all. What a practice can answer, and where the tag must not go.
Taking it off again
Uninstall the custom module, delete the entry in the asset injection module, or remove the line from your theme's html.html.twig. Then rebuild the cache, or the old markup keeps being served.
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
- Can I not just paste it into a custom block?
- In practice, no. The text format applied to that block filters the script element out on render, and the editor often removes it on save as well. Nothing reports the loss, so it reads as though the install simply failed. Use a module, an asset injection module, or a template override.
- Which route should I choose?
- If your site ships from a repository, the small custom module, because the install is then reviewable and travels with your deployments. If you only have the admin interface, the asset injection module. The template override is the right answer only when you already maintain a custom theme.
- Does this depend on a particular Drupal version?
- The tag itself does not. It is plain HTML with no dependency on anything Drupal provides, so it works anywhere a body tag is rendered. What changes between versions is the library definition syntax and the exact wording of the cache screen, not the install.
- Why does the console name my domain as refused?
- The page origin has to be on that assistant's allowlist, and the apex and www forms count as two different origins. Add the exact origin the console printed, including the scheme, then reload.
Keep reading
- Install on WordPressA code snippets plugin, or a small plugin of your own, hooking wp_footer. Not Appearance, then the theme file editor.
- Install on GhostSettings, then Code injection, then the Site Footer box. The alternative is default.hbs in a custom theme.
- Install on JoomlaThe Templates screen, under System in Joomla 4 and 5 and under Extensions in Joomla 3, editing index.php in a copy of your template. Or a Custom module in a footer position.
- 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.