【Qiitaアナリティクス】"自分の記事がどれだけ伸びているか" を見える化するスプレッドシートを作りました 🚀

# 🏰 作ったもの

## Qiitaアナリティクス
自分が Qiita に投稿した記事について、
- view 数
- いいね 数
- ストック数

の推移を時系列で見ることができるスプレッドシート (**Qiitaアナリティクス**) を作りました！

テンプレートにして公開しているので
**今すぐ誰でも**、使い始めることができます！🏃‍♂️

▶︎▶︎▶︎ [**Qiitaアナリティクス テンプレート**](https://docs.google.com/spreadsheets/d/1ggO4erE3lLw3XiLfy8GNgNPI5swLg6JdX8QI5NESmoo/edit#gid=279393869) ◀︎◀︎◀︎

:::note info
使い始め方を知りたい方はこちら
→ [🚀 使い始めるための準備](#-使い始めるための準備)
:::





# 🧞‍♂️ 何ができるのか
大きく以下 3つ です。
- [記事全体としてどのくらい伸びているのか見られる](#記事全体としてどのくらい伸びているのか見られる)
- [各個別の記事についてどのくらい伸びているのか見られる](#各個別の記事についてどのくらい伸びているのか見られる)
- [直近の各種データを一覧で見られる](#直近の各種データを一覧で見られる)

## 記事全体としてどのくらい伸びているのか見られる
自分が書いた記事全体の [view数, いいね数, ストック数] について、
・累計値を時系列で見ることができます (みどりの部分)
・前日との増減も比較できます (オレンジの部分)

左半分が集計データ、
右半分が集計データをグラフ化したダッシュボードです。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/76047202-e382-f6f9-8e51-8060da68c2c9.png">

なんとなく 1日 に 1回 見て、
「昨日はこんなに view数 が増えてる！ 嬉しい！😊」
「記事全体で見ると 1日 に 200view くらいあるんだ！ 意外と見てもらえてて嬉しい！😊」
「合計 view数 10万超えた！ 嬉しい！😊」
とか思うことができます。

## 各個別の記事についてどのくらい伸びているのか見られる
記事ごとの [view数, いいね数, ストック数] についても、
・累計値を時系列で見ることができます (みどりの部分)
・前日との増減も比較できます (オレンジの部分)

左半分が集計データ、
右半分が集計データをグラフ化したダッシュボードです。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/d0e444fd-32b0-36fd-5299-9d12cabf2956.png">

赤色のプルダウンからデータ表示する対象記事の切り替えが可能です。

[![赤色のプルダウンからデータ表示対象記事を切り替え](https://i.gyazo.com/a7533800c74bf821c52068365cb3b9c7.gif)](https://gyazo.com/a7533800c74bf821c52068365cb3b9c7)

記事投稿後 1週間 とかの数値の動きを見て
「トレンドに載るとやっぱり一気に view数 跳ね上がるな！🤔」
「view数 の伸びに対していいね数とストック数が控えめだな... どうしてだろう...？🤔」
「トレンドに載ったわけでもないのに急に数字跳ねてるところがある！ どこかで誰かがシェアしてくれたのかな...？🤔」
など、色々考えることができます。

## 直近の各種データを一覧で見られる
自分が書いた全記事について、
直近 [view数, いいね数, ストック数] がいくつなのか見ることができます。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/82939b0b-fa36-352c-ef91-7576b04a98af.png">


# 🤔 なぜ作ったのか
## 自分が欲しかったから
これに尽きます。

「普段、自分の記事がどれくらい見てもらえているのかぱっと見でわかるダッシュボードが欲しいなあ...」
とずっと思い続けてきました。

Qiita には Googleアナリティクス との連携機能が用意されていますが、
多機能すぎて逆に使いにくそう (勝手なイメージ) なのと、

自分が見たいデータを見たいように取得して好き勝手加工して...
ということがやりたかったので自作しました。


# 🚀 使い始めるための準備
Qiitaアナリティクス を使い始めるためには以下の準備が必要です。
1. [Qiita の個人用アクセストークンを作成する](#1-qiita-の個人用アクセストークンを作成する)
2. [Qiitaアナリティクス を自分の Googleドライブ にコピーする](#2-qiitaアナリティクス-を自分の-googleドライブ-にコピーする)
3. [Qiitaアナリティクス の初期設定をする](#3-qiitaアナリティクス-の初期設定をする)

## 1. Qiita の個人用アクセストークンを作成する
**① アプリケーションの設定画面にアクセスする**
https://qiita.com/settings/applications

**② [新しくトークンを発行する] をクリックする**
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/33448138-84b8-6e65-14fe-c81bae88279d.png">

**③ 必要項目を入力してトークンを発行する**
アクセストークンの説明はお好みで。
スコープは [read_qiita] だけで十分です。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/20c64522-bc56-7a3f-b42a-89fc8b228ff1.png">

**④ 発行されたトークンをコピーして控えておく**

発行がうまくいけば画面にトークンが表示されるはずなので
**必ず、忘れずに、コピーしてどこかに控えておいてください！**

(あとで行う Qiitaアナリティクス の初期設定のときに使用します)


## 2. Qiitaアナリティクス を自分の Googleドライブ にコピーする
**① 以下から Qiitaアナリティクス のテンプレートにアクセスする**

▶︎▶︎▶︎ [**Qiitaアナリティクス テンプレート**](https://docs.google.com/spreadsheets/d/1ggO4erE3lLw3XiLfy8GNgNPI5swLg6JdX8QI5NESmoo/edit#gid=279393869) ◀︎◀︎◀︎

**② [ファイル > コピーを作成] をクリック**
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/6ff7f51c-4b2d-c26e-8470-e61ea4895883.png">

**③ [コピーを作成] をクリック**
<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/b0f68500-6dd1-e988-7797-11e731e06f85.png">

**④ 空っぽの Qiitaアナリティクス が表示されれば完了！**
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/d954c678-409c-4310-25bc-a1b86a6c6c87.png">

## 3. Qiitaアナリティクス の初期設定をする
**① [拡張機能 > Apps Script] をクリック**!
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/265488b2-97d3-6ccb-8504-4f133a44f9aa.png">

**② [▷ 実行] をクリック**
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/57263942-00d6-67a1-002d-5fc89f297fbf.png">

**③ 各種サービスへのアクセスを承認する**
GAS あるあるですが、初回のスクリプト実行時には承認が求められるので
画面の案内にしたがって承認していきます。

:::note warn
初めて見る方だと表示内容の仰々しさに驚いてしまうかもしれませんが、
Qiitaアナリティクス は『秘密裏に個人情報や各種データを取得、どこかに送信』
みたいなことは**一切やっていない**ので安心してください。

ソースコードを読んで確かめていただいても構いません。
→ [QiitaAnalytics](https://github.com/Ryo-Nakano/QiitaAnalytics/tree/main)
:::

[権限を確認] をクリック
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/706f9099-b4c2-90cb-2971-d1013353c4d0.png">

任意の Google アカウントを選択
<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/321138c4-623e-9f45-b76a-cb7a878ef0ca.png">

[詳細] をクリック
<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/73093ada-e7d0-5d9e-95f1-b7249a714e6a.png">

[QiitaAnalytics（安全ではないページに移動）] をクリック
<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/45d44c43-64ab-0a2f-4a93-95485c6e7f3b.png">

少し下にスクロールして [許可] をクリック
<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/d140d6a6-172f-c787-8e3e-d94cacd9aa03.png">
ここまでできれば承認作業は完了です 👏

**④ スプレッドシートのタブに移動して QiitaAnalytics の初期設定を完了させる**

前述の承認作業を終えたら、
あとは QiitaAnalytics の初期設定を行なうために
スプレッドシートを開いているタブに戻ってください。

あらかじめ用意しておいた Qiita API のアクセストークンを
入力欄に貼り付けて [OK] をクリック
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/60043399-b803-e976-4298-e6227e8c2418.png">

[OK] をクリック
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/89fa8a44-3781-b67b-8482-5acd1db75764.png">

[OK] をクリック ( スプレッドシートID の取得と保存は自動で行われます)
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/cc971a33-5860-a5fd-5b03-e97c88245c73.png">

このモーダルが表示されたら初期設定完了です！ 🎉
画面をリロードしてください。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/174009c6-3491-7981-e91a-5c82fd19f416.png">

画面をリロードしてタブに **[カンタン操作]** というものが追加されていたら
おそらく初期設定はうまくいっています。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/44c5f3aa-df9b-de71-2a46-dfb3224540e3.png">

:::note warn
もし初期設定が途中で止まってしまうなどうまくいかなかった場合は
再度 `initializeQiitaAnalytics` を実行してみてください。
:::

:::note warn
Qiitaアナリティクスは**毎日 23:30 前後**に
Qiita API からその日の記事データを取得するようになっています。

シートにデータが反映されるのは 23:30 以降となるため
それまで気長にお待ちください 🙏

待ちきれない場合は
**[カンタン操作 > Qiita から現時点の記事データを取得してシートに保存]**
を実行してもらえれば、その時点の記事データが取得されてシートに反映されます。
:::


# 🛠️ 使い方 (タブ別)
Qiitaアナリティクス には非表示にされているものも含めて
全部で 5つ のタブが用意されています。

- [全体](#全体)
- [記事ごと](#記事ごと)
- [最新の結果](#最新の結果)
- [_DB (非表示)](#_db-非表示)
- [_options (非表示)](#_options-非表示)

## 全体
自分が書いた記事全体の [view数, いいね数, ストック数] について、
・累計値を時系列で見ることができます (みどりの部分)
・前日との増減も比較できます (オレンジの部分)

左半分が集計データ、
右半分が集計データをグラフ化したダッシュボードです。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/76047202-e382-f6f9-8e51-8060da68c2c9.png">
なんとなく 1日 に 1回 見て、
「昨日はこんなに view数 が増えてる！ 嬉しい！😊」
「記事全体で見ると 1日 に 200view くらいあるんだ！ 意外と見てもらえてて嬉しい！😊」
「合計 view数 10万超えた！ 嬉しい！😊」
とか思うことができます。

## 記事ごと
記事ごとの [view数, いいね数, ストック数] についても、
・累計値を時系列で見ることができます (みどりの部分)
・前日との増減も比較できます (オレンジの部分)

左半分が集計データ、
右半分が集計データをグラフ化したダッシュボードです。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/d0e444fd-32b0-36fd-5299-9d12cabf2956.png">
赤色のプルダウンからデータ表示する対象記事の切り替えが可能です。
[![赤色のプルダウンからデータ表示対象記事を切り替え](https://i.gyazo.com/a7533800c74bf821c52068365cb3b9c7.gif)](https://gyazo.com/a7533800c74bf821c52068365cb3b9c7)

記事投稿後 1週間 とかの数値の動きを見て
「トレンドに載るとやっぱり一気に view数 跳ね上がるな！🤔」
「view数 の伸びに対していいね数とストック数が控えめだな... どうしてだろう...？🤔」
「トレンドに載ったわけでもないのに急に数字跳ねてるところがある！ どこかで誰かがシェアしてくれたのかな...？🤔」
など、色々考えることができます。
## 最新の結果
自分が書いた全記事について、
直近 [view数, いいね数, ストック数] がいくつなのか見ることができます。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/82939b0b-fa36-352c-ef91-7576b04a98af.png">

後述する _DB タブの中から
最新の日付のものだけを表示するようになっているので
「ちゃんと昨日分の記事データを取得できてるかな？」
という確認のために使っています。


## _DB (非表示)
Qiita から取得した記事データを蓄積している、
**データベース**としての役割を果たしているタブです。
基本的にここをいじる必要はありません。

毎日 23:30 前後に Qiita API にリクエストをして
その時点で投稿されている記事一覧を取得して
"_DB" タブに保存するような形になっています。
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/67945d47-9b87-9eee-1584-816f1d334d6c.png">
スプレッドシートに明るい方であればこちらのタブにあるデータを使って
ご自身で**新しいタブを作ってデータを集計したりダッシュボードを作ったり**などしていただけます。
ぜひご活用ください！ 🏃‍♂️


## _options (非表示)
"記事ごと" タブで使う、
プルダウン選択肢として出すデータを置いてあるタブです。
基本的にここをいじる必要はありません。
<img width=450 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/c78c67f5-06a5-18ea-58ae-0892505dddaa.png">


# 💡 作るときに工夫したこと
## UIUX に関すること
### できるだけスクリプトエディタを開かずに使えるようにする
特に初期設定まわりについて、わざわざ

1. スクリプトエディタを開いてもらって
2. スクリプトプロパティに スプレッドシートID と Qiita のアクセストークン貼り付けてもらって
3. 次はトリガーも設定してもらって...

などなど自力でやってもらうのは**地獄すぎる**と考えたため、
できるだけここの手間を省けるように作りました。

具体的には
- `initializeQiitaAnalytics` を呼び出せば設定が完了するようにする
- スクリプトプロパティへの Qiita API アクセストークン登録はモーダル画面に入力してもらう
- スプレッドシートID をスクリプトから自動で [取得 → 保存] できるようにする
- トリガーの設定をスクリプトから自動で行えるようにする

などの工夫をしました。

--

ほんとうは `initializeQiitaAnalytics` の呼び出しすら
スプレッドシートの初回起動時に自動で呼び出すようにしようと考えていたのですが、

GAS の初回実行時にはどうしても承認作業が必要になることから断念しました。
( onOpen で呼び出すと承認作業時に表示されるモーダルが出てこないため)

シンプルに自分の力不足の可能性もあるので
もし良い方法をご存知の方がいらっしゃいましたら
コメント等にてご教示いただけますと幸いです...！🙏

--

参考
- [モーダル表示 (SpreadsheetApp.getUi)](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app?hl=ja)
- [スプレッドシートID の自動取得 (Spreadsheet#getId)](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet?hl=jp#getid)
- [スクリプトプロパティの取り扱い (PropertiesService.getScriptProperties)](https://developers.google.com/apps-script/reference/properties/properties-service?hl=ja#getScriptProperties())
- [トリガーの作成 (ScriptApp.newTrigger)](https://developers.google.com/apps-script/reference/script/script-app?hl=ja#newTrigger(String))
- [トリガーの削除 (ScriptApp.deleteTrigger)](https://developers.google.com/apps-script/reference/script/script-app?hl=ja#deletetriggertrigger)


### 使う色を少なく、色ごとに意味を持たせるように
デザインをできるだけシンプルに見やすくするために
使う色を少なく、色ごとに意味を持たせるように工夫しました。

具体的には
**・緑：累計**
**・オレンジ：前日との比較**
という形で

集計データとグラフの色使いを合わせることで
ぱっと見でどのデータにどのグラフが対応しているのかわかるようにしました。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/97490f9a-aced-cf12-0e51-491941269a04.png">

--

当初は [view数, いいね数, ストック数] の 3つ で色を使い分けていましたが
"記事ごと" タブが記事選択プルダウンも含めて 4色 使うことになってしまい
なんだかうるさい印象だったのでやめました。

また、余談ですが
使用する 2色 に緑とオレンジを選定している理由は
弊社 Matcher株式会社 のプロダクト『[**Matcher**](https://matcher.jp/)』が
メインカラーに緑を、アクセントカラーにオレンジを使用しているためです。

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/ca89a1cc-04b0-f9f4-70d4-9cd5a7663c6c.png">

ただ愛着があって気に入っているという、個人的な理由だけで
ここに UIUX 観点の理由はありません。笑

--

参考
- [見やすいプレゼン資料の作り方 - リニューアル増量版](https://www.slideshare.net/yutamorishige50/ss-41321443)

配色の話というよりはプレゼン資料の作り方に関する資料ですが、
僕は学生時代にこのスライドではじめて
[ベースカラー, メインカラー, アクセントカラー] という考え方を知ったため
こちらの資料を貼っております。

### 記事のタイトルを編集しても変更前と同じ記事として扱われるようにする
"記事ごと" タブでは "_DB" タブに保存されているデータの中から
選択した記事のデータのみに絞り込んで表示するような形になっています。

このとき、記事タイトルの一致で絞り込みをすると
もし記事タイトルを途中で編集したらシート上では別記事として取り扱われてしまいます。
そうならないように "_options" タブの作りを工夫しました。

具体的には
1. "_DB" タブから記事の ID 一覧を取得する (**UNIQUE関数**)
2. ID に対して "_DB" タブから最新の記事タイトルを取得する (**SORT関数, VLOOKUP関数**)
3. プルダウンでタイトルを選択すると "_options" タブが参照されて対応する ID が取得され、絞り込みに用いられる (**QUERY関数**)

という形です。
ちょっと言葉でわかりやすく説明するのが難しいので
気になる方はシートの関数を見てみてください！🙏

--

ポイントは "_DB" タブから
『ID が一致する、最新の記事タイトルを取得する』ことです。

これを実現するために、
1. SORT関数 に**列の順番を変えたデータ**を渡す ( {} を使って新しい配列を作成)
2. VLOOKUP関数 の第二引数に **SORT関数 で並び替えたデータ**を渡す

ということをしています。

詳細な説明は既に他の方が書かれた素晴らしい記事がありますので
以下の参考記事をご参照ください。

--

参考
- [【保存版】スプレッドシートで配列や行列を作成する方法まとめ](https://tanuhack.com/array-matrix-creation/)
- [（Gスプレッドシート）VLOOKUP関数で下から検索する](https://www.officeisyours.com/entry/2020/07/23/104740)
- [Google スプレッドシートで配列を使用する](https://support.google.com/docs/answer/6208276?hl=ja)
- [UNIQUE 関数](https://support.google.com/docs/answer/10522653?hl=ja&sjid=5565703293211236924-AP)
- [SORT](https://support.google.com/docs/answer/3093150?hl=ja&sjid=5565703293211236924-AP)
- [VLOOKUP](https://support.google.com/docs/answer/3093318?hl=ja)
- [QUERY](https://support.google.com/docs/answer/3093343?hl=ja&sjid=5565703293211236924-AP)


## 開発に関すること
### グローバルスコープの名前空間汚染を最小限にする
GAS 開発にどうしてもついて回るのがグローバルスコープの名前空間汚染です。
Web エディタ上でファイルを分けてもスコープが共有されているため
同じ変数名や関数名を使うと名前が被ってしまいます。

それを解消するためにいつも GAS の開発を行うときは
Clasp x Webpack でローカルで、ディレクトリを分けて開発を行っています。

:::note info
Clasp x Webpack で GAS 開発をしたい方はこちらをご参照ください。
[**【TypeScript + Webpack】今すぐ誰でも、ローカルで GoogleAppsScript の開発を始められるテンプレート (初心者向け)**](https://qiita.com/Ryo-Nakano/items/50366600543c2888ada7)

※ TypeScript ではなく JavaScript でも開発を行えます
:::

--

src ディレクトリの構成は以下のようになっており、
operations ディレクトリの中に諸々の処理が関数単位でまとめられています。

<img width=350 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/96c830a8-5ab6-b74b-2ada-ea2131b91101.png">

例えば、`operations/initialize_qiita_analytics.js` には以下のような内容が書いてあり、
```javascript
import setQiitaApiToken from "./set_qiita_api_token";
import setSpreadsheetId from "./set_spreadsheet_id";
import setTriggersIfNeeded from "./set_triggers_if_needed";

const initializeQiitaAnalytics = () => {
  setQiitaApiToken();
  setSpreadsheetId();
  setTriggersIfNeeded();
  showDoneModal();
};

const showDoneModal = () => {
  const ui = SpreadsheetApp.getUi();
  const title = '設定が完了しました！';
  const body = [
    '画面をリロードしてください',
  ].join('\n');
  ui.alert(title, body, ui.ButtonSet.OK);
};

export default initializeQiitaAnalytics;
```

↑ これを `index.js` で global オブジェクトのプロパティに渡しています。
```javascript
import Operations from 'operations';

global.initializeQiitaAnalytics = Operations.initializeQiitaAnalytics;
global.addTabFunctions = Operations.addTabFunctions;
global.storeItemDataDaily = Operations.storeItemData;
global.storeItemData = Operations.storeItemData;
global.setQiitaApiToken = Operations.setQiitaApiToken;
global.setSpreadsheetId = Operations.setSpreadsheetId;
```

こうすると、エディタ上から呼び出せる関数を
↑ で global オブジェクトのプロパティに渡したものだけにすることができます。(スッキリ)
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210717/0fd93483-a03d-4bfc-8c23-202d97784004.png">

--

...と、ここまで書いたんですが、

わざわざ Clasp x Webpack なんてことをしなくても
**Class をうまく使って処理をカプセル化すれば
グローバルスコープの名前空間汚染もせず、きれいにファイルを分けて開発できる**

ということに最近気がついてしまったため、
小規模の GAS 開発であれば Web エディタ上で済ませることが増えそうな気がしています。

熟練のエンジニアの方であれば当然のことと思うのですが、
自分にとっては大きな進歩と感じているためこちらもまた別途記事を書こうと思います！