=== Synth Antispam – AI Comment Spam Protection ===
Contributors: synthplatform
Tags: AI, antispam, woocommerce, contact form 7, spam protection
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 0.2.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

AI comment spam protection for WordPress. No CAPTCHA, no keyword lists, no auto-deletion. One-click setup with explainable verdicts.

== Description ==

**Spammers learned to write around keyword filters. Synth reads what a comment is actually trying to promote.**

Keyword lists and blocklists miss polite, well-written spam: the "Great article, very helpful!" comment with a casino link in the author URL, the fake SEO agency, the crypto pitch dressed up as a question. Synth uses an AI model to understand the intent of new comments — so it catches spam that looks human, while legitimate comments continue through your normal WordPress moderation. No CAPTCHA, no puzzles, nothing extra for your visitors.

Synth is an AI spam classifier for WordPress comments. It analyzes what a comment is trying to promote instead of matching it against static keyword lists.

= What it blocks =

* SEO and link-building spam, including links hidden in the author URL field
* Casino, crypto, adult and pharma promotions
* Fake "great post!" comments written to carry a link
* Rewritten and misspelled spam that slips past keyword rules
* Pingback spam and trackback spam, including automated submissions through XML-RPC
* Spam submitted through the REST API

= Why it's better than a rule list =

* **Rewording doesn't help the spammer.** Rules match strings, so spammers change the string. The model reads the message — and the message is the thing being sold.
* **Nothing to maintain.** No keyword lists, blocklists or regex to update.
* **Synth never automatically deletes comments.** Spam goes to the Spam folder (or the moderation queue in strict mode) and can be restored in one click. Synth never moves a comment to Trash.
* **You see why.** A verdict column in the Comments list (and on the WooCommerce Products → Reviews screen) shows the spam category and confidence for every checked comment.
* **No CAPTCHA, no visitor friction.** No puzzles or extra fields. Submitting a comment waits for the service for up to 2 seconds; the verdict follows in the background. No tracking scripts on your pages.
* **Your decisions come first.** Synth never touches a comment you or another moderation plugin already marked as spam or trash, never changes a comment whose status a moderator has already changed, and never publishes a comment your site held for review, so it runs fine alongside your existing setup. A held comment it finds to be spam still goes to the Spam folder (in strict mode it stays in the queue).
* **Your site keeps accepting comments.** If the service is unreachable, or your included checks run out, AI classification pauses and comments follow the fallback you chose: they continue through your normal WordPress moderation (default) or are held for review.

= WooCommerce product reviews =

If your shop runs WooCommerce, Synth Antispam checks product reviews the same way it checks comments. A product review is submitted through the same WordPress comment form, so reviews are covered as soon as a site key is set — there is nothing extra to switch on.

* A spam review goes to the Spam folder (or the moderation queue in strict mode) and can be restored in one click, exactly like a comment.
* The verdict column appears on the **Products → Reviews** screen, where WooCommerce lists reviews.
* Reviewers who already have an approved review or comment on your site are trusted and skipped.

Synth looks for promotional and link spam in reviews. It does not judge whether a review is genuine, so it is not a filter for fake or invented reviews.

= Contact Form 7 =

Synth Antispam checks Contact Form 7 submissions too (**Settings → Synth Antispam → Contact Form 7**). Spam is marked as spam by Contact Form 7 itself, so its email is not sent. Install Flamingo to keep a copy of every submission.

= Start protecting comments in a few clicks =

1. Install and activate.
2. Open **Settings → Synth Antispam** and press **Get a site key** — no account to create, no API key to copy.
3. Done. Every site starts with an included allowance of AI checks — see [current plans](https://wordpress.synth.locker/pricing).

Until a key is set, the plugin sends nothing except when you press **Get a site key**, and WordPress decides on every comment exactly as before.

= Data minimization =

Synth sends only the data needed to classify a comment or a form submission: the comment text, author name and URL, the email domain, and a per-site pseudonymous hash of the email. It does not receive the commenter's full email address, IP address, raw User-Agent, cookies or your post content. Commenters who already have an approved comment are skipped entirely. What is sent, when, and how long it is kept is listed under "External services" below.

== External services ==

This plugin needs the Synth Antispam service (`wp-api.synth.locker`, operated by LightApps OÜ, Estonia) to classify comments and, when Contact Form 7 checks are on, form submissions. Nothing is sent until a site key is set, except the request made when you press **Get a site key**.

Every setting and mode of the plugin works on every plan; only the number of AI checks depends on the plan.

**Requests the plugin makes**

Every request below carries the plugin version and WordPress's own User-Agent header, which names your site address and WordPress version (not the commenter's browser); all except **Get a site key** also carry your site key and, in a separate header, your site address.

* Submit a comment (or a WooCommerce product review, pingback or trackback) for a verdict — fields listed below. This request also carries your site key and your site address; the first such request is what ties the key to your site.
* Submit a form for a verdict — only while Contact Form 7 checks are on; the same fields (see `content.body`), and the visitor waits for the verdict.
* Collect the verdict a moment later — sends only the identifier the service issued for that comment.
* Report a moderator correction — off by default (`synth_wp_send_feedback` filter returns false); when enabled, sends only the identifier and the moderator's decision (spam / not spam).
* Get a site key — only when you press the button; sends only the plugin version and the User-Agent header.
* Test connection — only when you press the button; sends one sample comment ("ping", with no commenter details) and costs one check.
* Check the remaining allowance — only while an administrator has the settings screen open; sends the site key and site address. Costs no check; with a new key it may be the request that ties the key to your site.
* Site Health status — only while an administrator has Tools → Site Health open, at most once every 15 minutes; sends a fixed test identifier and costs no check.
* Start a purchase — only when you press an upgrade button; sends Synth the site key, site address, selected option and the settings-page path to return to, then opens Stripe Checkout. Card data goes directly to Stripe and never reaches your site, this plugin or Synth.

**Exactly what is sent, field by field.** The complete list, matching the plugin's request builder:

* `schema_version` — request format version.
* `plugin_version` — installed plugin version.
* `surface` — `wp_comment` or `wp_cf7`.
* `object_type` — comment, review, pingback, trackback or form.
* `content.body` — the comment text; for a form, its subject and message.
* `content.author_name` — the name entered.
* `content.author_url` — the website entered.
* `content.author_email_domain` — only the email domain, e.g. `gmail.com`, never the address.
* `content.author_id_hash` — a per-site salted hash of the email; cannot be linked across sites.
* `context.author_status` — `registered` or `anonymous`.
* `context.is_reply` — whether it is a reply.
* `context.site_locale` — your site language.
* `context.client_ip_status` — whether an IP was present, never the IP.
* `context.has_user_agent` — whether a User-Agent was present, never the string.

**What is never sent:** full email address, IP address, raw User-Agent, post title or body, HTTP referrer, cookies. From a Contact Form 7 form: no attachments, hidden or internal fields, list, checkbox or radio choices, or email fields other than the sender's.

**Retention:** verdict records expire after 24 hours. Separately, the service keeps copies of each submitted request, its verdict and any later correction to train and improve its models. These copies are stored as sent, have no expiry and cannot currently be turned off. This applies to form submissions as well: the service keeps its copy of each submitted form message indefinitely, as sent. To have your site's copies deleted, email support@synth.locker with your site address. Uninstalling deletes your site's salt but not copies already taken. Held form submissions are kept on this site for 7 days, then deleted automatically; deleting the plugin removes them at once.

* Terms of Use: https://synth.locker/assets/legal/wordpress-terms-of-use.html
* Privacy Policy: https://synth.locker/assets/legal/wordpress-privacy-policy.html
* Pricing: https://wordpress.synth.locker/pricing
* Stripe: https://stripe.com/legal · https://stripe.com/privacy

**Paste-ready paragraph for your privacy policy.** The same list for site owners who write their policy by hand, minus the four fields that describe the request's shape rather than the commenter or the submission (`schema_version`, `plugin_version`, `surface` and `object_type`). It is generated from the same manifest as the field list above, so it cannot fall behind it:

> Synth Antispam sends each comment (and each WooCommerce product review, pingback or trackback) to the Synth Antispam classification service — an external processor — to obtain a spam verdict. What is sent: the comment body; the commenter’s display name; the commenter’s website URL; the domain part (not the full address) of the commenter’s email address; a one-way salted hash derived from that email address; whether the commenter is anonymous or a registered user of this site; whether the comment is a reply; the site’s language; whether an IP address was present at all, never the address itself; whether a User-Agent string was present at all, never the string itself. If Contact Form 7 checks are on, form submissions are sent the same way, the form’s subject and message standing in for the comment body. Comments from people who already have an approved comment on this site are not sent to the service at all. The commenter’s full email address, IP address and raw User-Agent string are never sent, in any case. Verdicts are retained by the service for 24 hours and then expire automatically. Separately from that, the service keeps its own copy of everything listed above, together with the verdict it produced and any correction a moderator of this site later makes to that verdict, and uses those copies to train and improve the Synth spam-classification models. Those copies are kept indefinitely and have no expiry date; the comment text and the commenter details above are kept as sent, not anonymised or aggregated. This applies to form submissions as well: the service keeps its copy of each submitted form message indefinitely, as sent. This applies to every site that uses the service: there is no setting that turns it off. To have this site’s stored copies deleted, write to support@synth.locker. Uninstalling this plugin deletes this site’s local secret value, after which any previously sent hash can no longer be linked back to an email address, by this site or by the service.

= Every address that appears in the source =

A search of this plugin's files finds these addresses and no others:

* `wp-api.synth.locker` — the Synth Antispam service above; changeable on the settings screen or in `wp-config.php`. **The only address this plugin sends a request to.**
* `checkout.stripe.com` — Stripe's payment page. Nothing is sent there by the plugin; it only checks that the payment page it was handed really is Stripe's before opening it in your browser.
* `synth.locker`, `wordpress.synth.locker`, `stripe.com`, `wordpress.org`, `www.gnu.org` and `fsf.org` — links (terms, privacy, pricing and plugin home pages, Stripe's documents, the support forum in the translation template, the GPL licence). Nothing is sent to them.
* `support@synth.locker` — the email address for deletion requests.
* Not addresses: the example `your-synth-endpoint.example` in the empty settings field, `gmail.com` in the field list above, the translation-template placeholder `LL@li.org`, and names that appear only inside code comments and are never contacted (`wp-api-dev.synth.locker`, `evil.example`, `https://x`, `http://api`, `http://localhost`).

== Installation ==

1. Install from **Plugins → Add New** (search "Synth Antispam") and activate.
2. Go to **Settings → Synth Antispam** and press **Get a site key**, or paste a key you already have.
3. Press **Test connection**.
4. Optional: choose Spam folder or strict mode (moderation queue), and what happens if the service is unreachable or the allowance runs out.

Multisite: set a network-level key before network-activating.
Advanced: the service address can be changed on the settings screen or in `wp-config.php`.

== Frequently Asked Questions ==

= Does Synth use CAPTCHA? =

No. Visitors see no CAPTCHA, puzzles or extra fields. Synth checks the comment in the background.

= Is there a free plan? =

Every site starts with an included allowance of AI spam checks, with no card required. Sites that need more checks can upgrade to a paid plan — see https://wordpress.synth.locker/pricing.

= What happens when the included checks run out? =

AI classification pauses until the allowance resets or you upgrade. Comments follow the fallback you selected — they continue through your normal WordPress moderation (default) or are held for review — so your site never stops accepting comments.

= How is Synth different from keyword-based spam filters? =

Keyword filters look for known words, domains or patterns. Synth analyzes the intent and context of the comment, which helps it recognize rewritten and human-looking promotional spam without maintaining rule lists.

= Can I use Synth together with Akismet or another moderation plugin? =

Yes. Synth never touches a comment another plugin or a moderator already marked as spam or trash, never changes a comment whose status a moderator has already changed, and never publishes a comment held for review, so it can run alongside your existing moderation setup. A held comment it finds to be spam still goes to the Spam folder (in strict mode it stays in the queue).

= Can Synth be used as an Akismet alternative? =

Yes. Synth can be used on its own for WordPress comment spam protection, or alongside Akismet and other moderation plugins. If another plugin has already marked a comment as spam or trash, Synth leaves it unchanged.

= Will it delete my comments? =

No. Synth never automatically deletes comments or moves them to Trash. Spam goes to the Spam folder (or the moderation queue in strict mode), where you can restore it.

= Will it slow down my site? =

It adds no scripts to your pages. Submitting a comment waits for the service for up to 2 seconds; the verdict follows in the background.

= Can spam be held for review instead of going to Spam? =

Yes — turn on strict mode.

= What happens if the service is unreachable? =

Comments follow the fallback you chose: they continue through your normal WordPress moderation (default) or are held for review.

= How are Contact Form 7 submissions handled? =

Checks are on for a new installation; a site updated from an earlier version sees a one-time notice offering to turn them on. Flamingo, by the author of Contact Form 7, keeps a copy of every submission, including those marked as spam. The visitor waits while the check runs — usually a few seconds, rarely more than about eight. If no verdict arrives in time, "When the service is unreachable" decides: let your site decide sends the email as usual; hold marks the submission as spam. When your monthly checks are used up, submissions always go through unchecked — "When the monthly check quota is used up" applies to comments only. A decision already made by Contact Form 7 or another plugin, such as Akismet or reCAPTCHA, is left as it is and costs no check.

= What if someone floods my contact form? =

The first submission from an address is checked as usual. Once Synth classifies a submission as spam, further submissions from the same address are held without a check for 10 minutes; if spam keeps coming from that address, the window grows up to one hour. No more than three submissions from one address are checked at the same time. Held submissions are marked as spam by Contact Form 7 and listed in the held-submissions journal (Contact → Held submissions), where the button "Not spam — deliver" sends the form's email as if it had never been held. If your site is behind a proxy or CDN that does not pass the visitor's address on to WordPress, all visitors share one address, so after a spam submission the window applies to everyone. The filters `synth_wp_cf7_address_cooldown` (seconds, 0 turns it off) and `synth_wp_cf7_address_concurrent` (0 turns it off) adjust both limits.

= Where do held form submissions go? =

Into the held-submissions journal: Contact → Held submissions (Settings → Held submissions while Contact Form 7 is not active). Every submission the plugin holds is listed there for 7 days with its subject, sender, the reason it was held and the start of its message, then deleted automatically. The journal keeps up to a limit of held submissions; when it is full, further held submissions are still marked as spam by Contact Form 7 but not kept, and the journal shows how many. "Not spam — deliver" sends the email the form would have sent, to its usual recipient; the automatic reply to the sender and file attachments are not sent again. Delivering a submission also lets the same sender through again: the plugin forgets its verdict on that text and ends the waiting period for their address.

= What does the sender see when a submission is held? =

The form's own spam message — Synth does not replace it. Contact Form 7 shows the text set in Contact → your form → Messages → "Submission was referred to as spam", which by default reads "There was an error trying to send your message. Please try again later." It is the same message a visitor sees when Akismet or reCAPTCHA holds a submission, so you decide its wording once, for every reason. A person held by mistake is told to try again rather than that the message was sent.

= Which submissions are checked? =

Comments, pingbacks and trackbacks from the comment form, REST API and XML-RPC, and WooCommerce product reviews submitted through the review form on the product page. Commenters and reviewers with an already-approved comment or review are trusted and skipped. With Contact Form 7 checks on, also every Contact Form 7 submission, except those from logged-in moderators.

= Does it work on multisite? =

Yes, with a key per site or a network-level key.

= Does the plugin do anything before I add a site key? =

No. Apart from the **Get a site key** button, it sends no requests, and WordPress decides on every comment exactly as it would without the plugin.

= What happens to my site key if I delete the plugin? =

It stays, so reinstalling keeps your checks. Enable "Delete the site key when the plugin is deleted" to remove it.

= For site owners: GDPR and similar privacy laws =

Mention Synth in your privacy policy, including what is sent and how long it is kept, with the 24-hour verdict retention and the indefinite retention of training copies (see "External services"). You need a lawful basis for processing commenter data.

== Screenshots ==

1. AI verdicts in the Comments list — see spam category and confidence for every checked comment.
2. One-click site key setup — no account creation or API key copy-and-paste.
3. Choose Spam folder or strict mode, and what happens if the service is unreachable.
4. Remaining checks and upgrade options on the settings screen.
5. Spam goes to the Spam folder, never Trash — restore anything in one click.

== Changelog ==

= 0.2.0 =
* Added: Contact Form 7 submissions are checked for spam. Spam is marked as spam by Contact Form 7 itself, so its email is not sent; legitimate submissions arrive as before. Checks are on for new installations; after an update, a one-time notice offers to turn them on.
* Added: the held-submissions journal (Contact → Held submissions). Held form submissions are kept on this site for 7 days, and "Not spam — deliver" sends the form's email as if it had never been held.
* Added: after a spam verdict, further submissions from the same address are held without a check for a short time, so a burst of form spam does not use up your checks.

= 0.1.3 =
* Added: WooCommerce product reviews are checked for spam the same way as comments, and the verdict column appears on the Products → Reviews screen.
* Fixed: the settings page now points to Settings → Privacy → Policy Guide (previously Tools), and a few more interface texts can be translated.

= 0.1.2 =
* Fixed: comments submitted through the REST API now receive their verdict; previously the check was spent but the verdict was never applied.
* Fixed: the comment text is now sent exactly as the commenter wrote it (previously apostrophes and quotes arrived escaped), so repeated identical comments are also recognised from the local cache again.
* Added: a single review request in the admin, shown on the Comments and Synth Antispam settings screens only after Synth has caught at least 20 spam comments over 14 days or more. You can postpone it or switch it off, and nothing is offered in exchange for a review.

= 0.1.1 =
* Updated the plugin description and the directory listing text. No functional changes.

= 0.1.0 =
* Initial public release.
* AI spam detection for comments, pingbacks and trackbacks (comment form, XML-RPC).
* Verdict column with spam category and confidence.
* One-click site key and connection test.
* Strict mode and configurable fallback for outages or exhausted checks.
* Multisite support.

== Upgrade Notice ==

= 0.2.0 =
Adds spam checking for Contact Form 7, with a journal of held submissions and a one-click "Not spam — deliver". On an updated site, turn the checks on from the notice or in Settings → Synth Antispam.

= 0.1.3 =
Adds spam checking for WooCommerce product reviews, with the verdict column on the Products → Reviews screen.

= 0.1.2 =
Comments submitted through the REST API now receive their verdict, comment text is sent exactly as written, and a single review request you can postpone or switch off.

= 0.1.1 =
Text-only update (plugin description and listing); no functional changes.

= 0.1.0 =
Initial public release.
