Support for invisible hCaptcha
Is your feature request related to a problem? Please describe.
I recently learned about invisible captchas, and found out that hCaptcha supports them. Implementing it on the embedded form on my website was fairly straightforward and works beautifully! The initial implementation of hCaptcha was clunky, and didn't mesh well with the website design. This option is a lot more seamless.
Describe the solution you'd like
I would love to see an option for invisible captchas in the provided Listmonk embed code (this could be an additional checkbox in the Settings > Security captcha section, or a checkbox in the Form page).
To implement it, I had to do the following (updated instructions):
-
Add an
idattribute to the Listmonk form -
Add an
idattribute to the submit button -
Add
data-callback="onSubmit"anddata-size="invisible"attributes to the hcaptcha<div> -
Add an additional script before the hosted one
The final form code looks like this:
<form method="post" action="https://mylistmonkinstance.com/subscription/form" target="_blank" class="listmonk-form" id="listmonk-form">
<div>
<h3>Subscribe</h3>
<input type="hidden" name="nonce" />
<p><input type="email" name="email" required placeholder="E-mail" /></p>
<p><input type="text" name="name" placeholder="Name (optional)" /></p>
<p>
<input id="321" type="checkbox" name="l" checked value="54321" />
<label for="321">My List</label>
</p>
<div class="h-captcha" data-sitekey="1234567" data-callback="onSubmit" data-size="invisible"></div>
<input type="submit" value="Submit" id="listmonk-form-submit">
<script type="text/javascript">
const form = document.getElementById('listmonk-form');
function validate(event) { // add back client-side validation
event.preventDefault();
if (form.checkValidity()) {
hcaptcha.execute(); // if the form is valid, run captcha
} else {
form.reportValidity(); // if the form is invalid, display the error messages
}
}
function onLoad() {
var element = document.getElementById('listmonk-form-submit');
element.onclick = validate; // run the validate function when the submit button is clicked
}
function onSubmit(token) {
form.submit(); // submit the form if the hcaptcha is succesful
}
</script>
<script src="https://js.hcaptcha.com/1/api.js?onload=onLoad" async defer></script>
</div>
</form>
old instructions for binding the challenge to a button (but interferes with client-side validation)
-
Add an id to the Listmonk form
-
Remove the hcaptcha divs:
<div class="h-captcha" data-sitekey="1234567"></div> <script src="https://js.hcaptcha.com/1/api.js" async defer></script> -
Add an
h-captchaclass, anddata-sitekey="your_site_key"+data-callback="onSubmit"attributes to the submit button input, like this:<input type="submit" value="Submit" class="h-captcha" data-sitekey="1234567" data-callback="onSubmit"/> -
Add a data callback and the hCaptcha script:
<script type="text/javascript"> function onSubmit(token) { document.getElementById('listmonk-form').submit(); } </script> <script src="https://js.hcaptcha.com/1/api.js" async defer></script>
The final form code looks like this:
<form method="post" action="https://mylistmonkinstance.com/subscription/form" target="_blank" class="listmonk-form" id="listmonk-form">
<div>
<h3>Subscribe</h3>
<input type="hidden" name="nonce" />
<p><input type="email" name="email" required placeholder="E-mail" /></p>
<p><input type="text" name="name" placeholder="Name (optional)" /></p>
<p>
<input id="321" type="checkbox" name="l" checked value="54321" />
<label for="321">My List</label>
</p>
<input type="submit" value="Submit" class="h-captcha" data-sitekey="1234567" data-callback="onSubmit"/>
<script type="text/javascript">
function onSubmit(token) {
document.getElementById('listmonk-form').submit();
}
</script>
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
</div>
</form>
Thank you @candidexmedia this is cool! I've implemented it but I see form validation doesn't seem to work anymore following this way. As the captcha gets validated, it directly submit the form and bypasses any browser validation.
So if there's an error on the email or name field, user only understands after submitting and not while still being on the form.
I wonder if you found a way to keep hCaptacha invisible while not losing browser form validation?
@ImaCrea Thank you for flagging this! I've read through the hcaptcha docs, did some digging, and rewrote the whole thing so that the client-side validation goes through first:
The final form code looks something like this:
<form method="post" action="https://mylistmonkinstance.com/subscription/form" target="_blank" class="listmonk-form" id="listmonk-form">
<div>
<h3>Subscribe</h3>
<input type="hidden" name="nonce" />
<p><input type="email" name="email" required placeholder="E-mail" /></p>
<p><input type="text" name="name" placeholder="Name (optional)" /></p>
<p>
<input id="321" type="checkbox" name="l" checked value="54321" />
<label for="321">My List</label>
</p>
<div class="h-captcha" data-sitekey="1234567" data-callback="onSubmit" data-size="invisible"></div>
<input type="submit" value="Submit" id="listmonk-form-submit">
<script type="text/javascript">
const form = document.getElementById('listmonk-form');
function validate(event) { // add back client-side validation
event.preventDefault();
if (form.checkValidity()) {
hcaptcha.execute(); // if the form is valid, run captcha
} else {
form.reportValidity(); // if the form is invalid, display the error messages
}
}
function onLoad() {
var element = document.getElementById('listmonk-form-submit');
element.onclick = validate; // run the validate function when the submit button is clicked
}
function onSubmit(token) {
form.submit(); // submit the form if the hcaptcha is succesful
}
</script>
<script src="https://js.hcaptcha.com/1/api.js?onload=onLoad" async defer></script>
</div>
</form>
Main changes from the previous version:
- added back the hcaptcha div
- added
data-callback="onSubmit"anddata-size="invisible"attributes to the hcaptcha<div> - removed hcaptcha HTML attributes that would bind the challenge to the submit button
- modified the first script so that it runs the client-side validation first
- gave the submit button an ID
- added
?onload=onLoadto the hcaptcha script src URL because I saw it in the docs example. Is it actually needed? No clue, lol...
You can see it in action on my homepage: www.candide.media
Working nicely @candidexmedia ! Thanks for sharing, it's very cool
This issue has been marked 'stale' after 90 days of inactivity. If there is no further activity, it will be closed in 7 days.