Google隐形reCAPTCHA:如何避免提交前触发图片验证挑战
Hey Laurent, I totally get why this is frustrating—having a captcha pop up before the user even decides to sign is a big UX killer. The good news is this is an easy fix! The root issue in your code is that you're automatically executing the reCAPTCHA challenge as soon as the page loads (via window.grecaptcha.execute(recaptchaId); in your onScriptLoad function). Let's adjust this so it only runs when the user clicks your submit button.
Step 1: Remove the Auto-Execute on Page Load
First, we'll get rid of that early execute() call and restructure the submission logic to tie directly to the user's click. Here's the updated JavaScript:
window.onScriptLoad = function () { var htmlEl = document.querySelector('.g-recaptcha'); var captchaOptions = { 'sitekey': 'xxxxxxxxxxxxxxxxxxxxxxxxxxx', 'size': 'invisible', 'badge': 'inline', callback: window.onUserVerified }; var inheritFromDataAttr = true; recaptchaId = window.grecaptcha.render(htmlEl, captchaOptions, inheritFromDataAttr); console.log('recaptchaId=', recaptchaId); // REMOVED: The early execute call that was triggering captcha on page load }; window.onUserVerified = function (token) { console.log('token=', token); // Once verification passes, send the form data via AJAX submitPetitionForm(token); }; function onSubmitBtnClick () { var token = window.grecaptcha.getResponse(recaptchaId); console.log('token=', token); if (!token) { // Only trigger the captcha challenge HERE, when the user clicks submit window.grecaptcha.execute(recaptchaId); return; } // If we already have a valid token, submit immediately submitPetitionForm(token); } // Helper function to handle AJAX submission (keeps code clean) function submitPetitionForm(token) { $.ajax({ url: 'process.php', type: 'post', dataType: 'json', data : { 'lastname' : $("#lastnameField").val(), 'firstname' : $("#firstnameField").val(), 'city' : $("#cityField").val(), 'postalCode' : $("#postalcodeField").val(), 'g-recaptcha-response' : token }, success:function(data) { // Replace with your user-facing success message alert("Thank you for signing our petition!"); }, error: function(xhr, textStatus, error){ console.log(xhr.statusText); console.log(textStatus); console.log(error); } }); }
Step 2: Clean Up Redundant HTML Attributes
Your HTML is mostly good, but we can remove the duplicate data-sitekey from the submit button (since we're already defining it in the JS render options) to avoid confusion:
<html> <head> <script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onScriptLoad" async defer></script> <script type="text/javascript" src="js/petition.js"></script> ... </head> <body> <form id="petitionForm" onsubmit="return false;"> <input id="lastnameField" type="text" name="lastname" placeholder="Lastname" required value="Doe"> <input id="firstnameField" type="text" name="firstname" placeholder="Firstname" required value="John"> <input id="postalcodeField" type="text" name="postalCode" placeholder="Postal Code" required value="ABCDEF"> <input id="cityField" type="text" name="city" placeholder="City" value="Oslo"> .... <!-- Removed redundant data-sitekey and data-callback attributes --> <input type="submit" name="login" class="g-2" id="signButton" value="Signer" onclick="onSubmitBtnClick();"> <div class="g-recaptcha" id="recaptchaElement" style="align-content: center"></div> </form> ... </body> </html>
Why This Works
- We eliminate the early
grecaptcha.execute()call, so no captcha challenges fire before the user interacts with your form. - When the user clicks "Signer", we first check for an existing valid token. If none exists, we trigger the reCAPTCHA challenge right then.
- Once the user completes the challenge (or gets automatically verified without one), the
onUserVerifiedcallback runs and submits the form via AJAX.
This ensures the captcha only appears after the user has decided to sign—keeping your UX smooth and focused on your petition's core message.
内容的提问来源于stack exchange,提问作者Laurent

