Widget

Frameworks

Idiomatic install for the frameworks our users ship in most often.

Next.js (App Router)

Add the script in your root layout. Identify users in a client wrapper.

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>
  );
}
tsx
// src/app/_components/duggai-identify.tsx
"use client";
import { useEffect } from "react";
import { useUser } from "@/lib/auth";

export function DuggAIIdentify() {
  const user = useUser();
  useEffect(() => {
    if (!user) return;
    window.DuggAI?.identify({
      id: user.id,
      email: user.email,
      hash: user.duggaiHash,
      traits: { name: user.name },
    });
  }, [user]);
  return null;
}

Remix

Add to your root tags() or just inline in root.tsx:

tsx
// app/root.tsx
export default function App() {
  return (
    <html>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <script
          src="https://duggai.com/embed.js"
          data-key={process.env.DUGGAI_KEY}
          defer
        />
      </body>
    </html>
  );
}

React (Vite, CRA)

The widget is framework-agnostic — drop it into index.html:

html
<!-- index.html -->
<body>
  <div id="root"></div>
  <script
    src="https://duggai.com/embed.js"
    data-key="duggai_pk_XXXXXXXXXXXX"
    defer
  ></script>
</body>

Identify users from a useEffect in your top-level provider.

Vue 3 / 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,
        },
      ],
    },
  },
});
vue
<!-- composables/useDuggAIIdentify.ts -->
<script setup>
import { onMounted, watch } from "vue";
import { useUser } from "~/composables/useUser";

const user = useUser();
watch(user, (u) => {
  if (!u) return;
  window.DuggAI?.identify({
    id: u.id,
    email: u.email,
    hash: u.duggaiHash,
    traits: { name: u.name },
  });
});
</script>

Svelte / SvelteKit

html
<!-- src/app.html -->
<body>
  %sveltekit.body%
  <script
    src="https://duggai.com/embed.js"
    data-key="duggai_pk_XXXXXXXXXXXX"
    defer
  ></script>
</body>

Astro

Add to src/layouts/Base.astro:

astro
---
const key = import.meta.env.PUBLIC_DUGGAI_KEY;
---
<html>
  <body>
    <slot />
    <script
      src="https://duggai.com/embed.js"
      data-key={key}
      defer
    ></script>
  </body>
</html>
Mobile / native apps
The widget is web-only today. Native apps (React Native, Flutter, iOS/Android) can use the DuggAI API directly to embed a chat experience. Email support@duggai.comif you need this and we'll share the in-progress mobile SDK.