Our Contact Form Was Silently Rejecting Customers

This one’s a bit embarrassing. But if it happened to us, a company that does Cloudflare security for a living, it can happen to anyone. So here’s the whole story.

The symptom: nothing

That’s the scary part. There was no error email, no angry customer, no red warning in WordPress. The contact form on our own website just… stopped delivering messages. For months.

Visitors filled it in, clicked Send, and got a vague failure message (if they noticed at all). We heard nothing.

What was going on

Back in 2025, someone put a Cloudflare Access application in front of the WordPress admin area, /wp-admin. Sounds sensible: lock the admin area behind a proper login. I’d recommend something similar myself.

The catch is a file called /wp-admin/admin-ajax.php. Despite the name, it isn’t just for admins. It’s how lots of WordPress features talk to the server from the public side of the site, and Elementor forms send their submissions through it.

So every time a visitor pressed Send, their browser posted the form to admin-ajax.php, Cloudflare Access said “who are you? Log in first”, and the submission died with a 401 Unauthorized.

How we found it

While rebuilding the site I was going through Cloudflare’s Security → Analytics → Events and Zero Trust logs, and saw a steady trickle of blocked POST requests to admin-ajax.php: about 120 in 30 days.

To show you exactly what that looks like, I recreated the mistake on our lab site: a rule that protects the whole /wp-admin folder, with no exception for admin-ajax.php. The lab uses a WAF custom rule rather than an Access application, so the block shows up in Security Events under the rule’s name; the real one was Access, which answers with a 401 and logs in Zero Trust instead. Either way, fill in the contact form, press Send, and this is all the visitor gets:

A contact form filled in with a name, email and message, and a red message under the Send button: Sorry, something went wrong. Your message was not sent.
All the visitor sees. No error code, no explanation, no message delivered.

And this is what Cloudflare records: a blocked POST to /wp-admin/admin-ajax.php, by the rule protecting the admin folder.

A Security Events entry: method POST, path /wp-admin/admin-ajax.php, blocked by the rule protecting the whole /wp-admin folder. IP address and network blurred.
The form submission, blocked as if it were an admin request. (IP address blurred.)

Going through our real ones, almost all were spam bots. So in a twisted way the broken setup was a very effective spam filter. But “almost all” isn’t “all”. Some of those could easily have been real people trying to reach us, and we’ll never know who.

The fix

  1. Removed the Access application from /wp-admin.
  2. Widened our existing WAF rule so that /wp-login.php and /wp-admin are blocked for everyone except trusted IPs, with admin-ajax.php explicitly excluded. (Full rule in Why your WordPress login page shouldn’t be public.)
  3. Added proper spam protection to the form itself: Elementor’s built-in honeypot field, plus Cloudflare Turnstile. Now spam is stopped by tools designed to stop spam, not by accident.
  4. Turned on “Collect Submissions” in Elementor, so every form entry is also saved in WordPress. If email delivery ever breaks, the messages are still sitting in the dashboard.

On the lab site, the same rule with admin-ajax.php left out lets the form straight through:

The same contact form, now with a passed Cloudflare Turnstile check and a green message under the Send button: Thanks, your message has been sent.
Same form after the fix: admin-ajax.php excluded from the rule, and Turnstile added. Through it goes.

What you should check on your own site

  • Test your contact form from outside your network. Phone off Wi-Fi, mobile data, fill it in, send it. Did it arrive? Do this every few months, and after any security change.
  • Look for blocked requests to admin-ajax.php in your Cloudflare security events. If you see real-looking traffic being blocked there, you have this problem.
  • Save submissions in WordPress as well as emailing them. Email is the most fragile part of any website.
  • Be careful with “protect the whole admin folder” rules, whether in Cloudflare, a security plugin or .htaccess. Always carve out admin-ajax.php.

The lesson

Security changes that fail loudly get fixed in five minutes. Security changes that fail silently can cost you customers for months. Whenever you lock something down, test the things that should still work, not just the things that should now be blocked.

Not sure if your form is quietly failing? Send us a message. Yes, it works now. We check.

Naming Conventions for Cloudflare WAF Rules (and Why Ours Needed Fixing) (Cloudflare WAF)

Naming Conventions for Cloudflare WAF Rules (and Why Ours Needed Fixing)

Is Your Host Running an End-of-Life PHP Version? (WordPress)

Is Your Host Running an End-of-Life PHP Version?

Backups That Actually Work: The 3-2-1 Rule for Small Business Websites (Backups)

Backups That Actually Work: The 3-2-1 Rule for Small Business Websites

Cloudflare Turnstile vs reCAPTCHA for Small Business Forms (Spam protection)

Cloudflare Turnstile vs reCAPTCHA for Small Business Forms

Why Your WordPress Login Page Shouldn’t Be Public (Cloudflare WAF)

Why Your WordPress Login Page Shouldn’t Be Public

PHP2Shell: What It Is, and How to Protect Your WordPress Site (Security alert)

PHP2Shell: What It Is, and How to Protect Your WordPress Site