いいねボタンをQooQに適用するカスタマイズ例

更新  
公開
当サイトはアフィリエイト広告を使用しています

Blogger Google Apps Script QooQ web



こちらのページの内容をQooQに適用しました。

QooQはデフォルトでシェアボタンのまとまりが2つあります。

シェアボタンのならびに「いいねボタン」と「カウンター」を設置するカスタマイズです。

位置や色などはCSSで調整してください。...

目次

概要

「いいねボタン」と「カウンター」をそれぞれ2か所に設置。それぞれ連動できるようにする。(片方のボタンが押されたら、もう片方のボタンも反応する。)

事前準備

「いいね」の追加・集計にはGoogleスプレッドシート、Google Apps Scriptを利用します。

具体的なGoogleスプレッドシート、Google Apps Scriptは以下のものを使います。

Google Apps Scriptで簡単作成!ブログにいいねボタンを設置する方法-すたすた式

また、Google Apps Scriptは「デプロイ」という作業をします。「デプロイ」がはじめてという方はこちらも一読しておくと作業がスムーズです。

初心者向けGoogle Apps Scriptでウェブアプリをデプロイする方法・手順-すたすた式

HTML

シェアボタンの場所に「いいねボタン」と「カウンター」を追加します。

シェアボタンの場所:

        <b:includable id='shareButtons' var='post'>
<div class='single-share'>
  <a class='single-share-twitter' expr:href='&quot;https://twitter.com/intent/tweet?url=&quot; + data:post.canonicalUrl + &quot;&amp;text=&quot; + data:post.title' target='_blank' title='ツイッターでつぶやく'>t</a>
  <a class='single-share-facebook' expr:href='&quot;https://www.facebook.com/sharer/sharer.php?u=&quot; + data:post.canonicalUrl + &quot;&amp;t=&quot; + data:post.title' target='_blank' title='フェイスブックでシェア'>f</a>
  <a class='single-share-hatena' expr:href='&quot;http://b.hatena.ne.jp/add?mode=confirm&amp;url=&quot; + data:post.canonicalUrl' title='はてなブックマークに追加'>B!</a>
  <a class='single-share-pocket' expr:href='&quot;https://getpocket.com/edit?url=&quot; + data:post.canonicalUrl + &quot;&amp;title=&quot; + data:post.title' target='_blank' title='Pocketに保存'>P</a>
  <a class='single-share-line' expr:href='&quot;https://social-plugins.line.me/lineit/share?url=&quot; + data:post.canonicalUrl' target='_blank' title='LINEで送る'>L</a>
</div>
</b:includable>

「いいねボタン」と「カウンター」を追加:

       <b:includable id='shareButtons' var='post'>
<div class='single-share'>
  <a class='single-share-twitter' expr:href='&quot;https://twitter.com/intent/tweet?url=&quot; + data:post.canonicalUrl + &quot;&amp;text=&quot; + data:post.title' target='_blank' title='ツイッターでつぶやく'>t</a>
  <a class='single-share-facebook' expr:href='&quot;https://www.facebook.com/sharer/sharer.php?u=&quot; + data:post.canonicalUrl + &quot;&amp;t=&quot; + data:post.title' target='_blank' title='フェイスブックでシェア'>f</a>
  <a class='single-share-hatena' expr:href='&quot;http://b.hatena.ne.jp/add?mode=confirm&amp;url=&quot; + data:post.canonicalUrl' title='はてなブックマークに追加'>B!</a>
  <a class='single-share-pocket' expr:href='&quot;https://getpocket.com/edit?url=&quot; + data:post.canonicalUrl + &quot;&amp;title=&quot; + data:post.title' target='_blank' title='Pocketに保存'>P</a>
  <a class='single-share-line' expr:href='&quot;https://social-plugins.line.me/lineit/share?url=&quot; + data:post.canonicalUrl' target='_blank' title='LINEで送る'>L</a>
  <!--いいねボタンとカウンター-->
  <button id="upVoteButton" class="upvote-button" title="この記事にいいね" aria-label="この記事にいいね" aria-pressed="false" type="button">いいね</button>
  <div id="upVoteCounter" class="upvote-counter" aria-live="polite"></div>
</div>
</b:includable>

シェアボタンのまとまりは2か所ありますが変更箇所はこの1か所でOKです

JavaScript

gas_WebApps_URLのところにデプロイしたウェブアプリのURLをコピペしてください。

scriptURL = "gas_WebApps_URL",

scriptURL = "https://script.google.com/.../exec",

JavaScript:

/**
 * ボタンがクリックされたとき、記事のタイトルとURLをGoogle Apps Script(GAS)経由でスプレッドシートに書き込みます。
 * 書き込まれたURLは集計され、webサイトを開いたときにその集計された数が表示されます。
 *
 * QooQ用にカスタマイズ
 *
 * @param {Object} options - オプションオブジェクト
 * @param {string} options.buttonSelector - ボタン要素のID
 * @param {string} options.counterSelector - いいねの数を表示する要素のID
 * @param {string} options.scriptURL - GASスクリプトのURL
 */
/*! Copyright:2025 sutajp | Released under the MIT license | https://sutasutashiki.blogspot.com/p/mit-license.html */
function setupUpVote(options) {
  "use strict";
  const {
    buttonSelector = ".upvote-button",
    counterSelector = ".upvote-counter",
    scriptURL = "gas_WebApps_URL",
  } = options || {};

  const currentURL = window.location.origin + window.location.pathname;
  const upVoteButtons = document.querySelectorAll(buttonSelector);
  const upVoteCounters = document.querySelectorAll(counterSelector);

  // countを宣言
  let count = 0;
  let previousCount = 0; // エラー発生前のカウントを保持

  async function getUpVoteCount() {
    const param = { currentURL };
    const query = new URLSearchParams(param);

    try {
      const response = await fetch(`${scriptURL}?${query}`);

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      count = await response.json(); // グローバルなcountを更新

      upVoteCounters.forEach((counter) => {
        counter.textContent = count;
      });
    } catch (error) {
      console.error("Fetch Error:", error);
      upVoteCounters.forEach((counter) => {
        counter.textContent = "通信エラーが発生しました。";
      });
    }
  }

  async function sendTitleAndURL() {
    upVoteButtons.forEach((btn) => {
      if (btn.disabled) return;
      btn.disabled = true;
      btn.ariaPressed = true;
      const upVoteIcon = btn.querySelector(".upvote-icon");
      if (upVoteIcon) {
        upVoteIcon.dataset.disabled = true;
      }
    });
    previousCount = count; // エラー発生前のカウントを保存
    upVoteCounters.forEach((cnt) => {
      cnt.textContent = parseInt(cnt.textContent, 10) + 1; // 楽観的更新
    });

    const params = new URLSearchParams({
      sendTitle: document.title,
      sendURL: currentURL,
    });

    try {
      const response = await fetch(scriptURL, {
        method: "POST",
        headers: {
          "Accept": "application/json", //JSON形式のレスポンスを明示
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: params,
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      console.log("いいね送信成功");
    } catch (error) {
      console.error("Fetch Error:", error); // エラーオブジェクト全体を表示
      upVoteCounters.forEach((counter) => {
        counter.textContent = "通信エラーが発生しました。";
      });

      upVoteCounters.forEach((cnt) => {
        cnt.textContent = previousCount; // エラー発生前のカウントに復元
      });
    }
  }

  getUpVoteCount();

  upVoteButtons.forEach((button) => {
    button.addEventListener("click", sendTitleAndURL);
  });
}

setupUpVote();

メモ

ボタン、カウンターがそれぞれ2個あるのでdocument.querySelectorAll()でそれぞれ要素を取得。

forEach()で繰り返し処理。

設置場所など

下のようにJavaScriptを<b:if cond='data:view.isSingleItem'>ではさむと記事(投稿)のみでプログラムが実行します。

<b:if cond='data:view.isSingleItem'>
  <script>
    
  JavaScriptのコード

  </script>  
</b:if>

設置場所は</body>の上付近にしました。

コードの一番最後setupUpVote();でJavaScriptを実行しています。

bodyタグの上の方に設置する場合はsetupUpVote();を下のコードに書き換えることを検討してください。

document.addEventListener("DOMContentLoaded", function () {
  setupUpVote();
});


検索

お知らせ

カテゴリー

Random Picks

すたすた式

Enjoy!👍

QooQ