The widget is one script tag. It adds a report button to a website and opens a form that attaches the page, browser and recent console errors. This page lists everything it accepts; the website guide walks through a first setup.
<script src="https://snagfrog.com/widget.js" data-app="your-app" async></script>
Options
Options are data- attributes on the script tag. The app's Install tab has a configurator that writes them.
| Attribute | Default | What it does |
|---|---|---|
data-app | required | Your app's slug. |
data-color | #2669e8 | The button's colour (hex). |
data-label | translated "Report a bug" | The button's text. |
data-button | shown | "none" hides the button; open the form yourself with Snag.open(). |
data-icon-only | off | A round button; the label becomes its tooltip. |
data-icon | frog | "chat", "bug", "idea", "question", "megaphone", "none", or an https image address. |
data-size | md | "sm", "md" or "lg" button. |
data-radius | popup 16, button a pill | Corner radius in pixels, 0 to 32, for the popup and the button. |
data-position | right | "right" or "left". |
data-offset-x, data-offset-y | 20 | Distance from the corner in pixels. |
data-z-index | 2147483000 | The button and popup's stacking order. |
data-layout | form | "form" (every field on one screen), "composer" (one message box), "guided" (one question at a time) or "home" (a welcome screen with a row per kind of report). |
data-kinds | bug,feedback,question | Which kinds of report to offer. |
data-kind | none | The kind selected when the form opens. |
data-popup-color | the app's colour | The colour used inside the popup (hex). |
data-title | the app's name | The popup's header. |
data-avatar | none | An https image for the header. |
data-greeting | none | An opening message in the chat layouts. |
data-width, data-height | 440 × 720 | Popup size on desktop, in pixels: width 320 to 640, height 400 to 900. |
data-theme | auto | "auto", "light" or "dark". |
data-lang | the page's <html lang>, else English | One of the 17 supported languages, for example "de". |
data-hotkey | none | A keyboard shortcut such as "alt+b" or "mod+shift+k" (mod is ⌘ on a Mac, Ctrl elsewhere). |
data-console | on | "off" stops keeping console errors for reports. |
data-page-url | path | "path" (no query string or fragment), "full" or "none". |
data-errors | off | "auto" sends uncaught errors and unhandled rejections on their own. |
data-version | none | Your app's version, attached to captured errors. |
data-key | none | The app's publishable key (snag_pk_…), for apps set to accept only errors that carry it. |
JavaScript API
| Call | What it does |
|---|---|
Snag.open(options?) | Opens the form. { kind, title, description, context } fill in fields; any other key is added to the context. |
Snag.close() | Closes the form. |
Snag.show() / Snag.hide() | Shows or hides the button. |
Snag.identify({ email, name }) | Who is reporting: fills in their name and email. |
Snag.setContext({ key: value }) | Details attached to every report from this page. |
Snag.on(event, fn) / Snag.off(event, fn) | Listen for "open", "close" or "submit". |
Calls made before the script has loaded can be queued, and the same line works afterwards:
window.Snag = window.Snag || { q: [] };
Snag.q.push(["identify", { email: user.email, name: user.name }]); Your own buttons
Any element with data-snag-open opens the form when clicked. data-snag-kind, data-snag-title and data-snag-description fill in the form, and data-snag-source lands in the report's context so those reports are easy to filter.
What is kept private
- Console errors stay in the page until someone sends a report. Before they leave it, addresses in them lose their query string and anything that looks like a token is redacted.
- A home folder in a file path becomes
~. - The page address is sent without its query string unless you set
data-page-url="full". - Captured errors never include the query string, whatever
data-page-urlsays.
Content-Security-Policy
The widget uses no inline scripts and no eval. A page with a policy needs:
script-src https://snagfrog.com (the script) frame-src https://snagfrog.com (the report form) img-src https://snagfrog.com (the button icon; plus your own host for a custom icon) connect-src https://snagfrog.com (only with data-errors="auto")
Questions
How big is the widget script?
The script every page loads holds only the button, the API and the error hooks. The popup, the hotkey handling and the sending code load on demand: when the button is hovered or pressed, Snag.open() is called, a hotkey is set, or an error is to be sent.
What does the widget send without the user doing anything?
Nothing by default. Console errors are kept in the page and only attached when someone sends a report. With data-errors="auto", uncaught errors and unhandled promise rejections are sent on their own, at most ten distinct ones per page load.
Does the page address include the query string?
Not by default. data-page-url is "path" unless you change it: the address without its query string or fragment. "full" sends the whole address and "none" sends none.
More reference pages
Start a free 30-day trial · All docs · Guides · Compare with other tools · Changelog