Skip to content
Developers

Embed the widget

Add Practicl to any page with a single script tag. It renders a chat bubble your visitors can ask, answering from the pages of your website that Practicl has read.

Add the snippet

Drop the script tag below in just before the closing </body> tag of any page. Nothing else on your page needs to change.

<script src="https://app.staging.practicl.io/widget.bundle.js"
        data-api-key="pk_live_..."
        data-source-id="SOURCE_UUID"
        data-api-base="https://api.staging.practicl.io"
        data-app-url="https://app.staging.practicl.io"
        defer></script>
data-api-base is the server root — do not include /api/v1. The widget appends the version path itself, so a base ending in /api/v1 produces /api/v1/api/v1/chat and every request 404s.

No access to the site’s code?

The snippet is a script tag, and every platform has somewhere to put one. Google Tag Manager needs no developer at all:

  1. Open Google Tag Manager and choose the container for your site.
  2. Tags → New. Name it "Practicl widget".
  3. Tag Configuration → Custom HTML. Paste the snippet into the HTML box.
  4. Triggering → All Pages.
  5. Save, then Submit → Publish.

Or use your platform’s own field for it:

  • WordPress — Install the "WPCode" plugin (or any header/footer scripts plugin) → Code Snippets → Header & Footer → Footer box → paste → Save. Not the theme file editor: a theme update overwrites it.
  • Webflow — Project settings → Custom code → Footer code → paste → Save, then Publish the site.
  • Wix — Settings → Custom code → Add custom code → paste → Add code to: All pages, Place code in: Body – end → Apply. Custom code needs a Premium plan with a connected domain.
  • Squarespace — Settings → Advanced → Code injection → Footer → paste → Save. Code injection needs a Business plan or above.
  • HubSpot — Settings → Website → Pages → choose the domain → Site footer HTML → paste → Save.

The Widget screen in the dashboard has the same steps beside your own snippet, an “Email this to my developer” button, and a link that opens the same assistant on our site with nothing to install.

Add your site to the allowed domains

Do this before you load the page. Open Settings in the dashboard, find Allowed domains, and add the origin the widget will run on — scheme and host, no path:

https://www.example.com
https://staging.example.com

Add one entry per origin. https://www.example.com and https://example.com are different origins to a browser, and so is a staging subdomain — if you test on https://staging.example.com first, add that too.

Without this the widget loads and answers nothing. The browser blocks the request before it reaches us and reports it as a CORS error in the console — “No ‘Access-Control-Allow-Origin’ header is present” — which names neither the cause nor the fix. If the bubble appears and every question fails, this is almost always why.

Attributes

The script tag is configured entirely with data attributes:

  • data-api-key — required. The pk_live_ share key that authorises the widget. The source in data-source-id must be inside this key’s scope, and if the key lists allowed domains, the page must be served from one of them. The Embed panel creates a key scoped to your website source and to the origin you enter.
  • data-source-id — required. The website source the widget answers from. The Embed panel offers only website sources that have finished being read; uploaded documents are answered in the app and through share links.
  • data-api-base — the API host the widget calls, server root only: the widget appends the version path itself. Defaults to https://api.staging.practicl.io.
  • data-app-url — the workspace host used for hand-off. Defaults to https://app.staging.practicl.io.

There is no organisation attribute. The key identifies the organisation, and it is the only part of the snippet a visitor cannot edit in their own browser.

The key is a pk_live_ share key, scoped to the document or documents you want exposed. It is safe to ship in your page markup because it can only read those documents.

Two separate allowlists mention domains, and they do opposite things. The one on the key is optional and narrows — set it and the key is refused from any origin but the ones you name. The one in Settings, described in the next step, is required and widens: until your site is on it, nothing answers at all.

How it renders

  • A floating chat bubble sits in the corner of your page and opens a 400×600 drawer.
  • The widget mounts inside an open shadow DOM custom element, <practicl-widget>, so its styles cannot collide with or be broken by your page, and it never blocks clicks on the rest of your site. That is the element to target if you need to position the widget from your own CSS.
  • The API key is sent as the X-Api-Key header, never in a URL or query string.

Branding

On load the widget calls GET /api/v1/config to pull your accent colour, greeting, company name and corner position, so it matches your site out of the box. Set these values in the dashboard.

What a visitor sees

A circular button in the corner of your page. Opening it shows a consent notice first — “This assistant uses AI to answer your product questions. Conversations may be stored and reviewed to improve accuracy” — with a link to your privacy policy, and two buttons: I understand — start chat and Cancel.

There is no message box until that is accepted. It is shown once per visitor, not once per question.

After that they type a question and the answer streams in, with its sources marked inline — [Source 2, p.16–18] — so a reader can see which part of the document each claim came from.

Hand-off to the full workspace

An Open full manual link carries the conversation into the full Practicl workspace, where the visitor gets the PDF side by side with the chat.

It calls POST /api/v1/transfer to mint a short-lived token, which is carried once in the workspace URL and then stripped from it. The share key itself is never put in a URL.

Analytics events from the widget are recorded via POST /api/v1/events, so you can see how visitors use it.