Install the widget
read as.mdYour agent’s chat widget is one script tag. Every web service — a framework you build, a static generator, a CMS, a hosted site builder — has a place for code that runs on every page, right before </body>. The tag goes there once and the launcher appears on every page. The tag is the same everywhere; only where your site lets you put it differs.
The tag
Section titled “The tag”Copy it from the console’s Embed tab (it renders with your real app id) or take it from here and put your app id in place of app_abc123 — the console shows it, and guuey apps list prints it:
<!-- guuey widget. Add this site to the app's allowed domains or the embed is refused. --><script src="https://widget.guuey.com/v1.js" data-app="app_abc123" async></script>The loader reads data-app from its own tag and mounts; there is nothing else to write. When you want options — theme, launcher label, colours, position, a sign-in token endpoint — the console renders a two-script form instead (the bar layout is the one exception: the single tag carries it as data-layout="bar"); both forms are on Embed & share, and the loader is a permanent contract: paste once and it keeps working.
Where it goes
Section titled “Where it goes”Find the one template that wraps every page of your site and put the tag just before </body>:
- A framework you build (Next.js, Astro, Nuxt, SvelteKit, Vite/React, Rails, Laravel, Django…) — the root layout or base template.
- A static generator (Jekyll, Hugo, Eleventy…) — the footer include or the default layout.
- A CMS or hosted site builder (WordPress, Webflow, Squarespace, Framer, Shopify, Wix…) — the site-wide “custom code” / “code injection” setting, in its footer or end of body slot. The per-platform pages give the exact clicks as they land here.
- A single-page app — once, in the root layout; the launcher follows route changes. To hide it on in-app routes, see Hiding the launcher on in-app routes.
Before it shows
Section titled “Before it shows”- Allow your site’s origin. The widget is embeddable only on domains you’ve allowed: console → your app → Embed → Allowed origins, or
guuey apps update <appId> --domains <origin>. A bare hostname (example.com) covers the apex and every subdomain; a scheme-prefixed origin (https://example.com) is an exact match. Changes take effect within about 15 seconds — reload your page after saving. Details: Allow your site’s domain. - If your site sets a Content-Security-Policy, allow
https://widget.guuey.cominframe-srcandconnect-src, and admit the tag and the loader’s one<style>: under a nonce-based policy put the page’s nonce on the tag (the loader carries it onto that<style>); under a host allowlist addhttps://widget.guuey.comtoscript-srcand'unsafe-inline'tostyle-src— nothing else. Why those: the CSP section. - Verify with
guuey apps check <appId> --origin <origin>— the same check the widget makes.
One prompt for any stack
Section titled “One prompt for any stack”Give this to your coding agent (Claude Code, Codex, Cursor); it works out your stack and does the four steps above, asking only for what these pages already say. Copiable:
Install the Guuey chat widget on this site. Before changing anything, readhttps://docs.guuey.com/install-widget.md and https://docs.guuey.com/embed.md(the raw markdown of the two pages) and follow them exactly; do not inventoptions or steps they do not contain.
1. Identify this site's stack and the one template or setting that wraps every page (root layout, footer include, or the site-wide custom-code footer slot).2. Put this tag there, just before </body>, with my app id <appId> in place of app_abc123: <script src="https://widget.guuey.com/v1.js" data-app="app_abc123" async></script> Add nothing else to the tag — except your page's CSP nonce, if the site uses nonces (step 4).3. Tell me the exact origin(s) my pages are served from (scheme + host) so I can add them to the app's allowed domains in the console (Embed → Allowed origins) or with: guuey apps update <appId> --domains <origin>. Remind me that a bare hostname covers the apex and every subdomain, while a scheme-prefixed origin is an exact match, and that changes take about 15 seconds to apply.4. If this site sets a Content-Security-Policy, add exactly these allowances and nothing more. If the policy uses nonces (script-src 'nonce-...'): render the site's per-request nonce on the widget tag the way its other script tags carry it — that is what lets the loader run, and the loader puts the same nonce on the one <style> it injects; then allow https://widget.guuey.com in frame-src and connect-src. If the policy uses host allowlists: add https://widget.guuey.com to script-src, frame-src and connect-src, and 'unsafe-inline' to style-src.5. If this is a single-page app and the launcher should not show on in-app routes, apply the hiding pattern from embed.md — otherwise leave it on every page.6. When I've saved the origin, verify with: guuey apps check <appId> --origin <origin>Stop and ask me before any step those two pages do not describe.Editing your site by hand?
Section titled “Editing your site by hand?”If you manage your site without a coding agent, the per-platform pages give the exact place, verified against the vendor’s own documentation and dated:
- Plain HTML and static site builders
- Next.js
- WordPress
- Shopify
- Wix
- Squarespace
- Webflow
- Framer
- Vite single-page apps (Create React App noted there)
- Astro
- Jekyll
- Laravel
More land here as our visitors’ stacks ask for them. Until yours is listed, the rule is the same: the site-wide footer / end-of-body slot, one tag, then the three steps above.