--- name: install-widget description: >- Install the Quackback widget in a host application and identify signed-in users with a verified token. Use when setting up Quackback, adding the feedback or messenger widget, wiring Quackback("init"), or implementing Quackback identify / ssoToken / logout. --- # Install the Quackback widget Follow these steps IN ORDER. Do not invent APIs. Make the smallest change that works — add alongside existing code, do not restructure the host app. Credentials come from the user or from Admin → Settings → Widget → Install: - Instance URL (example: `https://feedback.example.com`) - `QUACKBACK_WIDGET_SECRET` — server-only. Never commit it or ship it to the browser. If either value is missing, ask once, then continue. ## STEP 1: Detect the stack Look at dependency and lock files (`package.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `Gemfile`, `composer.json`, `requirements.txt`, `go.mod`, …) to choose the package manager and where root layout / auth live. If Quackback is already installed and initialized, do not rewrite it. Skip to STEP 3 and add only what is missing (usually identify). ## STEP 2: Load the widget Initialize once, in the root layout / app shell — the same place other third-party scripts load. Not on a single page. **HTML / any site** — paste before ``: ```html ``` Replace `INSTANCE_URL` with the workspace URL, no trailing slash. **SPA** — the snippet or the npm package both work. Prefer the approach that already exists. If you add the package, use the repo's package manager (`npm install` / `pnpm add` / `bun add` / `yarn add`). Do not hand-edit `package.json`. ```js import { Quackback } from '@quackback/widget' Quackback.init({ instanceUrl: process.env.NEXT_PUBLIC_QUACKBACK_URL }) ``` The widget must appear for anonymous visitors after `init`. Do not gate the snippet on login. ## STEP 3: Identify signed-in users Read [references/identify-users.md](references/identify-users.md) now. Then implement it. Identify is required for signed-in users. Anonymous visitors need no identify call. 1. Add a **server-only** route that reads the host session, signs a short-lived HS256 JWT with `QUACKBACK_WIDGET_SECRET`, and returns `{ ssoToken }`. 2. Call identify as soon as the host knows who the user is: when the app first loads if they are already signed in, and immediately after login or signup. Once per session — not on every client navigation. 3. If the user is already known at init time, pass `{ ssoToken }` as `identity` on `init` instead of a separate identify call. 4. Call `Quackback("logout")` from the host logout handler. Always, even if you do not expect a shared computer. Do not call `Quackback("identify", { id, email })`. That unverified shape is rejected. ## STEP 4: Store credentials If valid values already exist in `.env` / `.env.local`, leave them. Otherwise write: - `QUACKBACK_WIDGET_SECRET` — server-only - A public env var for the instance URL if the client needs it (`NEXT_PUBLIC_*` / `VITE_*` for the URL only) Never put the secret in public env vars, the snippet, or client bundles. ## STEP 5: Verify - Widget launcher appears on a logged-out page. - After login (or on an already-authenticated load), the server route returns `{ ssoToken }` and the client identifies once. - Logout clears identity; the launcher stays. - Secret is not in the client bundle. ## Rules - Match the host app's auth, routing, and package manager. Reuse existing session helpers. - Do not rename `ssoToken`. - If you cannot tell where layout or auth live, ask one question, then continue. - More detail: https://quackback.io/docs/widget/installation and https://quackback.io/docs/widget/identify-users