reCAPTCHA v2 Integration

Implement visible reCAPTCHA v2 "I'm not a robot" checkbox protection for maximum spam prevention.

Overview

reCAPTCHA v2 displays a checkbox that users must click to verify they are human. It may show additional challenges like selecting images if the initial assessment is uncertain.

✨ Key Features

  • Visible "I'm not a robot" checkbox
  • Optional image challenges for suspicious traffic
  • Binary pass/fail result (no scoring)
  • Higher security than v3 but more friction
  • Better for high-value forms requiring certainty

Setup Process

1

Get reCAPTCHA v2 API Keys

Visit the Google reCAPTCHA Admin Console and:

  • Create a new site
  • Select "reCAPTCHA v2" → "I'm not a robot" Checkbox
  • Add your domains (including localhost for testing)
  • Copy your Site Key and Secret Key
2

Add reCAPTCHA to Your HTML Form

Add the reCAPTCHA v2 script and checkbox to your form:

<!DOCTYPE html>
<html>
<head>
  <!-- Add reCAPTCHA v2 script -->
  <script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
  <form action="https://connect.kitoform.com/f/YOUR_ENDPOINT" method="POST">
    <div>
      <label for="name">Full Name</label>
      <input type="text" name="name" id="name" required />
    </div>
    
    <div>
      <label for="email">Email Address</label>
      <input type="email" name="email" id="email" required />
    </div>
    
    <div>
      <label for="message">Message</label>
      <textarea name="message" id="message" rows="5" required></textarea>
    </div>
    
    <!-- reCAPTCHA v2 checkbox -->
    <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY"></div>
    
    <button type="submit">Send Message</button>
  </form>
</body>
</html>
3

React Implementation

For React applications, you can use react-google-recaptcha:

npm install react-google-recaptcha
import { useState, useRef } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

const ContactForm = () => {
  const [recaptchaValue, setRecaptchaValue] = useState(null);
  const recaptchaRef = useRef();

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!recaptchaValue) {
      alert('Please complete the reCAPTCHA');
      return;
    }
    
    const formData = new FormData(e.target);
    formData.append('g-recaptcha-response', recaptchaValue);
    
    try {
      const response = await fetch('https://connect.kitoform.com/f/YOUR_ENDPOINT', {
        method: 'POST',
        body: formData
      });
      
      if (response.ok) {
        alert('Form submitted successfully!');
        // Reset form and reCAPTCHA
        e.target.reset();
        recaptchaRef.current.reset();
        setRecaptchaValue(null);
      } else {
        alert('Submission failed. Please try again.');
      }
    } catch (error) {
      console.error('Submission error:', error);
      alert('An error occurred. Please try again.');
    }
  };

  const handleRecaptchaChange = (value) => {
    setRecaptchaValue(value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="name">Full Name</label>
        <input type="text" name="name" id="name" required />
      </div>
      
      <div>
        <label htmlFor="email">Email Address</label>
        <input type="email" name="email" id="email" required />
      </div>
      
      <div>
        <label htmlFor="message">Message</label>
        <textarea name="message" id="message" rows="5" required />
      </div>
      
      {/* reCAPTCHA v2 component */}
      <ReCAPTCHA
        ref={recaptchaRef}
        sitekey="YOUR_SITE_KEY"
        onChange={handleRecaptchaChange}
      />
      
      <button type="submit" disabled={!recaptchaValue}>
        Send Message
      </button>
    </form>
  );
};

export default ContactForm;
4

Configure Kitoform Settings

Configure reCAPTCHA v2 in your Kitoform dashboard or via API:

{
  "settings": {
    "captchaProvider": "recaptcha",
    "recaptchaEnabled": true,
    "recaptchaVersion": "v2",
    "recaptchaSiteKey": "6Lc-your-site-key",
    "recaptchaSecretKey": "6Lc-your-secret-key",
    "recaptchaExpectedHostname": "yoursite.com",
    "securityLevel": "strict"
  }
}

Customization Options

Theme and Size

Customize the appearance of the reCAPTCHA checkbox:

<!-- Light theme (default) -->
<div class="g-recaptcha" 
     data-sitekey="YOUR_SITE_KEY" 
     data-theme="light"
     data-size="normal">
</div>

<!-- Dark theme -->
<div class="g-recaptcha" 
     data-sitekey="YOUR_SITE_KEY" 
     data-theme="dark"
     data-size="normal">
</div>

<!-- Compact size -->
<div class="g-recaptcha" 
     data-sitekey="YOUR_SITE_KEY" 
     data-size="compact">
</div>

Callback Functions

Handle reCAPTCHA events with callback functions:

<div class="g-recaptcha" 
     data-sitekey="YOUR_SITE_KEY"
     data-callback="onRecaptchaSuccess"
     data-expired-callback="onRecaptchaExpired"
     data-error-callback="onRecaptchaError">
</div>

<script>
function onRecaptchaSuccess(token) {
  console.log('reCAPTCHA completed:', token);
  // Enable form submission
  document.getElementById('submit-btn').disabled = false;
}

function onRecaptchaExpired() {
  console.log('reCAPTCHA expired');
  // Disable form submission
  document.getElementById('submit-btn').disabled = true;
}

function onRecaptchaError() {
  console.log('reCAPTCHA error');
  // Handle error state
}
</script>

Programmatic Control

Control reCAPTCHA programmatically with the JavaScript API:

<script>
// Render reCAPTCHA explicitly
var recaptchaId = grecaptcha.render('recaptcha-container', {
  'sitekey': 'YOUR_SITE_KEY',
  'theme': 'light',
  'callback': function(token) {
    console.log('Token:', token);
  }
});

// Get response token
var token = grecaptcha.getResponse(recaptchaId);

// Reset reCAPTCHA
grecaptcha.reset(recaptchaId);
</script>

<!-- Container for programmatic rendering -->
<div id="recaptcha-container"></div>

Configuration Options

Data AttributeValuesDefaultDescription
data-sitekeystring-Your reCAPTCHA site key (required)
data-themelight, darklightVisual theme
data-sizenormal, compactnormalSize of the widget
data-callbackfunction name-Called when user completes CAPTCHA
data-expired-callbackfunction name-Called when CAPTCHA expires
data-error-callbackfunction name-Called when CAPTCHA encounters error

Security Benefits

✅ Advantages

  • Very high spam blocking effectiveness
  • Clear pass/fail result (no ambiguity)
  • Works well for critical forms
  • Additional challenges for suspicious users

⚠️ Considerations

  • Adds friction to user experience
  • May reduce conversion rates
  • Accessibility concerns for some users
  • Requires user interaction

Best Practices

✅ Do's

  • Place the reCAPTCHA near the submit button
  • Validate that reCAPTCHA is completed before allowing submission
  • Provide clear error messages if validation fails
  • Reset reCAPTCHA after form submission
  • Use appropriate theme (light/dark) for your design

❌ Don'ts

  • Don't hide the reCAPTCHA checkbox
  • Don't allow form submission without reCAPTCHA completion
  • Don't add multiple reCAPTCHA widgets to the same form
  • Don't forget to handle expired tokens

Testing

Test Keys

Use these test keys for development (they will always pass):

Test Site Key:

6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI

Test Secret Key:

6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

Note: Test keys always return a successful response. Use only for development and testing.

Related Documentation