Date

Google FormをカスタマイズHTMLからFetch APIで送信する方法

  • Share on Hatena
  • Share on Twitter
  • Share on Facebook
Go back to top
目次 HTML で埋め込むメリット・デメリット メリット デメリット HTML でフォームを組む JS でフォームを送信 submit イベントにイベントリスナーを設定 URLSearchParams でパラメータの組み立て Fetch API でフォームの送信 まとめ

Google Form を カスタム HTML に埋め込み、JavaScript の Fetch API で送信する方法を紹介します。

デメリットが大きいですが、数週間など短期間なら要件次第で有用でしょう。

しかし Google Form の仕様変更で壊れるので、長期間使うならリスクが高いので避けましょう。実際に仕様変更が 2022 年にありました。

HTML で埋め込むメリット・デメリット

メリット

  • カスタム HTML なので、好きなデザインのフォームを組める
  • Google フォームを使っていないように見え、回答者に安心感がある
  • 簡単にフォームが構築できる

デメリット

  • Google フォームが公式にサポートしていないので、仕様変更で壊れる
  • js でフォームを送信に失敗してもハンドリングできない

HTML でフォームを組む

こちらを参考に Google Form の input 要素の name を抽出します。

<form action="https://docs.google.com/forms/u/0/d/e/xxxxxx/formResponse" method="POST" class="google-form" > <div> <label for="email">メールアドレス</label> <input id="email" type="email" name="" placeholder="example@example.co.jp" required /> </div> <button type="submit" name="button">送信</button> </form>

JS でフォームを送信

コード全文を先に紹介します。

function submitGoogleForm(e: Event) { e.preventDefault() const urlSearchParams = new URLSearchParams() const form = e.target as HTMLFormElement const inputs = form.getElementsByTagName('input') for (let i = 0; i < inputs.length; i++) { urlSearchParams.append(inputs[i].name, inputs[i].value) } fetch(form.action, { method: form.method, mode: 'no-cors', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: urlSearchParams.toString(), }).then((res) => console.log(res)) } const googleForm = document.getElementsByClassName('google-form') for (let i = 0; i < googleForm.length; i++) { googleForm[i].addEventListener('submit', submitGoogleForm) }

submit イベントにイベントリスナーを設定

まず、フォームにイベントリスナーを設定し、フォーム送信時に関数が実行されるようにします。汎用性を考えてgoogle-formというクラスをフォームにつけています。

そして関数の最初 e.preventDefault() でフォームの内容を指定した URL へ送信するというデフォルトの動作をキャンセルします。

function submitGoogleForm(e: Event) { e.preventDefault() // 処理 } const googleForm = document.getElementsByClassName('google-form') for (let i = 0; i < googleForm.length; i++) { googleForm[i].addEventListener('submit', submitGoogleForm) }

URLSearchParams でパラメータの組み立て

URL のクエリー文字列の操作を行うURLSearchParamsインターフェイスがあるので、これを使います。直感的に key と value が追加でき、クエリー文字列に変換できます。

URLSearchParams - Web API | MDN

値を追加する方法は、URLSearchParams.append()URLSearchParams.set()の 2 種類があります。

URLSearchParams.append()は同じ key でセットしても上書きされませんが、URLSearchParams.set()は上書きされる違いがあります。

const urlSearchParams = new URLSearchParams() const form = e.target as HTMLFormElement const inputs = form.getElementsByTagName('input') for (let i = 0; i < inputs.length; i++) { urlSearchParams.append(inputs[i].name, inputs[i].value) }

Fetch API でフォームの送信

基本的には、Google フォームと異なるドメインからフォームを送るはずです。

しかしFetch APIは、セキュリティ上の理由から同一オリジンポリシーに従います。デフォルトだと以下のようなCORS エラーでリクエストが遮断されます。

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://some-url-here. (Reason: additional information here).

そこで、モードにno-corsを設定します。それによりCORS-safelisted methodsCORS-safelisted request-headersだけを使ったリクエストを送り、成功するとopaque filtered responseが返ってきます。

同一オリジンポリシーを無視してたデータが取得できるのは脆弱性に繋がるため、opaque filtered responseはデータがフィルタリングされています。type がopaqueとなり、status が0、body がnullとなり、エラーレスポンスと区別できないレスポンスになります。

body には、URLSearchParams.toString()でオブジェクトをクエリー文字列に変換した値を設定します。

fetch(form.action, { method: form.method, mode: 'no-cors', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: urlSearchParams.toString(), }) }

まとめ

Google Form を カスタム HTML に埋め込み、JavaScript の Fetch API で送信することは技術的には可能です。

しかしデメリットも大きいため、きちんと理解して使いましょう。