Install guide
Installing a chat assistant in an Angular project
The Angular install is a single line in src/index.html. The reason this page is longer than that is one wrong turn: angular.json has a scripts array that looks purpose built for third-party code, and using it for a hosted loader breaks the install in a way that is genuinely hard to read from the symptoms.
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 Angular
src/index.html, after the app root element and immediately before the closing body tag.
Any Angular workspace built with the CLI. src/index.html is the source document the build copies and augments, so you always control it, on every project type.
Step by step
- 1Open src/index.html in the application project, not the generated copy under dist.
- 2Find the app root element inside the body.
- 3Paste the tag on its own line after it and immediately before the closing body tag.
- 4Leave the build configuration alone. Do not add the loader to the scripts array in angular.json, and do not save a local copy of it into your assets.
- 5Serve the application and confirm the launcher appears. The local development origin has to be on the allowlist separately for this to work.
- 6Build, deploy, and confirm again on the production origin, since those are two different origins as far as the browser is concerned.
What goes wrong on Angular
The scripts array in angular.json destroys the install
That array takes file paths inside your workspace, not URLs, so the only way to use it at all is to download a copy of the loader and point at the file. The builder then bundles that file into one of your own output bundles and writes its own script tag for it. Your data-key attribute never existed on that tag, because there was no tag, only a file.
What you get is the loader running with no key, a console warning that the key is missing, and nothing rendered. The array is for code you own and want bundled. This is a hosted loader, and it has to stay a tag in the document.
The index.html under dist is generated
The build writes a fresh index.html into the output directory with hashed bundle references. Editing that copy works until the next build replaces it, and deployments usually run a fresh build, so the change never arrives in production.
Always edit src/index.html and let the build carry it through.
Change detection is not involved, so zone.js is not either
It is a reasonable thing to worry about and the answer is no. The launcher lives in a closed shadow root and the conversation panel loads in its own frame, so nothing the widget does happens inside your component tree.
You do not need to run it outside the Angular zone and it will not trigger extra change detection cycles. It is also why nothing on your page can restyle the launcher, and why the launcher cannot restyle your page.
Origins to allowlist
These are the origins a Angular site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.
- http://localhost:4200
- 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 Angular 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 Angular 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 src/index.html and rebuild. If you also added a local copy of the loader to the scripts array while trying to get it working, remove that entry and delete the file.
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 add it from a component or a service instead?
- You can, by creating the element and appending it to the body, then calling the destroy method on the global when the component is destroyed. It is only worth it if you want the widget on some routes and not others.
- Why does the console say the key is missing when it is in my index file?
- Something between your source and the served document rewrote the tag. The usual culprits are the scripts array in angular.json and an optimisation step in a deployment pipeline. View source on the served page and read the tag as the browser received it.
- Does it break server side rendering?
- No. The tag is markup and the loader acts only in a browser, so a server render emits the tag and does nothing else with it.
- Which Angular versions does this work with?
- All of them, because none of it is Angular. It is one HTML element in a document that Angular happens to boot into.
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.