Install guide
Installing a chat assistant in an ASP.NET Core project
The shared layout is the right file and the only surprise is what sits next to the closing body tag: an optional section that individual views fill in. Putting the tag inside it, which is what most tutorials would have you do with a script, gives you the widget on one page and nowhere else.
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 ASP.NET Core
Views/Shared/_Layout.cshtml for controllers and views, or Pages/Shared/_Layout.cshtml for Razor Pages. Immediately before the closing body tag.
Any ASP.NET Core project that displays server built pages, whether views or pages. Projects that serve only an API and hand the front end to a separate application need the tag in that application instead.
Step by step
- 1Open the shared layout: Views/Shared/_Layout.cshtml in a controller and view project, or Pages/Shared/_Layout.cshtml in a Razor Pages project.
- 2Scroll to the bottom. Above the closing body tag you will find the layout's script references and a call that pulls in an optional section named Scripts.
- 3Paste the tag after that section call and before the closing body tag, so it is part of the layout itself and not part of anything a view supplies.
- 4If your project has more than one shared layout, note which one applies where. The view start file decides, and an area can carry its own.
- 5Run the project and confirm the launcher appears on the home page and on a second page that uses the same layout.
- 6Publish, then confirm again on the deployed site, because the local addresses and the deployed address are different origins and need listing separately.
What goes wrong on ASP.NET Core
The Scripts section belongs to the view, not to the layout
The layout ends with a call for an optional section named Scripts, and each view decides whether to supply it. Anything a view puts there appears only on that view's pages. So a tag added inside a view's Scripts block installs the widget on exactly one page, which is rarely what anybody meant.
Keep the tag in the layout file, below the section call. It is then part of every page the layout builds, and no view can drop it by choosing not to supply the section.
There is usually more than one shared layout
A project of any size accumulates them. Areas can carry their own shared layout, an identity area often has one, and a view start file in a subfolder can point a whole branch of the site at a different layout entirely. Editing the one at Views/Shared covers the pages that use it and no others.
The symptom is a widget that is present across the main site and missing throughout one section, usually the account or admin pages. Search the project for layout files rather than assuming the one you opened is the only one.
A content policy written by your own middleware
ASP.NET Core does not impose a script policy on you, but plenty of teams add one as a response header in the request pipeline, often years before anybody tried to add a third party tag. That header decides which hosts may serve scripts and which the page may connect to.
The distinguishing detail is what the browser console says. A policy problem names a directive and the blocked address. An allowlist problem names your site as an origin the assistant refuses. If it is the first, the fix is in the middleware that writes the header, not anywhere in the layout.
Origins to allowlist
These are the origins a ASP.NET Core site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.
- https://localhost:5001
- http://localhost:5000
- https://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 ASP.NET Core 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 ASP.NET Core 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 shared layout and rebuild. If you added it to more than one layout, remove each copy, since any remaining one still installs the widget on the pages it covers.
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
- Views or Razor Pages, does the file differ?
- Only the folder. A controller and view project keeps the shared layout under Views/Shared, a Razor Pages project keeps it under Pages/Shared. The tag and its position are identical in both.
- Which local address do I allowlist?
- Whichever ones your project actually listens on. The launch settings file in the project lists them, and recent project templates pick the port numbers when the project is created rather than using a fixed pair. Read them from that file rather than guessing.
- Does it need a tag helper?
- No. It is plain HTML in a layout file, and the view engine passes it through untouched. Nothing about it needs the tag helper machinery.
- Will it work behind Windows authentication?
- The widget itself will, because it runs in the visitor's browser like any other script. What will not work is a crawl of a site that requires a domain sign in, so the material the assistant reads has to come from somewhere reachable without those credentials.
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.