Form submissions not arriving in Netlify UI

rivelin-site: https://www.rivelinrobotics.com/
Site ID: 87f3f08f-234e-40c4-8398-057b65cf14fe

I’m having trouble with the submission of forms from my website. As background, around 5 months ago I underwent a massive overhaul of the website’s structure and plugins and in the process have broken a couple of things, one being forms.

For context:
I use an invisible react-google-recaptcha

When executing the captcha, I receive a captcha token in response. A request is then sent to ‘/’ and I receive a response with a status code of 200 and ok: true. I do not, however, have the form appear in the UI.

When executing without a captcha, the form works as expected and appears in the UI. I’m having trouble understanding why the inclusion of the captcha is having an effect on the result when both responses are the same.

I have tried:
Changing execution mode of the captcha from synchronous to asynchronous, logging responses from fetch commands, toggling netlify bool and captcha bool

I have read: Response code of 200 on Netlify Forms but the submission is not showing up on dashboard - #6 by hrishikesh
and I do have a redirect in my netlify.toml file, however I’m unsure what to change if this is the problem. If someone could help work out the issue it would be much appreciated.

netlify.toml

[[redirects]]
    from = "/*"
    to = "/"
    status = 200

[[headers]]
  for = "/*.js"
  [headers.values]
    Content-Type = "application/javascript"

[[plugins]]
package = "@algolia/netlify-plugin-crawler"
    [plugins.inputs]
    branches = ['master']
    disabled = false
    pathPrefix = "/"
    customDomain = "rivelinrobotics.com"
    renderJavaScript = true

index.html:

<!DOCTYPE html>
<html>

<head>
  <base href="/" />
  <title>Rivelin Robotics</title>
  <meta name="application-name" content="Rivelin Robotics" />
  <meta name="apple-mobile-web-app-title" content="Rivelin Robotics" />
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="icon" type=image/png href="/rr_favicon.png" sizes="32x32" />

  <link rel='stylesheet'
    href="https://fonts.googleapis.com/css?family=Atkinson+Hyperlegible:400,400italic,700,700italic" />
</head>

<body>
  <link rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/@algolia/algoliasearch-netlify-frontend@1/dist/algoliasearchNetlify.css" />
  <script type="text/javascript"
    src="https://cdn.jsdelivr.net/npm/@algolia/algoliasearch-netlify-frontend@1/dist/algoliasearchNetlify.js"></script>
  <div id="app"></div>
  <form name="contact" netlify data-netlify-recaptcha="true" data-netlify="true" netlify-honeypot="bot-field" hidden>
    <input type="text" name="firstName">
    <input type="text" name="lastName">
    <input type="email" name="email">
    <input type="text" name="companyName">
    <textarea name="message">
  </textarea>
  </form>
  <form name="demoRequest" netlify data-netlify-recaptcha="true" data-netlify="true" netlify-honeypot="bot-field" hidden>
    <input type="text" name="firstName">
    <input type="text" name="lastName">
    <input type="email" name="email">
    <input type="text" name="companyName">
  </form>
  <form name="datasheetRequest" netlify data-netlify-recaptcha="true" data-netlify="true" netlify-honeypot="bot-field" hidden>
    <input type="text" name="firstName">
    <input type="text" name="lastName">
    <input type="email" name="email">
    <input type="text" name="companyName">
  </form>
</body>

</html>

index.jsx

import React from 'react';
import { Helmet } from 'react-helmet';
import ReCAPTCHA from 'react-google-recaptcha';
import HeaderLargeDesktop from '../HeaderLargeDesktop';
import HeroLargeDesktop3 from '../HeroLargeDesktop3';
import ButtonHover from '../ButtonHover';
import Footer from '../Footer';
import './LrgRequestADemo.scss';

const siteKey = process.env.REACT_APP_SITE_RECAPTCHA_KEY;

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

class LrgRequestADemo extends React.Component {
  constructor(props) {
    super(props);
    this.recaptchaRef = React.createRef();
    this.state = {
      firstName: '',
      lastName: '',
      email: '',
      companyName: '',
      submitSuccess: false,
      submitFailed: false,
    };
  }

  onRecaptcha = (e) => {
    e.preventDefault();
    console.log('onRecaptcha method triggered');
    // Wait for reCAPTCHA to complete
    this.recaptchaRef.current.executeAsync().then((token) => {
    // Call your form submission method with the token
    this.submitCallback(token);
    })
    .catch((error) => {
      console.error('Error in reCAPTCHA execution:', error);
    });
  };

  submitCallback = (token) => {
    console.log('reCAPTCHA Token:', token);
    fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: encode({
        'form-name': 'demoRequest',
        'g-recaptcha-response': token,
        ...this.state,
      }),
    })
      .then((response) => {
        console.log('Response:', response);
        if (response.ok) {
          this.setState({
            firstName: '',
            lastName: '',
            email: '',
            companyName: '',
            submitSuccess: true,
            submitFailed: false,
        });
          this.recaptchaRef.current.reset(); // Reset reCAPTCHA
        } else {
        console.error('Form submission failed:', response.statusText);
         this.setState({ submitSuccess: false, submitFailed: true });
      }
    })
      .catch((error) => {
        console.error('Error:', error);
        this.setState({ submitSuccess: false, submitFailed: true });
      });
  };

  handleChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  };

  render() {
    const {
      firstName,
      inputType1,
      inputPlaceholder1,
      lastName,
      inputType2,
      inputPlaceholder2,
      headerLargeDesktopProps,
      heroLargeDesktop3Props,
      email21Props,
      email22Props,
      buttonHoverProps,
      footerProps,
    } = this.props;

    return (
      <div className='container-center-horizontal'>
        <div className='lrg-request-a-demo screen'>
          <Helmet>
            <meta
              name='robots'
              content='index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1'
            />
            <title>Request A Demo | Rivelin</title>
            <meta name='description' content='Metal finishing made simple' />
            <meta name='keywords' content='Rivelin demo' />
            <meta property='og:description' content='Metal finishing made simple' />
            <meta property='og:site_name' content='Rivelin Robotics' />
            <meta property='og:title' content='Request A Demo' />
            <meta name='og:image' content='https://www.rivelinrobotics.com/img/mask-group-4@1x.png' />
            <meta
              name='og:image:secure_url'
              content='https://www.rivelinrobotics.com/img/mask-group-4@1x.png'
            />
            <meta
              name='image'
              property='og:image'
              content='https://www.rivelinrobotics.com/img/mask-group-4@1x.png'
            />
            <meta property='og:image:type' content='image/png' />
            <script src="https://www.google.com/recaptcha/api.js" async defer></script>
          </Helmet>
          <HeaderLargeDesktop {...headerLargeDesktopProps} />
          <HeroLargeDesktop3>{heroLargeDesktop3Props.children}</HeroLargeDesktop3>
          <form onSubmit={(e) => this.onRecaptcha(e)}>
            <div className='form-1'>
              <div className='first-name-2'>
                <div className='overlap-group-23'>
                  <div className='field-3 border-2px-gallery'></div>
                  <div className='st-name atkinsonhyperlegible-normal-bunker-26px'>{firstName}</div>
                  <input
                    className='x-5 atkinsonhyperlegible-normal-onyx-26px'
                    name='firstName'
                    placeholder={inputPlaceholder1}
                    type={inputType1}
                    value={this.state.firstName}
                    onChange={this.handleChange}
                  />
                </div>
              </div>
              <div className='last-name-2'>
                <div className='overlap-group-23'>
                  <div className='overlap-group-24'>
                    <div className='field-3 border-2px-gallery'></div>
                    <div className='st-name atkinsonhyperlegible-normal-bunker-26px'>{lastName}</div>
                  </div>
                  <input
                    className='x-6 atkinsonhyperlegible-normal-onyx-26px'
                    name='lastName'
                    placeholder={inputPlaceholder2}
                    type={inputType2}
                    value={this.state.lastName}
                    onChange={this.handleChange}
                  />
                </div>
              </div>
              <div className='form-1-item'>
                <div className='overlap-group-25'>
                  <div className='overlap-group-26'>
                    <div className='field-4 border-2px-gallery'></div>
                    <div className='email-1 atkinsonhyperlegible-normal-rose-26px'>
                      <span className='atkinsonhyperlegible-normal-bunker-26px'>
                        {email21Props.spanText1}
                      </span>
                      <span className='atkinsonhyperlegible-normal-rose-26px-2'>*</span>
                    </div>
                  </div>
                  <input
                    className='x-3 atkinsonhyperlegible-normal-onyx-26px'
                    name='email'
                    placeholder=' '
                    type='email'
                    required
                    value={this.state.email}
                    onChange={this.handleChange}
                  />
                </div>
              </div>
              <div className='form-1-item'>
                <div className='overlap-group-25'>
                  <div className='overlap-group-26'>
                    <div className='field-4 border-2px-gallery'></div>
                    <div className='email-1 atkinsonhyperlegible-normal-rose-26px'>
                      <span className='atkinsonhyperlegible-normal-bunker-26px'>
                        {email22Props.spanText1}
                      </span>
                      <span className='atkinsonhyperlegible-normal-rose-26px-2'>*</span>
                    </div>
                  </div>
                  <input
                    className='x-3 atkinsonhyperlegible-normal-onyx-26px'
                    name='companyName'
                    placeholder=' '
                    type='text'
                    required
                    value={this.state.companyName}
                    onChange={this.handleChange}
                  />
                </div>
              </div>
              {!!this.state.submitSuccess && (
                <div className='submit-success'>
                  <span className='atkinsonhyperlegible-normal-bunker-24px'>Success! We'll be in touch.</span>
                </div>
              )}
              {!!this.state.submitFailed && (
                <div className='submit-failure'>
                  <span className='atkinsonhyperlegible-normal-bunker-24px'>
                    Woops! Something went wrong, try again or contact info@rivelinrobotics.com
                  </span>
                </div>
              )}
              <ReCAPTCHA
                ref={this.recaptchaRef}
                size='invisible'
                sitekey={siteKey}
                tabindex={3}
                onChange={(token) => this.submitCallback(token)}
              />
              <div className='submit-3'>
                <button type='submit' className='button-container-3'>
                  <ButtonHover />
                  <ButtonHover className={buttonHoverProps.className} />
                </button>
              </div>
            </div>
          </form>
          <Footer
            className={footerProps.className}
            privacyPolicyLinkProps={footerProps.privacyPolicyLinkProps}
            youtubeProps={footerProps.youtubeProps}
            linkedinProps={footerProps.linkedinProps}
            githubProps={footerProps.githubProps}
          />
        </div>
      </div>
    );
  }
}

export default LrgRequestADemo;

hi @rr-robert

I see you’re already talking to my colleague on the helpdesk so let’s continue the conversation over there!

1 Like

In November 2020 the Netlify backend engineer Jen said on this post:

Hey @paweljurczynski,
We usually return a 303 when there is an issue with the reCAPTCHA. Are you using a custom reCAPTCHA? If so, can you confirm that it is configured to work with your domain (you’d do that in your Google dashboard)? If not, can you please share your form code? It could be that you set data-netlify-recaptcha=“true” but then do not create the necessary div with the reCAPTCHA in the body of your form.

Chris McCraw emailed me yesterday with:

303 responses are not common on our platform, so I am 99% sure that none of the code Netlify has written would cause this. We use exclusively 301 and 302 redirects in our automatic redirects and in the code we publish such as the next-runtime, or in responding to a form submission

So I must be in the 1%.

I’ve spent an all-nighter and 18 straight hours trying to fix this issue. Can we work together to investigate why Netlify is rejecting my reCAPTCHA v2 invisible?

This thread from 2020 helped solve it. Thanks to @Jen and @paweljurczynski . The present day support team at Netlify could have helped me solve this in 10 minutes instead of 18 hours. I’m a paying customer with Pro subscription.