Sitecore 9 Forms – Google reCAPTCHA form element

Hello Sitecorians,

Hope you’re playing around with Sitecore 9 and with the newly introduced cool features in it. Recently, I’ve been exploring Sitecore Forms and implemented the Google Re-captcha form element within the Sitecore forms. Re-captcha is the basic requirement for the form submission process and in order to implement this, we’ve to write some code to it.

Before you go through with this post in detail, you must know the basics of Sitecore Forms.

We will go through step by step process to implement the Google Recaptcha with Sitecore Forms using the custom form element. And will create a generic component which you can use for any other form as well.

I started with creating the custom form element based on the guide: walkthrough_creating_a_custom_form_element

As per the requirement, I created two properties:

  • Public Key
  • Private Key

And Core DB Items look like:

GoogleRecaptcha class:

namespace SitecoreForms.Helpers
{
    public class GoogleRecaptcha : MultipleLineTextViewModel
    {
        public string PublicKey { get; set; }

        public string PrivateKey { get; set; }

        protected override void InitItemProperties(Item item)
        {
            base.InitItemProperties(item);

            PublicKey = StringUtil.GetString(item.Fields["Public Key"]);
            PrivateKey = StringUtil.GetString(item.Fields["Private Key"]);
        }

        protected override void UpdateItemFields(Item item)
        {
            base.UpdateItemFields(item);

            item.Fields["Public Key"].SetValue(PublicKey, true);
            item.Fields["Private Key"].SetValue(PrivateKey, true);
        }
    }
}

I’ve inherited from MultipleLineTextViewModel instead of FieldViewModel. I’ll explain to you later that Why I inherit from MultipleLineTextViewModel and not FieldViewModel as given in the document.

Added the following code to the HTML:

@model SitecoreForms.Helpers.GoogleRecaptcha

<script src='https://www.google.com/recaptcha/api.js'></script>

<textarea id="@Html.IdFor(m => Model.Value)" class="googleRecaptchaClass hide" name="@Html.NameFor(m => Model.Value)" data-sc-tracking="@Model.IsTrackingEnabled" data-sc-field-name="@Model.Name"></textarea>
<div id='recaptcha' class="g-recaptcha" data-sitekey=@Model.PublicKey></div>
<span id="captcha" style="margin-left:100px;color:red" />

Note: I’ve added textarea as Hidden and have provided the class – googleRecaptchaClass.

And then as you go through all the steps properly as mentioned in the document — You should be able to see reCAPTCHA element which you can then drag and drop into the form design layout area.

Now as you drag and drop the element into the form designer — You’ll get an error:

That is because you have not provided the Public Key.

Provide the public and private(secret) key in the element properties. Save the form and then reload the page. You will see reCAPTCHA is loading properly.

Are we done?

No – not yet. The most important thing is validation and that too both client and server-side validation.

Where should we add the client-side and server-side validation code and create a generic component? Don’t worry, Sitecore Community is there by your side. 🙂

While creating a form – I followed this blog: Responsive Sitecore 9 Form with Bootstrap — I provided “custom-class” to the form in the form-settings. This class will be added to the <form> tag by which we can fetch it in the JavaScript.

[Responsive Form]

And then I was thinking of where should I add the appropriate code for the client and server side validation. It was a challenge because the JavaScript which is loading is minified. And a very nice and useful post came from Jason Wilkerson – Sitecore 9 Forms and AJAX with SXA — I followed that to see how we can show the thank-you message instead of redirecting a user on the new page [which is the default submit action]. Now, while thinking about the challenge I was facing — an idea popped into my head for the client side validation.

Added the following required javascript for client-side validation to SXALayout.cshtml

XA.component.rbaForms = (function ($) {
        var api = {};

        api.init = function () {
            $(window).bind('load', function () {
                var form = $('.custom-form');
                if (form) {
                    $(form).submit(function () {
                        var recaptchaResponse = grecaptcha.getResponse();
                        if (recaptchaResponse.length == 0) {
                            document.getElementById('captchaError').innerHTML = "You can't leave Captcha Code empty";
                            return false;
                        }
                        else {
                            document.getElementById('captchaError').innerHTML = "";
                            $('.googleRecaptchaClass').val(recaptchaResponse);
                            return true;
                        }
                    });
                }
            });
        };
        return api;

    }(jQuery, document));
    XA.register("rbaForms", XA.component.rbaForms);

captchaError — That is just for showing the client side error message. You must be thinking why I created the hidden text-area and also in above code, I’m passing the reCAPTCHA response in hidden text-area. Well, that is for server-side validation. Yes – Was facing an issue for sending the captcha response on the server-side.

For the server-side validation – I created a custom submit action following Walkthrough: Creating a custom submit action – And then tried to debug the code for server-side validation. But the challenge is I’m not able to get the captcha response in the field property on the server-side.

In the form builder ajax request data, I was able to see the captcha response properly but how should I send the response to the server and validate?

var recaptchaResponse = formSubmitContext.Fields;

I was able to see the value of Name, Email, and Message but not the captcha response.

WHY?

If you see formbuilder ajax request carefully – You’ll see that each element has .ItemID and .Value associated with element GUID — Which then will be mapped with the Field and Value for Single-line Text and Multiple-line Text (text-area) and were available in the Value of each field respectively. What about the captcha?

Now, if you remember we inherited MultipleLineTextViewModel in GoogleRecaptcha class and not FieldViewModel as per the document– that is because there is no value property in the FieldViewModel – while if you go through the MultipleLineTextViewModel class — you’ll see the value property. In order to bind the value property with the captcha response — I went to MultipleLineText.cshtml and based on that, added the hidden text-area which we did earlier, and before form submit, we validate re-captcha on client side and then update hidden text area with the captcha response – which will then appear in the GoogleRecaptcha Field value. 🙂

 protected override bool Execute(string data, FormSubmitContext formSubmitContext)
        {
            // Validate re-captcha and send true or false response
            // If Re-captcha is valid -- we'll send true else false.

            var recaptchaResponse = formSubmitContext.Fields;

            GoogleRecaptcha googleRecaptchaFieldValue = formSubmitContext.Fields.Where(x => x is GoogleRecaptcha).FirstOrDefault() as GoogleRecaptcha;

            if (googleRecaptchaFieldValue != null)
            {
                bool isCapthcaValid = ValidateCaptcha(googleRecaptchaFieldValue.Value, googleRecaptchaFieldValue.PrivateKey);

                try
                {
                    if (isCapthcaValid)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }
            return false;
        }

        public static bool ValidateCaptcha(string response, string secret)
        {
            var client = new WebClient();
            var reply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, response));

            var captchaResponse = JsonConvert.DeserializeObject<CaptchaResponse>(reply);

            return Convert.ToBoolean(captchaResponse.Success);

        }
 public class CaptchaResponse
    {
        [JsonProperty("success")]
        public bool Success { get; set; }

        [JsonProperty("error-codes")]
        public List<string> ErrorMessage { get; set; }
    }

You can now add the newly built Form element to any form and provide the appropriate Public and Private (Secret) Key. In the client-side validation in JavaScript we are identifying the form based on “custom-form” class, so for any new form where you add Google ReCaptcha element – you’ll have to provide the same class in order to get it working.

Make sure ValidateReCaptcha submit action is assigned to submit button and is the first to trigger before saving data and redirect.

This is just one approach I found to implement reCAPTCHA in Sitecore Forms. If you know any other better way, do reply in comments below.

Happy Sitecoring! 🙂

 

37 thoughts to “Sitecore 9 Forms – Google reCAPTCHA form element”

  1. Hi Nikki,

    Thanks for the article. I have implemented a similar solution in that I am validating the recaptcha server-side using a custom submit action. If my custom submit action fails, the recaptcha (the entire iframe) just disappears. Have you seen this issue with your implementation as well? Thanks,

    Jessica

  2. Hi Nikki,
    I am trying the same, Google Recaptcha ServerSide Validation. Found this blog very informative. Could you please share the source code for reference?

    Thanks

  3. I followed this implementation and found that if we put more than one forms with this reCAPTCHA field, the form submission will fail, any suggestion?

  4. Understand this an old thread and my question does not relate directly to this topic but think the people are likely to help me.
    There is any way in which validate ReCaptcha in another language? I am working on a form for a Chinese language site but there appears to be no way to validate it other languages, just English.
    Any comments would be most helpful.
    Thanks

  5. Hi Nikki
    Nice article. First result on Google for integrate ReCaptcha in Sitecore 9 Forms.. helped a lot.. can I get source code please?

    1. Thanks for referring an article. I don’t have the source code due to machine getting formatted. A lot of Sitecorian are asking for the source code. I’ll try to do the steps again and will update the post.

  6. Hi,
    Great article, Nickki, is it possible send me the source code for this tutorial? Since I’m also missing a few things.

  7. Thanks Nikkipunjabi great article. Would you mind emailing me the code as well? I don’t know for instance what assembly MultipleLineTextViewModel is in.

  8. Hi,
    Thanks for the article, Nickki, is it possible to attach all the source that you used for this to the article?, We got the recaptcha to show but are not able to validate and think we’re missing a few things.

  9. Also you could use StringInputViewModel instead of MultipleLineTextViewModel and likewise use a input type=hidden instead of textarea with a class to hide it, again accomplishes same thing but I think it is neater

  10. Hi Nikkipunjabi,
    Nice article it helped me to go through my implementation of invisible re-captcha, to make it even better your solution I’d only change instead of custom action to validate the re-captcha I created a custom validation type so you add the recaptcha and on the properties panel you chose to use re-captcha validation, accomplishes the same thing but I think it is a neater solution.

    Cheers

    1. Hi Fernando I am trying to do the same use a Custom Validation type for recaptcha field. Will you be able to share the source code of the custom validation type and view model class please.

Leave a Reply to jaya Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.