Home_ja - s-aska/google-form-proxy GitHub Wiki

これはなんですか?

Google Form に対しあらゆるWebサイトから投稿できるようにする非公式プロダクトです。

注意

このプロダクトは Google Form の仕様変更によって将来突然動かなくなる可能性があります。

Google Form は iframe による埋め込みに対応しているので、iframe または Google Form へのリンクに切り替えて下さい。

使い方

サーバーにデプロイ

Heroku を使う場合は https://github.com/s-aska/google-form-proxy/ の Deploy to Heroku ボタンを使います。

既にProxyサーバーが提供されている場合、このステップはスキップします。

Google From でアンケートを作る

1. アンケート作成

https://docs.google.com/forms/u/0/ でアンケートを作成します。

質問をすべて 記述式 で作成し、保存します。

質問を 必須 にしたり 選択式 にすると正しく回答が記録されないことがあり危険です。

2. アンケートのフォームキーを控える

「プレビュー」から回答ページに遷移できます。

回答ページのURLは https://docs.google.com/forms/d/{フォームキー}/viewform となっています。

例)

https://docs.google.com/forms/d/1Qf48eC4C7-oknhHNzly/viewform

この 1Qf48eC4C7-oknhHNzly の部分が フォームキー です、控えておきます。

3. 質問のkeyを控える

回答ページでJavascriptコンソールを開いて以下をコマンドを実行します。 参考

var ds = document.querySelectorAll('input[name^="entry"]'); var s = ''; for (var i = 0; i < ds.length; i++) { ds[i].removeAttribute('jsname');s += ds[i].outerHTML + "<br>\n" }; s.replace(/hidden/g, 'text');

すると 回答欄に使うHTML が質問の数だけ上から順に出てきます、これを後で使うのでメモしておきます。

例)

<input type="hidden" name="entry.1070492133" jsname="L9xHkb">,
<input type="hidden" name="entry.1070492134" jsname="L9xHkb">,
<input type="hidden" name="entry.1070492135" jsname="L9xHkb">

4. オリジナルのアンケート回答画面を作る

下記のサンプルをベースに組みます。

<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.2.min.js" integrity="sha256-lZFHibXzMHo3GGeehn1hudTAP3Sc0uKXBXAzHX1sjtk=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
(function ($, window, document) {
$(document).ready(function(){
  var spinner = new Spinner();
  var form = $('form[data-form-key]');

  form.on('submit', function(e){
    e.preventDefault();

    var errors = [];
    var missing_labels = {};
    var missings = [];
    form.find('[required]').each(function(){
      var ele   = $(this);
      var name  = ele.attr('name');
      var val   = ele.attr('type') === 'radio'
                ? form.find('input[name="' + name + '"]:checked').val()
                : ele.attr('type') === 'checkbox'
                ? ele.is(':checked')
                : ele.val();
      if (!val) {
        var label = ele.data('label') || name;
        if (label in missing_labels) {
          return;
        }
        missing_labels[label] = true;
        missings.push(label);
      }
    });
    if (missings.length) {
      alert('右記の項目が未入力です。[ ' + missings.join(', ') + ' ]');
      return false;
    }

    var data = form.serialize();
    var formKey = form.data('form-key');
    spinner.spin(document.body);
    $.ajax({
      url: "https://google-form-proxy.herokuapp.com/" + formKey,
      data: form.serialize(),
      type: "POST",
      crossDomain: true,
      dataType: 'json'
    }).done(function(data){
      spinner.spin();
      alert('回答ありがとうございました。');
      location.href = form.data('return-url');
    }).fail(function(){
      spinner.spin();
      alert('回答は失敗しました。');
    });
  });
});
})(jQuery, window, document);
</script>
</head>
<body>
  <form data-form-key="フォームキー" data-return-url="回答後に移動するURL">
    回答欄エリア
    <button>回答</button>
  </form>
  <img src="https://google-form-proxy.herokuapp.com/" style="display:none">
</body>
</html>
4-1. フォームキーをform要素に指定

<form data-form-key="フォームキー"> のフォームキーを 2. で控えた フォームキー に置き換えます。

例)

<form data-form-key="1Qf48eC4C7NESlzdbMocq-oknhHNzly3IfFMBqO8qbCM">

4-2. 回答用の入力欄を質問の数だけ作る

3. で取得した 回答欄に使うHTMLhiddentext に変え、jsname を消します。

修正前)

<input type="hidden" name="entry.1070492133" jsname="L9xHkb">,
<input type="hidden" name="entry.1070492134" jsname="L9xHkb">,
<input type="hidden" name="entry.1070492135" jsname="L9xHkb">

修正後)

<input type="text" name="entry.1070492133">
<input type="text" name="entry.1070492134">
<input type="text" name="entry.1070492135">

これがオリジナルフォームの入力欄となります。

必須入力にしたい場合は requireddata-label を付けます。

ラジオボタンを必須入力にする場合、先頭の回答にだけ requireddata-label を付けます。

例)

質問1: 
  <input type="radio" name="entry.1070492133" required data-label="質問1"> 選択肢1
  <input type="radio" name="entry.1070492133"> 選択肢2<br>
質問2: <input type="text" name="entry.1070492134" required data-label="質問2"><br>
質問3: <input type="text" name="entry.1070492135" required data-label="質問3"><br>

※古いブラウザでは無視されます。

回答欄の説明や改行などは適時追加します。

例)

性別:
  <input type="radio" name="entry.1070492133" value="男性" required data-label="性別"> 男性
  <input type="radio" name="entry.1070492133" value="女性"> 女性<br>
好きな食べ物: <input type="text" name="entry.1070492134" required data-label="好きな食べ物"><br>
メールアドレス: <input type="text" name="entry.1070492135" required data-label="メールアドレス">

出来上がった回答欄を「回答欄エリア」に貼り付けます。

完成例
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.2.min.js" integrity="sha256-lZFHibXzMHo3GGeehn1hudTAP3Sc0uKXBXAzHX1sjtk=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
(function ($, window, document) {
$(document).ready(function(){
  var spinner = new Spinner();
  var form = $('form[data-form-key]');
  form.on('submit', function(e){
    e.preventDefault();

    var errors = [];
    var missing_labels = {};
    var missings = [];
    form.find('[required]').each(function(){
      var ele   = $(this);
      var name  = ele.attr('name');
      var val   = ele.attr('type') === 'radio'
                ? form.find('input[name="' + name + '"]:checked').val()
                : ele.attr('type') === 'checkbox'
                ? ele.is(':checked')
                : ele.val();
      if (!val) {
        var label = ele.data('label') || name;
        if (label in missing_labels) {
          return;
        }
        missing_labels[label] = true;
        missings.push(label);
      }
    });
    if (missings.length) {
      alert('右記の項目が未入力です。[ ' + missings.join(', ') + ' ]');
      return false;
    }

    var data = form.serialize();
    var formKey = form.data('form-key');
    spinner.spin(document.body);
    $.ajax({
      url: "https://google-form-proxy.herokuapp.com/" + formKey,
      data: form.serialize(),
      type: "POST",
      crossDomain: true,
      dataType: 'json'
    }).done(function(data){
      spinner.spin();
      alert('回答ありがとうございました。');
      location.href = form.data('return-url');
    }).fail(function(){
      spinner.spin();
      alert('回答は失敗しました。');
    });
  });
});
})(jQuery, window, document);
</script>
</head>
<body>
  <form data-form-key="1Qf48eC4C7-oknhHNzly" data-return-url="http://www.google.co.jp/">
    性別:
    <input type="radio" name="entry.1070492133" value="男性" required data-label="性別"> 男性
    <input type="radio" name="entry.1070492133" value="女性"> 女性<br>
    好きな食べ物: <input type="text" name="entry.1070492134" required data-label="好きな食べ物"><br>
    メールアドレス: <input type="text" name="entry.1070492135" required data-label="メールアドレス">
    <button>回答</button>
  </form>
  <img src="https://google-form-proxy.herokuapp.com/" style="display:none">
</body>
</html>
</body>
</html>

動作確認・設置

どこかにアップロードして動くか確かめ、デザインを整え、本命のサイトに設置します。

⚠️ **GitHub.com Fallback** ⚠️