Widget reference
Every option, as a config key and as a data attribute, plus the window.Jot API.
Options
Every option exists twice: as a data-jot-* attribute on the
script tag, and as a config key in the
packages. They mean exactly the same thing.
| Config key | Attribute | Default | What it does |
|---|---|---|---|
projectKey | data-jot-key | — | Required. Your project key, from Project → Settings |
trigger | data-jot-trigger | "fab" | "fab" is the round Jot button; "tab" is a vertical FEEDBACK tab |
edge | data-jot-edge | "right" | Which side the trigger sits on: "left" or "right" |
offset | data-jot-offset | 50 | Vertical position, as a percent of the viewport height |
environment | data-jot-env | — | Tags every report with an environment. Trimmed and lowercased |
autostart | data-jot-autostart | true | false keeps the widget unmounted until you call Jot.init() |
| — | data-jot-internal | — | "true" hides the widget from ordinary visitors — see below |
<script
src="https://cdn.jsdelivr.net/npm/@usejot/widget@1/dist/jot.js"
data-jot-key="jot_pk_your_key"
data-jot-trigger="tab"
data-jot-edge="left"
data-jot-env="staging"
></script>Environments
environment stamps every Jot from that page with a name you choose —
staging, preview-142, production. Filter the inbox by it so production
reports and preview noise never mix. Agents can filter by it too.
Internal only
data-jot-internal="true" keeps the widget invisible to your customers on a
public page:
- The widget mounts only when the page is opened with
?jot=truein the URL. - The browser remembers that, so later visits stay in.
?jot=falseforgets it.
Pair it with Internal-only mode in Project → Settings → Who can leave Jots so Jot also refuses anyone who isn't a signed-in team member.
Calling Jot.init() yourself skips the ?jot=true check — your page's own code
deciding to show the widget is consent enough.
window.Jot
The script defines one global.
| Call | Does |
|---|---|
Jot.init() | Mounts the widget. Use with autostart: false, e.g. after cookie consent |
Jot.open() | Opens the widget, as if the trigger was clicked |
Jot.destroy() | Removes the widget from the page. Jot.init() brings it back |
Jot.version | The API version, currently "1" |
// after your consent tool says yes:
window.Jot?.init();Mounting twice is harmless — the second call does nothing. The packages call
Jot.destroy() for you when their component unmounts.
What it does to your page
As little as possible:
- Renders inside a shadow root — no styles cross in either direction.
- Sits out of the page flow — zero layout shift, no new scrollbar.
- Never changes your
<body>styles and never traps focus while closed. - Loads in stages: a loader of about a kilobyte up front, the rest when someone opens it, the recorder only when someone presses Record.
Privacy classes
| Class | Effect |
|---|---|
jot-mask | Text masked in recordings, painted over in screenshots |
jot-block | Left out of recordings, painted over in screenshots |
jot-ignore | Typing in it is not recorded |
More in Privacy & masking.