# How to keep a feedback widget from slowing your site

> Load the widget with defer, keep it free of dependencies, and avoid network requests until a visitor sends feedback. The Escuta Produto widget is one script of about 5 KB compressed with no fonts or images. Measure your pages with and without it before you call it cheap.

Source: https://escutaproduto.com/resources/feedback-widget-performance
Last updated: 2026-10-09

## Every third-party script has a cost

A feedback widget is a third-party script, and every third-party script competes with your own content for the browser. The browser must download the file, parse it, run it and draw anything it adds. On a slow phone connection or an older device, that work can delay the moment a visitor can read or tap the page. The widget's job is small, but the cost is paid on every page where you install it, so it is worth checking.

The good news is that a widget that does little on load can be cheap. The question to answer is not "is the widget fast" but "what does the widget do on my pages, and when".

## Load the script with defer

Add the `defer` attribute to the script tag. It tells the browser to download the file while it keeps parsing the HTML, and to run the script after the document is parsed:

```html
<script src="https://escutaproduto.com/widget.js" data-key="pk_your_product_key" defer></script>
```

Without `defer`, a script in the head can block the parser until the file arrives. With `defer`, the page content is already in place when the widget starts. The widget finds its own script tag through `document.currentScript`, and it falls back to a query for the script if that is not available, so the attributes still apply.

If you need the widget to load after everything else, insert the script yourself once the page has finished loading:

```js
window.addEventListener("load", () => {
  const script = document.createElement("script");
  script.src = "https://escutaproduto.com/widget.js";
  script.dataset.key = "pk_your_product_key";
  document.body.appendChild(script);
});
```

The trade-off is that the feedback button appears a moment later. For most sites that is fine, because nobody needs the button in the first half second.

## Keep the payload small

The Escuta Produto widget is a single file of about 5 KB compressed before any server compression. It has no dependencies, so the browser does not download a framework, a component library or a second script to run it. Its styles are part of the same file and are written into its own shadow root.

Small matters, but so does what the file does at load time. The widget builds its markup, attaches a shadow root and mounts one element on the body. The panel starts hidden, and it becomes visible only when someone opens it. A hidden panel costs little to draw, so the cost stays low on pages where nobody opens the widget.

Options that do not change the file size include `data-trigger="none"`, which only hides the floating button. Hiding the button saves visual clutter, not download time. Judge the widget by the file and the work it does, not by what it looks like.

## Make no requests until someone sends

After the script loads, the widget makes no further network request until a visitor submits the form. There are no analytics calls, no tracking pixels, no font downloads and no image requests. The only request is the POST that sends the feedback, and it happens after a click.

This is worth checking in your own network panel. Load a page with the widget, leave it alone, and look at the requests the browser made. You should see the script and nothing else from the widget's domain. If you see more, the extra requests come from your own code or from another tool on the page.

## Avoid the preflight request

When a browser sends a cross-origin request with a custom content type such as `application/json`, it first sends a preflight request with the OPTIONS method to ask permission. That is a second round trip before the real message goes out. The widget sends its body as `text/plain` with a UTF-8 charset. That content type counts as a simple request, so the browser skips the preflight and sends the message directly.

The widget also sets `keepalive: true` on the request. That flag lets the browser finish the request if the visitor navigates away right after sending, which matters for a form people submit and leave. Neither choice changes what the server receives. The body is still the same JSON, and the server reads it as the widget sends it.

## Measure the impact before and after

Do not rely on a feeling. Measure one page with and without the widget, using the same device profile and network settings each time. Run a Lighthouse audit or a WebPageTest run, and compare these results:

1. Total Blocking Time, which shows how long the main thread was busy.
2. The time until the page's main content first appears on screen.
3. The number of requests and total bytes on the page.
4. The Performance panel in Chrome DevTools, which shows any long task the widget adds at load.

Run each test three times and use the median, because one run can vary a lot. If the numbers move in a way you can see on a real phone, act on it. If they do not, the widget is probably not your bottleneck, and the next step is to look at your own images and scripts.

## What the Escuta Produto widget loads and when

The widget loads once, with the script tag you add to your page. It appends one host element to the body, then waits. It sends a request only when a visitor sends feedback. It does not poll the server, does not fetch settings on load and does not load anything from a third party. The panel and the form are built in memory and stay hidden until someone opens them.

For attributes and the snippet, see the [widget docs](/docs/widget). If the script loads on every page, check your policy as well, using [content security policy for third-party widgets](/resources/content-security-policy-widgets). For how the widget stays separate from your page's styles, read [why embeddable widgets use Shadow DOM](/resources/shadow-dom-for-widgets).

## Set up the Escuta Produto widget without slowing your pages

Install the script with `defer` on the pages where feedback makes sense, such as the product itself, rather than on every marketing page. Measure one page before and after. If you have a slow page that does not need feedback, leave the widget off it, or use the delayed loading pattern above on the pages where the button matters less. Those choices keep the widget useful without adding weight to the pages where it adds no value.

## Frequently asked questions

### Does a feedback widget slow down my website?

A small widget with defer has a modest effect, mostly from the download and the work done at load. Measure one page with and without it, using the same device and network, to see the real impact on your site.

### What does the defer attribute do on a script tag?

It downloads the script while the page is still being parsed and runs it after the HTML is read. The page content appears without waiting for the script to run, which helps the first view.

### Why does the feedback request avoid a preflight?

The widget sends its body as text/plain, which is a simple content type. The browser then skips the extra permission request it would send for a JSON body, so the message goes out in one round trip.
