【Next.js × microCMS】人気記事一覧を表示してみた

【Next.js × microCMS】人気記事一覧を表示してみた

Next.jsmicroCMSTypeScript

おはこんにちばんは。今回は Next.js × microCMS で 人気記事一覧を Google Analytics Reporting API v4 を利用し表示してみました!

よくブログとかで人気記事一覧とか目にしますよね。WordPress の場合はプラグインを利用すれば比較的簡単に出来そうですが、自作ブログだとどうすべきか悩みました。

そこで今回は、Google Analytics Reporting API v4 を利用して人気記事一覧を表示する方法を紹介していきます。

実行環境

  • Next.js 10.0.4
  • React 17.0.0

Google APIs を有効にする

プロジェクトを作成

Google APIs にアクセスし、プロジェクトの選択 をクリックし、新しいプロジェクト をクリックします。

blog image

プロジェクト名に任意の名前をつけてプロジェクトを作成します。

blog image

Google Analytics API の有効化

APIとサービスの有効化 をクリックして Google Analytics API を有効化します。

blog image

blog image

これで有効化されました。続いて認証情報を作成します。

認証情報の作成

認証情報を作成 をクリックします。

blog image

下記の情報を選択します。必要な認証情報 をクリックします。

  • 使用するAPI:Analytics Reporting API
  • APIを呼び出す場所:ウェブサーバー(node.js, Tomcat など)
  • アクセスするデータの種類:アプリケーションデータ

blog image

下記の情報を選択します。次へ をクリックします。

  • サービスアカウント名:任意
  • ロール:閲覧者
  • キータイプ:JSON

blog image

自動的にjsonがダウンロードされます。このjsonは後ほど利用するので、適切に保管しておきます。

Google Analytics の閲覧権限を付与

Google Analyticsの設定を行っていきます。

Google Analytics を開き、左下の歯車マーク から ビューの設定 をクリックします。

blog image

ビューIDを後ほど利用するのでメモっておいてください。

次にユーザ管理をクリックし、+ ボタンを押してユーザを追加します。

ユーザのメールアドレスには、先程ダウンロードしたjsonファイルに記載されている client_email の値を入れて、ユーザを追加します。

blog image

これでgoogle APIs周りの設定は完了です。

パッケージの追加

それでは実装を進めていきます。今回は、Node.js用のライブラリである google-api-nodejs-client を利用します。

1$ yarn add googleapis

ページビュー上位を取得する処理

人気記事一覧を表示したいので、ページビューが上位の3位のパスを取得するコートを書いていきます。

1import { analyticsreporting_v4, google } from 'googleapis';
2import { isEmpty } from 'lodash';
3
4const getTopArticle = async (): Promise<analyticsreporting_v4.Schema$GetReportsResponse> => {
5 const client = await google.auth.getClient({
6 scopes: 'https://www.googleapis.com/auth/analytics.readonly',
7 credentials: {
8 client_email: process.env.GOOGLE_APPLICATION_CLIENT_EMAIL,
9 private_key: (process.env.GOOGLE_APPLICATION_PRIVATE_KEY ?? '').replace(
10 /\\n/gm,
11 '\n',
12 ),
13 },
14 });
15
16 const analyticsreporting = google.analyticsreporting({
17 version: 'v4',
18 auth: client,
19 });
20
21 const res = await analyticsreporting.reports.batchGet({
22 requestBody: {
23 reportRequests: [
24 {
25 viewId: process.env.GOOGLE_ANALYTICS_VIEW_ID,
26 dateRanges: [
27 {
28 startDate: '30daysAgo',
29 endDate: '1daysAgo',
30 },
31 ],
32 dimensions: [
33 {
34 name: 'ga:pagePath',
35 },
36 ],
37 metrics: [
38 {
39 expression: 'ga:pageviews',
40 },
41 ],
42 orderBys: [
43 {
44 fieldName: 'ga:pageviews',
45 sortOrder: 'DESCENDING',
46 },
47 ],
48 pageSize: 3,
49 dimensionFilterClauses: [
50 {
51 filters: [
52 {
53 dimensionName: 'ga:pagePath',
54 operator: 'REGEXP',
55 expressions: ['^/blogs/[0-9a-zA-Z\\-]+$'],
56 },
57 ],
58 },
59 ],
60 },
61 ],
62 },
63 });
64
65 return res.data;
66};
67
68const getTopArticlePaths = async (): Promise<string[]> => {
69 const topArticle = await getTopArticle();
70
71 const ids: string[] = [];
72 const rows = topArticle.reports
73 ? topArticle.reports[0]?.data?.rows ?? []
74 : [];
75
76 rows.forEach((row) => {
77 if (row.dimensions && !isEmpty(row.dimensions)) {
78 ids.push(row.dimensions[0].replace('/blogs/', ''));
79 }
80 });
81
82 return ids;
83};
84
85export { getTopArticle, getTopArticlePaths };

以下の環境変数は先ほどダウンロードしたjsonの clientemail privatekey を利用します。view_id は先ほどメモしたやつです。

1process.env.GOOGLE_APPLICATION_CLIENT_EMAIL
2process.env.GOOGLE_APPLICATION_PRIVATE_KEY
3process.env.GOOGLE_ANALYTICS_VIEW_ID

ブログのページビューのみを取得したいので、正規表現で /blogs/英数字ハイフン が含むのみを取得するようにしています。

1dimensionFilterClauses: [
2{
3 filters: [
4 {
5 dimensionName: 'ga:pagePath',
6 operator: 'REGEXP',
7 expressions: ['^/blogs/[0-9a-zA-Z\\-]+$'],
8 },
9 ],
10}]

次に以下のようにページビュー上位3位までの記事を取得します。

1export const getStaticProps: GetStaticProps = async (): Promise<{
2 props: Props;
3}> => {
4 const ids = await getTopArticlePaths();
5 const str = ids.join(',');
6
7 const key = {
8 headers: { 'X-API-KEY': process.env.API_KEY ?? '' },
9 };
10 const topBlogs = await fetch(
11 `https://your-service.microcms.io/api/v1/blogs?ids=${str}`,
12 key,
13 )
14 .then((res) => res.json())
15 .catch(() => null);
16
17 const topArticleBlogs = compact(
18 ids.map((id) => topBlogs?.contents.find((b) => b.id === id)),
19 );
20
21 return {
22 props: {
23 topArticleBlogs,
24 },
25 };
26};

以下は microCMS が順番を作成順に変えてしまうので、Articleのid順に並び替えています。

1const topArticleBlogs = compact(
2 ids.map((id) => topBlogs?.contents.find((b) => b.id === id)),
3);

これで人気記事を取得出来たはずなので、あとは良しなに表記するだけです。お疲れ様でした。

さいごに

今回は人気記事一覧を表示する方法についてご紹介しました!意外と調べても参考になる実装方法がなかったので誰かの参考になれば幸いです。

(microCMSのidsはidの順番に返して欲しいと思うこの頃。方法あるのかな?)