1

I have a custom wordpress registration form, that works well. However, I am really struggling to get a recaptcha in to prevent spam. I'd prefer a v3, but would be ok with a v2 if it's easier to implement.

I tried to be clever and add a honeypot hidden field, and even a math question field, but the spam sign-ups are still coming through.

I know the form works with this code (no recaptcha):

HTML

<form method="post" id="registration-form" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>">
  <input type="hidden" name="action" value="custom_registration_form">


  <label for="first_name"><?php _e('First Name', 'line'); ?> *</label>
  <input type="text" name="first_name" id="first_name" required>

  <label for="last_name"><?php _e('Last Name', 'line'); ?> *</label>
  <input type="text" name="last_name" id="last_name" required>

  <label for="title"><?php _e('Title', 'line'); ?> *</label>
  <input type="text" name="title" id="title" required>

  <label for="organization"><?php _e('Organization', 'line'); ?> *</label>
  <input type="text" name="organization" id="organization" required>

  <label for="email"><?php _e('Email', 'line'); ?> *</label>
  <input type="email" name="email" id="email" required>

  <label for="password"><?php _e('Password', 'line'); ?> *</label>
  <input type="password" name="password" id="password" required>

  <label for="anti-bot"><?php _e('What is 10 + 5?', 'line'); ?> *</label>
  <input type="text" name="anti-bot" id="anti-bot" required>
  
  <input type="hidden" name="your-email" id="your-email">

  <input type="submit" id="wp-submit" value="<?php _e('Register', 'line'); ?>" style="margin-top:10px;">
</form>


<script>
  jQuery(document).ready(function(){
    function getUrlParameter(name) {
      name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
      var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
      var results = regex.exec(location.href);
      return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, '    '));
    };

    var the_email = getUrlParameter('email');

    jQuery('#email').val(the_email);
  });
  jQuery('#wp-submit').on("click", function(event){
    if(jQuery('#your-email').val()){
      alert('Sorry, it appears our site thinks you may be a spam bot. If you\'re not, please contact us for help');
      event.preventDefault();
    }
    if(jQuery('#anti-bot').val() != "15") {
      alert('Sorry, the answer to the number question is wrong. Please try again');
      event.preventDefault();
    }

  });
  document.getElementById('registration-form').addEventListener('submit', function(event) {
    var form = event.target;
    var password = form.querySelector('#password');
    var your_email = form.querySelector('#your-email');    
    
    // Show error message if there are errors
    if (errorMessage) {
      alert(errorMessage);
      event.preventDefault();
    }

});
</script>

functions.php

add_action( 'admin_post_custom_registration_form', 'custom_registration_form' );
add_action( 'admin_post_nopriv_custom_registration_form', 'custom_registration_form' );

function custom_registration_form() {
  $errors = array();

  if ( isset( $_POST['first_name'] ) && isset( $_POST['last_name'] ) && isset( $_POST['title'] ) && isset( $_POST['organization'] ) && isset( $_POST['email'] ) && isset( $_POST['password'] ) ) {  

    $username = $_POST['email'];
    $password = $_POST['password'];
    $email = $_POST['email'];
    $first_name = $_POST['first_name'];
    $last_name = $_POST['last_name'];
    $title = $_POST['title'];
    $organization = $_POST['organization'];

    $user_id = wp_create_user( $username, $password, $email );
    
    if ( is_wp_error( $user_id ) ) {
      $errors[] = $user_id->get_error_message();
    }

    if ( count( $errors ) > 0 ) {
      foreach ( $errors as $error ) {
        echo '<p>' . $error . ' <a href="/login/">Try logging in</a></p>';
      }
    } else {
      // Set user meta data
      update_user_meta( $user_id, 'first_name', $first_name );
      update_user_meta( $user_id, 'last_name', $last_name );
      update_user_meta( $user_id, 'mepr_title', $title );
      update_user_meta( $user_id, 'mepr_organization', $organization );

      // Log the user in
      wp_set_current_user( $user_id );
      wp_set_auth_cookie( $user_id );

      // Redirect to the homepage
      wp_redirect( home_url() );
      exit;
    }
  }
}

However, when I try and add a recaptcha, the form doesn't submit correctly. By changing the code to the below, I can click the register button without filling in ANY fields, and it just goes to: 'mydomain.com/wp-admin/admin-post.php' and a white page.

<!-- add the recaptcha api -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

<form method="post" id="registration-form" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>">
  <input type="hidden" name="action" value="custom_registration_form">
  
  <label for="first_name"><?php _e('First Name', 'textdomain'); ?></label>
  <input type="text" name="first_name" id="first_name" required>

  <label for="last_name"><?php _e('Last Name', 'textdomain'); ?></label>
  <input type="text" name="last_name" id="last_name" required>

  <label for="title"><?php _e('Title', 'textdomain'); ?></label>
  <input type="text" name="title" id="title" required>

  <label for="organization"><?php _e('Organization', 'textdomain'); ?></label>
  <input type="text" name="organization" id="organization" required>

  <label for="email"><?php _e('Email', 'textdomain'); ?></label>
  <input type="email" name="email" id="email" required>

  <label for="password"><?php _e('Password', 'textdomain'); ?></label>
  <input type="password" name="password" id="password" required>
    
  <!-- add the recaptcha button -->
  <button class="g-recaptcha" 
        data-sitekey="I ADD MY SITEKEY HERE" 
        data-callback='onSubmit' 
        data-action='submit'>Submit</button>          

</form>

<script>
   <!-- add the submit code -->
  function onSubmit(token) {
    document.getElementById("registration-form").submit();
  }
</script>

What am I doing wrong? I'm open to other ideas not using recaptcha to stop spam.

user2115227
  • 147
  • 2
  • 9
  • 24
  • For the white page see: https://stackoverflow.com/q/1475297/367456 and following. It helps if you add the concrete errors as clarifications to your question by [edit]ing them in. Additionally, are you aware that you first create the user and then do any checks apart just of _isset()_? Everyone could just fire up a HTTP POST request sending some form data in (which is what certainly happens in your case). – hakre Jun 29 '23 at 10:50
  • Thanks. I'm hoping someone can help recode my code so so that it registers the user as it should, but without the spam! Open to suggestions as an answer – user2115227 Jun 30 '23 at 11:04

3 Answers3

2

In the recaptcha part, you should modify your onSubmit function to execute the recaptcha verification and only submit the form if the verification is successful.

like this:

function onSubmit(token) {
    document.getElementById("g-recaptcha-response").value = token;
    document.getElementById("registration-form").submit();
  }
harry
  • 147
  • 7
  • Thanks Harry. This didn't seem to do anything. I think the issue is not just with the recaptcha, but to do with the way the form is submitting with .submit(). It's ignoring all the 'required' fields and the 'action' on submit, and just going to mydomain.com/wp-admin/admin-post.php – user2115227 Apr 23 '23 at 09:10
0

I will take a guess here, but when you added the button, you removed the controls you were making on the fields and, most importantly, the e.preventDefault(). A button in a form, by default, causes the submit, so if you don't add a js part in wich you prevent the default submit behavior, it will send to the server the empty form. You should implement this first, then you can go with the rest of Recaptcha process.

Hope this helps

0

your functions.php code seems fine. how ever It seems there might be an issue with how the reCAPTCHA is integrated with the form in your html codes. The same happened to me once, maybe you need to update the button element with the reCAPTCHA class to use a div element instead. then Add a div element with the class g-recaptcha and the data-site key attribute set to your reCAPTCHA site key. after that, you need to Modify the onSubmit function to handle the form submission and reCAPTCHA verification.

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

<form method="post" id="registration-form" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
  <input type="hidden" name="action" value="custom_registration_form">

  <label for="first_name"><?php _e('First Name', 'textdomain'); ?></label>
  <input type="text" name="first_name" id="first_name" required>

  <label for="last_name"><?php _e('Last Name', 'textdomain'); ?></label>
  <input type="text" name="last_name" id="last_name" required>

  <label for="title"><?php _e('Title', 'textdomain'); ?></label>
  <input type="text" name="title" id="title" required>

  <label for="organization"><?php _e('Organization', 'textdomain'); ?></label>
  <input type="text" name="organization" id="organization" required>

  <label for="email"><?php _e('Email', 'textdomain'); ?></label>
  <input type="email" name="email" id="email" required>

  <label for="password"><?php _e('Password', 'textdomain'); ?></label>
  <input type="password" name="password" id="password" required>

  <!-- add the recaptcha button -->
  <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY" data-callback="onSubmit" data-action="submit"></div>

  <button type="submit">Submit</button>
</form>

<script>
  // add the submit code
  function onSubmit(token) {
    var form = document.getElementById("registration-form");

    // Verify reCAPTCHA response
    if (token) {
      // Prepare data for form submission
      var formData = new FormData(form);
      formData.append('g-recaptcha-response', token);

      // Perform form submission
      fetch(form.action, {
        method: form.method,
        body: formData
      }).then(function(response) {
        // Handle the form submission response
        if (response.ok) {
          // Registration successful
          alert('Registration successful!');
        } else {
          // Registration failed
          alert('Registration failed. Please try again later.');
        }
      }).catch(function(error) {
        console.error('Error:', error);
        alert('An error occurred. Please try again later.');
      });
    } else {
      alert('Please complete the reCAPTCHA verification.');
    }
  }
</script>
  • Don't forget to change your site key in the code .

-btw if you are using a page builder like elementor there are easier ways to do this.