ページビュー数を表示する

2021年11月6日(土) 15時27分55秒 | 35 view

JAMStackでもページビュー数を取得して表示したい! ということで実装しました。
技術要素はこちら

  • Google Analytics Reporting API v4
  • google-api-php-client
  • MicroCMS patch API


Google Analyticsのデータを閲覧権限で取得してきてNuxtのビルド時にごそっとpatchイベントを介してMicroCMS上で確認できるような設計にしました。


最終的にこんな感じでpv数がmicroCMSで確認できます。

あとは通常のJAMStackと同じで取得したpv数を表示する流れです。

実装:
まずPHPでGoogle Analytics Reporting APIの導通をします
こちらのページを参考に簡単に作れました。


そのあと、今回は記事ページのpv一覧がほしいので、このようにphpを記述しました

<?php
// Google API クライアントライブラリの読込み
require_once __DIR__ . '/google-api-php-client/vendor/autoload.php';
// 鍵ファイルのパス
$key_file_location = __DIR__ . '/service-account-credentials.json';
// ビューID
$view_id = 'view_id';

// 認証処理
$client = new Google_Client();
$client->setApplicationName('sample');
$client->setAuthConfig($key_file_location);
$client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
$analytics = new Google_Service_AnalyticsReporting($client);

// データを取得する期間
$dateRange = new Google_Service_AnalyticsReporting_DateRange();
$dateRange->setStartDate('2020-09-01');
$dateRange->setEndDate('today');

// 取得するメトリクスの指定
// https://developers.google.com/analytics/devguides/reporting/core/dimsmets
// PV
$pageviews = new Google_Service_AnalyticsReporting_Metric();
$pageviews->setExpression('ga:pageviews');

//ディメンションをpathに設定
$dimention = new \Google_Service_AnalyticsReporting_Dimension();
$dimention->setName( 'ga:pagePath' );

//部分一致"post"でページ全体をフィルタリング
$filter = new \Google_Service_AnalyticsReporting_DimensionFilter();
$filter->setDimensionName( 'ga:pagePath' );
$filter->setOperator( 'PARTIAL' );
$filter->setExpressions( [ 'post' ] );

//フィルタを適用
$filters = new \Google_Service_AnalyticsReporting_DimensionFilterClause();
$filters->setFilters([$filter]);

// リクエストの作成
$request = new Google_Service_AnalyticsReporting_ReportRequest();
$request->setViewId($view_id);
$request->setDateRanges($dateRange);
$request->setMetrics(array($pageviews));
$request->setDimensions( [ $dimention ] );
$request->setDimensionFilterClauses( $filters );

// リクエスト実行
$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
$body->setReportRequests(array($request));
$reports_obj = $analytics->reports->batchGet($body);

// オブジェクトを配列変数に変換
$reports_array = json_decode(json_encode($reports_obj), true);

//一旦整形する
$pageviewarray = $reports_array['reports'][0]['data'][rows];
$outputarray = [];

//クエリパラメータ付きのパスは同一PVとして加算する
for ($i = 0; $i < count($pageviewarray); $i++) {
    $realpath = explode("?",$pageviewarray[$i]['dimensions'][0])[0];
    if(substr($realpath, -1) != '/'){
        $realpath = $realpath . "/";
    }
    if($outputarray[$realpath]['pageview'] == null){
        $outputarray[$realpath]['pageview'] = intval($pageviewarray[$i]['metrics'][0]['values'][0]);
    }else{
        $outputarray[$realpath]['pageview'] += intval($pageviewarray[$i]['metrics'][0]['values'][0]);
    }
}
//JSで扱いやすいようにフォーマット変更
$output =  [];

for ($l = 0; $l < count($outputarray) - 1; $l++) {
    if(substr(array_keys($outputarray)[$l],0,6) == "/post/"){
        $obj = array('path'=>array_keys($outputarray)[$l],'id'=>rtrim(substr(array_keys($outputarray)[$l],6),'/'),'pageview'=>$outputarray[array_keys($outputarray)[$l]]['pageview']);
    }
    array_push($output,$obj);
}

echo json_encode($output);


するといい感じにAPIができました



あとはこいつをnuxt.config.jsでビルド時に記事ページにpatchします

let pvobj = await axios.get("getpageview.php");
for(let pv = 0;pv<pvobj.data.length;pv++){
  try {
    console.log("try : " + pvobj.data[pv].id);
    await axios.patch('https://yourdomain.microcms.io/api/v1/post/'+pvobj.data[pv].id,{"pv":pvobj.data[pv].pageview},{headers: { "X-MICROCMS-API-KEY": "your_microcms_key","Content-Type":"application/json" }})
  } catch (e) {
    console.log('Error!!')
  }
  console.log("done");
}


これでmicroCMSにPV数が記録されます。

問題点:
ビルドプロセスにpatch処理を入れたことで、microCMS側で設定しているGithub ActionのRepository dispatchイベントが発火され続け、Github Actionsのワークフロー一覧が大変なことになりました。





POSTイベントで自動投稿する記事があったので、API入稿もCIを走らせていましたが、今後patchを動かしていくのであればCI動いては困るので、API入稿でのCI発火は止めました。

また、このプロセス追加によってビルド時間が1分→5分くらいに伸びました
そんなにリアルタイム性が求めらていないデータなので、今後Github Actionsの無料枠を逼迫するようであればPHPにそのままpatchの処理を移管してcronでも適当に週一くらいで走らせる設計に変更しようと思います。