HPのフォームからGoogle Apps Scriptでスプレッドシートに転記&自動返信する方法

お問合せフォーム自動返信 DX化
お問合せフォーム自動返信

「お問い合わせフォームを作りたいけど、バックエンドの構築が大変…」

「問い合わせデータをエクセルで管理したいけど、いちいち手動で入力するのは面倒…」

「お客様には自動で返信メールを送りたいけど、プログラミングの知識が少なくて…」

こんな悩みを持つ方は多いのではないでしょうか?

今回は、Reactで作成したフォームからGoogle Apps Script(GAS)を使ってデータをスプレッドシートに自動転記し、同時に自動返信メールを送信する方法をご紹介します。バックエンド構築の手間なく、Googleのサービスだけで完結するため、ITリソースの限られた中小企業でも導入しやすい解決策です。

ReactフォームとGoogle Apps Scriptで自動返信付き問い合わせを作る理由

「なぜReactとGoogle Apps Scriptの組み合わせなのか?」と疑問に思う方もいるでしょう。その主なメリットを見ていきましょう。

顧客対応がラクになる

問い合わせフォームからの入力データが自動でスプレッドシートに転記され、さらに顧客へ自動返信メールが送られるため、手作業による転記ミスや返信忘れを防止できます。特に少人数で運営している中小企業では、この自動化による工数削減効果は絶大です。

バックエンド不要で素早く導入できる

従来の方法では、フォームデータを受け取るためのサーバーサイドの実装が必要でした。しかしGoogle Apps Scriptを活用すれば、バックエンドの構築なしにデータの保存や自動返信メールの送信が可能です。これにより、開発工数とコストを大幅に削減できます。

スプレッドシートで一元管理できる

お問い合わせデータがすべてGoogleスプレッドシートに集約されるため、チーム内での情報共有や分析が容易になります。さらに、スプレッドシートの条件付き書式や関数を活用すれば、対応状況の可視化や統計分析も簡単に実現できます。

ReactフォームからGoogle Apps Scriptにデータを送り、スプレッドシートに転記&自動返信する方法

それでは実際に、ReactフォームからGoogle Apps Scriptを使ってデータをスプレッドシートに転記し、自動返信する方法を順を追って解説します。

Reactで問い合わせフォームを作る(基本構造と状態管理)

まずは、Reactで基本的な問い合わせフォームを作成します。以下は簡単なフォームの例です。

import React, { useState } from 'react';

function ContactForm() {
  // フォームの状態を管理
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    subject: '',
    message: ''
  });
  
  // 送信状態を管理
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitResult, setSubmitResult] = useState(null);
  
  // 入力変更時のハンドラ
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };
  
 // Google Apps Scriptにデータを送信する関数
  const sendToGAS = async (data) => {
  // 後ほど実装するGoogle Apps Scriptへのデータ送信処理
 };

  // フォーム送信時のハンドラ
  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);
    
    try {
      const result = await sendToGAS(formData);
      setSubmitResult({ success: true, message: '送信に成功しました。' });
    } catch (error) {
      setSubmitResult({ success: false, message: '送信に失敗しました。' });
      console.error('送信エラー:', error);
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <div className="contact-form">
      <h2>お問い合わせフォーム</h2>
      
      {submitResult && (
        <div className={`result ${submitResult.success ? 'success' : 'error'}`}>
          {submitResult.message}
        </div>
      )}
      
      <form onSubmit={handleSubmit}>
        <div className="form-group">
          <label htmlFor="name">お名前</label>
          <input
            id="name"
            name="name"
            type="text"
            value={formData.name}
            onChange={handleChange}
            required
          />
        </div>
        
        <div className="form-group">
          <label htmlFor="email">メールアドレス</label>
          <input
            id="email"
            name="email"
            type="email"
            value={formData.email}
            onChange={handleChange}
            required
          />
        </div>
        
        <div className="form-group">
          <label htmlFor="subject">件名</label>
          <input
            id="subject"
            name="subject"
            type="text"
            value={formData.subject}
            onChange={handleChange}
            required
          />
        </div>
        
        <div className="form-group">
          <label htmlFor="message">お問い合わせ内容</label>
          <textarea
            id="message"
            name="message"
            value={formData.message}
            onChange={handleChange}
            rows="5"
            required
          />
        </div>
        
        <button type="submit" disabled={isSubmitting}>
          {isSubmitting ? '送信中...' : '送信する'}
        </button>
      </form>
    </div>
  );
}

export default ContactForm;

このコードは、名前、メールアドレス、件名、お問い合わせ内容を入力するシンプルなフォームです。React HooksのuseStateを使用して、フォームの入力データと送信状態を管理しています。

fetchでGoogle Apps ScriptにデータをPOSTする方法

次に、フォームデータをGoogle Apps Scriptに送信する関数を実装します。この関数は前述のsendToGASとして使用されます。「Google Apps ScriptのウェブアプリのURL」は後述の手順で取得したURLに置き換えます。

const sendToGAS = async (data) => {
  // Google Apps ScriptのウェブアプリのURL
  const gasUrl = 'Google Apps ScriptのウェブアプリのURL(後述の手順で取得)';
  
  // フォームデータをURLSearchParamsに変換
  const formData = new URLSearchParams();
  for (const key in data) {
    formData.append(key, data[key]);
  }
  
  // Google Apps Scriptにデータを送信
  const response = await fetch(gasUrl, {
    method: 'POST',
    mode: 'no-cors',  // 重要: CORSの制約を回避するために必要
    cache: 'no-cache',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: formData
  });
  
  // no-corsモードではレスポンスの詳細情報が取得できないため、
  // 送信が完了したらtrueを返す(エラーハンドリングは別途考慮が必要)
  return true;
};

ここで重要なのはmode: 'no-cors'の設定です。Google Apps Scriptは異なるドメインからのリクエストに対してCORSの制約があるため、この設定が必要になります。ただし、この設定によりレスポンスの詳細情報が取得できなくなるため、エラーハンドリングには注意が必要です。

スプレッドシートに転記するApps Scriptコードの書き方

次に、Google Apps Script側の処理を実装します。まず、Google Driveでスプレッドシートを作成し、次にGoogle Apps Scriptのエディタを開きます(拡張機能 > Apps Script)。

以下のようなコードを記述します:

// POSTリクエストを処理する関数
function doPost(e) {
  try {
    // パラメータを取得
    const params = e.parameter;
    const name = params.name || '名前なし';
    const email = params.email || 'メールなし';
    const subject = params.subject || '件名なし';
    const message = params.message || '内容なし';
    const timestamp = new Date();
    
    // スプレッドシートに記録
    recordToSpreadsheet(name, email, subject, message, timestamp);
    
    // 自動返信メールを送信
    sendAutoReply(name, email, subject);
    
    // 応答を返す
    return ContentService.createTextOutput(JSON.stringify({
      result: 'success',
      message: 'データを正常に処理しました'
    })).setMimeType(ContentService.MimeType.JSON);
    
  } catch (error) {
    // エラー発生時の処理
    console.error('エラーが発生しました: ' + error.message);
    return ContentService.createTextOutput(JSON.stringify({
      result: 'error',
      message: error.message
    })).setMimeType(ContentService.MimeType.JSON);
  }
}

// スプレッドシートにデータを記録する関数
function recordToSpreadsheet(name, email, subject, message, timestamp) {
  // アクティブなスプレッドシートを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('問い合わせ') || ss.insertSheet('問い合わせ');
  
  // ヘッダーがなければ追加(初回実行時)
  if (sheet.getLastRow() === 0) {
    sheet.appendRow(['タイムスタンプ', '名前', 'メールアドレス', '件名', 'メッセージ', '対応状況']);
  }
  
  // データを追加
  sheet.appendRow([
    timestamp,
    name,
    email,
    subject,
    message,
    '未対応'  // 初期状態は未対応
  ]);
}

このスクリプトはdoPost関数でPOSTリクエストを受け取り、送信されたデータをスプレッドシートに記録します。スプレッドシートが存在しない場合は自動的に「問い合わせ」という名前のシートを作成し、必要なヘッダーも設定します。

ユーザーに自動返信メールを送る方法(GASのメール送信機能)

続いて、自動返信メールを送信する機能を追加します。Google Apps ScriptのMailAppサービスを使用して、問い合わせを送信したユーザーに確認メールを送ります。

// 自動返信メールを送信する関数
function sendAutoReply(name, email, subject) {
  // メールの件名
  const mailSubject = '【自動返信】お問い合わせありがとうございます';
  
  // メールの本文
  const mailBody = `
${name} 様

お問い合わせいただき、ありがとうございます。
以下の内容で承りました。

■件名
${subject}

担当者が確認次第、改めてご連絡いたします。
今しばらくお待ちくださいますよう、お願い申し上げます。

------------------------------
株式会社〇〇
〒123-4567
東京都〇〇区〇〇町1-2-3
TEL: 03-1234-5678
Email: info@example.com
------------------------------
`;
  
  // メール送信
  MailApp.sendEmail({
    to: email,
    subject: mailSubject,
    body: mailBody
  });
}

この関数は、ユーザーのメールアドレスに対して自動返信メールを送信します。メール本文には、ユーザーの名前や問い合わせ件名を含めて、より丁寧な対応を演出しています。

Google Apps ScriptのウェブアプリのURLを取得

作成したGoogle Apps Scriptをウェブアプリとしてデプロイし、Google Apps ScriptのウェブアプリのURLを取得する手順は以下の通りです:

  1. スクリプトエディタで「デプロイ」ボタンをクリック
  2. 「新しいデプロイ」を選択
  3. デプロイのタイプとして「ウェブアプリ」を選択
  4. 次の設定を行う:
    • 説明:「お問い合わせフォーム処理」など分かりやすい名前
    • ウェブアプリの実行者:「自分(あなたのGoogleアカウント)」
    • アクセスできるユーザー:「全員(匿名ユーザーを含む)」
  5. 「デプロイ」ボタンをクリック
  6. デプロイが完了すると「ウェブアプリのURL」が表示されるので、このURLをコピーしておく

このURLが、先ほどReactのコードで使用したgasUrlに設定する値です。デプロイが完了したら、このURLを使用してReactフォームからGAS側へデータを送信できるようになります。

ReactフォームとGoogle Apps Scriptを連携して実行テスト

すべての実装が完了したら、実際にフォームから送信テストを行います。以下の手順でテストを実施しましょう:

  1. Reactアプリケーションを実行し、問い合わせフォームにテストデータを入力
  2. 「送信する」ボタンをクリックしてデータを送信
  3. Google Apps Scriptのログ(表示 > ログ)を確認し、エラーがないか確認
  4. スプレッドシートを開き、データが正しく記録されているか確認
  5. テストで使用したメールアドレスに自動返信メールが届いているか確認

これらのステップでエラーが発生した場合は、各コードを見直して修正します。特に、Google Apps ScriptのURLが正しく設定されているか、必要な権限が付与されているかを確認してください。

ReactフォームとGoogle Apps Script連携の注意点とセキュリティ対策

便利なReactフォームとGoogle Apps Scriptの連携ですが、セキュリティ面での注意点もあります。実運用前に以下のポイントを確認しましょう。

no-corsモードの制約と実装上の注意

mode: 'no-cors'設定を使用すると、フロントエンド側からレスポンスの詳細情報を取得できなくなります。そのため、エラーハンドリングが難しくなる点に注意が必要です。より高度なエラーハンドリングを実現するためには、以下のような対策を検討できます:

  1. 処理結果をURLパラメータとしてリダイレクト先に渡す
  2. セッションストレージやローカルストレージに一時的な識別子を保存し、別のAPIで結果を確認する
  3. Google Apps Script側でCORS対応のヘッダーを設定(ただし完全な対応は難しい場合も)

GASの公開設定によるリスクと制限

Google Apps Scriptを「全員(匿名ユーザーを含む)」に公開すると、URLを知っている人なら誰でもアクセスできます。そのため、以下の制限を検討する必要があります:

  1. リクエスト回数の制限(Google Apps Scriptには1日あたりの実行回数に制限があります)
  2. アクセス元の検証(正規のフォームからのリクエストかを確認)
  3. 機密情報の処理方法の見直し(特に個人情報を扱う場合は注意が必要)

スパム対策や認証なし公開の危険性

公開フォームはスパム攻撃の標的になりやすいため、以下のような対策を実装することをお勧めします:

  1. reCAPTCHAなどの導入
  2. 送信頻度の制限(同一IPからの連続送信を制限)
  3. 入力値のバリデーションを厳格化(特殊文字やスクリプトの排除)
  4. ハニーポットフィールド(人間には見えないダミーフィールドを設置し、ボットの検出に利用)

トークンチェックやReferer検証の導入例

より安全な実装のために、トークンチェックやリファラー検証を導入する例を示します:

// React側でのトークン生成
const generateToken = () => {
  return Math.random().toString(36).substr(2) + Date.now().toString(36);
};

// 送信時にトークンを含める
const sendToGAS = async (data) => {
  const token = generateToken();
  sessionStorage.setItem('formToken', token);
  
  const formData = new URLSearchParams();
  formData.append('token', token);
  // その他のデータ追加...
  
  // 送信処理...
};
// GAS側でのトークンとReferer検証
function doPost(e) {
  // リファラーチェック
  const referer = e.parameter.referer || '';
  const allowedDomains = ['example.com', 'www.example.com'];
  
  const isValidReferer = allowedDomains.some(domain => 
    referer.indexOf(domain) !== -1
  );
  
  if (!isValidReferer) {
    return ContentService.createTextOutput(JSON.stringify({
      result: 'error',
      message: '不正なアクセスです'
    })).setMimeType(ContentService.MimeType.JSON);
  }
  
  // 以降の処理...
}

最後に:Reactフォーム×Google Apps Script連携のセキュリティを意識しよう

ReactフォームとGoogle Apps Scriptの連携は、手軽な問い合わせフォームのソリューションです。しかし、その便利さの裏には、適切なセキュリティ対策が不可欠です。本記事で紹介した基本的な実装方法とセキュリティ対策を参考に、安全かつ効率的なフォームシステムを構築してください。

特に、個人情報や機密情報を扱う場合は、専門家のアドバイスを求めるか、より厳格なセキュリティ設計を検討することをお勧めします。適切なセキュリティ対策を施せば、ReactフォームとGoogle Apps Scriptの組み合わせは、業務効率化に大いに貢献するでしょう。