# Widget configuration

Configure Annot8 script attributes, runtime commands, analytics consent, keyboard shortcuts, and screenshot privacy controls.

Source: https://docs.annot8.app/docs/widget/configuration



Most of what you'd want to configure lives in the dashboard, where it applies to
every site embedding the project without a redeploy. The script tag handles the
rest.

## Script attributes [#script-attributes]

```html
<script
  src="https://www.annot8.app/widget.js"
  data-project-id="pj_xxxxxxxxxxxx"
  data-convex-url="https://your-deployment.convex.cloud"
  data-theme="auto"
  data-label="Feedback"
  async
></script>
```

| Attribute                | Description                                                                      |
| ------------------------ | -------------------------------------------------------------------------------- |
| `data-project-id`        | **Required.** Your project key (`pj_...`)                                        |
| `data-convex-url`        | **Required.** Backend URL for your deployment                                    |
| `data-dashboard-url`     | Dashboard origin. Inferred from the script `src` when omitted                    |
| `data-theme`             | `light`, `dark`, or `auto` (default — follows the visitor's OS preference)       |
| `data-label`             | Launcher label, overriding the dashboard setting                                 |
| `data-public-slug`       | Public link slug for guest feedback. Usually auto-discovered                     |
| `data-analytics-consent` | `true` only once consent has been obtained                                       |
| `data-shortcuts`         | `true` turns on the <kbd>C</kbd> and <kbd>I</kbd> page shortcuts. Off by default |
| `data-config`            | A JSON string carrying any of the above keys                                     |

Every value is validated. A project key in the wrong shape, a backend URL that
isn't HTTPS (except `localhost` and `127.0.0.1`), a URL carrying credentials, or
an unrecognised theme is discarded rather than passed through.

The JSON form is equivalent, and useful when a template makes long attribute
lists awkward:

```html
<script
  src="https://www.annot8.app/widget.js"
  data-project-id="pj_xxxxxxxxxxxx"
  data-config='{"convexUrl":"https://your-deployment.convex.cloud","theme":"dark","label":"Report issue"}'
  async
></script>
```

## What's configured in the dashboard instead [#whats-configured-in-the-dashboard-instead]

| Setting                                           | Where                           | Applies                    |
| ------------------------------------------------- | ------------------------------- | -------------------------- |
| Primary colour, corner, launcher label, pin style | **Settings → Appearance**       | Next page load, everywhere |
| Which hostnames the widget runs on                | **Settings → Environments**     | Immediately                |
| Analytics and Live chat on/off                    | **Settings → Features**         | Next page load             |
| Show the widget in production                     | **Settings → Features**         | Next page load             |
| AI model, visitor audience                        | **Settings → Sharing & safety** | Immediately                |

`data-label` is the one place the script tag wins: when present it overrides the
dashboard label, which is handy when one project serves several surfaces.

## Keyboard shortcuts [#keyboard-shortcuts]

Single-letter shortcuts are **off by default**, because keys pressed on your
page belong to your site. To turn them on, add `data-shortcuts="true"` to the
script tag, or pass `shortcuts: true` in `data-config` or to `init`:

```html
<script
  src="https://www.annot8.app/widget.js"
  data-project-id="pj_xxxxxxxxxxxx"
  data-convex-url="https://your-deployment.convex.cloud"
  data-shortcuts="true"
  async
></script>
```

| Key            | Does                                  |
| -------------- | ------------------------------------- |
| <kbd>C</kbd>   | Toggle comment mode (pin a comment)   |
| <kbd>I</kbd>   | Toggle inspect mode (pick an element) |
| <kbd>Esc</kbd> | Leave comment or inspect mode         |

<kbd>Esc</kbd> works whether or not shortcuts are on. The letter keys are
ignored while someone is typing in a field, and when <kbd>Ctrl</kbd>,
<kbd>Cmd</kbd>, <kbd>Alt</kbd>, or <kbd>Shift</kbd> is held.

## Runtime API [#runtime-api]

The loader exposes an Intercom-style command function. Calls made before the
script finishes loading are queued and replayed.

```js
// Re-initialise, e.g. once your consent manager grants analytics consent.
window.Annot8("init", {
  projectId: "pj_xxxxxxxxxxxx",
  convexUrl: "https://your-deployment.convex.cloud",
  dashboardUrl: "https://www.annot8.app",
  theme: "dark",
  analyticsConsent: true,
});

// Record a custom analytics event (requires Analytics enabled and consented).
window.Annot8("track", "signup_clicked", { plan: "pro" });

// Record a conversion, with an optional value.
window.Annot8("trackConversion", "purchase", 49.99);
```

The same methods are available directly as `Annot8.init(...)`,
`Annot8.track(...)`, and `Annot8.trackConversion(...)`.

Calling `track` or `trackConversion` before Analytics is enabled and consented
is a no-op — nothing is transmitted and nothing throws, so you can leave the
calls in place unconditionally.

### Withdrawing analytics consent [#withdrawing-analytics-consent]

Re-initialise with consent off to stop the tracker:

```js
window.Annot8("init", {
  projectId: "pj_xxxxxxxxxxxx",
  convexUrl: "https://your-deployment.convex.cloud",
  analyticsConsent: false,
});
```

Your consent manager should also clear the host-page keys, each suffixed with
the project id: `ca_visitor_id:<projectId>` in `localStorage`, and
`ca_session_id:<projectId>`, `ca_session_start:<projectId>`, and
`ca_session_activity:<projectId>` in `sessionStorage`.

## Keeping sensitive content out of screenshots [#keeping-sensitive-content-out-of-screenshots]

Annot8 already masks every `input`, `textarea`, `select`, content-editable
region, `iframe`, `video`, and anything marked `[data-private]` in generated
screenshots. For anything else, mark it:

```html
<!-- Obscured in the screenshot, but the layout is preserved -->
<section data-annot8-redact>Private account details</section>

<!-- Omitted from the screenshot render entirely -->
<div data-annot8-ignore>...</div>
```

You can also declare up to 25 selectors before the widget loads:

```html
<script>
  window.annot8RedactSelectors = [
    ".customer-profile",
    "[data-sensitive]",
    "#payment-summary",
  ];
</script>
```

<Callout type="warn">
  Screen recording is a browser-level capture and **cannot** be redacted
  automatically. The reviewer is warned and must review the recording before
  submitting it. Test your exclusions on every browser and page state you
  support.
</Callout>

Annot8's screen recording never requests microphone audio. A voice note is
always a separate, deliberate action.

## Live chat [#live-chat]

When **Live chat** is enabled in **Settings → Features**, the panel gains a
**Messages** tab. Welcome message, email requirement, availability hours, and AI
auto-replies are all configured in the dashboard — see
[Live chat](/docs/chat/overview).

Remember that on a production host the whole panel is hidden unless **Show
widget in production** is on.

## Next [#next]

<Cards>
  <Card title="Customization" href="/docs/widget/customization">
    Colour, corner, label, theme.
  </Card>

  <Card title="What gets captured" href="/docs/widget/capture">
    Attachments and diagnostics.
  </Card>
</Cards>
