Gatsby & Styled Components form with custom reCaptcha v2 invisible rejects all submissions despite status 200

Really struggling to get my portfolio site’s contact form to work properly. I’ve attempted to implement additional spam filters by using the “honeypot” and custom “reCaptcha” methods. My honeypot doesn’t even get recognized. But more problematic is the recaptcha v2 invisible. I’ve followed the Netlify recaptcha docs explicitly for the custom reCaptcha implementation. I have my own web-service api running that validates the recaptcha token generated by my client side. The entire google recaptcha flow is working fine - client tries to submit form → challenged by recaptcha → token generates → token is validated by my own custom backend that talks to google → a status true/false success is returned to my frontend by my backend web-service.

Where things seem to fall apart is in the form data submission to netlify. I’ve got a “g-recaptcha-response” form data field that contains the token, and I’m passing all my other form data as well. I’ve tried just passing the success status (true, false) to the g-recaptcha-response field - but this doesn’t work either. I get a 200 response from Netlify indicating a good form submission, but the form submission never hits my Netlify form submission dashboard in the verified section, nor in the spam section.

Ok - so here’s some code for you. To be very clear - I’m using the react-google-recaptcha package to generate my Recaptcha component. That code is as follows:

let recaptchaInstance = useRef();
const siteKey = process.env.GATSBY_RECAPTCHA_SITE_KEY;
<ReCAPTCHA
              ref={recaptchaInstance}
              size="invisible"
              sitekey={siteKey}
              theme="dark"
              badge="inline"
            />

This is a pretty simple implementation and I just programmatically execute the async instance of getting a token in the handleSubmit function that you’ll see below - again, all this code works fine. Tokens generate and are correctly validated via a backend webservice that connects to google as per the google recaptcha implementation docs.

Here’s the html form and supplied attributes:

<ContactFormWrapper>
          <ContactForm
            name="new-portfolio-contact"
            id="contact-form"
            netlify-honeypot="subject"
            data-netlify="true"
            data-netlify-recaptcha="true"
            method="POST"
          >
            <input type="hidden" name="new-portfolio-contact" value="contact" />
            <FormGroup>
              <NameInput
                type="text"
                id="name"
                name="name"
                value={name}
                onChange={e => onChange(e)}
                aria-required
                required
              />
              <FormLabelFloating htmlFor="name">your name</FormLabelFloating>
            </FormGroup>
            <FormGroup>
              <EmailInput
                type="email"
                id="email"
                name="email"
                value={email}
                onChange={e => onChange(e)}
                aria-required
                required
              />
              <FormLabelFloating htmlFor="email">your email</FormLabelFloating>
            </FormGroup>
            <AltFormGroup className="hidden">
              <SubjectInput
                name="subject"
                id="subject"
                tabIndex="-1"
                value={subject}
                onChange={e => onChange(e)}
              />
              <FormLabelFloating htmlFor="subject">subject</FormLabelFloating>
            </AltFormGroup>
            <FormGroup>
              <TextArea
                cols="30"
                rows="10"
                id="message"
                name="message"
                value={message}
                onChange={e => onChange(e)}
                aria-required
                required
              ></TextArea>
              <FormLabelFloating htmlFor="message">
                message body
              </FormLabelFloating>
            </FormGroup>
            <div>
              <ContactSubmitButton
                id="mySubmitBtn"
                onClick={e => checkInputs(e)}
                aria-label="contact form submit button to send your message to Jon"
                aria-disabled={blockedIPs.some(address => address === ip)}
              >
                <FaArrowRight />
              </ContactSubmitButton>
              <p>send your message!</p>
            </div>
            <ReCAPTCHA
              ref={recaptchaInstance}
              size="invisible"
              sitekey={siteKey}
              theme="dark"
              badge="inline"
            />
          </ContactForm>

I use an encode function to manage the form data from state:

const encode = data => {
    return Object.keys(data)
      .map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
      .join("&");
  };

And there’s a lot happening in the form submission function, but here’s the part where I’m sending data off to netlify:

const handleSubmit = async () => {
    const formBtn = document.getElementById("mySubmitBtn");
    try {
      const token = await recaptchaInstance.current.executeAsync();
      const body = { token };
      const response = await axios.post(
        `https://portfolio-recaptch-service.onrender.com/recaptcha`,
        body
      );
      await setFormFieldWithRecpatchaResponseFromServer(token);
      setShowSpinner(false);
      if (response.data.success) {
        setContent({
          ...content,
          title: `Thank you ${name}!`,
          body: `Really feeling the love! Thank you for reaching out! I'll be in touch soon.`,
        });
        fetch("/", {
          method: "POST",
          headers: {
            "Content-type": "application/x-www-form-urlencoded",
          },
          body: encode({ "form-name": "new-portfolio-contact", ...formData }),
        })
          .then(res => {
            setShow(true);
            setFormData({
              name: "",
              email: "",
              subject: "",
              message: "",
              "g-recaptcha-response": "",
            });
            return console.log(res);
          })
          .catch(error => {
            console.log(error);
            setContent({
              ...content,
              title: "Uh oh...",
              body: "Sorry! Please try submitting your details later.",
            });
            setShow(true);
          });
      }
    } catch (error) {
      console.error(error);
      setContent({
        ...content,
        title: "Server issues...",
        body: "Sorry! Please try submitting your details later.",
      });
      setShow(true);
    }
    formBtn.setAttribute("aria-disabled", "false");
  };

The form submissions work if I take the “data-netlify-recaptcha” attribute out of the form element. However, if I remove that, my Netlify dashboard tells me I’m not using any additional spam features. I’m wondering if even need to worry about this or use the netlify data recaptcha attribute? I’m using my own recaptcha validation and only proceed with form submission if I get a success from my api which gets the result from google. Am I overthinking this? It just seems odd that Netlify forms has such a problem here. It’s also unclear what the “g-recaptcha-response” field of the netlify data should contain? Are you looking for the token? Or for success boolean that comes from the google verification? I’ve added all the suggested environment variables to the netlify dashboard for this application, although that seems redundant to me as well, given I’m doing all the verification with keys and secrets via my own webservice. I’ve read through various other help topics here an none seem to address this same issue. To be clear - I’m getting Status 200 responses when sending my form data to netlify with the recaptcha component - but no form submission ever shows up anywhere in the form submission dashboards.

The live production deploy is : https://joncollins.dev
The netlify site name is : https://newdevsite.netlify.app

both of these have been whitelisted in the google recaptcha admin console.

Any help or insights would be appreciated. And yes, I know Askimet is pretty good at diverting spam. But I’d really like to get this recaptcha working properly. Thank you in advance!

Hey there,

Thanks for sharing such a detailed post-- this made looking into your obstacle easier for the support team :netlisparkles:

We can see that on the production deploy, the form submissions work (we submitted one last night and one this morning.) I assume it is working because you have disabled the data-netlify-recaptcha.

If you wish to prevent spammers using your form, we suggest sticking to netlify recaptcha. You can read about how to implement this in our documentation.

Additionally, instead of using react-google-recaptcha, try implementing it with just the data-netlify-recaptcha attribute without your custom implementation. We require a specific type of Recaptcha to work - which is the most common one (you click on it, it shows some pictures to select). The current implementation that you have, will still allow spammers to send form submissions by replicating the post request to your site.

Let us know if this gets you on the right track!