June 18, 2020 • ☕️ 4 min read
English

Netlify Formを利用すれば、serverlessのGatsbyにも問い合わせフォームを簡単に作れるでしょう。しかし、無料プランは1ヶ月100通のメッセージしか受信できないので、スパム対策しっかりしたほうがいいでしょう。( ´艸`)

普通のhttp postであれば、Netlify Formページのマニュアルを参照すれば難しくない組み込めますが、今回はAjaxで実装してみましょう。

要望

ランディングページにNetlify Formで組み込んだ問い合わせフォームのスパム対策を行う。

スパム対策:

  1. Honeypot field
  2. reCAPTCHA 2

Honeypot field

Honeypot fieldとは?英語なんですが、ここへ

Ajaxでフォームをコミットするため、formにnetlify-honeypotを追加する必要がありません。非表示にinputを組み込めば簡単にできます。

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

reCAPTCHAのキーペアを取得

https://www.google.com/recaptcha/admin, reCAPTCHA v2のサイトキーとシークレットキーを取得。

get-recaptcha-1.jpg

サイトキーシークレットキーをコピー

get-recaptcha-2.jpg

Netlifyに環境変数を追加

Settings -> Build & deploy -> Environment

  • SITERECAPTCHAKEY: サイトキー
  • SITERECAPTCHASECRET: シークレットキー

netlify-environment-variable.jpg

ソースコードの修正

  1. react-google-recaptchaのインストール

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

    <form
      data-netlify="true"
      data-netlify-recaptcha="true"
    >
    ...
    </form>
  3. サイトキーを.env.developmentに書き込むと、developモードで起動したら、Gatsbyが自動的にprocess.envに読み込んでくれる(製品版のビルドするとき、同じ内容を.env.productionに書き込まなければいけない)

    SITE_RECAPTCHA_KEY=6LdtK6YZAAAAAK3iDB-14qX7bJv2d1KuIz_GR7LT
  4. reCAPTCHAコンポーネントをformに追加

    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. submitするとき、パラメータ名g-recaptcha-responseとしてvalueをPOSTする

    fetch("/", {
      ...,
      body: {
        "g-recaptcha-response": encodeURIComponent(recaptchaValue),
      }
    })
  6. ソースコードを整理

    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>
      );
    }

完了

AjaxでNetlify FormをPOSTした場合、意外にワナが多くて、ご参考まで。。。


関連投稿

ランディングページに問い合わせフォームのサードパーティ・ コードの遅延

August 10, 2020

Gatsbyをバージョンアップした後developモード起動できない問題

May 10, 2020

Blog part of ThunderMiracle.com