Just to put some hard Bot Guard event-log numbers behind this as well, I had a look at my forum.
One caveat: unfortunately I only have a few hours of event-log data at the moment, as I recently cleared the logs while testing a new Bot Guard version. So I would not present these numbers as a long-term benchmark yet.
Another important caveat: these stats are only for sessions that reached the challenge state. On my system I am not currently logging the very basic bots that fail immediately at the interstitial stage. Other sites can enable that logging on their own installs if they want to measure that layer as well. But in practice, those failures are almost certainly not genuine humans, because the only real requirement to pass the interstitial is having JavaScript enabled.
I’ll follow up again once I have at least 12–24 hours of cleaner data. Tomorrow is Sunday, so with any luck I will manage the rare achievement of not developing and testing a new version and wiping my own logs again.
For this particular question,
session_hash is probably the cleanest unit because it represents the browser session that was actually challenged.
The query I used was:
SQL:
SELECT
COUNT(*) AS challenged_sessions,
SUM(has_pass = 1 OR has_fail = 1) AS captcha_result_sessions,
SUM(has_pass = 1) AS sessions_with_pass,
SUM(has_fail = 1) AS sessions_with_fail,
SUM(has_fail = 1 AND has_pass = 0) AS fail_only_sessions,
SUM(has_pass = 1 AND has_fail = 0) AS pass_only_sessions,
SUM(has_pass = 1 AND has_fail = 1) AS fail_then_or_also_pass_sessions,
SUM(has_pass = 0 AND has_fail = 0) AS no_captcha_result_sessions,
ROUND(SUM(has_pass = 1 OR has_fail = 1) / COUNT(*) * 100, 2) AS challenge_to_result_rate,
ROUND(SUM(has_pass = 1) / COUNT(*) * 100, 2) AS challenge_to_pass_rate,
ROUND(SUM(has_fail = 1) / NULLIF(SUM(has_pass = 1 OR has_fail = 1), 0) * 100, 2) AS fail_rate_among_result_sessions,
ROUND(SUM(has_pass = 0 AND has_fail = 0) / COUNT(*) * 100, 2) AS no_result_rate
FROM (
SELECT
`session_hash`,
MAX(`event_type` = 'challenge_required') AS has_challenge,
MAX(`event_type` = 'captcha_pass') AS has_pass,
MAX(`event_type` = 'captcha_fail') AS has_fail
FROM `xf_zee_botguard_event`
WHERE `event_type` IN ('challenge_required', 'captcha_pass', 'captcha_fail')
AND `session_hash` IS NOT NULL
AND `session_hash` <> ''
GROUP BY `session_hash`
) AS x
WHERE has_challenge = 1;
The latest result is:
Code:
challenged sessions: 416
captcha result sessions: 99
captcha passed sessions: 99
sessions with at least one fail: 12
fail-only sessions: 0
pass-only sessions: 87
fail then/or also pass sessions: 12
challenged with no result: 317
challenge to captcha result: 23.80%
challenge to pass: 23.80%
fail rate among result sessions: 12.12%
no result after challenge: 76.20%
So in this sample, around three quarters of challenged sessions never produced a CAPTCHA result at all. In fact, since I first checked, challenged sessions increased from 388 to 416, but CAPTCHA-result sessions only increased from 98 to 99. So the newer data is moving further in the same direction: most challenged sessions are not completing the proof step.
That is the most useful part for me. If Bot Guard was heavily challenging genuine users, I would expect a much higher proportion of challenged sessions to complete the CAPTCHA and continue. Instead, most challenged sessions appear to stop at the proof step.
I would not call the 23.80% pass rate the false-positive rate either. I would treat it as the maximum possible false-positive ceiling from that data. That would only be the false-positive rate if every CAPTCHA-passing session was a genuine human.
In reality, a CAPTCHA pass proves capability, not humanity. Any bot that is already capable of rendering JavaScript can potentially also be fitted with CAPTCHA-solving capability. So some percentage of those 99 passing sessions may still be bots or automated traffic that survived the challenge.
The 12 sessions that failed at least once are also interesting, but I would not overstate that either. All of them eventually had a pass event, so a fail is better treated as a risk signal rather than a definitive bot verdict. Humans can fail a CAPTCHA once. Repeated failures, pass/fail cycling, or strange behaviour after passing would be more concerning.
So my current read is:
- GA/Matomo are useful for spotting obvious collateral damage
- Bot Guard event logs are better for understanding the actual challenge funnel
- interstitial failures are a separate earlier layer, and are not included in the numbers above
- challenged with no result is probably the strongest positive signal
- CAPTCHA pass should reduce suspicion, but should not fully prove the session is human
- the raw pass rate is best treated as an upper-bound false-positive ceiling
- the true human false-positive rate is likely lower than the pass rate
This also lines up with what I have seen practically. My AdSense revenue has not dipped since running Bot Guard, while forum load has dropped significantly. If genuine users were routinely being blocked or pushed away, I would expect to see that show up in revenue, engagement, or complaints. So far, I have not seen that.
So while this is only a small data window because of my recent log clear, the early signal is broadly what I would want to see: most challenged sessions do not complete the proof step, normal analytics/revenue do not appear to be materially damaged, and server load is noticeably lower.
A built-in stats view would definitely make this much easier to see, and is on the near-term radar. Stay tuned.