素人なりにGoogle Sitesにいいね！ボタンを配置してみた

# 概要

Google Siteに社内ページを運営していますが、社員がちゃんと見てくれるのか？とか気になるところです
また、見た人はコメントまでしたくないが、一応読んだよ！と反応したい人はいるはずです
そこで見たよ！の証として気軽に「いいね！」してもらえるように「いいね！」ボタンをつけたい思ったのがきっかけです

そして、つい先日初めてGoogle Apps Scriptを触って作った素人なので、とりあえず動くものを実装した程度のものです(;´･ω･)
なのでエラー処理してなかったり、コードの冗長化してたりしています
あととりあえず「いいね！」の回数をカウントアップだけしている状態で、同じ人がクリックしたらカウントダウンといった処理もない

せっかくなので、やった記録をメモとして残していきたいと思います
もし、なにかアドバイスや質問があればお気軽にコメント頂ければ幸いです

# 初めに

まずGoogle SitesにJavascriptゴリゴリ書けばいけるじゃん！？と思われる方もいるかと思いますが、、、
そう！Google SitesでJavascriptが書けないんです！
そこでいろいろ調べた結果以下のような構成ならイケるとわかりました

以下にてGoogle Apps Script･･･GASと省略します

## 構成

ガジェット(xxxx.xml) → → Google Sites
↓↑
GAS（Webアプリケーション）
↓↑
Google SpreadSheet（データ保存）

1．Google Sitesからガジェットを挿入
2．そのガジェットからGAS経由でSpreadSheetのデータ取得・更新

以下で各手順について説明します


# 1.いいね！のカウントを保存するためのSpreadSheetを作りましょう

以下のようにA1（キー値）とB1（カウント値）はタイトル行としてブックを作成してください
（2行目以降はボタンを押した時に自動追加されます。この段階では不要）
また、必要に応じてシート名も名前変えてください
最後にブックIDを控えといてください

![spreadsheet.png](https://qiita-image-store.s3.amazonaws.com/0/30522/fb5be3b9-a71c-2fec-556b-6c023196c92f.png)


# 2.SpreadSheetのデータを読み書きするためのWebアプリケーションとして動くGASを作りましょう

「ツール」-「スクリプトエディタ」
![menu-script.png](https://qiita-image-store.s3.amazonaws.com/0/30522/d6f0784a-7560-26b0-60ea-64148a7c82cc.png)


基本的にJavascriptを書く感じなので、書いたことがある方は抵抗なく書けるかと思います
リクエストを受け付ける関数とSpreadSheetのデータの更新と取得する関数をそれぞれ実装
プロジェクト名とファイル名は適当で構いません

[APIリファレンス](https://developers.google.com/apps-script/reference/spreadsheet/)

![gas.png](https://qiita-image-store.s3.amazonaws.com/0/30522/a16b29e3-5de0-3c8d-3571-c297e9576586.png)

「ブックID」は手順1で控えたブックIDに差し替えてください
「シート名」も同様です

```lang:main.gs

var BOOK_ID = 'ブックID';
var SHEET_NAME = 'シート名';

//取得用のリクエスト処理
function doGet(request) {
      
  var bookId = BOOK_ID;
  var sheetName = SHEET_NAME;

  try {
    var book = SpreadsheetApp.openById(bookId);
    
    var sheet = book.getSheetByName(sheetName);
    
    var key = request.parameters.key;
        
    var likeCount = getLikeCountByKey(sheet, key);
    
    var respJson = [{
      key: key[0],
      count: likeCount
    }];
    
    return ContentService.createTextOutput(JSON.stringify(respJson)).setMimeType(ContentService.MimeType.JSON);
  } catch (e) {
    Logger.log(e);
    return ContentService.createTextOutput(JSON.stringify(e)).setMimeType(ContentService.MimeType.JSON);
  }
}

//更新用のリクエスト
function doPost(request) {
    
  var bookId = BOOK_ID;
  var sheetName = SHEET_NAME;
  
  try {
    var book = SpreadsheetApp.openById(bookId);
    
    var sheet = book.getSheetByName(sheetName);
    
    var key = request.parameters.key;
    
    var likeCount = updateLikeCountByKey(sheet, key);
    
    var respJson = [{
      key: key[0],
      count: likeCount
    }];
  
    return ContentService.createTextOutput(JSON.stringify(respJson)).setMimeType(ContentService.MimeType.JSON);
  } catch (e) {
    Logger.log(e);
    return ContentService.createTextOutput(JSON.stringify(e)).setMimeType(ContentService.MimeType.JSON);    
  }
}


function getLikeCountByKey(sheet, key) {
  var count = 0;
    
  //シートが存在しない場合
  //シートが空の場合
  if(!sheet || sheet.getLastColumn() == 0.0 || sheet.getLastRow() == 0.0) {
    return count;
  }
  
  //対象のkeyのカウントを取得
  var lastRow = sheet.getLastRow();
  for(var rowIndex = 2; rowIndex <= lastRow; rowIndex++) {
    
    var range = sheet.getRange(rowIndex, 1, 1, 2);
    var values = range.getValues();
    if(values[0][0] == key) {
      count = values[0][1];
      break;
    }
  }
  
  return count;
}

function updateLikeCountByKey(sheet, key) {
  var count = 0;
    
  //シートが存在しない場合
  //シートが空の場合
  if(!sheet || sheet.getLastColumn() == 0.0 || sheet.getLastRow() == 0.0) {
    return count;
  }
  
  //対象のkeyのカウントを取得
  var lastRow = sheet.getLastRow();
  for(var rowIndex = 2; rowIndex <= lastRow; rowIndex++) {
    
    var range = sheet.getRange(rowIndex, 1, 1, 2);
    var values = range.getValues();
    if(values[0][0] == key) {
      count = values[0][1] + 1;
      //値を更新
      sheet.getRange(rowIndex, 2).setValue(count);
      return count;
    }
  }
  
  //対象のkeyがない場合は新規作成
  count = count + 1;
  sheet.getRange((lastRow + 1), 1).setValue(key);
  sheet.getRange((lastRow + 1), 2).setValue(count);
  
  return count;
}
```

## Webアプリケーションとしてのエンドポイントを取得

「公開」-「ウエブ アプリケーションとして導入」
![url.png](https://qiita-image-store.s3.amazonaws.com/0/30522/851e56d9-66c6-a4ce-2af2-d9e3bd5fb8d0.png)

* * *

アプリケーションにアクセスできるユーザを「**全員（匿名ユーザを含む）**」にしてください
ウエブアプリケーションのURLは控えてください
![setting.png](https://qiita-image-store.s3.amazonaws.com/0/30522/ced1ec77-beae-c0bd-7442-76498dfcdf9f.png)


## **ここ重要！**

私はここで無駄にハマりましたOrz
GASの使い方をよく理解していなかったのが問題ですが･･･
今後GASを修正したりすると思うんですが、**普通にコードを保存しただけでは公開されているサービスにそのコードは反映されません！**
んじゃ反映させるためには
**プロジェクトバージョンで「新規作成」を選択すること！**

![point.png](https://qiita-image-store.s3.amazonaws.com/0/30522/ac90e7cb-5b75-1d56-20b7-8932b8a6fac1.png)



# 3.必要なライブラリファイルをアップロード（公開）しましょう

後述のガジェット内で使うライブラリやJSファイルをGoogle Sitesから（S3、Box、OneDriveなどなど）参照できるように公開しましょう
今回はGoogle Sitesの添付ファイルにアップロードする形で説明します

アップロードしたファイル：
　likebutton.xml･･･ガジェットのファイル
　likebutton.js･･･ガジェットのJSファイル（データ通信、更新）
　bootstrap.min.css･･･ボタンのスタイルのみのCSS
　thumbs-up.png･･･いいね！アイコン画像
　jquery-2.2.4.min.js･･･jquery

　likebutton.jsはGASとガジェットの通信をコントロールする部分
　コードは下部リポジトリを参照してください

![upload.png](https://qiita-image-store.s3.amazonaws.com/0/30522/fa1e3c52-2ac6-d91d-f15c-ba324dec7bd8.png)


# 4.ガジェットを作りましょう

以下が「いいね！」ボタン本体です。
手順1で公開したライブラリやJSファイルを読み込む（URLは適宜に書き換えてください）

**設置数分のガジェットを作成する必要があります**
（クリックイベントのパラメータが共通化できなかったため･･･）
複数設置する場合はソース内の**key1**をすべて変更してください
getLikeCountやclickイベントで渡すパラメータ値（key1）はすべての「いいね！」ボタンの中で**一意**である必要があります

**1ページに1つのみ設置する場合はURLをパラメータ（キー値）にすれば設置数分のガジェットを作る必要はない**

```lang:likebutton-key1.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
    <ModulePrefs title="Like Button" />
    <Content type="html">
        <![CDATA[
            <head>
                <link rel="stylesheet" href="google siteのベースURL/bootstrap.min.css"></link>
                <script src="google siteのベースURL/jquery-2.2.4.min.js"></script>
                <script src="google siteのベースURL/likebutton.js"></script>
                <script type="text/javascript">
                    $(document).ready(function(){
                        likeButton.getLikeCount('key1');
                    });
                </script>
            </head>
            <body>
                <button type="button" class="key1 btn btn-primary btn-sm" onclick="likeButton.click('key1');">
                    <img src="google siteのベースURL /thumbs-up.png" alt="like" class="like-icon" height="16px" width="16px" /> いいね！ <span class="count"></span>
                </button>
            </body>
        ]]>
    </Content>
</Module>
```

# 5.ガジェットを設置しましょう

ページの編集モードで「いいね！」ボタンを設置したいところでガジェットを挿入します
![gadgets.png](https://qiita-image-store.s3.amazonaws.com/0/30522/e589d564-4b54-0a1b-4249-ea7ace390ff0.png)


「URLを指定してガジェットを追加」で手順4でアップロードしたガジェットのURLを入力して追加
![gadget-url.png](https://qiita-image-store.s3.amazonaws.com/0/30522/8e1fe166-94d0-55c6-f4b7-ceeec95f313e.png)


表示関連の設定（おすすめ設定は以下です）
![gadget-view.png](https://qiita-image-store.s3.amazonaws.com/0/30522/4f212d2a-a029-f0eb-bc63-bdd4e49f772d.png)


# 6.確認

このようにボタンが表示され、カウントアップするようになりましたら完成です
サンプルコードではユーザの一意判定を行っていないので、何回でもクリックできてしまいます。。。
![preview.png](https://qiita-image-store.s3.amazonaws.com/0/30522/74e7cb61-5193-fd5b-006e-f2eb774a3d95.png)


# 7.サンプルコード

https://github.com/comefigo/likebutton-for-google-site


以上


最後までご覧に頂きましてありがとうございました
ここまで問題なく設置できましたでしょうか？
お役に立てれば幸いです