Get Started
Manual install
The plain script tag, framework recipes, and CSP notes for engineers who want to wire it up by hand.
Plain HTML
Drop this near the closing </body>:
html
<script
src="https://duggai.com/embed.js"
data-key="duggai_pk_XXXXXXXXXXXX"
defer
></script>Next.js (App Router)
Use the Script component from next/script in your root layout:
tsx
// src/app/layout.tsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Script
src="https://duggai.com/embed.js"
data-key={process.env.NEXT_PUBLIC_DUGGAI_KEY}
strategy="afterInteractive"
/>
</body>
</html>
);
}Next.js (Pages Router)
tsx
// pages/_app.tsx
import Script from "next/script";
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Script
src="https://duggai.com/embed.js"
data-key={process.env.NEXT_PUBLIC_DUGGAI_KEY}
strategy="afterInteractive"
/>
</>
);
}React (Vite, CRA, Remix)
Add the script in your index.htmllike the plain HTML example. Don't load it inside a React component — the widget self-mounts to the DOM and React doesn't need to know about it.
Vue / Nuxt
ts
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
src: "https://duggai.com/embed.js",
"data-key": process.env.DUGGAI_KEY,
defer: true,
},
],
},
},
});Svelte / SvelteKit
Add to app.html:
html
<!-- src/app.html -->
<body>
%sveltekit.body%
<script
src="https://duggai.com/embed.js"
data-key="duggai_pk_XXXXXXXXXXXX"
defer
></script>
</body>Content Security Policy
If you set a CSP, allow the widget's origin in script-src, connect-src, and img-src:
http
Content-Security-Policy:
script-src 'self' https://duggai.com;
connect-src 'self' https://duggai.com;
img-src 'self' data: https://duggai.com;Single-page apps
The widget watches for route changes via the History API and updates the page-context signal it sends to the agent. No extra wiring needed — but if you call history.pushState manually for analytics, the widget will pick that up too.
Identifying logged-in users
The
data-key attribute is your widget public key (prefix duggai_pk_) and is safe to ship in client code. To prove a user is who they claim to be (so the agent can read their account context), call DuggAI.identify({ id, hash }) where hashis an HMAC-SHA256 of the user id computed on your server using your widget's webhook secret. Never expose the webhook secret in client code.