=== Stopbot ===
Contributors: stopbot
Tags: stopbot, blocker, security, bot protection, firewall
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Protect WordPress frontend traffic using the STOPBOT Blocker V2 API endpoint.

== Description ==

STOPBOT Blocker V2 checks public WordPress frontend visitors with the STOPBOT Blocker V2 endpoint before WordPress renders the page.

The plugin only uses:

https://api.stopbot.net/services/blockerv2

It supports API key configuration, Blocker V2 confname, safe params/header forwarding, proxy IP handling, logged-in user bypass, redirect responses, HTTP status code responses, visitor logs, and diagnostic logs.

== Installation ==

1. Upload the `stopbot` folder to `/wp-content/plugins/`, or upload a zip from WordPress Admin > Plugins > Add New.
2. Activate `Stopbot`.
3. The setup wizard opens automatically after activation.
4. Enter your STOPBOT API key and Blocker V2 configuration name.
5. Click Save & Test Connection.
6. Enable protection after the test succeeds.

== Setup Wizard ==

The setup wizard helps users complete the first installation:

* Create or copy the Blocker V2 configuration name from panel.stopbot.net.
* Connect a valid STOPBOT API key.
* Test the connection to the Blocker V2 endpoint.
* Enable frontend protection.

The connection test uses one Blocker V2 API request.

== Configuration ==

Required:

* STOPBOT API key
* Blocker V2 configuration name (`confname`)

Enter both values in Settings > Stopbot > Main.

== External Services ==

This plugin connects to the Stopbot API service to check public WordPress frontend visitors before WordPress renders the page.

Service used:

https://api.stopbot.net/services/blockerv2

Provider:

STOPBOT.NET

Service website:

https://stopbot.net/

Documentation:

https://docs.stopbot.net/v2

Privacy Policy:

https://docs.stopbot.net/information/privacy-policy

Terms of Services:

https://docs.stopbot.net/information/terms-of-services

When data is sent:

* When the administrator clicks Save & Test Connection.
* When Enable Protection is turned on and a public frontend page request is checked.

Data sent to Stopbot:

* STOPBOT API key.
* Blocker V2 configuration name.
* Visitor IP address.
* Visitor user agent.
* Current page URL.
* Safe query parameters, only when Request Data is enabled.
* Safe request headers, only when Request Data is enabled.

Why data is sent:

Stopbot uses this data to return the Blocker V2 decision, including whether the visitor should be accepted, blocked, redirected, or served a configured HTTP status response.

== Bundled Libraries ==

This plugin includes Chart.js 4.5.1 for the Visitor Log statistics graph.

Chart.js is licensed under the MIT license. The bundled license file is included at:

assets/js/chartjs-license.txt

The bundled Chart.js source file is included at:

assets/js/chart.js

== Frequently Asked Questions ==

= Does this plugin use other STOPBOT endpoints? =

No. This plugin only uses the Blocker V2 endpoint.

= Does it protect wp-admin? =

No. WordPress admin, AJAX, cron, login, and XML-RPC paths are skipped to reduce lockout risk.

= What happens when a visitor is blocked? =

The plugin follows the Blocker V2 response. `RedirectURL` redirects the visitor, and `HTTPStatusCode` returns the configured HTTP status.

= How do I control which WordPress paths are checked? =

Use Path Rules. Exclude mode checks all frontend pages except the listed paths. Include mode checks only the listed paths.

= How do I prevent ERR_TOO_MANY_REDIRECTS when RedirectURL points to a WordPress page? =

The plugin automatically skips a redirect when `pageResponseContents` points to the same page as the current request. It ignores query strings, treats HTTP and HTTPS as the same page, and normalizes repeated or trailing slashes in the path. For landing pages that should never be checked, use Path Rules with Exclude mode.

= Should I enable proxy headers? =

Only enable proxy headers when the site is always behind a trusted proxy such as Cloudflare, Nginx, Apache, Caddy, or a load balancer.

Set this option to `"Off"` for normal hosting, or when you are not sure. If this option is enabled on a public origin without a trusted proxy, visitors may spoof their IP address using headers such as `X-Forwarded-For`.

Use this simple rule:

* Cloudflare is active and the origin only accepts Cloudflare traffic: enable it.
* A trusted reverse proxy or load balancer controls the real visitor IP header: enable it.
* Normal hosting or unsure: `"Off"`.

= Does this plugin cache Stopbot API responses? =

No. The plugin calls the Stopbot API for each checked frontend page request so Blocker V2 decisions do not become stale or cross over between different URLs, user agents, params, or headers.

= Does this plugin keep visitor logs? =

Yes. The Visitor Log tab stores recent Stopbot checks in a dedicated WordPress database table named with the active WordPress prefix, for example `wp_stopbot_blockerv2_visitor_log`. The table is created when the plugin is activated and dropped when the plugin is uninstalled. The tab loads visitor rows by database page, supports 10, 25, 50, or 100 results per page, and refreshes the current page every 60 seconds while the settings page remains open. It supports database sorting by date/time and IP address, plus filters for device, OS, browser, country, ISP, and description. The Status column includes the API HTTP response code. Its statistics graph uses the bundled local Chart.js library on the Stopbot settings page. It does not store API keys or full page URLs. Device, OS, and browser are detected from the visitor user agent.

= Why does it look like nothing happens when I open the website? =

By default, logged-in WordPress users are bypassed to prevent administrator lockout. Test from an incognito/private browser window, log out first, or temporarily disable logged-in user bypass.

When protection is enabled and configured, the plugin asks WordPress cache plugins to avoid full-page caching by setting no-cache flags and headers. If a page was already cached before the plugin ran, purge LiteSpeed/server/CDN cache once so WordPress can execute the protection hook on the next request.
