Short answer for AI agents
- What: one
<script>tag with the site's public key:<script src="https://achlaai.com/w.js" data-key="YOUR_PUBLIC_KEY" defer></script>. The real key (starts withpk_) is in the Achla AI dashboard under Settings → Embed code. - Where: in the HTML of every page that should have search, just before
</body>, exactly once per page. - WordPress / Drupal: prefer the official plugin (WordPress.org, Drupal.org) over pasting the tag.
- Inline mode needs
<div id="ai-search"></div>on the page; attach mode needs a CSS selector of an existing search<input>. Default (bubble) needs nothing else. - Verify:
curl -s "https://achlaai.com/api/widget-config?key=YOUR_PUBLIC_KEY"must return"enabled":true; the browser console must show no[ai-search]lines; a test question must return an answer with sources. - Always finish by verifying — see Verify the installation.
- Something wrong: every console message starts with
[ai-search] AISX-…— look the code up in Troubleshooting (Markdown).
Prerequisites
The widget shows itself only after the server explicitly enables it for the key. That requires all of the following, set up in the dashboard:
- An account with Achla AI, with the site registered.
- Site ownership verified (via the widget tag or a CMS plugin connection).
- An active plan (paid subscription or the Free plan).
- The first indexing of the site finished — Overview in the dashboard shows the status.
Check from any terminal (no login needed — the key is public):
curl -s "https://achlaai.com/api/widget-config?key=YOUR_PUBLIC_KEY"{"enabled":true,"config":{…}}— ready; the widget will appear wherever the tag is installed.{"enabled":false}— key unknown or replaced, project not active, index not ready, or ownership/plugin connection invalid. The dashboard shows project, indexing and connection status; a stale or deleted key is not flagged there — compare the key in the tag with Settings → Embed code first (AISX-W110).{"error":"bad_request"}(HTTP 400) — the key value is malformed (AISX-W112).
The embed snippet
YOUR_PUBLIC_KEY with the key from Settings → Embed code (or copy the whole tag from there).<script src="https://achlaai.com/w.js" data-key="YOUR_PUBLIC_KEY" defer></script>| Attribute | Required | Values | Purpose |
|---|---|---|---|
src | yes | https://achlaai.com/w.js | The widget. It sends its API requests to the same origin it was loaded from — do not copy the file to your own server or CDN. |
data-key | yes | public key, starts with pk_ | Identifies the site. Missing → AISX-W101; malformed → AISX-W112. |
defer | recommended | — | Load without blocking the page; the widget mounts once the document is ready. |
data-mode | no | bubble · inline · attach | Overrides the placement mode chosen in the dashboard, for this tag only. |
data-attach | no | CSS selector | The search <input> to attach to (used with attach mode); overrides the dashboard selector. |
data-position | no | br · bl · tr · tl | Corner of the floating button (bubble): bottom-right, bottom-left, top-right, top-left. |
data-preview | never on a live site | 1 | Dashboard preview only: the widget makes no network requests and answers with a canned demo. |
Which setting wins
The tag controls placement only (data-mode, data-attach, data-position). Everything visual — theme, accent colour, corner radius, title, placeholder, greeting — comes from the dashboard via the server and cannot be set in the tag. Placement attributes you omit (or give an unknown value) fall back to the dashboard setting.
- Put the tag in the HTML of every page that should show search, just before
</body>. - Exactly one tag per page. A second copy mounts a second widget (AISX-W105).
- If you add the tag with JavaScript, set
data-keyand the otherdata-*attributes before appending it to the page.
Placement modes
| Mode | What visitors see | Requirement on the page | If the requirement is missing |
|---|---|---|---|
bubble (default) | A floating “Ask AI” button in a corner that opens a chat panel. | None. | — |
inline | A search box embedded in your content. | An element <div id="ai-search"></div> in the page HTML. | Floating button instead + AISX-W104. |
attach | Your existing search field opens AI answers in a dropdown on Enter, with a link back to your regular results. | A CSS selector that matches an <input> of type text or search. | Floating button instead + AISX-W102 / AISX-W103 / AISX-W106. |
Switching to inline? Add the container first
Changing the mode to inline in the dashboard reaches every page within about 30 seconds (when changes take effect). Pages without <div id="ai-search"></div> fall back to the floating button. The container must be in the page when the widget mounts; one added later by client-side code is not picked up.
For attach, only the first element matched by the selector is used. Test the selector on the live page in the browser console: document.querySelector('input[type="search"]') (replace with your selector) must return your search input. Dashboard changes to mode or selector need no cache purge — see When do changes take effect?.
CMS plugins use one placement mode for the whole site
The WordPress plugin and the Drupal module each have a single placement setting for the whole site. In Bubble or Attach they load the widget on every public page; in Inline they load it only on pages that contain the shortcode/block, and all other pages get no widget at all (no floating button). A floating button everywhere plus an inline box on one page is not possible with the plugins — use manual tags for that (below).
Mixed placement with manual tags (bubble everywhere, inline on one page)
With manual tags this works, because data-mode on the tag overrides the dashboard mode for that tag:
- Step 1: Keep the dashboard mode at Bubble.
- Step 2: On all pages except the target page, use the normal tag (no
data-mode). - Step 3: On the target page, use a single tag with
data-mode="inline"and add<div id="ai-search"></div>where the box should appear. - Step 4: Never put two widget tags on one page — the second copy mounts a second widget (AISX-W105, install-check AISX-C303).
<script src="https://achlaai.com/w.js" data-key="YOUR_PUBLIC_KEY" data-mode="inline" defer></script>
<div id="ai-search"></div>Install paths
Plain HTML / any server-rendered site
- Step 1: Copy the tag from Settings → Embed code in the dashboard.
- Step 2: Paste it into the shared layout/template of your site, just before
</body>, so it is on every page. - Step 3: For inline mode, also add
<div id="ai-search"></div>where the search box should appear. - Step 4: Deploy, purge any page cache/CDN cache for the HTML, then run the checks in Verify the installation.
WordPress — official plugin (recommended)
- Step 1: Install Achla AI Search for WordPress from WordPress.org (current version 0.3.5): Plugins → Add New, or upload the ZIP.
- Step 2: Activate it, open Settings → Achla AI Search and select Connect.
- Step 3: Complete the ownership step on Achla AI, return to WordPress and wait for the connection and indexing status.
- Step 4: Keep Bubble placement or choose Inline or Attach (test an Attach selector before saving), then switch Show the widget on.
- Step 5: Inline: insert the shortcode
[achla_search]or the block Achla AI Search (achlaai/inline-search) on the pages where the search box should appear — it outputs the#ai-searchcontainer for you.
Note
The plugin loads the widget through its own loader script (not a /w.js tag), so a grep for /w.js will not find it. The plugin uses one placement mode for the whole site: with Inline it loads the widget only on pages that contain the shortcode or block — other pages show nothing (no floating button) and no console message is printed; in Bubble or Attach the shortcode/block outputs nothing. For a floating button everywhere plus an inline box on one page, use manual tags instead of the plugin (Mixed placement). Do not also paste the manual tag while the plugin is active.
WordPress — manual tag (without the plugin)
Paste the tag into your theme's footer template just before </body>, or use a header/footer code-snippet plugin that outputs it on every page. Use either this or the official plugin, never both.
Drupal — official module
- Step 1: Install Achla AI Search for Drupal (Drupal 10.3+ and 11.3+, PHP 8.1+):
composer require 'drupal/achlaai_search:^0.3'. A ZIP is also available on Drupal.org. - Step 2: Enable the module
achlaai_search(Extend page, ordrush en achlaai_search). - Step 3: Open Administration → Configuration → Web services → Achla AI Search (
/admin/config/services/achlaai-search) and connect the site. - Step 4: Choose placement: Bubble, Inline (place the block Achla AI Search in a region via Block layout), or Attach (the selector must pass the browser preview before it can be saved).
Note
The module uses one placement mode for the whole site: in Bubble or Attach it adds the widget to every non-admin page; in Inline only the Achla AI Search block loads it, so pages without the block get no widget at all (no floating button). The block outputs nothing unless the placement is Inline. Like the WordPress plugin, it loads the widget through its own loader, not a /w.js tag.
Single-page apps (React, Next.js, Vue …)
- Add the tag once, in the root HTML document/layout, so it is loaded once per full page load. The widget mounts once and has no JavaScript API for re-mounting.
- Bubble works best: the button is appended to
<body>and survives client-side navigation as long as your app does not replace<body>. - Inline needs
<div id="ai-search"></div>present when the widget mounts (server-rendered HTML). If your router later removes or re-creates that element, the inline box disappears until the next full page load. - Attach binds to the input element that exists at mount time; if the app re-renders that input, the binding is lost.
Verify the installation
- Step 1: The tag is in the served HTML (manual installs). Expect exactly one match:
- Step 2: The key is enabled — must contain
"enabled":true: - Step 3: In the browser, open the page with DevTools → Console: there must be no lines starting with
[ai-search]. Any such line carries anAISX-…code — see Troubleshooting. - Step 4: The widget is visible: the floating button (bubble), the inline box (inline), or a dropdown when you press Enter in your search field (attach).
- Step 5: Ask a test question about your site: the answer should cite sources from your pages.
- Step 6: Run the installation check (replace the URL with a page of your site):
curl -s "https://achlaai.com/api/install-check?url=https://YOUR-SITE.example". It downloads the page, finds the tag, checks the key and the placement, and returnsAISX-C3xxfindings with fixes as JSON —AISX-C309means the installation looks correct. The Check installation button in the dashboard runs the same check for your site.
curl -s "https://YOUR-SITE.example" | grep -o '<script[^>]*/w\.js[^>]*>'curl -s "https://achlaai.com/api/widget-config?key=YOUR_PUBLIC_KEY"document.querySelectorAll('.aisx-btn, .aisx-inline, .aisx-drop').lengthContent-Security-Policy
If your site sends a Content-Security-Policy header, it must allow the widget origin. The widget loads its script from that origin, requests its configuration and answers from the same origin, and injects its stylesheet as a <style> element:
script-src https://achlaai.com;
connect-src https://achlaai.com;
style-src 'unsafe-inline';A blocked script or request shows up in the browser console as a CSP violation (not as an [ai-search] line), or as AISX-W111 / AISX-W121 when the configuration or a search request is blocked.
What not to do
- Do not include the tag twice (theme + tag manager, or plugin + manual tag).
- Do not edit the key by hand — copy it from the dashboard.
- Do not copy
w.jsto your own server or CDN: the widget sends requests to the origin it was loaded from, so a copy calls the wrong server and misses updates. Always load it fromhttps://achlaai.com/w.js. - Do not set
data-preview="1"on a live site. - Do not block
https://achlaai.comin your CSP (see Content-Security-Policy).