web制作

Googleフォームを静的サイトに埋め込みカスタマイズ【非同期通信Ajax】

本ページにはプロモーションが含まれています。

2023年8月20日追記:CORS制約について追記と、JavaScript版のコードも出しました。

こんにちは、フリーランスエンジニア歴6年のしょーごです。

みなさん静的サイトにフォームの埋め込みを行う際、これまで難儀しなかったでしょうか?

私は最初はフォームの実装方法がわからず、フォームのためにわざわざWordPressのContact Form 7を使うほどでした。

静的サイトのフォーム選択肢
  1. PHP工房
  2. Googleフォーム(今回はこれ!)
  3. Responsive Mailform

今回はこの中で「Googleフォームを使って自作フォームで送信する方法」を解説します。

前提条件

  • jQuery使用
  • 結構無理やり(コーポレートサイトよりかアンケート向き)

後述しますがデメリットもあるので、採用可否はよく判断してください。

しょーご

この記事を書いたのは
しょーご@samurabrass

このブログ「しょーごログ」の運営者。本業でエンジニアとしてサイト制作やシステム開発を数年行っており、ブログとYouTubeで情報発信を行っている。駆け出しエンジニアのコーディング課題添削も行う

\現役エンジニアのレビュー付き/

実践レベルのコーディング課題公開中

デザインカンプからのコーディング練習課題【オリジナルポートフォリオを準備できるようになりました】
販売ページはこちら
  • デザインカンプからのコーディングを経験したい
  • 現役エンジニアのレビューを受けてみたい
  • 即戦力級のポートフォリオを用意したい

2024年にデザインを完全リニューアルしています!

コーディングに自身をつけるにはプロからのレビューを貰うのが必須なため、制作会社も利用するレビューツールで添削をしています。

しょーごログ-コーディング課題のレビュー
レビューの様子

Web制作学習ロードマップにも取り入れているため、学習終了まで迷わず進むことが可能です。コーディングを本気で仕事したい方はぜひご活用ください!

無料の入門編から本格企業サイトまで/

この記事の反響

Googleフォームをサイトに埋め込む

デフォルトのGoogleフォームをそのまま埋め込むとUXが微妙なのですが、実はフロントエンドのみの自作フォームでもGoogleフォームと紐づければ送信できるようになります。

以下のような見た目だけのHTMLフォームでも、

Googleフォームと連携させれば、送信することで非同期で画面遷移させずに、完了メッセージを出すことができます。

もちろん完了画面にも遷移させられます。

ゴール:Googleフォームで静的サイトのフォームを動くようにする

この記事を読んでできるようになること

  • Googleフォームと自社サイトフォームの紐付け
  • 送信完了後、同ページに「お問い合わせありがとうございました」のメッセージが出せる
  • サンクスページに遷移できる
しょーご

自社サイトにバックエンド不要で手軽にフォームが実装できるようになります!!

Googleフォームを作る

まずはGoogleフォームの作成をします。

ドメインがeditだとformが見つけられないため、ドメイン末尾が「viewform」となっていることを確認ください。

googleフォーム
作成画面の場合、フォーム右上のプレニューより参照してください
googleフォーム作成

HTMLフォームで作る予定のものと、当然同じものを作ります

Googleフォームのinputのnameとformのaction先のURLをメモる

まずはわかりやすいようにフォームに適当に値を入れておきます。

値を入れておいた方が検証しやすいので、必ず入れてください。

googleフォーム name 場所

chromeの検証機能で探します(Windowsの場合Ctrl + F、Macの場合⌘+Fで検索バーが出ます

検証ツールでinputまたはentry.と入力し、確認してください。

①inputの場合

Googleフォーム name 場所

②entry.の場合

googleフォーム name 場所

actionの値も押さえる

googleフォーム action
actionの値も確認、送信先はactionに入っているため

この数字の部分が自作フォームのnameに入ることになるので、actionの値と共に、メモしておいてください。

メールアドレスが見つからない場合

「メールアドレスを収集する」の場合、input群の一番下にname=”emailAddress”で格納されています。

googleフォーム name 場所

まだnameを探せない人用図解

Googleフォームを静的サイトに埋め込みカスタマイズ【非同期通信Ajax】
Googleフォームを静的サイトに埋め込みカスタマイズ【非同期通信Ajax】
valueはフォームに入力した値を連動している

検証ツールでの検索に慣れましょう!!。
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エラーは学校の規則のようなもので、他の学校の教室に勝手に入ることは通常許可されていませんが、特別な許可があれば入ることができるのと似ています。

CORSポリシーに沿うと、Access-Control-Allow-Originを設定しないといけないのですが、CORSエラーが発生した場合でもFormの内容自体はしっかりとGoogle Formへ送られているので今回は良しとしました。

ステータスコード0で成功、200でfalseの補足

本来は、HTTP 200番台 Success(成功レスポンス)は、クライアントからリクエストがサーバに送られ理解されて受理された状態で、falseではないはずです。

しかし、ブラウザがクロスオリジンのリクエストに対して正しいCORSヘッダーを受け取らない場合、実際のHTTPステータスコード(たとえば200)を返す前にリクエストをブロックします。

この場合、AJAXリクエストのステータスコードとして0が返されます。

ステータスコード0と200
  • ステータスコード 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つのどれかです。

CORS制約の回避方法3つ
  1. サーバーサイドのプロキシを使用する: 自分のサーバーにエンドポイントを作成し、そのエンドポイントにデータをPOSTします。次に、サーバーサイドのコードはGoogle Formにデータを転送します。この方法で、ブラウザは直接Google Formにリクエストを送信するのではなく、自分のサーバーにリクエストを送信します。そのため、CORS制約は回避されます。
  2. JSONPを使用する: JSONPはCORS制約を回避する古いテクニックですが、セキュリティ上の懸念があり、今日の多くのシナリオで推奨されていません。また、すべてのサービスやAPIがJSONPをサポートしているわけではありません。
  3. CORSヘッダーを設定する: これはGoogle Formのエンドポイントに直接アクセス権を持っている場合にのみ可能です。しかし、Google FormはユーザーにCORSヘッダーの設定を許可していないので、この方法は使用できません。

最も実用的なのは、オプション1(サーバーサイドのプロキシを使用する)です。自分のサーバーにエンドポイントを設定し、クライアントからのリクエストを受け取り、それをGoogle Formに転送することでCORSの問題を回避できます。

しょーご

ブラウザから直にリクエストを送らなければいいと。

とはいえ、サーバー建てるのがめんどくさいからGoogle Form使ってるねんって感じなんですが。

受託制作では相手と確認を協力すること!!

案件では、相手にGoogleフォームを作ってもらう必要があります。
ほんの少し、相手のITリテラシーが必要かもです。

また、必ず受託制作の場合は、クライアントと自分両者で目視で、Googleフォームに回答が届いているか、確認してください!

Googleフォームを静的サイトに埋め込みカスタマイズ【非同期通信Ajax】
しょーご

フォーム周りの動作は、実案件では最重要レベルのチェック事項です。

【まとめ】Googleフォームは静的サイトで軽く使いたい場合に

今回は、Googleフォームを静的サイトに埋め込みajaxでカスタマイズする方法を解説しました。

CORS制約があり、案件で大事なフォームを扱うにはちょっと怖いですかね…

しょーご

対企業に使うなら、プロキシサーバーを立てるのが良さげで、これならCORS制約を受けず、正常なステータスコードが得られます。

私はこれまで期間限定のアンケートサイトなどで、Googleフォームの集計機能が便利ということで何度かプロキシサーバーを建てず、この記事のコードを実案件で使用しています。

それでサイト公開期間中に何か不具合が起きたことはないので、このブログ記事でも紹介しているのですが、企業サイトでがっつりフォームを作るならPHP工房が安パイでしょうか。

お手軽に動くフォームを設置するのならGoogleフォームなのかなと思います。

ということで、ここまでお疲れさまでした☺️

追加で、自動返信メールなどを付与したい場合

GASを使うとGoogleフォームで自動返信メールなんかも実装できちゃいます。

アクセシビリティまで配慮したフォームコーディングはこちら

全部入力されてないと送信できない処理はこちら

Web制作者を目指す人向け厳選記事!

実務レベルまでの堅実なロードマップ公開中

Web制作の案件獲得方法はこちらから

実案件の進め方はこちら

即戦力になれるコーディング課題

HTML初心者からWordPress実案件レベルまでのコーディング演習課題を「専用ページ」にて公開しています。

デザインカンプからのコーディング練習課題【オリジナルポートフォリオを準備できるようになりました】
  1. Figma,Photoshopデザインからのコーディング
  2. サーバーアップロードでサイト公開
  3. プロによる最大3回の表示確認特典
  4. レビュー返しは爆速
  5. 2024年にデザイン刷新!被らないポートフォリオ

初級編」は初めてデザインからコーディングする方向け
中級編」はJavaScriptやjQueryの練習
上級編」はWordPressの実案件を模擬体験できるレベル感にしています。

中級者の方には高難易度課題を詰め合わせた「即戦力セット」も出しています。

全課題で「実務レベルの、プロの厳しいレビュー」を受けられるようにしています。

また、2024年には随時デザインの刷新をしており、完全リニューアル!!

他者と差をつけられるポートフォリオが準備できます!

コーディング課題 中級 中級Ex
しょーご

制作会社も使用する専用レビューツールで分かりやすく添削していきます!

基本的に「まとめて購入」していただくとかなりお得になります↓

コーディング課題
まとめて購入

全部盛りこちらから
中級以上こちらから
即戦力編こちらから

コーディングは書籍だけではなかなか実力がつかないので、実務レベルのレビューを受けて自身をつけたい人は是非挑戦してみてください!

しょーごログ-コーディング課題のレビュー
レビューの様子

\課題の購入はこちらから/

応援して頂ける方へ

ご寄付を頂けると今後の更新の励みになります!

🍺 ビールをプレゼントする

あなたに是非読んでほしい記事です!
});