June 18, 2020 • ☕️ 3 min read
日本語

Netlify Form is quite easy to build a contact form in serverless architecture like Gatsby. But the free plan only allows 100 submissions a month, so spam filter is really important at this point.( ´艸`)

It’s not hard to follow the instructions in Netlify’s form spam filter page to make a normal http post contact form. But it’s quite challenging to do this with ajax for landing page. Let’s try ajax way today.

What to do

Make a Netlify form in landing page with spam filters, like:

  1. Honeypot field

  2. reCAPTCHA 2

Honeypot field

What is Honeypot field? You can find some introductions HERE.

Adding netlify-honeypot to form prop is not necessary when post form data by ajax. We can do it simply by adding a hidden input to the contents of the form.

Copy
const [inputs, setInputs] = React.useState({});

const handleChange = React.useCallback(
  (event) => {
    setInputs({
      ...inputs,
      [event.target.name]: event.target.value,
    });
  },
  [inputs],
);

<form>
  <p hidden>    <label htmlFor="bot-field">      Don’t fill this out: <input name="bot-field" onChange={handleChange} />    </label>  </p>  <label>Email:<input type="text" name="email" onChange={handleChange} /></label>
</form>

reCAPTCHA v2

Get reCAPTCHA’s Key pair

https://www.google.com/recaptcha/admin, reCAPTCHA v2’s site key and secret key.

get-recaptcha-1.jpg

Copy site keysecret key

get-recaptcha-2.jpg

Add site key and secret key to Netlify’s variables

SettingsBuild & deployEnvironment

  • SITE_RECAPTCHA_KEY: site key
  • SITE_RECAPTCHA_SECRET: secret key

netlify-environment-variable.jpg

Modify source code

  1. Install react-google-recaptcha

    Copy
    yarn add react-google-recaptcha
  2. formにdata-netlifydata-netlify-recaptchaを追加

    Copy
    <form
      data-netlify="true"
      data-netlify-recaptcha="true"
    >
    ...
    </form>
  3. Output site key to .env.developmentso Gatsby will read it to process.env automatically. (You have to make .env.production with the same contents in production build)

    Copy
    SITE_RECAPTCHA_KEY=6LdtK6YZAAAAAK3iDB-14qX7bJv2d1KuIz_GR7LT
  4. Add reCAPTCHA component to form

    Copy
    import ReCAPTCHA from 'react-google-recaptcha';
    
    const [recaptchaValue, setRecaptchaValue] = React.useState("");
    const handleChangeReCAPTCHA = React.useCallback((value) => {
      setRecaptchaValue(value);
    }, []);
    
    <form
      data-netlify="true"
      data-netlify-recaptcha="true"
    >
      ...
      <ReCAPTCHA sitekey={process.env.SITE_RECAPTCHA_KEY} onChange={handleChangeReCAPTCHA} />
    </form>
  5. Use g-recaptcha-response as parameter name in form data to post

    Copy
    fetch("/", {
      ...,
      body: {
        "g-recaptcha-response": encodeURIComponent(recaptchaValue),
      }
    })
  6. Put all together

    Copy
    import ReCAPTCHA from 'react-google-recaptcha';
    
    function ContactForm() {
      const [inputs, setInputs] = React.useState({});
      const [recaptchaValue, setRecaptchaValue] = React.useState("");
      const handleChange = React.useCallback(
        (event) => {
          setInputs({
            ...inputs,
            [event.target.name]: event.target.value,
          });
        },
        [inputs],
      );
      const handleChangeReCAPTCHA = React.useCallback((value) => {
        setRecaptchaValue(value);
      }, []);
    
      const handleSubmit = React.useCallback(
        (event) => {
          const submitForm = event.currentTarget;
          event.preventDefault();
          event.stopPropagation();
          if (recaptchaValue != null && recaptchaValue !== "") {
            fetch("/", {
              method: "POST",
              headers: { "Content-Type": "application/x-www-form-urlencoded" },
              body: encodeObj({
                "form-name": "form1",
                "g-recaptcha-response": recaptchaValue,
                ...inputs,
              }),
            })
              .catch(() => console.log('POST ERROR'));
          }
        },
        [inputs, recaptchaValue],
      );
    
      return (
        <form
          data-netlify="true"
          data-netlify-recaptcha="true"
          onSubmit={handleSubmit}
        >
          {/* You still need to add the hidden input with the form name to your JSX form */}
          <input type="hidden" name="form-name" value="form1" />
          <p hidden>
            <label htmlFor="bot-field">
              Don’t fill this out: <input name="bot-field" onChange={handleChange} />
            </label>
          </p>
          <p>
            <label>Email: <input type="text" name="email" /></label>
          </p>
          <p>
            <label>Message: <textarea name="message"></textarea></label>
          </p>
          <p>
            <button type="submit">Send</button>
          </p>
        </form>
      );
    }

That’s all


Relative Posts

How to add search to a multilingual Gatsbyjs site with algolia

May 1, 2021

gatsby develop not working after upgrade

May 10, 2020

ThunderMiracle

Blog part of ThunderMiracle.com