こんにちは。海乃もずくです。
はてなブログにどうしてもポケモンのアクセスカウンターを設置したくてGASで頑張ってみたのでやり方を共有します。
無料ブログに設置できるアクセスカウンターの種類は限られてくるので、好きなデザインを使いたい方も多いと思います。
(デザイン自体は結構豊富ですが、キャラクター系なんかは自前じゃないとほぼないです。)
そんな人のお役に立てれば幸いです。
#・はじめに(作ったきっかけ)
こちらのサイトさんでアクセスカウンター用のアイコンを配布してくださっているのですが、どうやって設置するのかわからず。。。
どうやらホームページやWordPressならPHPとかで実装できるようですが、ファイルのアップロードが必要になるため無料ブログに置くことはできなさそう。
調べても無料ブログに設置する方法は全然出てきませんでした。
…GDriveとGASとGoogleAnalyticsを駆使すればいけそうな気がする(° ° )???
と言うわけで、こんな感じでサイドバーに設置してみました。(アクセス数が切ないですが)
ここに設置してます→もずくのブログ
ざっくり言うとGASでGoogleAnalyticsのデータを引っ張ってきて画像を並べたhtmlを出力し、それをはてなブログ側でiframeで表示しています。
まずはやり方だけ簡単に説明して、最後に解説など書いてみようと思います。
あまり詳しくない人でも設置できるように書いたつもりなのでちょっと長いかもしれません。
慣れている人は読み飛ばしつつお付き合い下さい。
#・作り方解説
##①(準備)アクセスカウンターに使う画像素材を用意する
まずはカウンター用の数字アイコン画像を用意しましょう。
冒頭でも書きましたが、私はこちらから頂いてきました。
保存した画像をGoogleDriveにアップロードします。
フォルダーとかはどこでも構いません。私はわかりやすいようにcounter_imgフォルダを作ってひとまとめにしておきました。
デフォルトでは「制限付き」になっているので、「リンクを知っている全員」に変更します。
画像のリンクを取得すると下記のようになっていると思います。
https://drive.google.com/file/d/【ID】/view?usp=sharing
【ID】のところの英数字の羅列を控えておきます。
面倒ですが0から9までの画像全て控えます。
##②GoogleAppsScriptで新しいプロジェクトを作成
GoogleAppsScriptでプロジェクトを作成します。
全く使ったことがない方はこちら(外部サイト)↓を参考に作ってみてください。
(今回はスプレッドシートの機能は使用しませんが、特に気にしなければスプレッドシートから作ってもらっても問題ありません。)
プロジェクト名はなんでも良いです。
無題のプロジェクトのままでも特に問題ないですが、私はアクセスカウンターとしておきました。
##③GoogleAnalyticsAPIを使えるようにする
こちらを参考にAPIを有効化します。
APIが追加されると下図のように、「サービス」の下にAPI名が表示されます。
注意したいのが、
Analytics → GA3のAPI
AnalyticsData → GA4のAPI
という部分ですね。紛らわしい。
今回はGA3を使うので「Analytics」の方さえ出ていれば問題ありません。
##④アクセスカウンターを表示するスクリプトを作る
GoogleAppsScriptでアクセスカウンターを作っていきます。
GA3のビューID確認方法は↓を参考にしました。
https://auto-worker.com/blog/?p=3005
!注意!
GoogleAnalyticsには現行のGA4と少し古いGA3があります。
GA4のAPIはベータ版(2021/10/4現在)らしく使い方も少し面倒くさそうだったので今回はGA3で作りました。
お使いのGoogleAnalyticsのバージョンがGA4の場合、このままでは使用できないのでご注意ください。
まずデフォルトで入っている「コード.gs」の中身を書いていきます。
【】になっているところは各々置き換えてください。
function doGet(e) {
//一旦evaluate()をしないとsplitletsが実行されない
var html = HtmlService.createTemplateFromFile('index').evaluate();
//setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)をセットしていないとiframeで表示できない
var output = HtmlService.createHtmlOutput(html).setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
return output;
}
function getID(num){
switch(num){
case 0:return "【0の画像のID】";break;
case 1:return "【1の画像のID】";break;
case 2:return "【2の画像のID】";break;
case 3:return "【3の画像のID】";break;
case 4:return "【4の画像のID】";break;
case 5:return "【5の画像のID】";break;
case 6:return "【6の画像のID】";break;
case 7:return "【7の画像のID】";break;
case 8:return "【8の画像のID】";break;
case 9:return "【9の画像のID】";break;
}
}
function getSpecifiedDigit(num,period){
let gadata
let GaID = "ga:【GA3のビューID】";
if(period == "long"){
//累計アクセス数を取得(あまり古い日付から始めると失敗するっぽい?)
gadata = Analytics.Data.Ga.get(GaID,"2021-08-01","today","ga:users");
}
else{
//periodの指定がなければ今日のアクセス数を返す
gadata = Analytics.Data.Ga.get(GaID,"today","today","ga:users");
}
//データはjson形式で取得されるので、GASで扱えるように変換する
let json = JSON.parse(gadata);
//取得したデータからアクセス数を取りだす
let users = json['totalsForAllResults']['ga:users'];
let len = users.length;
//取得したい桁数がアクセス数の桁数より多い場合は0を返す
if (len < num ){
return 0;
}
let spl = users.toString().split("");
//numで指定した桁の値を返す
return spl[len-num];
}
function getImageUrl(num,period){
//numには下から数えた桁数を渡す (下から1桁目なら1を渡す)
let DigNum = Number(getSpecifiedDigit(num,period));
return "https://drive.google.com/uc?id=" + getID(DigNum);
}
「ファイル」の横の+ボタンからHTMLを追加して、index.htmlを作成します。
(下の画像は追加後のものです。デフォルトではindex.htmlは存在しません。)
中身は↓です。工夫のかけらもないですね。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div>今日</div>
<img src="<?!=getImageUrl(6);?>">
<img src="<?!=getImageUrl(5);?>">
<img src="<?!=getImageUrl(4);?>">
<img src="<?!=getImageUrl(3);?>">
<img src="<?!=getImageUrl(2);?>">
<img src="<?!=getImageUrl(1);?>">
<div>累計</div>
<img src="<?!=getImageUrl(6,'long');?>">
<img src="<?!=getImageUrl(5,'long');?>">
<img src="<?!=getImageUrl(4,'long');?>">
<img src="<?!=getImageUrl(3,'long');?>">
<img src="<?!=getImageUrl(2,'long');?>">
<img src="<?!=getImageUrl(1,'long');?>">
</body>
</html>
##⑤デプロイする
この辺を参考にデプロイしましょう
アクセスユーザーの設定は必ず下図のようにしてください。
自分以外のアクセスで表示されなくなってしまいます。
(デプロイの説明文は図の通りでなくても大丈夫です。)
デプロイしたら、ウェブアプリのURLをコピーしておきましょう。
##⑥はてなブログ側で表示させる
(はてなブログじゃなくてもやり方は大体同じはずです。)
今回ははてなブログのサイドバーに設置してみます。
デザイン編集画面の「サイドバー」メニューからモジュールを追加を選択
(画像は既にアクセスカウンターを追加済みのものです…)
モジュール名をアクセスカウンターにして、コードのところに下記のコードを書き込みます。
<iframe width=252 src="【⑤でコピーしたウェブアプリのURL】">
※察しの良いポケモン厨の方は気づいたと思いますが、width=252は特に意味はないです。(努力値)
気持ち悪ければ260とかにしてもらって全然構いません。
以上で終了です。
お疲れ様でした。
以降はあとがき的なものになります。
カスタムして使いたい方は参考になるかもしれません。
#【躓いたところ】
###・Scriptletsが実行されない
###・iframeで表示できない
(GASのScriptletsについてはこちらで解説されています。)
GASのHTML表示方法を検索すると、
HtmlService.createTemplate
HtmlService.createTemplateFromFile
HtmlService.createHtmlOutput
HtmlService.createHtmlOutputFromFile
↑この辺が割とまぜまぜで出てきます。
サンプルコードによって違うのでよく見ないでコピペすると間違います。
(底辺プログラマーあるある自虐ネタです。よく見ないで使ってました。。。)
コード.gsのコメントにちょこっと書いたのですが、
HtmlService.createHtmlOutputFromFile('index')
とするとScriptletsが実行されず、HTML内に!=(スクリプト)?>と直接表示されてしまいました。
どうやら
HtmlService.createTemplateFromFile('index').evaluate()
としないとScriptletsが実行されない?らしいです
ところが、
HtmlService.createTemplateFromFile('index')
だとScriptletsは実行されるのですが、iframeで表示できませんでした。
調べたところ、こんな情報を発見
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)を設定しないとiframeで表示できないらしい。
しかし、HtmlService.createTemplateにはsetXFrameOptionsModeが無いらしくScriptletsとiframeの両立ができなくてしばらく途方に暮れました。
結局、一旦createTemplate().evaluate()した後にcreateOutputするという方法でいけました。(コード.gsの通り)
果たしてこんな方法でいいのかはよくわかりませんが、もっとスマートなやり方があったら教えて欲しいです。
###・画像の表示
この辺りを参考にしたのですが、画像の共有リンクをに貼るだけでは画像が表示できません。
https://drive.google.com/uc?id=XXXXXXXX
という形じゃないといけないようですね。
ただ、iPhoneだとうまく表示されないとかとか。
でも上の記事にある、トークンを含めたURLを生成するという方法もうまくいかず。。。
スマホ表示ってサイドバー出ないしいいんじゃない???
ってことで諦めました。
パソコンとiPadでは表示されたので、まあ良いでしょう←
というか、canvasとかでちゃんと画像を生成してから表示するならこんな苦労もないのかもしれません。
私はHTML弱者なのでやむなく適当に画像を並べただけになりましたが。
詳しい方は改良してもっと綺麗に表示したり色々できるんじゃないでしょうか。
(詳しい方はこんなページ見にきてない説が有力)
#【おわりに】
正直そんなにGASもHTMLも詳しくない人が頑張って書いたものなので、いろいろと拙い部分はあると思います。
まあ動いてるしいいんじゃない?(底辺プログラマーの常套句)
最後に、ただの宣伝になりますが、普段はポケモンの記事を書いたり
YouTubeにポケモンのパーティ作り動画を上げたりしています。
海乃もずくのチャンネル↓
基本一人4役で漫才みたいなことをやってる変な動画ですが、もし良かったら見ていってくれると嬉しいです。
#【参考ページなど】
GA3APIのリファレンス
GA4を使う場合はこちらが参考になるかもしれません。GCPに慣れてないので私は逃げました←
記事内で何度も引用させて頂きました。製作中も大変お世話になりました。ありがとうございます。