The script tag
DOMContentLoaded — you do
not need to call init().
The key belongs in the page. It is a publishable key, public by construction;
what protects it is the origin check, not secrecy.
With no key on the tag, the widget logs one warning and does nothing. It never
throws into your page.
Where to put it
On every page you want the agent to work on, including the ones it needs to navigate through. The agent can only act on controls that are on screen, so a page without the widget is a page it cannot walk a user into.defer is recommended — the widget never blocks rendering.
Script tag attributes
Everything below is optional.Configuration
Identity on the tag
If your server renders the page and already knows who the user is, you can put identity straight on the tag instead of callingidentify():
data-user-id, data-user-email, data-user-name,
data-user-company, data-user-plan, data-user-phone,
data-user-created-at. Empty attributes are ignored.
A programmatic
identify() call wins over the tag. The tag’s identity is
adopted only when identify() has not already recorded one — so an
interactive login updates identity correctly without you clearing anything.Configuring with a global instead
If setting attributes is awkward in your framework, setwindow.PeeveConfig
before the script loads:
init() option, then the script tag
attribute, then PeeveConfig.
The npm package
Peeve.init injects the same script tag from the same CDN with the same key. It
is idempotent, and it will not add a second tag if one is already on the page —
so having both is harmless.
The package works with any frontend and has no dependencies. It is SSR-safe:
init is a no-op on the server, and identify / reset calls made before the
widget finishes loading are queued and flushed when it appears.
There are two names here and they are not the same object.
Peeve (capital)
is what the npm package exports. window.peeve (lowercase) is the running
widget on the page. Both are covered in
the JavaScript API.Verifying the install
1
Check the widget booted
In the browser console,
window.peeve should be defined. If it is not, the
script did not load or the tag had no key — check for the
[peeve] no data-publishable-key… warning.2
Check the config call
In the network tab, look for the widget’s bootstrap request to
api.peeve.ai. A 200 with "ok": true means the key and origin
resolved.If enforcement.disabled is true, the workspace is not entitled to serve —
check the kill switch, the trial expiry and the subscription.3
Check it has been mapped
If
mapped is false in that response, the widget stays hidden for end
users on purpose — a real visitor should never meet an unmapped cursor. Run
the baseline capture from the dashboard.Content Security Policy
If your app sets a CSP, allow:widget.js, which
is why cdn.peeve.ai must be in script-src and not only connect-src. API
calls go to api.peeve.ai.
If you set data-endpoint, add that origin to connect-src instead.