WPForms showing submission and reCAPTCHA errors

WPForms Lite + reCAPTCHA v3: leerer Token durch WP-Optimize JavaScript-Optimierung

Das Kontaktformular hatte zuvor normal funktioniert. Nach Änderungen an der JavaScript-Optimierung schlug das Absenden jedoch mit einem Google-reCAPTCHA-Fehler fehl. Die Fehlermeldung allein sagte noch nicht, ob der Schlüssel, der Score-Schwellenwert, der Consent-Status oder der Formularcode die Ursache war. Erst die Network-Analyse in den DevTools zeigte den entscheidenden Hinweis: Der Request an wp-admin/admin-ajax.php kam mit HTTP 200 zurück, im JSON stand aber success:false – und das Feld wpforms[recaptcha] war im Multipart-Request leer.

WPForms mit allgemeinem Sende- und reCAPTCHA-Fehler während des Tests
Das sichtbare Symptom: WPForms sendet nicht erfolgreich und meldet einen reCAPTCHA-Fehler.

Testumgebung

Dieser Artikel beschreibt einen konkreten Produktionsfall. Er soll nicht behaupten, WP-Optimize würde WPForms grundsätzlich beschädigen. Zum Zeitpunkt der Analyse liefen WordPress 7.1, PHP 8.5.7, WPForms Lite 2.0.1.1, WP-Optimize 4.6.1, Complianz 7.5.4 und Polylang 3.8.7. WPForms verwendete Google reCAPTCHA v3 mit einem Score Threshold von 0,4; der No-Conflict Mode war deaktiviert.

WPForms-Einstellungen mit ausgewähltem Google reCAPTCHA v3
Für das Formular war Google reCAPTCHA v3 aktiv.
WPForms mit reCAPTCHA-Schwellenwert 0,4 und deaktiviertem No-Conflict Mode
Threshold 0,4 und No-Conflict Mode OFF waren Teil der Umgebung, aber nicht die bestätigte Ursache.

HTTP 200 ist noch kein erfolgreicher Submit

Der wichtigste Diagnoseschritt war, nicht beim HTTP-Status stehenzubleiben. In den DevTools öffnete ich den Request an admin-ajax.php und las den Response-Body. Der Webserver antwortete mit HTTP 200, WPForms meldete im JSON aber success:false zusammen mit einem reCAPTCHA-Fehler. Der HTTP-Transport war also erfolgreich, der Formularvorgang selbst nicht.

Danach prüfte ich den Multipart-Body. Das Feld wpforms[recaptcha] war vorhanden, hatte beim Fehler aber keinen Wert. Das war der entscheidende Hinweis. reCAPTCHA v3 erzeugt per JavaScript einen Token für die geschützte Aktion und dieser muss an das Backend gesendet werden. Ein leeres Feld liefert dem Backend keinen verwendbaren Token zur Verifikation.

Content-Disposition: form-data; name="wpforms[recaptcha]"

# während FAIL:
# leerer Wert

Warum Complianz nicht vorschnell zum Root Cause wurde

Auf der Website wird reCAPTCHA über den Consent-Mechanismus gesteuert. Nach Zustimmung waren die Google-Skripte und das reCAPTCHA-iframe im Network sichtbar. Zusätzlich testete ich Accept → reload → submit; der Fehler blieb bestehen. Damit war Consent in diesem konkreten Fall keine ausreichende Erklärung für den leeren Token.

A/B-Test: Minify und Merge gemeinsam ausschalten

Als nächsten kontrollierten Test deaktivierte ich in WP-Optimize gleichzeitig:

  • Enable minification of JavaScript files,
  • Enable merging of JavaScript files.

Nach dem Speichern löschte ich Minify- und Page-Cache. Danach gelangen zwei Formular-Submits hintereinander. Damit war die JavaScript-Processing-Schicht in dieser Installation als Konfliktbereich bestätigt.

Die Grenze der Aussage ist wichtig: Ich habe in diesem Durchlauf nicht separat „nur Minify OFF“ und „nur Merge OFF“ getestet. Deshalb behaupte ich nicht, dass ausschließlich Minification oder ausschließlich Merging die einzelne Ursache war.

Finaler Fix: Optimierung behalten, nur WPForms ausschließen

Das Ziel war nicht, JavaScript-Optimierung dauerhaft abzuschalten. Stattdessen wurden Minify und Merge wieder aktiviert und der reale WPForms-Lite-Frontend-Asset unter folgendem Menü ausgeschlossen:

WP-Optimize → Minify → JavaScript → Exclude JavaScript from processing

/wp-content/plugins/wpforms-lite/assets/js/frontend/wpforms.min.js

Auf der Seite gab es bereits eine separate Ausnahme für Post Views Counter. Die finale Liste lautete:

/wp-content/plugins/post-views-counter/js/frontend.js
/wp-content/plugins/wpforms-lite/assets/js/frontend/wpforms.min.js

WP-Optimize unterstützt offiziell das Ausschließen einzelner JavaScript-Dateien aus Minification und Merging. Das ist für mich die sauberere Lösung: Die Optimierung bleibt für den Rest der Website aktiv, nur der betroffene Script-Asset wird normal ausgeliefert.

False Lead: /wpforms/ war hier der falsche Pfad

Zwischenzeitlich hatte ich folgende Zeile eingetragen:

/wp-content/plugins/wpforms/assets/js/frontend/wpforms.min.js

Sie sieht plausibel aus und ähnliche Pfade finden sich in Dokumentation für andere WPForms-Varianten. In dieser Installation mit WPForms Lite war sie aber falsch. Der tatsächlich geladene Asset lag unter wpforms-lite.

WP-Optimize mit falschem wpforms-Pfad statt wpforms-lite in der JavaScript-Ausnahmeliste
False Lead, nicht die finale Konfiguration: Der Pfad /wpforms/... traf den real geladenen Lite-Asset nicht.

Darum sollte man die Exclusion-Zeile nicht blind kopieren, sondern den tatsächlich geladenen Script-URL im Network oder Seitenquelltext prüfen.

Purge und frische Browser-Session gehören zum Test

Nach der Exclusion wurden Minify- und Page-Cache geleert und die Verifikation in einer frischen privaten Browser-Session durchgeführt. Während der Umstellung gab es noch einen einzelnen EN-Fehler mit leerem Token, bevor die finalen Tests stabil liefen. Eine gespeicherte Exclusion-Zeile allein ist deshalb kein ausreichender QA-Nachweis.

Am Ende funktionierten normale Submits in PL, EN und DE.

Erfolgreiche WPForms-Bestätigung nach der Änderung
Nach der Änderung und erneutem QA lief der Formular-Submit erfolgreich.

So prüfe ich den Fix

  1. Minify-Cache und Page-Cache löschen.
  2. Ein neues privates Browserfenster öffnen.
  3. Consent entsprechend dem eingesetzten CMP setzen.
  4. Das Formular real absenden.
  5. Im Network den Request an admin-ajax.php öffnen.
  6. Den JSON-Body prüfen, nicht nur HTTP 200.
  7. Bei einem Fehler den Multipart-Body prüfen: wpforms[recaptcha] muss vorhanden und nicht leer sein.
  8. Confirmation und tatsächliche Mail-Zustellung prüfen.

Was in diesem Fall nicht als Ursache bestätigt wurde

  • Score Threshold 0,4;
  • No-Conflict Mode;
  • Consent allein – Accept → reload → submit blieb zunächst fehlerhaft;
  • der Text der globalen WPForms-Fehlermeldung;
  • der falsche Pfad /wpforms/..., der schlicht nicht den richtigen Lite-Asset traf.

Lokalisierungsfalle beim reCAPTCHA Fail Message

Ein manuell eingetragener polnischer Text im globalen Feld Fail Message erschien auch auf der englischen Version. Nach dem Zurücksetzen auf den WPForms-Standard lokalisierte sich die Meldung wieder nativ: EN auf Englisch, PL auf Polnisch und der DE-Backend-Response auf Deutsch.

Standardzustand des WPForms reCAPTCHA Fail Message Felds
Das globale Fail-Message-Feld eignet sich hier nicht als manuelle Übersetzung pro Sprache.
Vergleich der nativen WPForms reCAPTCHA-Fehlermeldungen in Englisch und Polnisch
Mit dem WPForms-Standard wurden EN und PL wieder nativ lokalisiert.

Separater deutscher Frontend-Bug

Bei einem absichtlich ausgelösten reCAPTCHA-Fehler zeigte sich noch ein unabhängiges Problem: Der Backend-JSON-Response enthielt sowohl den allgemeinen deutschen Fehler als auch die detaillierte reCAPTCHA-Meldung, im Frontend erschien aber nur der allgemeine Header. Das ließ sich in einem neuen privaten Fenster reproduzieren. Normale deutsche Submits nach Consent funktionierten, daher ist das kein Root Cause des leeren Tokens. Der Fall wurde separat auf WordPress.org gemeldet.

Deutsches WPForms-Frontend mit allgemeinem Fehler und JSON-Antwort mit zusätzlicher reCAPTCHA-Meldung
Separater DE-Finding: Das Backend liefert die detaillierte Meldung, das Frontend rendert sie in diesem Test nicht.

Rollback

Falls die Exclusion unerwartete Nebenwirkungen erzeugt, ist der Rollback klein: die WPForms-Zeile aus der Exclusion-Liste entfernen, speichern und Cache leeren. Für einen Diagnosetest kann man Minify und Merge temporär deaktivieren. Es ist nicht nötig, WP-Optimize oder den Page Cache dauerhaft komplett abzuschalten, wenn nur ein einzelner Asset betroffen ist.

Fazit

Der nützlichste Teil dieser Diagnose war nicht „Optimierung ausschalten“, sondern zuerst zu prüfen, was tatsächlich im Request landet. HTTP 200 versteckte hier einen Anwendungsfehler. Das leere wpforms[recaptcha] führte schneller zur richtigen Schicht als weitere Änderungen an Threshold, Übersetzungen oder CAPTCHA-Optionen. Erst danach bestätigte der A/B-Test den Zusammenhang mit dem JavaScript-Processing, und eine enge Asset-Exclusion ließ Minify und Merge für den Rest der Website aktiv.

Hat dir diese Anleitung geholfen?

Wenn sie dir etwas Zeit oder Nerven gespart hat, kannst du mir einen Kaffee ausgeben.