After having issues with Google reCAPTCHA v2 and a custom WordPress implementation, I started coding an optimized version using the invisible version of Google reCAPTCHA v3.
Based on the post ID variable, I have added several extra fields to the form (not shown here).
Optionally, there’s a handy [cf8]
shortcode.
I have named this form feature CF8.
Prerequisites
The prerequisites for this contact form are, obviously, a Google reCAPTCHA v3 (the invisible one). Create one here.
The WordPress Function:
/**
* CF8: Quick contact form with Google reCAPTCHA v3
*
* @return HTML string
*/
function wppd_cf8() {
global $post;
$postId = $post->ID;
$emailTo = 'email@example.com';
$out = '';
$out = '<form id="cf8-form" method="post">
<p>
<input type="hidden" name="contact_to" id="contact-to" value="' . $emailTo . '" readonly>
<input type="hidden" name="contact_id" id="contact-id" value="' . $postId . '">
<input type="text" name="contact_name" id="contact-name" placeholder="Full Name *">
<input type="email" name="contact_email" id="contact-email" placeholder="Email *">
<input type="text" name="contact_phone" id="contact-phone" placeholder="Phone">
<textarea name="contact_notes" id="contact-notes" rows="3" placeholder="Your Enquiry *"></textarea>
</p>
<p>
<input type="submit" name="cf8_send" id="cf8-send" value="Send" data-ip="1.2.3.4">
</p>
<div id="cf8-response"></div>
</form>';
return $out;
}
add_shortcode( 'cf8', 'wppd_cf8' );
The WordPress Action
function wppd_action_cf8() {
$to = filter_input(INPUT_POST, 'to', FILTER_VALIDATE_EMAIL);
$pid = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$phone = filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING);
$notes = filter_input(INPUT_POST, 'notes', FILTER_SANITIZE_STRING);
$captcha = filter_input(INPUT_POST, 'token', FILTER_SANITIZE_STRING);
if (!$captcha) {
echo '<h2>Please check the the captcha form.</h2>';
exit;
}
$secretKey = "BAXtnHN2u5rGtplZ4n5gBAXtnHN2u5rGtplZ4n5g";
$ip = $_SERVER['REMOTE_ADDR'];
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = [
'secret' => $secretKey,
'response' => $captcha
];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$responseKeys = json_decode($response,true);
header('Content-type: application/json');
if ($responseKeys["success"] && $responseKeys["score"] >= 0.5) {
$body = '<h3>A new quick contact has been sent from <a href="' . get_permalink($pid) . '">' . get_the_title($pid) . '</a>!</h3>
<p>Contact details:</p>
<p>
<b>Name:</b> ' . $name . '<br>
<b>Email:</b> ' . $email . '<br>
<b>Telephone:</b> ' . $phone . '<br><br>
<b>Sent From:</b> <a href="' . get_permalink($pid) . '">' . get_the_title($pid) . '</a><br>
<b>Post ID:</b> ' . $pid . '<br><br>
<b>Notes:</b> ' . $notes . '
</p>
<p>
<small>Email sent to ' . $to . ' on ' . date('Y-m-d, H:i') . '</small><br>
<small>Google reCAPTCHA score: ' . $responseKeys['score'] . '</small>
</p>';
$headers[] = "Content-Type: text/html;";
$subjectLine = 'CF8 Contact Request - ' . get_the_title($pid);
wp_mail($to, 'CF8 Contact Request', $body, $headers);
// Return response
echo json_encode([
'success' => 'true',
'score' => $responseKeys["score"]
]);
} else {
echo json_encode([
'success' => 'false',
'score' => $responseKeys["score"]
]);
}
wp_die();
}
add_action('wp_ajax_wppd_action_cf8', 'wppd_action_cf8');
add_action('wp_ajax_nopriv_wppd_action_cf8', 'wppd_action_cf8');
The CSS
#cf8-response {
font-size: 14px;
}
The JavaScript
document.addEventListener('DOMContentLoaded', () => {
/**
* CF8: Quick contact form with Google reCAPTCHA v3
*/
if (document.getElementById('cf8-form')) {
document.getElementById('cf8-form').addEventListener('submit', (event) => {
event.preventDefault();
document.getElementById('cf8-response').innerHTML = 'Sending...';
let to = jQuery("#contact-to").val(),
id = jQuery("#contact-id").val(),
reference = jQuery("#contact-reference").val(),
name = jQuery("#contact-name").val(),
email = jQuery("#contact-email").val(),
phone = jQuery("#contact-phone").val(),
notes = jQuery("#contact-notes").val();
if (name !== '' && email !== '' && phone !== '' && notes !== '') {
grecaptcha.ready(() => {
grecaptcha.execute("cy08Qu0dkGIsCDBaXKf1cy08Qu0dkGIsCDBaXKf1", {
action: "create_comment"
}).then((token) => {
document.getElementById('cf8-form').insertAdjacentHTML('afterBegin', '<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
let request = new XMLHttpRequest(),
requestString = '';
requestString += '&to=' + to;
requestString += '&id=' + id;
requestString += '&reference=' + reference;
requestString += '&name=' + name;
requestString += '&email=' + email;
requestString += '&phone=' + phone;
requestString += '¬es=' + notes;
requestString += '&token=' + token;
request.open('POST', ajaxVar.ajaxUrl, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.onload = () => {
response = JSON.parse(request.response);
if (response.success) {
document.getElementById("cf8-response").innerHTML = "Email sent successfully!";
} else {
document.getElementById("cf8-response").innerHTML = "An error has occured!";
}
};
request.send('action=wppd_action_cf8' + requestString);
});;
});
} else {
document.getElementById("cf8-response").innerHTML = "An error has occured!";
}
});
}
});
And that is all!
Make sure you create a custom plugin or integrate it into your existing plugin. Dumping the code in functions.php
is always a bad idea.