tech.sinayaka.com

GatsbyJSで問い合わせフォーム

2023-02-06
2026-07-08
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 2026
    サイトマップ