Install guide
Installing a chat assistant on a Hugo static site
Hugo writes flat files, so nothing is live until you build and deploy. The rule that saves you doing this job twice is to never edit inside the themes directory. Hugo resolves layouts from your own project first, so a copy in your layouts directory wins and survives the next theme update.
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 Hugo
layouts/_default/baseof.html in your project root, or the footer partial that baseof calls, immediately before the closing body tag.
Any Hugo site, including one built on a theme you did not write. No module and no configuration change is needed, only a template file and a rebuild.
Step by step
- 1Look for layouts/_default/baseof.html in your project root. If it is not there, the theme is supplying it from its own layouts/_default directory.
- 2Copy that file into your own layouts/_default directory, keeping the path identical. Hugo checks the project before the theme, so your copy takes precedence with no configuration at all.
- 3Paste the tag on its own line immediately before the closing body tag in your copy.
- 4If baseof calls a footer partial, copying just that partial into layouts/partials and putting the tag there works equally well, and leaves you a much smaller file to keep in step with the theme.
- 5Run the site locally and confirm the tag is present in the page source.
- 6Build the site and deploy the output directory. The live site keeps serving the previously generated HTML until that build lands.
What goes wrong on Hugo
Editing the themes directory is work you will do twice
Themes usually arrive as a submodule or a module, and updating one replaces its files wholesale. An edit inside themes is discarded with no warning and no conflict to review, so the widget disappears on the day somebody bumps the theme and nobody connects the two events.
Hugo's lookup order exists precisely so you never have to touch the theme. A file at layouts/_default/baseof.html in your project overrides the theme's copy of the same path.
The development server is not the built site
Hugo's server builds into memory and reloads on save, so your change is visible instantly. The published site is whatever the last build wrote to the output directory, and that does not change until you build again and deploy.
Checking locally and then forgetting the deploy is the most common way a correct Hugo install looks broken. Confirm against the deployed page source, not the local one.
The local development origin is not allowlisted
The server binds to a local port, so the origin you are testing on is not your domain and will be refused. The tag is in the source, the console names the origin it rejected, and nothing renders.
Either add the local origin so you can test properly, or accept that the local check only tells you the tag is present and do the visual check after deploying.
Origins to allowlist
These are the origins a Hugo site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.
- http://localhost:1313
- 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 Hugo 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 Hugo 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 your copy of baseof.html or the footer partial, rebuild, and deploy. If that copy exists only to carry the tag, delete the whole file and fall back to the theme's version.
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
- baseof.html or a footer partial?
- The partial, if your theme already calls one at the end of the body, because you then copy a short file instead of the whole page skeleton. Functionally the two are identical.
- Can I read the key from site configuration instead?
- You could print it from your configuration file into the template, but there is no benefit. The key is a publishable identifier that ends up in the page source either way, and a literal line is easier to read and impossible to get wrong.
- What should a Hugo site index?
- Point the crawl at the built site rather than uploading your content directory. It reads rendered pages and follows the sitemap Hugo generates by default, so it sees exactly what a reader sees, shortcode output included.
- Why is the launcher missing on one section only?
- That section renders through a different base template. Hugo picks a layout per section and page type, so a section with its own baseof or its own single template never goes through the file you edited.
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.