編集

Google Apps ScriptとGoogleスプレッドシートを使っていいねボタンを作る

2023/12/227
いいねのアイコンとスプレッドシートに数字1が保存されている画像

Bloggerにいいねボタンを作りたい

Bloggerには、記事を応援するいいねボタンがありません。ボタンを押してくれた数を記録していく必要があるので、簡単には実装できず難しいのですが、Google Apps Script (GAS)を使うとそれが出来るという情報を手に入れたので、作りました。全部完成させるのはプログラミング素人の私には本当に難しかったです。でも先人の知恵のおかげでなんとかたどり着けました。この記事は少しずつ完成させたので段落を追うと作りがわかる様になっていると思います。最初に完成したコードを全部貼り付けておこうと思います。一応、この記事の読者はHTMLやJavaScriptについてある程度の知識があるか、調べればわかる能力のある程度の人が望まれます。

完成したコード

Blogger側(HTML)

<!--ボタンアイコンの定義-->
<symbol id='like' viewBox='0 0 122.88 106.16'><path d='M4.02,44.6h27.36c2.21,0,4.02,1.81,4.02,4.03v53.51c0,2.21-1.81,4.03-4.02,4.03H4.02 c-2.21,0-4.02-1.81-4.02-4.03V48.63C0,46.41,1.81,44.6,4.02,44.6L4.02,44.6zM63.06,4.46c2.12-10.75,19.72-0.85,20.88,16.48 c0.35,5.3-0.2,11.47-1.5,18.36l25.15,0c10.46,0.41,19.59,7.9,13.14,20.2c1.47,5.36,1.69,11.65-2.3,14.13 c0.5,8.46-1.84,13.7-6.22,17.84c-0.29,4.23-1.19,7.99-3.23,10.88c-3.38,4.77-6.12,3.63-11.44,3.63H55.07 c-6.73,0-10.4-1.85-14.8-7.37V51.31c12.66-3.42,19.39-20.74,22.79-32.11V4.46L63.06,4.46z'/></symbol>
<symbol id='liked' viewBox='0 0 122.88 106.16'><path d='M4.02,44.6h27.36c2.21,0,4.02,1.81,4.02,4.03v53.51c0,2.21-1.81,4.03-4.02,4.03H4.02 c-2.21,0-4.02-1.81-4.02-4.03V48.63C0,46.41,1.81,44.6,4.02,44.6L4.02,44.6zM63.06,4.46c2.12-10.75,19.72-0.85,20.88,16.48 c0.35,5.3-0.2,11.47-1.5,18.36l25.15,0c10.46,0.41,19.59,7.9,13.14,20.2c1.47,5.36,1.69,11.65-2.3,14.13 c0.5,8.46-1.84,13.7-6.22,17.84c-0.29,4.23-1.19,7.99-3.23,10.88c-3.38,4.77-6.12,3.63-11.44,3.63H55.07 c-6.73,0-10.4-1.85-14.8-7.37V51.31c12.66-3.42,19.39-20.74,22.79-32.11V4.46L63.06,4.46z'/><path d='M4.43,63.63c-2.869-2.755-4.352-6.42-4.427-10.11c-0.074-3.689,1.261-7.412,4.015-10.281 c2.752-2.867,6.417-4.351,10.106-4.425c3.691-0.076,7.412,1.255,10.283,4.012l24.787,23.851L98.543,3.989l1.768,1.349l-1.77-1.355 c0.141-0.183,0.301-0.339,0.479-0.466c2.936-2.543,6.621-3.691,10.223-3.495V0.018l0.176,0.016c3.623,0.24,7.162,1.85,9.775,4.766 c2.658,2.965,3.863,6.731,3.662,10.412h0.004l-0.016,0.176c-0.236,3.558-1.791,7.035-4.609,9.632l-59.224,72.09l0.004,0.004 c-0.111,0.141-0.236,0.262-0.372,0.368c-2.773,2.435-6.275,3.629-9.757,3.569c-3.511-0.061-7.015-1.396-9.741-4.016L4.43,63.63 L4.43,63.63z' fill='DarkSlateBlue'/></symbol>

<!--ボタン記載エリア-->
        <div class='sns-share-buttons'>いいねボタンはログイン不要で押せます&#12290;お気軽にどうぞ&#65281;リンクのアイコンはコピーボタンです&#12290;記事のタイトルとURLがコピーできます&#12290;
            <br/>最後まで読んでくださったあなたにいいことがありますように&#65281;&#65281;</div>
  <div class='sns-share-buttons'>
      <form action='WebアプリのURL' method='POST' name='likePostData' style='display:none' target='hidden_iframe'>
        <input expr:value='data:post.title + &quot; | &quot; + data:post.url' id='titleURL' name='titleURL' readonly='readonly' type='text'/>
        <iframe name='hidden_iframe'/>
  </form>
      <button id='likeBtn' title='この記事に いいね する'><svg aria-label='いいね' class='svg'><use href='#like'/></svg></button>
      <span id='likeSpan'/>
<!--JavaScriptエリア-->
<script>/*<![CDATA[*/
let likeSpan, likeBtn, likeInput, titleURL, n;

    likeSpan = document.getElementById("likeSpan");
    likeBtn = document.getElementById("likeBtn");
    likeBtn.addEventListener("click", likeSubmit);
    likeInput = document.getElementById("titleURL");
    titleURL = likeInput.value;
    const param = {titleURL};
    const query = new URLSearchParams(param);
fetch(`WebアプリのURL?${query}`)
  .then(response => response.json())
  .then(likeJson => {
count = likeJson.likeCount;
likeSpan.innerHTML = count;
});

function likeSubmit(){
    n = likeSpan.innerHTML;
    n++;
    likeSpan.innerHTML = n;
    likeSpan.classList.add("liked");
    likeBtn.disabled = true;
    likeBtn.innerHTML='<svg aria-label="いいね済みです" class="svg"><use href="#liked"/></svg>';
    likeBtn.title="あなたにいいことありますように!";
    document.likePostData.submit();
}
/*]]>*/</script>

GAS

/*いいね送信用POST*/
function doPost(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  sheet.insertRowBefore(1);
  sheet.getRange(1,1).setValue((new Date).toLocaleString('ja-JP'));
  sheet.getRange(1,2).setValue(e.parameter.titleURL);
}

/*いいね数検索用GET*/
function doGet(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
  const lastRow = sheet.getLastRow();
  const titleArray = sheet.getRange(2,1,lastRow-1,1).getValues().flat();
  const likeArray = sheet.getRange(2,2,lastRow-1,1).getValues().flat();
  const titleURL = e.parameter.titleURL;
  const postIndex = titleArray.indexOf(titleURL);

  let likeCount;
    if (postIndex >= 0) {
      likeCount = likeArray[postIndex]
    }else{
      likeCount = 0
    };

  const obj = {
    titleURL,
    likeCount
  }

  JSONData = JSON.stringify(obj, null, 2);
  return ContentService.createTextOutput(JSONData).setMimeType(ContentService.MimeType.JSON);
}

始めたきっかけ

これをやりたいと思ったのは、F-lightの作者であるふじやんさんのブログ、ふじろじっくに、そのものズバリの記事、いいねボタンを導入しましたがあるのを発見したからです。このアイディアは「さめ」さんという方が運営されているブログ、水面下でごちゃごちゃ言ってく雑記ブログの「【Blogger】いいねボタンを Google フォームを改造して作る」という記事から作成されたものだそうです。リンクはこちら。

【Blogger】いいねボタンを Google フォームを改造して作る

【Blogger】いいねボタンを Google フォームを改造して作る

以前、このブログで 【Blogger】リアクションウィジェットを Google フォームを改造して作る という記事を書いた。 上の記事のあとがきにも書いているけれど、そもそもリアクションは「いいね!」だけでもいいんじゃないかと思った。 そこで、いいねボタンを Google フ...

基本的にこれを参考にさせていただいてやっていくのですが、Googleフォームを使ってやっている事が気になりました。別にGoogleフォームを使わずともできる、ということと、Googleフォームを使わずスプレッドシートに直接保存する方がプログラミングっぽくて面白そうだったので、そちらでやってみたいと思います。

まずはボタンを作るHTML

ふじろじっくで使われていたいいねボタンをまんま使わせていただきました。ご本人に確認したところ、ボタンに使われているアイコンはフリー素材なので、帰属表記もなしで使って良いと言うことでした。一応ライセンスは確認しましたが、犯罪に使うことや、自分が著作権者であると主張することなどを除けばほぼ自由に使って良いようです。便利なサービスがあるんですねえ。
帰属表記なしでいいのですが、感謝の気持ちを込めて、今回使わせていただくフリー素材の提供元をご紹介しておきます。

Free icons for website with commercial use no attribution PNG and SVG Vector Free Download

Free icons for website with commercial use no attribution PNG and SVG Vector Free Download

Free icons for website with commercial use no attribution PNG and SVG free use any commercial projects no attribution required.

ほとんど自由に使わせてもらえるようですが一応、禁止事項がゼロではなかったのでUXWingのライセンスページも合わせてリンクを貼っておきます。

いいねボタン以外のFacebookやLINEなどのSNSアイコンはだいたい削除して、記事のアドレスコピーボタンのみ残しました。F-lightでは、SNS関係のボタンは<div class='sns-share-buttons'>と言うタグ内部に記載されています。ですからテーマの編集でこのdiv class='sns-share-buttons'という文字列を検索すれば見つけることができます。私は必要なさそうな記述は、丸ごと削除してしまいましたがもしかしたら記述を残しておきたいと感じる人もいるかもしれません。そのような場合は、例えばspan class='facebook'と書いてある所のすぐ後に半角スペースを空けてstyle="display:none"と入れれば記述を非表示にすることができると思います。

ボタンのアイコンはこんな感じです。

ボタンのSVGパスと、ボタンのHTMLを記述しておきます。親指を立てているアイコンにはlike、それにチェックマークが入ったアイコンにはlikedと言うIDをそれぞれつけています。これにより、後からIDを記載するだけでアイコンの呼び出しが可能となります。

<symbol id='like' viewBox='0 0 122.88 106.16'><path d='M4.02,44.6h27.36c2.21,0,4.02,1.81,4.02,4.03v53.51c0,2.21-1.81,4.03-4.02,4.03H4.02 c-2.21,0-4.02-1.81-4.02-4.03V48.63C0,46.41,1.81,44.6,4.02,44.6L4.02,44.6zM63.06,4.46c2.12-10.75,19.72-0.85,20.88,16.48 c0.35,5.3-0.2,11.47-1.5,18.36l25.15,0c10.46,0.41,19.59,7.9,13.14,20.2c1.47,5.36,1.69,11.65-2.3,14.13 c0.5,8.46-1.84,13.7-6.22,17.84c-0.29,4.23-1.19,7.99-3.23,10.88c-3.38,4.77-6.12,3.63-11.44,3.63H55.07 c-6.73,0-10.4-1.85-14.8-7.37V51.31c12.66-3.42,19.39-20.74,22.79-32.11V4.46L63.06,4.46z'/></symbol>
<symbol id='liked' viewBox='0 0 122.88 106.16'><path d='M4.02,44.6h27.36c2.21,0,4.02,1.81,4.02,4.03v53.51c0,2.21-1.81,4.03-4.02,4.03H4.02 c-2.21,0-4.02-1.81-4.02-4.03V48.63C0,46.41,1.81,44.6,4.02,44.6L4.02,44.6zM63.06,4.46c2.12-10.75,19.72-0.85,20.88,16.48 c0.35,5.3-0.2,11.47-1.5,18.36l25.15,0c10.46,0.41,19.59,7.9,13.14,20.2c1.47,5.36,1.69,11.65-2.3,14.13 c0.5,8.46-1.84,13.7-6.22,17.84c-0.29,4.23-1.19,7.99-3.23,10.88c-3.38,4.77-6.12,3.63-11.44,3.63H55.07 c-6.73,0-10.4-1.85-14.8-7.37V51.31c12.66-3.42,19.39-20.74,22.79-32.11V4.46L63.06,4.46z'/><path d='M4.43,63.63c-2.869-2.755-4.352-6.42-4.427-10.11c-0.074-3.689,1.261-7.412,4.015-10.281 c2.752-2.867,6.417-4.351,10.106-4.425c3.691-0.076,7.412,1.255,10.283,4.012l24.787,23.851L98.543,3.989l1.768,1.349l-1.77-1.355 c0.141-0.183,0.301-0.339,0.479-0.466c2.936-2.543,6.621-3.691,10.223-3.495V0.018l0.176,0.016c3.623,0.24,7.162,1.85,9.775,4.766 c2.658,2.965,3.863,6.731,3.662,10.412h0.004l-0.016,0.176c-0.236,3.558-1.791,7.035-4.609,9.632l-59.224,72.09l0.004,0.004 c-0.111,0.141-0.236,0.262-0.372,0.368c-2.773,2.435-6.275,3.629-9.757,3.569c-3.511-0.061-7.015-1.396-9.741-4.016L4.43,63.63 L4.43,63.63z'/></symbol>

<button id='likeBtn' title='この記事に いいね する'><svg aria-label='いいね' class='svg'><use href='#like'/></svg></button>
<span id='likeSpan'></span>

とりあえずここまでで、ボタンが作られた状態となるわけですね。ボタン内部はSVGのID、#likeを指定しています。ボタンの直後に書いてあるspanタグの中に、今まで押されたいいねの合計数が表示されるようにしていきたい形です。ボタンの大きさや囲みなどは人それぞれだと思うのでCSSは省略します。このサイトのソースコードからCSSを真似てもらってもいいですし、その他にもおしゃれなボタンは世間に沢山出ていますので参考にしてください。ボタンのHTMLは先ほどの<div class='sns-share-buttons'>タグの中に書いていきました。

ボタンをクリックしたら数字が1足される様にする

ボタンが押されたらいいねの数を1追加するJavaScriptを追加していきます。

<script>/*<![CDATA[*/
let likeSpan, likeBtn, n;

    likeSpan = document.getElementById("likeSpan");
    likeBtn = document.getElementById("likeBtn");
    likeBtn.addEventListener("click", likeSubmit);
    
function likeSubmit(){
    n = likeSpan.innerHTML;
    n++;
    likeSpan.innerHTML = n;
    likeSpan.classList.add("liked");
    likeBtn.disabled = true;
    likeBtn.innerHTML='';
    likeBtn.title="あなたにいいことありますように!";
}
/*]]>*/</script>

likeSpanはいいねの合計数が書かれる部分です。likeBtnは先ほどのボタンですね。likeSpanの値をnに代入して計算していくのですが、少しずつ完成させるのでまずは何も入っていない状態です。現在のいいね数が読み取られていたら、その数字が入ります。何も入っていない状態で読み取られると、0を読み取ったのと同じことになります。これがJavaScriptのn++の部分で1加えられ、ボタンがlikeBtn.disabledの部分で無効化され、SVGも#likedに変更される仕組みです。この部分はあくまでもユーザに数字が1増えたことを見せるための部分であって、実際の送信は別の方法で行うことになります。なお、likeSpan.classList.add("liked")は装飾用に付与したクラスです。機能的にはなくても成立します。同様に、いいね送信後のタイトルやsvg aria-labelなどはお好みで調整してください。

それと、<script>タグの後にある/*<![CDATA[*/と、</script>タグの前にある/*]]>*/はBlogger特有の記述でBloggerでは必要ですが通常のHTMLを使ったWebサイトでは不要です。有っても動くとは思います。流用する人で不要と感じた場合は適宜削除してください。

GoogleスプレッドシートをWebアプリにして、いいねが押されたタイトルを記録

ここからはこちらのサイトを参考にしていきます。

【作って学ぶ】GASとスプレッドシートでデータベースとWEBアプリケーションを作成する

【作って学ぶ】GASとスプレッドシートでデータベースとWEBアプリケーションを作成する

今回は、Google Apps Script (GAS)とスプレッドシートを用いてウェブアプリケーションを作成する方法を紹介します。HTMLで動作するサンプルコードとわかりやすい画像付き解説で紹介していますのでぜひご覧ください。

大変参考になるサイトです。Googleアカウントがあれば誰でもGoogleスプレッドシートは使えますので、Bloggerのユーザーであれば必ず使うことができるわけですね。これを応用すれば、お手軽Webサーバーの完成ですね。今回はいいねボタンを作るという比較的簡単な作業をやっていくわけですが、アイデア次第で活用法は無限大ですね。非常に高いポテンシャルが有ると思います。スプレッドシートを作ったら、GASでプログラミングをしてそのシートにデータが蓄積されていく様な形を作り、Webアプリ化を行えばBlogger側(Bloggerに限りませんが)からアクセスができる様になります。

ボタンが押されたらタイトルとURLを合体させた文字列を生成して、それを送り、保存していくことにします。単に、データの名前がかぶらないようにするだけであれば、アドレスだけでも充分なのですが、それだけでは、後からスプレッドシートを見たときにわかりにくいので、タイトルとURLを両方入れることにしました。スプレッドシートに行ったら、それをカウントするのはスプレッドシートそのものの機能でできます。

Googleスプレッドシートに送信(POST)、HTML側の作業

記事の方で送信用のformを作ります。

<form action='実行するWebアプリのURL' method='POST' name='likePostData' style='display: none;' target='hidden_iframe'>
<input expr:value='data:post.title + &quot; | &quot; + data:post.url' name='titleURL' readonly='readonly' type='text'/>
<iframe name='hidden_iframe'/>
</form>

HTMLに続きいいねボタン送信時のJavaScriptでフォームを送信します。

function likeSubmit(){
/*~~~中略~~~*/
    document.likePostData.submit();
}

GASを書いてデプロイしたら、そのURLに向けた非表示のformタグを作って、それを使って送信します。送信とは別にGETメソッドも使ってその場合の指示を分けたいのでこちらのいいねデータ送信はPOSTを使います。実行するWebアプリのURLは後々出てきます。なお、データの追記をしたいときには、通常POSTを使い、データの検索をしたいときには通常GETを使うので、そういった意味でも理にかなっています。inputタグの内容はBlogger独自タグによるものなので、他のサイトでは使えませんが、JavaScriptを利用すれば記事名とURLは生成できるはずなので、Blogger以外で行う場合はそちらを送信する様にしてもいいと思います。iframeは、送信時に別のページに行かない様にするためにformタグの中に作ります。フォーム送信を行うと、通常そのページに移動してしまうためです。インラインフレームはページの中のページと言う位置づけなので、移動先をインラインフレームにしておけばページから移動してしまうことがありません。あとはformタグに指定したnameを指定してsubmit()を付けることによって送信ができます。

Googleスプレッドシートに送信(POST)、スプレッドシートとGAS側の作業

フォームで送られた内容を、送信時刻付きでスプレッドシートに記録していきます。Googleスプレッドシートを開いたら適当な名前で保存し、シート1に保存される様にGoogle Apps Scriptを起動しましょう。

function doPost(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  sheet.insertRowBefore(1);
  sheet.getRange(1,1).setValue((new Date).toLocaleString('ja-JP'));
  sheet.getRange(1,2).setValue(e.parameter.titleURL);
}

Googleスプレッドシートの拡張機能から、Apps Scriptを選び、スクリプトを記載したら、デプロイを選んでウェブアプリとして公開します。公開先を全員(アドレスを知る世界中のすべての人々と言う事)にして行きます。権限承認の画面が出ますが、記事のいいね数は全て公開情報なので大丈夫でしょう。お手数ですが、Webアプリ作成の手順そのものの詳細は先ほどのリンク先を参照し、その通りに行ってください。

プログラムの説明です。まず最初の行でdoPostと言う関数を作ります。Google Apps Scriptの決まりでこの名前でないと動かないそうです。引数のeは、送られてきたデータを意味します。データには様々なものが付随してPOSTリクエストとして送られてきています。まずは現在開いているスプレッドシートの中で先頭のもの[0]を選択します。特に名前を変えていなければ、シート1です。次にsheet.insertRowBefore(1);で行番号1の前に行を挿入します。新しいPOSTリクエストが来たときに動かすわけですから、1行増やしてそこにデータを追記していくと言うわけです。その後で、日本時間に直した送信時刻を1行1列の部分、つまり新たなA1に入れます。送信内容から必要な、「いいねされた記事の名前とアドレス」を含むものだけを抽出する必要があります。名前はフォーム側でtitleURLとしました。この場合はe.parameter.titleURLがお目当てのデータになりますので、これを1行2列、つまり新たなB1に入力します。これをすることによって、普通にいいねボタンの機能がつくだけでなく、スプレッドシートに読者がいついいねしてくれたかも記録されるようになります。

これで、いいねボタンを押してみたらいいねと時刻が記録されていく様になります!!手製のプログラムが動くと言うのは嬉しいものですね!なお、一つ注意点として、Googleスプレッドシートは100万セルしか入れられない仕様がありますので、1記事につき1万以上もいいねがつくようなサイトではすぐにセルが枯渇することになります。その場合は送信時刻を入れたりせずにカウントだけするようなデザインにしなければならないでしょうね。このブログはそんなにいいねがつく事はあり得ないと思われますので、この方法でやっていきます。

いいねされた時刻とタイトルが記録されたスプレッドシート

これができたら、次はシート2を作って、そちらに1記事毎のいいねの合計数を計算する関数を入れていきましょう。

いいねタイトルの集計用のスプレッドシートで、A2の内容が書かれている。
いいねタイトルの集計用のスプレッドシートで、B2の内容が書かれている。

A1セルとB1セルはタイトルを書くことにしました。わかりやすい名前をつければいいと思います。A2セルには、=unique('シート1'!B:B)と記載します。こうすると、シート1のB列にたくさん有る記事名が、一つだけに並んでくれます。uniqueは、出たものは全て並べ、重複をなくす関数です。次に、B2セルに=ARRAYFORMULA(countif('シート1'!B:B,A2:indirect("A"&counta(A:A))))と記載します。複雑なのですが、一番内側から順に説明しますと、まずcountaで、このシートのA列の項目数を計算しています。例えばこの写真の例ならタイトルも含めて4つです。すると4という数字が返ってくるわけです。次のindirect("A"...の部分でセル名が作られます。この場合はA4セルができた形です。したがって、この前の部分と合わせて、A2からA4セルが範囲として指定された形になります。その前のcountifは、シート1のB列の内容から、先ほどまでで指定したA列の各文字列を探し、個数を返せ、という意味です。普通は全部のセルに個別に書かなければいけませんが、ARRAYFORMULAが使われている関係で、1回この数式を書くだけでA2からA4すべてのセルの内容について、数えてB2からB4のセルに書いてくれるわけです。この関数で、今後いいねがどこまで増えても、どの記事にいいねがついても、数を書き続けてくれます。COUNTAで行数を数え、最後のセルの番号を求める、INDIRECTでセルの名前にする、そしてARRAYFORMULAとCOUNTIFで先ほど作ったセル範囲でどこまでも続けてシート1の記事タイトルを数えていく…という形、理解しづらいと思うのですが、これが理解できると気持ちがいいです。

これでいいねの記録と個数のカウントができましたので、次はGETリクエストを記載していきます。

GETリクエストを送っていいね数を取得する、GAS側の作業

先ほどのGASにGETリクエストを受けた時の内容を書いていきます。

function doGet(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
  const lastRow = sheet.getLastRow();
  const titleArray = sheet.getRange(2,1,lastRow-1,1).getValues().flat();
  const likeArray = sheet.getRange(2,2,lastRow-1,1).getValues().flat();
  const titleURL = e.parameter.titleURL;
  const postIndex = titleArray.indexOf(titleURL);

  let likeCount;
    if (postIndex >= 0) {
      likeCount = likeArray[postIndex]
    }else{
      likeCount = 0
    };

  const obj = {
    titleURL,
    likeCount
  }

  JSONData = JSON.stringify(obj, null, 2);
  return ContentService.createTextOutput(JSONData).setMimeType(ContentService.MimeType.JSON);
}

GETリクエストは、function doGet(e)という関数で処理していきます。これも、この名前でないと受け付けてくれません。2行目では、doPostの時と同じ様にシート2を取得していきます。今回は[1]がシート2に当たります。getLastRow()で最終行の数字を取得します。先ほどの例で言うと4行ですので4ですね。次のtitleArraylikeArrayはタイトルといいね数をそれぞれ配列として取得しています。最後についている.flatはもともと二次元配列になってしまっている取得配列を、一次元配列にする効果があります。

二次元配列とは、配列の中の要素もまた配列の状態になっているということです。例えば、[あ,い,う]は一次元配列で、[[あ,い,う],[か,き,く],[さ,し,す]]は二次元配列です。配列の要素として、また配列が入っていますね。スプレッドシートを配列として取得すると、Googleスプレッドシートで使われるGASでは、通常何もしないと二次元配列になります。スプレッドシートは通常二次元ですからそのほうが都合がいいんでしょうね。ですから、スプレッドシートからスクリプトを使ってデータを抽出すると、たとえ1列だけのデータであっても[[あ,い,う]]のような二次元配列になってしまうのです。このままでは検索ができませんから、一次元配列にする必要があるというわけです。

その次に、Blogger側(HTML)から開かれたページのタイトルとアドレスを合体させた文字列がURLに載せて送られてくる(後述します)ので、送られてきた内容をe.parameter.titleURLで取得します。次にそのタイトルをタイトルの配列から検索します。indexOfを使うと検索ができます。

そのあと、likeCountという変数を定義してif...else文を書いています。タイトルといいね数は全てシート中で横並びですから、検索して出てきた番号を使って、いいね数の配列からいいね数を探し出せます。例えば、上の写真で言うと、ICLを受けた感想の記事がパラメーターとして送られてきた場合、配列の2番目ですから、その数字、インデックス1(JavaScriptでは先頭は0として数えるから、2個目はインデックス1)が変数postIndexに入るわけです。その数字を使って、likeArray[postIndex]でいいね数1がlikeCountに入ります。もしも該当する記事の記載がない場合は、次のelseの文で、likeCountの値は0となるわけです。

こうして必要なデータが揃ったら、objと言う名前をつけてデータを中括弧にくくって入れて、JSON形式にして送ります。

GETリクエストを送っていいね数を取得する、 Blogger(HTML)側の作業

いいね数をカウントして該当ページに表示するには、そのページのタイトルとURLを合体させた文字列で検索をする必要がありますよね。先ほども少し述べましたが、これはURLの末尾に、その様な文字列(クエリと言います)を追加し、それを開くことで実現します。例えば、xというクエリの値はaにして、yというクエリの値はbにして、という場合であれば、?x=a&y=bの様な形をURLの末尾に付けて開けば、クエリを送りつつWebアプリを開くことができます。Webアプリ側でクエリの内容を読み取って後は対応するデータを検索して返せばいいですね。ページを開いた時に対応するアドレス名を作ることは、既にいいね送信の時にやっています。いいねボタンで送信させる文字列をそのまま流用できるのです。

let likeInput, titleURL;
    likeInput = document.getElementById("titleURL");
    titleURL = likeInput.value;
    const param = {titleURL};
    const query = new URLSearchParams(param);
fetch(`WebアプリのURL?${query}`)
  .then(response => response.json())
  .then(likeJson => {
count = likeJson.likeCount;
likeSpan.innerHTML = count;
});

今までに出てきているのと同じような方法でtitleURLの文字列を抽出します。送りたい内容はずばりこれなのでこれをそのまま中括弧でくくってオブジェクトparamにします。送る内容は1つだけなので、オブジェクトはこれで終わりです。その次のnew URLSearchParams(param)を使えば、クエリとして送信できる文字列の完成です。あとは、その文字列をWebアプリのURLにつけ、情報を取得するためのfetchを使います。ドルマークと中括弧は変数の値をそのまま文字列にしてくれと言う意味で、バッククオートで囲んだ文字列内ではこの書式で変数の値を利用できます。これはテンプレートリテラルと言われる便利な手法です。

fetchの後の2回のthenは返ってきたJSONをオブジェクトとして利用できる様にし、その中のlikeCountの値、つまりいいね数の数値を取得しています。あとはlikeSpanの中に書き込むだけです。これで終わりですね。

参考にしたウェブサイト

配列を検索する方法はこちらを参考にしました。

Google Apps Scriptで配列の検索をするindexOfメソッドとlastIndexOfメソッド

Google Apps Scriptで配列の検索をするindexOfメソッドとlastIndexOfメソッド

Google Apps Scriptでスプレッドシートのデータを配列に格納して操作をする方法をお伝えしています。今回は配列を検索するindexOfメソッド、lastIndexOfメソッドの使い方です。


フォーム送信の仕方はこちらを参考にしました。

JavaScriptのsubmitイベントで、フォーム送信をコントロールしよう | 侍エンジニアブログ

JavaScriptのsubmitイベントで、フォーム送信をコントロールしよう | 侍エンジニアブログ

この記事では「 JavaScriptのsubmitイベントで、フォーム送信をコントロールしよう 」といった内容について、誰でも理解できるように解説します。この記事を読めば、あなたの悩みが解決するだけじゃなく、新たな気付きも発見できることでしょう。お悩みの方はぜひご一読ください。


こちらでいいねボタンの送信用のGASのコードを学びました。初めはPOSTメソッドで何が送られているのかなかなか理解できませんでしたが、このサイトは具体的に送られる内容をごく短いGASの記述で可視化してくれるようなヒントをくれました。最も助けられたサイトの一つです。

Google AppScriptでHTTP POST(doPost)を受け付ける最小コード (2022年夏) - Qiita

Google AppScriptでHTTP POST(doPost)を受け付ける最小コード (2022年夏) - Qiita

Google AppScriptでHTTP POSTを受け付ける方法は、ググればかなり出てきます。2021年頃の仕様変更(参考URL^1 ^2)によって console.log や Logger.…


fetchの使い方はこちらの二つを参考にしました。ここがおそらく最大のハードルだと思います。

JavaScriptのfetch()の基本的な使い方を分かりやすく解説

JavaScriptのfetch()の基本的な使い方を分かりやすく解説

JavaScriptを使ったAPI処理は色んな方法があり最近ではライブラリを使うことが当たり前になりました。しかし初学者の方からすると基本を知らない状態でライブラリを見てもさっぱりだったりします。一番基本的な関数としてfetchというものがJavaScriptにあり、こちらから理解すると大体のライブラリは使えるようになるので解説していきます。

fetchメソッドの基本的な使い方【クエリパラメータとリクエストボディの使い分け】

fetchメソッドの基本的な使い方【クエリパラメータとリクエストボディの使い分け】

undefined


スプレッドシートをGASで操作する文はこちらを参考にしました。

GASでSpreadsheetを操作する時に役立つ知識

GASでSpreadsheetを操作する時に役立つ知識

undefined


ARRAYFORMULAの使い方はこちらを参考にしました。使い方の複雑な関数で、この方の書かれた内容がほぼ私のやりたいことと同じだったので本当に助かりました!

Arrayformulaで値が入っている最終行までを対象にしたい

Arrayformulaで値が入っている最終行までを対象にしたい

日々Google Apps Scriptを書く中で、気づいたことや作ったものなどを更新しています。


作業そのものとはあまり関係ないですが、Webアプリは何度も微調整をして出すことが多いと思います。デプロイは新規作成もできますが、固定URLにしていくこともできます。固定URLにしないと無駄にプロジェクトが増えていってしまいます。やり方はこちらを参考にしました。

GoogleAppsScript(GAS)を固定URLでデプロイする方法

GoogleAppsScript(GAS)を固定URLでデプロイする方法

GoogleAppsScript(GAS)でデプロイしたあとで修正したものをデプロイするときは「新しいデプロイ」をします。新しいデプロイはURLも変わるのでURLを変えずに新しいデプロイを適用する方法です


最後に、JavaScript全般に関して、こちらの2サイトを記載しておきます。JavaScript入門とMDN(Mozilla Developer Network)です。結局困った時に一番見ているのはこの二つです。JavaScript入門はより初心者向け、MDNはプロ向けな感じがします。正直初心者にMDNはきついのでまずはJavaScript入門で調べてみるといいと思います。

JavaScript入門

JavaScript入門

JavaScript はクライアント側で実行されるオブジェクト指向型のスクリプト言語です。 JavaScript を用いることで、動的にWebページの内容を書き換えたりフォームに入力された内容をクライアント側でチェックしたりできます。ここでは JavaScript の使い方として JavaScript のプログラミングの方法をサンプルを用いて解説していきます。

開発者向けのウェブ技術 | MDN

開発者向けのウェブ技術 | MDN

オープンなウェブは、開発者に素晴らしい機会をもたらします。これらの技術を最大限に活用するには、それらの使い方を知る必要があります。以下に、ウェブ技術のドキュメントへのリンクがあります。

あとがき

長らく書きかけだった記事にたくさんのいいねありがとうございます。ログイン不要で気軽に感謝の気持ちを表せるのっていいですよね。Bloggerユーザーに限らず、Webサイトにいいねボタンをつけたい時はあると思いますのでそんな時にこの記事がお役に立てば幸いです。それでは!