# How to collect feedback for a WordPress plugin

> For a WordPress plugin, add a feedback link to your settings page that opens a hosted form, and send submitted feedback from PHP with wp_remote_post to the Escuta Produto REST API. Avoid loading remote scripts in wp-admin, and send only what the site owner chose to submit.

Source: https://escutaproduto.com/resources/collect-feedback-wordpress-plugin
Last updated: 2026-10-09

## Why a plugin should not load a remote script in wp-admin

A WordPress plugin runs on sites you do not control, under an administrator who trusts your code. Loading a script from another domain into the admin screen adds a dependency that the site owner did not ask for. It also draws attention from reviewers and from security scanners, which are quick to flag external code in the dashboard.

For most plugins the better path is simpler: a link on your settings page that opens a hosted feedback form, and a PHP function that posts the message when the site owner chooses to send it. Both work without any remote code in the admin.

The [hosted feedback page](/docs/hosted-page) gives you a form at `https://escutaproduto.com/f/your-product-slug`. It works in any browser, follows the site owner's language and needs no install.

## Start with a link on the settings page

Register a settings page for the plugin and link to the form from it. Use the WordPress functions for the menu and escape the URL before printing it:

```php
add_action( 'admin_menu', function () {
    add_options_page(
        'Feedback',
        'Feedback',
        'manage_options',
        'your-plugin-feedback',
        'your_plugin_feedback_page'
    );
} );

function your_plugin_feedback_page() {
    $url = 'https://escutaproduto.com/f/your-product-slug?lang=en';
    echo '<p><a class="button button-primary" href="' . esc_url( $url ) . '" target="_blank" rel="noopener">Send feedback</a></p>';
}
```

You can prefill the email field with the site administrator's address, using `rawurlencode( get_option( 'admin_email' ) )` in the `email` query parameter. Only do this if the plugin's privacy notes say so. An admin email is personal data, and some site owners share their dashboard with colleagues.

## Think carefully about the deactivation moment

Many plugin teams want feedback when someone turns the plugin off. WordPress makes this harder than it sounds. A deactivation hook runs once, in the request that deactivates the plugin, and your plugin's code does not load on later page views while it is inactive. A notice scheduled from the hook will never appear.

Intercepting the Deactivate link with a script on the plugins screen is possible, but it is intrusive. It delays the click, and many administrators will find it annoying. Most plugins do better with the settings page link, a line in the readme and a visible link in the support documentation. Choose the lighter option unless you have a clear reason to believe that a more direct question is worth the friction.

## Send feedback from PHP with wp_remote_post

When the site owner submits a message from a form in your plugin, send it from the server. Server requests have no `Origin` header, so the allowed origins list does not block them. The function below builds the request with the site and plugin details:

```php
function your_plugin_send_feedback( string $message, string $kind = 'other' ): bool {
    $response = wp_remote_post( 'https://escutaproduto.com/api/v1/feedback', array(
        'headers' => array( 'Content-Type' => 'application/json' ),
        'body'    => wp_json_encode( array(
            'key'      => 'pk_your_product_key',
            'kind'     => $kind,
            'message'  => $message,
            'pageUrl'  => home_url( '/' ),
            'metadata' => array(
                'wordpress' => get_bloginfo( 'version' ),
                'plugin'    => YOUR_PLUGIN_VERSION,
                'php'       => PHP_VERSION,
            ),
        ) ),
        'timeout' => 10,
    ) );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    return 201 === wp_remote_retrieve_response_code( $response );
}
```

The function returns `true` only when the API replies with `201`. Show the owner a clear message in either case. If the call fails, tell them so, and keep the text in the form so they can try again.

Call the function only from a handler that checks a nonce and the user's capabilities, so a page visit or a stray request cannot send messages on the owner's behalf. The WordPress functions `check_admin_referer` and `current_user_can` cover both checks.

## Keep metadata to what the site owner submitted

WordPress sites differ in more ways than plugin teams expect. Sending the WordPress version, the plugin version and the PHP version helps you reproduce a bug. Sending the list of every other plugin on the site, the database name or any user records does not. The rule is simple: send only the details that help with the message, and state them in your privacy notes.

Metadata is a JSON object of up to 4 KB. Keep it to a few short values. The request body is capped at 16 KB, so trim very long messages before you send them.

## Respect the rate limit

The API allows 10 submissions per minute from the same IP address to the same product. A single site rarely gets close. Shared hosting is different: many sites can share one outbound IP, and a busy day across them can produce 429 responses. When you see one, show a short message such as "Too many messages from this server, try again in a minute" and keep the draft.

Escuta Produto does not queue requests for you, so the plugin decides what to do. Retrying straight away on a 429 only adds to the problem.

## Set up Escuta Produto for your plugin

Create a product for the plugin in the dashboard. Set its website, copy the public key into the plugin, and add the settings link with the hosted form URL. Submit a test message from a local WordPress install and confirm it arrives with the WordPress and plugin versions in the metadata.

Add a Slack or Discord webhook so new items reach the people who answer support. The [notifications guide](/docs/notifications) covers the setup. If your plugin also runs on a marketing site, the [article on collecting feedback in a Shopify app](/resources/collect-feedback-shopify-app) describes the same server-side pattern for another platform, and [adding a feedback widget to a WordPress site](/resources/feedback-widget-wordpress) covers the case where you want the widget on the public site itself. The [REST API reference](/docs/api) lists every field and response code.

## Frequently asked questions

### Can a WordPress plugin load the Escuta Produto widget in the admin dashboard?

Avoid it. Remote scripts in wp-admin are a sensitive area, and plugin reviewers look closely at external code. Use a link to the hosted feedback form from your settings page, and send feedback from PHP when the site owner submits a form.

### Does a WordPress site hit the feedback rate limit?

Each site usually has its own IP address, so the limit of 10 submissions per minute per IP and product rarely matters for one site. Shared hosting can put many sites behind one IP, so handle a 429 response by asking the owner to try again shortly.

### Is it safe to put the product key in plugin code?

Yes. The public key can only create feedback and never read it, so it can appear in the plugin source. Do not put any secret in the plugin, because the Escuta Produto API does not use one.
