こんにちは、フリーランスエンジニア歴6年のしょーごです。
みなさん静的サイトにフォームの埋め込みを行う際、これまで難儀しなかったでしょうか?
私は最初はフォームの実装方法がわからず、フォームのためにわざわざWordPressのContact Form 7を使うほどでした。
- PHP工房
- Googleフォーム(今回はこれ!)
- Responsive Mailform
今回はこの中で「Googleフォームを使って自作フォームで送信する方法」を解説します。
前提条件
- jQuery使用
- 結構無理やり(コーポレートサイトよりかアンケート向き)
後述しますがデメリットもあるので、採用可否はよく判断してください。
この記事を書いたのは
しょーご(@samurabrass)
このブログ「しょーごログ」の運営者。本業でエンジニアとしてサイト制作やシステム開発を数年行っており、ブログとYouTubeで情報発信を行っている。駆け出しエンジニアのコーディング課題添削も行う
\現役エンジニアのレビュー付き/
実践レベルのコーディング課題公開中
- デザインカンプからのコーディングを経験したい
- 現役エンジニアのレビューを受けてみたい
- 即戦力級のポートフォリオを用意したい
2024年にデザインを完全リニューアルしています!
コーディングに自身をつけるにはプロからのレビューを貰うのが必須なため、制作会社も利用するレビューツールで添削をしています。
Web制作学習ロードマップにも取り入れているため、学習終了まで迷わず進むことが可能です。コーディングを本気で仕事したい方はぜひご活用ください!
\無料の入門編から本格企業サイトまで/
この記事の反響
Googleフォームをサイトに埋め込む
デフォルトのGoogleフォームをそのまま埋め込むとUXが微妙なのですが、実はフロントエンドのみの自作フォームでもGoogleフォームと紐づければ送信できるようになります。
以下のような見た目だけのHTMLフォームでも、
Googleフォームと連携させれば、送信することで非同期で画面遷移させずに、完了メッセージを出すことができます。
もちろん完了画面にも遷移させられます。
ゴール:Googleフォームで静的サイトのフォームを動くようにする
この記事を読んでできるようになること
- Googleフォームと自社サイトフォームの紐付け
- 送信完了後、同ページに「お問い合わせありがとうございました」のメッセージが出せる
- サンクスページに遷移できる
自社サイトにバックエンド不要で手軽にフォームが実装できるようになります!!
Googleフォームを作る
まずはGoogleフォームの作成をします。
ドメインがeditだとformが見つけられないため、ドメイン末尾が「viewform」となっていることを確認ください。
HTMLフォームで作る予定のものと、当然同じものを作ります
Googleフォームのinputのnameとformのaction先のURLをメモる
まずはわかりやすいようにフォームに適当に値を入れておきます。
値を入れておいた方が検証しやすいので、必ず入れてください。
chromeの検証機能で探します(Windowsの場合Ctrl + F、Macの場合⌘+Fで検索バーが出ます)
検証ツールでinputまたはentry.と入力し、確認してください。
①inputの場合
②entry.の場合
actionの値も押さえる
この数字の部分が自作フォームのnameに入ることになるので、actionの値と共に、メモしておいてください。
メールアドレスが見つからない場合
「メールアドレスを収集する」の場合、input群の一番下にname=”emailAddress”で格納されています。
まだnameを探せない人用図解
HTMLフォームを作成
<div class="form-wrapper">
<form
action="https://docs.google.com/forms/hogehoge~"
id="form">
<div class="box">
<label for="name">お名前</label>
<input type="text" name="entry.396652" id="name" placeholder="お名前" required>
</div>
<div class="box">
<label for="mail">メールアドレス</label>
<input type="mail" name="entry.1934980" id="mail" placeholder="メールアドレス" required>
</div>
<div class="box">
<p class="box">お好きなプログラミング言語</p>
<div class="flex-box"><input type="radio" name="entry.1977612" required value="scala">
<p>scala</p>
</div>
<div class="flex-box"><input type="radio" name="entry.1977612" required value="kotlin">
<p>kotlin</p>
</div>
<div class="flex-box"><input type="radio" name="entry.1977612" required value="basic">
<p>basic</p>
</div>
</div>
<div class="box">
<textarea name="entry.181178" id="" cols="30" rows="10" placeholder="自由記述"></textarea><!-- /# -->
</div>
<input type="submit" class="submit-btn">
</form>
<p class="end-message">お問い合わせありがとうございました</p>
<p class="false-message">送信失敗です</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
.end-message {
display: none;
}
.false-message {
display: none;
}
ここで、googleフォームと同じ内容のHTMLフォームを作成し、nameとactionの値を合わせます。
下のend-messageとfalse-messageはjQueryで送信後に出現させたいので、
cssで標準でdisplay: none;で非表示にしています。
- formタグにid=”form”→form内のinputのvalueを取得するためid指定(名前は任意)
- jQuery読み込み→Ajax利用のため
- name=”entry.1977611″などと、entry.先ほどの数字とする
この辺りは後々必要になってくるので、記述しておきます。
GoogleフォームにHTMLフォームから送信してみる
とここで感動してもいいですが、
いきなりこんなページに飛ばされるのは、ユーザビリティ的に問題があります。
ここからajax実装で、この画面に遷移しないように手を加えていきましょう。
お問い合わせ完了メッセージをだす。
これはjQueryの記述です。urlの部分は、formのactionの送信先urlと同じものを入れて下さい。
$(document).ready(function () {
$('#form').submit(function (event) {
var formData = $('#form').serialize();
$.ajax({
url: "https://docs.google.com/forms/hogehoge",
data: formData,
type: "POST",
dataType: "xml",
statusCode: {
0: function () {
$(".end-message").slideDown();
$(".submit-btn").fadeOut();
//window.location.href = "thanks.html";
},
200: function () {
$(".false-message").slideDown();
}
}
});
event.preventDefault();
});
});
- #formのsubmitイベントが起こった時、serializeでform内のinputのvalueを取り出しformDataに代入
- $.ajaxでurlにgoogleフォーム送信先(action)のurl記入
- statusCodeが0の時に送信アクションで、jQueryのメソッドでsubmit-btnを消し、end-message(お問い合わせありがとうメッセージ)を表示。
- 最後にevent.preventDefaultでsubmitイベントを無効化し遷移させない
という流れ。
JavaScript版はこちら。
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('form');
if (form) {
form.addEventListener('submit', function(event) {
event.preventDefault();
const formData = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://docs.google.com/forms/u/0/d/e/hogehoge/formResponse', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 4はリクエスト完了を意味します
document.querySelector(".end-message").style.display = 'block';
document.querySelector(".submit-btn").style.display = 'none';
// window.location.href = "thanks.html";
// 以下の行でフォームの入力をリセットします
form.reset();
}
};
xhr.send(formData);
});
}
});
もしコードの意味が分からない場合はAIに解説してもらうのが便利です。このサイトではWeb制作におけるChatGPTの使い方やCursorの使い方を解説しているので、
そちらを参考にコードの解説をお願いしてみてください。
送信後完了メッセージをslideDownで表示することができました。
さりげに送信後submit-btnをfadeOutさせているところに、気配りを感じますよね?(二重投票防止のため)
サンクスページへ遷移
こちらは一瞬です。
statusCode: {
0: function () {
//$(".end-message").slideDown();
//$(".submit-btn").fadeOut();
window.location.href = "thanks.html";
},
window.location.hrefで送信後、thanks.htmlに飛ばしています。
css書いてないので、ページ遷移してる感がないですが、一応遷移してますw
こうしてみると、Googleフォームの集計機能すごいっすね…
Googleフォーム利用の問題点
バリデーション
入力必須ぐらいなら、
<input type="text" required>
みたいにrequired使えば
デフォでこのように表示してくれるけど、バリデーションはフロントよりサーバーサイド(PHP)でやるのが鉄板らしいから、どうなんでしょうか。
クロスドメイン・オリジン問題(Cross-Origin Resource Sharing (CORS))
今回の場合、Googleフォームと異なるドメインからフォームを送るはずです。
あるドメインで読み込まれたHTMLページ(sample.com)から、Javascriptなどブラウザ上で動作するプログラミング言語によって、異なるドメイン(sample2.com)のサービスに接続すること
実は、今回のフォームは送信後にChromeデベロッパーツールのconsoleにエラーメッセージが表示されます。
Google Form以外のサイトからhttps://docs.google.com/forms/...
へ直接POSTするとCORSエラーが発生してしまうのです。
ブラウザには、安全のため、あるウェブサイトが他のウェブサイトのデータを勝手に取得できないようにする制限があります。
CORSエラーは学校の規則のようなもので、他の学校の教室に勝手に入ることは通常許可されていませんが、特別な許可があれば入ることができるのと似ています。
CORSポリシーに沿うと、Access-Control-Allow-Originを設定しないといけないのですが、CORSエラーが発生した場合でもFormの内容自体はしっかりとGoogle Formへ送られているので今回は良しとしました。
ステータスコード0で成功、200でfalseの補足
本来は、HTTP 200番台 Success(成功レスポンス)は、クライアントからリクエストがサーバに送られ理解されて受理された状態で、falseではないはずです。
しかし、ブラウザがクロスオリジンのリクエストに対して正しいCORSヘッダーを受け取らない場合、実際のHTTPステータスコード(たとえば200
)を返す前にリクエストをブロックします。
この場合、AJAXリクエストのステータスコードとして0
が返されます。
- ステータスコード
0
:Google FormsにデータをPOSTすると、正常に送信された場合、ブラウザによるCORSポリシーにより、実際のHTTPステータスコードが返される前にレスポンスがブロックされます。
その結果、jQueryのAJAXリクエストのステータスコードとして0
が返されることがよくあります。これは、フォームの送信が実際に成功したことを示すものです。 - ステータスコード
200
:このコードは通常、HTTPリクエストが正常に完了したことを示します。ただし今回の場合、実際のHTTPステータスコードはJavaScriptから読むことができませんので、厳密には無くても良い記述です。
よって、jQueryは以下のコードでも動きます。
$(document).ready(function () {
$('#form').submit(function (event) {
var formData = $('#form').serialize();
$.ajax({
url: "https://docs.google.com/forms/u/0/d/e/hogehoge/formResponse",
data: formData,
type: "POST",
dataType: "xml"
})
.always(function() {
// CORS制約によるエラーに関係なく、この処理が実行されます。
$(".end-message").slideDown();
$(".submit-btn").fadeOut();
//window.location.href = "thanks.html";
});
event.preventDefault();
});
});
では、そもそものCORS制約の回避には何をすればいいのかと言うと、下記3つのどれかです。
- サーバーサイドのプロキシを使用する: 自分のサーバーにエンドポイントを作成し、そのエンドポイントにデータをPOSTします。次に、サーバーサイドのコードはGoogle Formにデータを転送します。この方法で、ブラウザは直接Google Formにリクエストを送信するのではなく、自分のサーバーにリクエストを送信します。そのため、CORS制約は回避されます。
- JSONPを使用する: JSONPはCORS制約を回避する古いテクニックですが、セキュリティ上の懸念があり、今日の多くのシナリオで推奨されていません。また、すべてのサービスやAPIがJSONPをサポートしているわけではありません。
- CORSヘッダーを設定する: これはGoogle Formのエンドポイントに直接アクセス権を持っている場合にのみ可能です。しかし、Google FormはユーザーにCORSヘッダーの設定を許可していないので、この方法は使用できません。
最も実用的なのは、オプション1(サーバーサイドのプロキシを使用する)です。自分のサーバーにエンドポイントを設定し、クライアントからのリクエストを受け取り、それをGoogle Formに転送することでCORSの問題を回避できます。
ブラウザから直にリクエストを送らなければいいと。
とはいえ、サーバー建てるのがめんどくさいからGoogle Form使ってるねんって感じなんですが。
受託制作では相手と確認を協力すること!!
案件では、相手にGoogleフォームを作ってもらう必要があります。
ほんの少し、相手のITリテラシーが必要かもです。
また、必ず受託制作の場合は、クライアントと自分両者で目視で、Googleフォームに回答が届いているか、確認してください!
フォーム周りの動作は、実案件では最重要レベルのチェック事項です。
【まとめ】Googleフォームは静的サイトで軽く使いたい場合に
今回は、Googleフォームを静的サイトに埋め込みajaxでカスタマイズする方法を解説しました。
CORS制約があり、案件で大事なフォームを扱うにはちょっと怖いですかね…
対企業に使うなら、プロキシサーバーを立てるのが良さげで、これならCORS制約を受けず、正常なステータスコードが得られます。
私はこれまで期間限定のアンケートサイトなどで、Googleフォームの集計機能が便利ということで何度かプロキシサーバーを建てず、この記事のコードを実案件で使用しています。
それでサイト公開期間中に何か不具合が起きたことはないので、このブログ記事でも紹介しているのですが、企業サイトでがっつりフォームを作るならPHP工房が安パイでしょうか。
お手軽に動くフォームを設置するのならGoogleフォームなのかなと思います。
ということで、ここまでお疲れさまでした☺️
追加で、自動返信メールなどを付与したい場合
GASを使うとGoogleフォームで自動返信メールなんかも実装できちゃいます。
アクセシビリティまで配慮したフォームコーディングはこちら
全部入力されてないと送信できない処理はこちら
Web制作者を目指す人向け厳選記事!
実務レベルまでの堅実なロードマップ公開中
Web制作の案件獲得方法はこちらから
実案件の進め方はこちら
HTML初心者からWordPress実案件レベルまでのコーディング演習課題を「専用ページ」にて公開しています。
- Figma,Photoshopデザインからのコーディング
- サーバーアップロードでサイト公開
- プロによる最大3回の表示確認特典
- レビュー返しは爆速
- 2024年にデザイン刷新!被らないポートフォリオ
「初級編」は初めてデザインからコーディングする方向け
「中級編」はJavaScriptやjQueryの練習
「上級編」はWordPressの実案件を模擬体験できるレベル感にしています。
中級者の方には高難易度課題を詰め合わせた「即戦力セット」も出しています。
全課題で「実務レベルの、プロの厳しいレビュー」を受けられるようにしています。
また、2024年には随時デザインの刷新をしており、完全リニューアル!!
他者と差をつけられるポートフォリオが準備できます!
制作会社も使用する専用レビューツールで分かりやすく添削していきます!
基本的に「まとめて購入」していただくとかなりお得になります↓
コーディングは書籍だけではなかなか実力がつかないので、実務レベルのレビューを受けて自身をつけたい人は是非挑戦してみてください!
\課題の購入はこちらから/
ご寄付を頂けると今後の更新の励みになります!