Install guide

Adding a chat assistant to a Laravel application

Laravel renders every page through a Blade layout, so the install is one paste into the layout your views extend. The two things that catch people are Blade escaping, which turns a tag written through an echo into visible text on the page, and the compiled view cache, which happily keeps serving the old layout after a deploy.

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 Laravel

resources/views/layouts/app.blade.php, or whichever layout your pages name in their @extends directive, immediately before the closing body tag.

Any Laravel application that renders Blade views on the server. If your front end is a separate build served on its own, the tag belongs in that application's index template rather than in Blade.

Step by step

  1. 1Open resources/views/layouts/app.blade.php. If you are not certain that is the layout in use, search resources/views for the closing body tag and see which files come back.
  2. 2Paste the tag on its own line immediately before the closing body tag, written as plain HTML.
  3. 3Do not echo it. Blade escapes echoed output, so a tag passed through a variable arrives as words printed on the page rather than as a script the browser runs.
  4. 4If your layout declares a scripts stack, push the tag onto that stack from a push block instead, so it lands with the rest of your scripts rather than above them.
  5. 5Deploy as usual, then clear the compiled views on the server. Until you do, Laravel can keep rendering the previously compiled copy of the layout out of storage/framework/views.
  6. 6Load any page and confirm the launcher appears. Config and route caching have no bearing on this. Only the view cache does.

What goes wrong on Laravel

Blade escapes whatever you echo

The double brace syntax exists to make output safe, which means it also makes a script tag inert. Store the tag in a config value, print it with double braces, and what you get is the tag itself displayed as text at the bottom of every page. It is one of the few install failures you can diagnose without opening the console.

Write the tag as literal markup in the template. There is no reason to route a static line through a variable, and doing so only raises a question about which echo syntax is safe here.

The compiled view cache outlives the deploy

Laravel compiles each Blade template once and reuses the compiled file under storage/framework/views. Normally a newer template timestamp invalidates it, but deploys that copy files into a fresh release directory, or that run from a read only mount, can leave a stale compiled layout in place.

Clearing views is one artisan command and belongs in your deploy script beside the config and route caching you already run. The symptom without it is a page whose source has no tag in it even though the file on disk clearly does.

One layout is rarely all your layouts

Applications acquire a second layout for the admin area, a third for marketing pages, and a stripped one for printable documents. Pasting into app.blade.php covers only the views that extend it, so the launcher vanishes the moment a visitor lands on something rendered from a guest layout.

Search resources/views for the closing body tag, list what comes back, and decide about each one deliberately. Leaving it off the admin layout is usually the right call rather than an oversight.

Origins to allowlist

These are the origins a Laravel site is typically served from. List every one you want the assistant to answer on, including the ones only you visit.

  • http://your-app.test
  • http://localhost:8000
  • 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.

Loader behaviour
One tag, nothing elseThere is no second file, no stylesheet and no package to install. The tag is the whole install.
Where it goesImmediately 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 requiredWithout it the loader stops and writes a warning to the browser console rather than rendering anything.
It finds itselfThe 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 onceA 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 tagEverything 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 lateOnly 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 collideThe 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 Laravel 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 Laravel 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, deploy, and clear the compiled views again. Nothing else in the application references it.

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 before the closing body tag?
Either. The tag defers, so it never blocks parsing wherever it sits. Before the closing body tag matches the convention in most Blade layouts and keeps the head for meta tags and stylesheets.
Can it answer from my database?
No. It answers from the material you index, which is files you upload or a crawl of your own site. Anything that exists only in a table behind an authenticated route is invisible to it, and it says it does not know rather than guessing.
How do I keep it off the admin panel?
Put the tag only in the public facing layout, not in the layout your admin views extend. That is cleaner than wrapping it in a condition, and it means no admin route can ever leak a launcher onto an internal screen.
It works locally but not in production. Why?
The local site and the production site are different origins, and only allowlisted ones render. Open the console on the production site: if the origin was refused, it is named there, and adding it is the entire fix.

Keep reading

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.