tech.sinayaka.com

GatsbyJSで問い合わせフォーム

2023-02-06
2025-07-13
5分
867語
GatsbyJS GatsbyGAS

GatsbyJS限定というわけでもないのですが、 問い合わせフォームをスプレッドシートに送信する仕組みを実装しました。 JavascriptからfetchでスプレッドシートのGAS(GoogleAppsScript)へ投げます。

問い合わせページHTML部

ChatGPTに聞いておおまかなパーツを作ってもらいます。

ChatGPT

スタイルとボタン処理を加えて、HTML部分は以下のようになりました。 ハニーポットなどbot対策は問題が発生してから対応します。YAGNI(ヤグニ)の精神です(# 覚えられない)。

“You ain’t gonna need it”、縮めて YAGNI とは、機能は実際に必要となるまでは追加しないのがよいとする、エクストリーム・プログラミングにおける原則である。
wiki

<form method="POST" onSubmit={doSubmit}>

<div className="main-heading">お問い合わせ</div>
<label htmlFor="name">名前:</label>
<input type="text" id="name" name="name"
    placeholder="お名前"
    maxLength="30"
    minLength="2"
    autoComplete="name"
    required/>

<label htmlFor="email">メールアドレス:</label>
<input type="text" id="email" name="email"
    placeholder="メールアドレス"
    autoComplete="email"
    required/>

<label htmlFor="message">メッセージ:</label>
<textarea id="message" name="message"
    rows="8"
    placeholder="お問い合わせ内容"
    required></textarea>

<div id="controls">
    <input type="button" id="btn_cancel" onClick={doCancel} value="修正する" style={{display:`none`}}/>
    <input type="submit" id="btn_submit" value="確認する"/>
</div>
</form>

問い合わせページJavascript部

「doSubmit」と「doCancel」の処理を以下のようにしました。 送信前に一旦コントロールをdisabledにして確認するフェーズをはさみます。 ゴリゴリのjsゴリラなのでjsでゴリ押ししてます(# もっと最新のスマートな方法募集)。

async function doSubmit(e) {
    if(!e) return;
    e.preventDefault();
    const doms = document.querySelectorAll("input[type='text'],textarea");
    if (document.body.classList.contains("confirm")) {
        // 見た目
        document.querySelector("#controls").innerHTML = `<input type="button" value="送信中..."/>`;
        document.body.classList.remove("confirm");

        // 送信処理
        const forms = {};
        doms.forEach(dom => {forms[dom.name] = dom.value;});
        const URL = `${process.env.GATSBY_MAILFORM_URL}`;
        const postparam = {
            "method"     : "POST",
            "mode"       : "no-cors",
            "Content-Type" : "application/x-www-form-urlencoded",
            "body" : JSON.stringify(forms)
        };
        await fetch(URL, postparam);

        // 見た目
        document.querySelector("#controls").innerHTML = `<input type="button" value="送信しました"/>`;
    }
    else {
        // 見た目
        doms.forEach((dom)=>{dom.setAttribute("disabled","");})
        document.body.classList.add("confirm");
        document.querySelector("#btn_cancel").style.display = "";
        document.querySelector("#btn_submit").value = "送信する";
    }
    return false;
}
function doCancel(e) {
    // 見た目
    const doms = document.querySelectorAll("input[type='text'],textarea");
    doms.forEach((dom)=>{dom.removeAttribute("disabled");});
    document.body.classList.remove("confirm");
    document.querySelector("#btn_cancel").style.display = "none";
    document.querySelector("#btn_submit").value = "確認する";
}

${process.env.GATSBY_MAILFORM_URL}のところは環境変数です。
.envファイルに変数を入れて外部で管理します。
デプロイ先の環境変数にも同じ名前で登録しておくと実際のページでも参照されます。 仕組みが理解できていませんが、直にページに書かないようにできるので利用します。
参考:(https://qiita.com/xrxoxcxox/items/4e337b96fc9017b3771c)

require("dotenv").config();

module.exports = {
GATSBY_MAILFORM_URL = "https://script.google.com/macros/s/XXXXXX/exec"

GATSBY_MAILFORM_URLはこのあと作るスプレッドシートのデプロイURLです。 スプレッドシートがデプロイ出来たら編集します。

スプレッドシートの作成

フォームデータを受け取るGoogleSpreadSheetを作成し、 シート1の名前を「form」にします。(# ファイルもシートと言うしファイル内の「シート」もシートというので分けた言い方募集)
1行目をラベル行として日付、名前、アドレス、内容など書いておきます。
メニュー → 拡張機能 → Apps Script でGASを起動します。
Googleアカウントを複数使役している人は「デフォルト」のアカウントで起動しないといけないので注意してください。
参考:(https://pkunallnet.com/pcinfo/google/gasnoopen/)

GAS起動

doPost関数を作りWebアプリとしてデプロイし、できたURLをGATSBY_MAILFORM_URLに適用します。

function doPost(e){
  if (!e) return;
  if (typeof(e["postData"]) === 'undefined') return;
  if (typeof(e.postData["contents"]) === 'undefined') return;

  const data = JSON.parse(e.postData.contents);
  const text_date = Utilities.formatDate(new Date(), "JST","yyyy-MM-dd HH:mm:ss");
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('form');
  sheet.insertRowBefore(2);
  sheet.getRange(2, 1, 1, 4).setValues([[text_date, data["name"], data["email"], data["message"]]]);
}

おわりに

環境変数でJavascript内の固有値を隠ぺい(?)できるので、 クライアント処理だけで各種サービスを往来できるのは便利な世の中です。
実際にはGASで受け取ったらLINE NotifyでLINEに通知するようにしました。




Copyright 2025
サイトマップ