はじめに
この記事では、Google FormsをカスタムUIで利用し、ページ遷移なしでフォームの回答を送信する方法を解説します。
この記事が解決する課題
通常、HTMLの<form>
タグでGoogle Formsにデータを送信すると、送信後にGoogleの確認ページに遷移してしまいます。
これを避けて、ユーザー体験を損なわずに自作のページ内で非同期にデータを送信したい、という課題を解決します。
ターゲット読者
- 独自のフロントエンドデザインでGoogle Formsを利用したい方
- JavaScriptのFetch APIを使ってフォームデータを非同期送信したい方
記事のゴール
この記事を読み終えることで、Fetch APIを用いてGoogle FormsにデータをPOSTし、ページ遷移を防ぐ実装方法を理解できます。
前提条件
この記事は、Google Formsの基本的な作成方法を理解していることを前提としています。
実装手順
実装は大きく分けて2つのステップで行います。
- Google Formsから送信先URLとエントリーIDを取得する
- Fetch APIを使ってデータをPOSTする
1. 送信先URLとエントリーIDの取得
まず、送信先となるURLと、各フォーム項目に対応するID(エントリーID)を特定します。
- 作成したGoogle Formのプレビュー画面を開きます。
- ブラウザの検証ツール(デベロッパーツール)を開き、Networkタブを表示した状態で、すべての項目にテストデータを入力して送信します。
- 送信後、Networkタブのリストから
formResponse
という名前のリクエストを探します。 -
formResponse
のHeaders
タブで、Request URL
を確認します。これがデータをPOSTする先のURLです。 - 次に
Payload
(またはRequest
) タブで、送信されたデータを確認します。entry.xxxx
のようなキーと、入力したテストデータが値として表示されています。このentry.xxxx
が各項目に対応するエントリーIDです。
ブラウザの検証ツールでformResponse
を確認し、リクエストURLとエントリーIDを控えておきます。
2. Fetch APIでデータをPOSTする
取得したURLとエントリーIDを使って、Fetch APIでデータを送信するJavaScriptコードを記述します。
HTMLの例
まず、データを入力するためのHTMLフォームを用意します。action
属性は不要です。
<form id="custom-form">
<input type="text" name="question1" placeholder="質問1の回答">
<input type="text" name="question2" placeholder="質問2の回答">
<textarea name="question3" placeholder="質問3の回答"></textarea>
<button type="submit">送信</button>
</form>
JavaScriptの例
次に、フォームの送信イベントを捕捉し、Fetch APIでデータをPOSTする処理を実装します。
document.getElementById('custom-form').addEventListener('submit', (e) => {
// デフォルトのフォーム送信をキャンセル
e.preventDefault();
// Google FormのURLとエントリーID
const GOOGLE_FORM_URL = 'https://docs.google.com/forms/d/e/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/formResponse';
const ENTRY_IDS = {
question1: 'entry.xxxx',
question2: 'entry.yyyy',
question3: 'entry.zzzz',
};
// フォームデータを取得
const formData = new FormData(e.target);
const formEntries = Object.fromEntries(formData.entries());
// POSTするデータを作成 (URLエンコード)
const body = new URLSearchParams();
body.append(ENTRY_IDS.question1, formEntries.question1);
body.append(ENTRY_IDS.question2, formEntries.question2);
body.append(ENTRY_IDS.question3, formEntries.question3);
// Fetch APIでデータを送信
fetch(GOOGLE_FORM_URL, {
method: 'POST',
mode: 'no-cors', // CORSエラーを回避するために必要
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: body.toString(),
})
.then(() => {
console.log('フォームが正常に送信されました。');
// ここでサンクスページの表示などの処理を行う
})
.catch((error) => {
console.error('送信中にエラーが発生しました:', error);
// エラー処理
});
});
コードのポイント
-
mode: 'no-cors'
: Google Formsのエンドポイントは外部ドメインからのリクエストを想定していないため、CORSポリシー違反のエラーが発生します。mode: 'no-cors'
を指定することで、レスポンスの内容にはアクセスできなくなりますが、リクエストを送信すること自体は可能になります。 -
Content-Type
:application/x-www-form-urlencoded
を指定します。 -
URLSearchParams
:URLSearchParams
オブジェクトを利用すると、キーと値をURLエンコードされたクエリ文字列 (key1=value1&key2=value2
) に簡単に変換できます。
注意点
- バリデーション: この方法では、Google Forms側で設定した「必須項目」などのバリデーションが機能しません。そのため、フロントエンド側で独自のバリデーションを実装する必要があります。
-
エラーハンドリング:
no-cors
モードでは、サーバーからのレスポンスコード(成功か失敗か)を受け取ることができません。送信が成功したかどうかの確実な判定は難しいため、ユーザーには「送信されました」と楽観的なUIを見せつつ、重要なフォームでは別の方法を検討する方が良いかもしれません。 - JavaScriptへの依存: この方法はJavaScriptが有効な環境でしか動作しません。
まとめ
Fetch APIと no-cors
モードを利用することで、ページ遷移なしでGoogle Formsにデータを送信できます。これにより、サーバーレスで無料のフォームバックエンドとしてGoogle Formsを活用しつつ、UI/UXを自由にカスタマイズすることが可能になります。
ただし、CORSの制約によるエラーハンドリングの難しさなどのデメリットも理解した上で利用することが重要です。
参考資料
- Using Google Drive for Form Submissions - より詳細な英語の解説記事です。