本サイトはプロモーションが含まれています

Gatsby製ブログでreCAPTCHA付きのNetlify Formを実装する方法(スパム対策)

導入

Gatsby 製のブログを作っていて、Netlify のフォーム機能を使ってお問い合わせフォームを実装したいと思いました。
しかし、最初はうまく動かなかったため、動くようにするまでの手順をまとめました。


手順

以下の 3 ステップで解決します。

  • form-name の input タグの追加
  • submit ボタンを押したときの処理を追加
  • reCAPTCHA の登録と Netlify への設定

form-name の input タグの追加

Gatsby のような静的サイトジェネレータでは、以下の input タグを追加する必要があります。

<input type="hidden" name="form-name" value="(formのname)" />

submit ボタンを押したときの処理を追加

次に、submit ボタンを押したときの処理を React で実装します。
今回はスパム対策として Google Recaptcha v2 も追加します。


まず、Recaptcha v2 を追加するためのパッケージをインストールします。

npm install --save react-google-recaptcha

そして、公式ページで紹介されている GitHub のコードを参考にし、送信ボタンを押したときの処理を追加します。
このように実装することで、reCAPTCHA に成功するとボタンが表示される簡易的なフォームが完成します。

import * as React from "react"
import { Link, graphql, navigate } from "gatsby"
import Recaptcha from "react-google-recaptcha"
import Layout from "../components/layout"
import Seo from "../components/seo"
const RECAPTCHA_KEY = process.env.GATSBY_APP_SITE_RECAPTCHA_KEY
if (typeof RECAPTCHA_KEY === "undefined") {
throw new Error(`
reCAPTCHAキーが登録されていません
`)
}
function encode(data) {
return Object.keys(data)
.map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
.join("&")
}
const Contact = ({ data, location }) => {
const siteTitle = data.site.siteMetadata?.title || `Title`
const [state, setState] = React.useState({})
const recaptchaRef = React.createRef()
const [recaptchaStatus, setRecaptchaStatus] = React.useState(false)
const handleChange = e => {
setState({ ...state, [e.target.name]: e.target.value })
}
const handleSubmit = e => {
e.preventDefault()
const form = e.target
const recaptchaValue = recaptchaRef.current.getValue()
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: encode({
"form-name": form.getAttribute("name"),
"g-recaptcha-response": recaptchaValue,
...state,
}),
})
.then(() => navigate(form.getAttribute("action")))
.catch(error => alert(error))
}
const recaptchaSuccess = () => {
setRecaptchaStatus(true)
}
return (
<Layout location={location} title={siteTitle}>
<Seo title="お問い合わせフォーム" />
<h1>お問い合わせフォーム</h1>
<p>これはサンプルです。</p>
<form
name="contact"
action="/success/"
method="POST"
data-netlify="true"
data-netlify-recaptcha="true"
onSubmit={handleSubmit}
>
{/*静的サイトジェネレータの場合必要*/}
<input type="hidden" name="form-name" value="contact" />
<div className="inputGroup">
<label htmlFor="name">お名前(必須): </label>
<input
type="text"
name="name"
id="name"
required
onChange={handleChange}
/>
</div>
<div className="inputGroup">
<label htmlFor="email">メールアドレス(必須): </label>
<input
type="email"
name="email"
id="email"
required
onChange={handleChange}
/>
</div>
<div className="inputGroup">
<label htmlFor="message">お問い合わせ内容(必須): </label>
<textarea
name="message"
id="message"
rows="5"
cols="50"
required
onChange={handleChange}
></textarea>
</div>
<div className="checkbox">
<input
type="checkbox"
name="agreement"
id="agreement"
required
onChange={handleChange}
/>
<label htmlFor="agreement">
<Link to="/privacy-policy/">プライバシーポリシー</Link>
に同意する(必須)
</label>
</div>
<div className="center">
<Recaptcha
ref={recaptchaRef}
sitekey={RECAPTCHA_KEY}
onChange={recaptchaSuccess}
/>
</div>
<div className="center">
<button type="submit" disabled={!recaptchaStatus}>
送信
</button>
</div>
</form>
</Layout>
)
}
export default Contact
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
}
`

各入力タグにonChangeを追加し、値が変更された際にstateとして各入力値を保持しています。
<Recaptcha>onChangeで指定している関数で、recaptcha に成功した場合、button の disable を false にしています。
<form>actionで遷移先の URL を指定しています。

reCAPTCHA の登録と Netlify への設定

また、reCAPTCHA に登録します。
自分の持つ Google アカウントを使い、このページから登録するサイトとどのタイプを追加するかを以下のように指定します。
reCAPTCHAへの登録
登録するドメインには、登録したいサイトのドメイン名とローカル環境での確認のため、localhost を追加します。
規約に同意して登録すると、サイトキーとシークレットキーが発行されます。
これを Netlify に登録します。


Netlify の「Site Setting」を開き、「Build & deploy」を開きます。
この「Build settings」の「Build command」を以下に変更します。

echo SITE_RECAPTCHA_KEY=$SITE_RECAPTCHA_KEY >> .env.production && gatsby build

また、先ほど取得したサイトキーとシークレットキーを環境変数として登録します。
同じく「Build & deploy」の「Environment」内の「Environment variables」に以下のようにサイトキーとシークレットキーを登録します。

KeyValue
GATSBY_APP_SITE_RECAPTCHA_KEY(先ほど取得したサイトキー)
SITE_RECAPTCHA_KEY(先ほど取得したサイトキー)
SITE_RECAPTCHA_SECRET(先ほど取得したシークレットキー)

これで Netlify での準備は完了です。
この登録によって、Netlify がバックエンドは担当してくれるようになります。


また、ローカル環境で確認する際は、.env.development と.env.production ファイルを作成し、以下の記述を追加してください。

GATSBY_APP_SITE_RECAPTCHA_KEY='(先ほど取得したサイトキー)'

あとは、Netlifyにデプロイするだけで作業が完了です。

完成したもの

完成したものは、以下のようなものです。
CSS で少しレイアウトを調整しています。
reCAPTCHA付きのお問い合わせフォーム


reCAPTCHA に成功すると、送信ボタンが使えるようになります。
reCAPTCHA認証成功の場合


送信が完了すると、自作の投稿完了ページに飛びます。
投稿完了


reCAPTCHA に成功した場合のみ、投稿内容が確認できるようになります。
投稿内容確認画面


終わりに

今回は、Gatsby 製ブログで reCAPTCHA 付きのお問い合わせフォームを実装しました。
次回は、404 ページが表示されない問題を修正する方法を紹介します。