現代の制作会社にとって、質が高く一貫性のあるレポート体制は、クライアントからの信頼を維持し、長期的な関係を築くうえで欠かせません。明確で有益なレポートがあれば、売上傾向の把握やキャンペーン効果の可視化、さらには投資対効果(ROI)の測定まで、さまざまな分析を行えます。

しかし、数十、あるいは数百のサイトを扱う制作会社にとって、定期的なレポート作成は大きな負担になりがちです。手作業による運用は時間を奪うだけでなく、スケールの妨げにもなります。

そこで役立つのが、データ取得を効率化し、自動化することです。レポート作成を自動化することで、新規プロジェクトの提案や戦略立案など、チームがより価値の高い業務に集中できるようになります。

以下、Kinsta APIを使ってサーバーデータを自動取得し、AIを活用して戦略的なレポートを生成する方法をご紹介します。

MyKinstaとKinsta API経由でKinstaの分析データにアクセス

Kinstaをご利用の場合は、MyKinstaから豊富な分析データにアクセスできます。ダッシュボードから「分析」をクリックすると、プラン全体のデータにアクセス可能です。

MyKinstaの「分析」画面
MyKinstaの「分析」画面

分析」画面はカテゴリごとに複数のタブに分かれています。

  • プランご利用状況:累計および個々のサイトごとのプランのリソース消費量を表示
  • 上位リクエスト:サイトへの主なリクエストを帯域幅とビューで分類して表示
  • キャッシュ:キャッシュの内訳、サーバーキャッシュの構成内訳、サーバーキャッシュバイパスなど、キャッシュ使用量の内訳を表示
  • CDNとエッジ:CDNの転送量、エッジキャッシュの転送量、CDNキャッシュから配信された上位ファイルのリストに関するデータなどを表示
  • デバイス:PC、タブレット、モバイルからの訪問の割合を表示
  • パフォーマンス:PHP MySQLの平均応答時間、PHPのスループット、PHPのスレッド制限など、さまざまなパフォーマンス指標を表示
  • レスポンス:エラーコードの詳細な内訳など、レスポンスコードに関する統計情報を表示
  • 位置情報とIP:サイトへのリクエストの発信元である上位の国、上位の都市、上位のクライアントIPのリストを表示

サイト」>(サイト名)>「分析」に移動すると、サイト単位で同様の分析データを確認することができます。

MyKinstaのサイト分析
MyKinstaのサイト分析

Kinstaの分析機能は豊富なデータを提供し、MyKinsta上でサイトのリソース使用状況や効率性、パフォーマンスを直感的に把握することができます。例えば、アクセスの多い地域や、最もリソースを消費しているリクエストなどもすぐにチェック可能です。

さらに、Kinsta APMツールと組み合わせることで、WordPressサイトのパフォーマンスをより効率的に最適化することができるようになります。

また、Kinstaの分析データは、Kinsta API経由でも取得できます。そのため、分析データを自動で取得し、独自のサーバーレポートや監視システムを構築することが可能です。

続いて、Kinsta APIのエンドポイントを見ていきます。

Kinsta APIの分析エンドポイント

Kinsta APIの分析エンドポイントを使用すると、サイトのリソースの使用状況と健全性に関する生のデータにアクセスすることができます。

  • 訪問数使用量(Visit usage)、サーバー帯域幅使用量(Server bandwidth usage)、CDN転送使用量(CDN Bandwidth usage):現在の請求期間における、ホスティングプランに対する各リソースの使用状況
  • 訪問数(Visits):指定した期間内に対象環境で記録された総訪問数
  • ディスク容量(Disc space):指定した期間内に対象環境で使用されたディスク容量
  • サーバー帯域幅(Sever bandwidth):指定した期間内に対象環境で消費されたサーバー帯域幅
  • CDN転送量(CDN bandwidth):指定した期間内に対象環境で消費されたCDN帯域幅
  • 上位アクセス国(Top Countries):指定した期間内にサイトへのリクエスト元となった主要な国を一覧
  • 上位アクセス都市(Top Cities):指定した期間内にサイトへのリクエスト元となった主要な都市
  • 上位クライアントIP(Top Client IPs):指定した期間内にサイトへのリクエスト元となった主要なクライアントIPアドレス一覧
  • アクセス分布(Visit Dispersion):指定した期間内におけるPC、タブレット、モバイル別のアクセス分布
  • レスポンスコード内訳(Response Code Breakdown):指定した期間内にサーバーから返されたHTTPステータスコードの内訳

以下は、analyticsエンドポイントの使用例です。

訪問数

以下はサイトへの総訪問数と、過去30日間にアクセスしたユニークIPアドレスの数を提供します。

https://api.kinsta.com/v2/sites/environments/{KINSTA_ENV_ID}/analytics/visits?time_span=30_days&company_id={KINSTA_COMPANY_ID}。

レスポンスは以下のようになります。

{
	"analytics": {
		"analytics_response": {
			"key": "uniqueip",
			"data": [
				{
					"name": "uniqueip",
					"total": 1000,
					"dataset": [
						{
							"key": "2025-10-28T00:00:00.000Z",
							"value": "1000"
						},
						{
							"key": "2025-10-28T00:00:00.000Z",
							"value": "900"
						},
						{
							"key": "2025-10-28T00:00:00.000Z",
							"value": "820"
						},
						...
					]
				}
			]
		}
	}
}

帯域幅

以下は、Kinsta APIにクエリを実行して、過去30日間のサーバーの帯域幅使用量を取得する例です。

https://api.kinsta.com/v2/sites/environments/{KINSTA_ENV_ID}/analytics/bandwidth?time_span=30_days&company_id={KINSTA_COMPANY_ID}。

Kinstaサーバーからの以下のレスポンスで、過去30日間の毎日の帯域幅使用量を確認できます。

{
	"analytics": {
		"analytics_response": {
			"key": "bandwidth",
			"data": [
				{
					"name": "bandwidth",
					"total": 1000,
					"dataset": [
						{
							"key": "2026-03-11T00:00:00.000Z",
							"value": "37347250"
						},
						{
							"key": "2026-03-12T00:00:00.000Z",
							"value": "9276458"
						},
						...
					]
				}
			]
		}
	}
}

CDN転送量

以下は、過去7日間のCDN転送量を調べる例です。

https://api.kinsta.com/v2/sites/environments/{KINSTA_ENV_ID}/analytics/cdn-bandwidth?time_span=7_days&company_id={KINSTA_COMPANY_ID}。

サーバーから以下のようなレスポンスが返されます。

{
	"analytics": {
		"analytics_response": {
			"key": "cdn-bandwidth",
			"data": [
				{
					"name": "cdn-bandwidth",
					"total": 1000,
					"dataset": [
						{
							"key": "2026-04-02T00:00:00.000Z",
							"value": "753447"
						},
						{
							"key": "2026-04-03T00:00:00.000Z",
							"value": "16911"
						},
						...
					]
				}
			]
		}
	}
}

KinstaのAPIキー(Bearerトークン)、環境ID、企業IDをAPI Playgroundに入力すれば、実際に自分で試すことができます。

API PlaygroundでKinsta APIをテスト
API PlaygroundでKinsta APIをテスト

Kinstaでサイト分析データにアクセスする方法を押さえたところで、続いてはそのデータを使って業務を自動化する実践例をご紹介します。レポート作成の自動化も、その活用例のひとつです。

今回は、Kinsta APIを使って制作会社向けのレポート作成フローを自動化する方法を見ていきます。具体的には、Pythonスクリプトを作成し、GitHub Actionsを活用してビルドと実行を自動化していきます。APIから取得した生データを表やグラフに変換し、Google AIにクエリを送信して最終レポートを生成します。

Kinsta APIとGoogle AIを使って自動レポートシステムを構築する

一定の間隔で自動生成されるレポートシステムを構築していきます。今回は、このシステムでKinsta APIにリクエストを送信し、訪問数、サーバー帯域幅、CDN転送量に関するデータを取得します。

その後、取得したデータをもとに、PDFファイル内にグラフや表を生成します。さらに、プロセスの一環としてデータをGemini APIに送信し、抽出したデータの分析結果を生成して、最終レポートに含めます。

GitHub ActionsとKinsta APIを使って生成された自動レポートのプレビュー
GitHub ActionsとKinsta APIを使って生成された自動レポートのプレビュー

GitHubでプロジェクトをセットアップする

GitHubのホームページで、緑色の「New」をクリックして、新規プロジェクトを作成します。空のプロジェクトを作成したら、「Settings」>「Secrets and variables」>「Actions」に進み、以下のスクリーンショットに示されているシークレットを追加してください。

GitHub Actionsリポジトリのシークレット
GitHub Actionsリポジトリのシークレット

GitHubのシークレットにAPI キーとIDを保存すると、誰にもアクセスできなくなるため、コードを安全に保つことができます。

GEMINI_API_KEY

Google AI API キーは、Google AI Studioのダッシュボードで生成できます。詳しくは、Google AIのドキュメントをご覧ください。

KINSTA_API-KEY

記事の指示に従って、Kinsta APIキーを生成します。

kinsta_company_id / kinsta_env_id / kinsta_site_id

サイトID、環境ID、企業IDは、MyKinstaの「サイト」>(サイト名)>「情報」で確認できます。

 

MyKinstaのサイト情報画面
MyKinstaのサイト情報画面

必要なライブラリとGitHub Actionsの設定

GitHubプロジェクトのルートディレクトリにrequirements.txtという名前のファイルを作成し、以下を貼り付けます。

google-genai
requests
matplotlib
fpdf2

このファイルには、プロジェクトに必要なコンポーネントが列挙されています。

  • google-genai:Geminiモデルと対話するためのGoogleのライブラリ
  • requests:HTTPリクエストを行うためのライブラリで、このプロジェクトでは、Kinsta APIにHTTPリクエストを送信するために使用
  • matplotlibグラフを作成し、データを視覚化するためのPythonライブラリ
  • fpdf2PDFファイルを生成するためのライブラリ

次に、以下のコードで.github/workflows/generate_report.ymlという名前のファイルを作成します。

name: Generate Kinsta Analytics Report

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build-and-run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run Report Script
        env:
          KINSTA_API_KEY: ${{ secrets.KINSTA_API_KEY }}
          KINSTA_ENV_ID: ${{ secrets.KINSTA_ENV_ID }}
          KINSTA_SITE_ID: ${{ secrets.KINSTA_SITE_ID }}
          KINSTA_COMPANY_ID: ${{ secrets.KINSTA_COMPANY_ID }}
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        run: python main.py

      - name: Upload Report
        uses: actions/upload-artifact@v4
        with:
          name: Kinsta-Advanced-Report
          path: "*.pdf"

GitHubはこのファイルを使って、GitHub Actionsでコードを自動的に実行します。もう少し詳しく見てみましょう。

name: Generate Kinsta Analytics Report

on:
  push:
    branches: [main]
  workflow_dispatch:
  • name:GitHubの「Actions」タブに表示されるプロジェクト名
  • on:いつワークフローを起動するかを指定
  • push:コード変更をメインブランチにプッシュするたびにワークフローが実行される
  • workflow_dispatch:ワークフローを手動で実行
jobs:
  build-and-run:
    runs-on: ubuntu-latest
  • jobs:実行するタスクの開始
  • build-and-run:特定の一連のアクションを識別する任意の名前
  • run-on:ワークフローを実行するシステムを指定
  • ubuntu-latest:Ubuntu Linuxの最新バージョンを設定
steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
  • steps:実行される一連の操作
  • name:実行する操作の名前
  • uses:あらかじめ設定されているGitHub モジュール(Action)
     - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
  • python -m pip install --upgrade pip:pip (Python パッケージマネージャ)を利用可能な最新バージョンに更新
  • pip install -r requirements.txtrequirements.txtファイルを読み込み、そこに記載されているパッケージをインストール
     - name: Run Report Script
        env:
          KINSTA_API_KEY: ${{ secrets.KINSTA_API_KEY }}
          KINSTA_ENV_ID: ${{ secrets.KINSTA_ENV_ID }}
          KINSTA_SITE_ID: ${{ secrets.KINSTA_SITE_ID }}
          KINSTA_COMPANY_ID: ${{ secrets.KINSTA_COMPANY_ID }}
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        run: python main.py
  • env:GitHub Secrets から環境変数の値を取得
  • run: python main.py:Pythonインタプリタを起動してmain.pyファイルを実行
     - name: Upload Report
        uses: actions/upload-artifact@v4
        with:
          name: Kinsta-Advanced-Report
          path: "*.pdf"
  • uses: actions/upload-artifact@v4 :GitHub Actionsで、スクリプトの実行中に生成されたファイルやフォルダ(成果物/アーティファクト)を保存・管理するために使用
  • with:設定パラメーターを設定

以上でプロジェクトの設定は完了です。続いてはPythonスクリプトを作成していきます。

Kinsta APIを自動でクエリする

設定を終えたら、GitHubプロジェクトのルートディレクトリに移動し、以下のコードでkinsta_utils.pyという名前の新規ファイルを作成します。

import requests
import os

KINSTA_API_KEY = os.getenv("KINSTA_API_KEY")
KINSTA_SITE_ID = os.getenv("KINSTA_SITE_ID")
KINSTA_ENV_ID = os.getenv("KINSTA_ENV_ID")
KINSTA_COMPANY_ID = os.getenv("KINSTA_COMPANY_ID")
BASE_URL = f"https://api.kinsta.com/v2/sites/environments/{KINSTA_ENV_ID}/analytics"

def get_headers():
    return {"Authorization": f"Bearer {KINSTA_API_KEY}"}
  • 最初の2つのimport文:HTTPリクエストを行うための標準ライブラリとオペレーティングシステム(os)と対話するためのモジュールを読み込む
  • 次の4行(os.getenv):GitHubのシークレットから認証情報を取得
  • BASE_URL:スクリプトが使用するKinsta APIのメインエンドポイントを定義
  • get_headers関数:Kinsta APIキーを含むAuthorization Headerを生成

次に、APIから返された生データをメガバイトに変換するヘルパー関数を作成します。

def format_bytes_to_mb(bytes_value):
    """Converts raw bytes from API to human-readable Megabytes."""

    try:
        # Standard conversion to MB
        # return round(int(bytes_value) / (1024 * 1024), 2)

        # Decimal standard (used in MyKinsta dashboard) 
        return round(int(bytes_value) / 1_000_000, 2)

    except (ValueError, TypeError):
        return 0
  • このコードには2つのオプションあり。1つ目は2進数標準(1024 x 1024)を使用し、2つ目は10進数標準を使用する。1_000_000で割ることで、PDFレポートの数値がMyKinstaの分析画面でクライアントに表示される数値と一致するようになる。

以下の関数は、Kinsta APIにクエリし、生データのセットを返します。

def fetch_kinsta_metric(endpoint, start_date, end_date):

    url = f"{BASE_URL}/{endpoint}"

    params = {
        "company_id": KINSTA_COMPANY_ID,
        "from": f"{start_date}T00:00:00.000Z",
        "to": f"{end_date}T23:59:59.000Z"
    }

    try:
        response = requests.get(url, headers=get_headers(), params=params)
        if response.status_code == 200:
            data_node = response.json()['analytics']['analytics_response']['data'][0]
            total = data_node.get('total', 0)
            dataset = data_node.get('dataset', [])[:7]
            return total, dataset

    except Exception as e:
        print(f"Error fetching {endpoint}: {e}")

    return 0, []
  • fetch_kinsta_metric関数:endpointstart_dateend_dateの3つの引数を受け取る。これらはリクエストURLを構築するために使用。endpointには、visitsbandwidthcdn-bandwidthのいずれかを指定可能。
  • params配列には、APIリクエストに必要なパラメータが格納される
  • Kinsta APIのレスポンスは、data_node というネストされたJSONオブジェクトで返される。このオブジェクトには、指定期間の集計値(total)と、日別データの一覧(dataset)が含まれる。

kinsta_utils.pyファイルの最後の関数は、サイト名を取得します。

def fetch_site_name():
    url = f"https://api.kinsta.com/v2/sites/{KINSTA_SITE_ID}"
    
    try:
        response = requests.get(url, headers=get_headers())
        if response.status_code == 200:
            data = response.json()
            site_data = data.get('site', {})
            
            site_label = site_data.get('display_name', 'Unknown Site')
            
            env_label = "Unknown Env"
            envs = site_data.get('environments', [])
            for env in envs:
                if env.get('id') == KINSTA_ENV_ID:
                    env_label = env.get('display_name')
                    break
            
            return f"{site_label} ({env_label})"
        else:
            print(f"Kinsta API Error: {response.status_code} - {response.text}")
    except Exception as e:
        print(f"Error fetching site name: {e}")
        
    return "Unknown Site"

このコードの流れは比較的シンプルです。sitesエンドポイントの詳細はこちらをご覧ください。

あとは、ワークフローを設定するだけです。

PythonとGeminiでワークフローを自動化

最後に作成するファイルは、アプリケーションの中心となるファイルです。GitHubプロジェクトのルートディレクトリにmain.pyを作成し、まずは以下のコードを追加します。

import os
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from google.genai import Client
from fpdf import FPDF, XPos, YPos
from datetime import datetime, timedelta
from kinsta_utils import fetch_kinsta_metric, format_bytes_to_mb, fetch_site_name

REPORT_LANG = "en" 
MODEL_ID = "gemini-2.5-flash" 
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
client = Client(api_key=GEMINI_API_KEY)

today = datetime.now()
curr_end_dt = today - timedelta(days=1)
curr_start_dt = today - timedelta(days=7)
prev_end_dt = today - timedelta(days=8)
prev_start_dt = today - timedelta(days=14)

CURR_RANGE = f"{curr_start_dt.strftime('%b %d')} - {curr_end_dt.strftime('%b %d')}"
PREV_RANGE = f"{prev_start_dt.strftime('%b %d')} - {prev_end_dt.strftime('%b %d')}"

DATES = [
    prev_start_dt.strftime("%Y-%m-%d"), 
    prev_end_dt.strftime("%Y-%m-%d"), 
    curr_start_dt.strftime("%Y-%m-%d"), 
    curr_end_dt.strftime("%Y-%m-%d")
]

CURR_DAYS_LABELS = [(curr_start_dt + timedelta(days=i)).strftime("%d %a") for i in range(7)]
PREV_DAYS_LABELS = [(prev_start_dt + timedelta(days=i)).strftime("%d %a") for i in range(7)]
X_AXIS_LABELS = [(curr_start_dt + timedelta(days=i)).strftime("%d") for i in range(7)]

この部分では、スクリプトの基本設定を行っています。

  • import文で必要なライブラリを読み込み、matplotlib.use('Agg')は画面表示を行わずにグラフを生成するための設定
  • 次のブロックでは、言語(en)とモデル(gemini-2.5-flash)を指定し、Googleクライアントを初期化
  • 続いて、直近7日間のデータとその前の7日間のデータを比較するための期間を定義
  • 最後に、表やグラフで使用するラベルを設定

次のステップでは、FPDFライブラリを使ってレポートページを生成する KinstaReportクラスを定義します。

class KinstaReport(FPDF):
    def __init__(self, site_name="Unknown Site"):
        super().__init__()
        self.site_name = site_name

    def header(self):
        self.set_font("Helvetica", "B", 8)
        self.set_text_color(150)
        # Site name
        self.cell(100, 10, f"Site: {self.site_name}", align="L")
        # Date generated
        self.cell(0, 10, f"Kinsta Analytics Report | Generated: {datetime.now().strftime('%Y-%m-%d')}", 
                  align="R", new_x=XPos.LMARGIN, new_y=YPos.NEXT)

    def add_metric_page(self, title, chart_path, prev_vals, curr_vals, unit=""):
        self.add_page()
        # Page title
        self.set_font("Helvetica", "B", 24)
        self.set_text_color(83, 51, 237)
        self.cell(0, 15, title, align="C", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        
        # Subtitle
        self.set_font("Helvetica", "I", 10)
        self.set_text_color(120)
        self.cell(0, 5, f"Comparison: {CURR_RANGE} vs {PREV_RANGE}", align="C", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        
        self.image(chart_path, x=10, y=42, w=190)
        
        # Data tables
        self.set_y(150)
        self.set_font("Helvetica", "B", 10)
        self.set_fill_color(245, 245, 255)
        self.set_text_color(83, 51, 237)
        
        # Table header
        col1, col2 = 35, 60
        self.cell(col1, 10, " Day (Prev)", border=1, align='C', fill=True, new_x=XPos.RIGHT, new_y=YPos.TOP)
        self.cell(col2, 10, f"Value {unit}", border=1, align='C', fill=True, new_x=XPos.RIGHT, new_y=YPos.TOP)
        self.cell(col1, 10, " Day (Curr)", border=1, align='C', fill=True, new_x=XPos.RIGHT, new_y=YPos.TOP)
        self.cell(col2, 10, f"Value {unit}", border=1, align='C', fill=True, new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        
        self.set_font("Helvetica", "", 10)
        self.set_text_color(50)
        for i in range(7):
            # Zebra striping
            fill = (i % 2 == 0)
            if fill: self.set_fill_color(250, 250, 250)
            else: self.set_fill_color(255, 255, 255)
            
            self.cell(col1, 9, f" {PREV_DAYS_LABELS[i]}", border=1, align='C', fill=fill, new_x=XPos.RIGHT, new_y=YPos.TOP)
            self.cell(col2, 9, f" {prev_vals[i]}", border=1, align='C', fill=fill, new_x=XPos.RIGHT, new_y=YPos.TOP)
            self.cell(col1, 9, f" {CURR_DAYS_LABELS[i]}", border=1, align='C', fill=fill, new_x=XPos.RIGHT, new_y=YPos.TOP)
            self.cell(col2, 9, f" {curr_vals[i]}", border=1, align='C', fill=fill, new_x=XPos.LMARGIN, new_y=YPos.NEXT)

このコードの詳細は割愛します。FPDFライブラリの詳細については、以下のリソースをご覧ください。

次に、generated_chart関数を定義します。この関数は、Kinstaから受け取った生データをチャートに変換します。

def generate_chart(labels, curr, prev, title, ylabel, filename, is_bar=False):
    plt.figure(figsize=(10, 5), dpi=100)
    ax = plt.gca()
    
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_color('#dddddd')
    ax.spines['bottom'].set_color('#dddddd')

    if is_bar:
        # Bar Chart for bandwidth
        bars = plt.bar(labels, curr, color='#00c4b4', alpha=0.6, label='Current Period', width=0.6)
        # Add labels above the bars
        for bar in bars:
            height = bar.get_height()
            plt.text(bar.get_x() bar.get_width()/2., height 0.02, f'{height}', ha='center', va='bottom', fontsize=8, color='#00a194')
    else:
        # Line chart for visits
        plt.plot(labels, curr, color='#5333ed', marker='o', markersize=6, linewidth=3, label='Current', zorder=3)
        plt.plot(labels, prev, color='#a1a1a1', linestyle='--', marker='x', markersize=5, linewidth=1.5, label='Previous', alpha=0.6)
        
        plt.fill_between(labels, curr, color='#5333ed', alpha=0.1)
    
    plt.title(title, fontsize=14, pad=20, color='#333333', fontweight='bold')
    plt.ylabel(ylabel, color='#666666')
    plt.xlabel("Day of Month", color='#666666')
    plt.legend(frameon=False, loc='upper right')
    plt.grid(axis='y', linestyle='--', alpha=0.3)
    plt.tight_layout()
    plt.savefig(filename)
    plt.close()

この関数では、Matplotlibライブラリを使用して、Kinstaから取得したデータをグラフに変換し、PDFレポートに挿入できるようにします。Matplotlibライブラリの使い方については、以下の公式ドキュメントをご参照ください。

最後に、ここまで説明してきた各パーツをまとめる関数を追加します。

def main():
    site_display_name = fetch_site_name()

    metrics = {
        "visits": {"title": "Site Visits", "unit": ""},
        "bandwidth": {"title": "Server Bandwidth", "unit": "(MB)"},
        "cdn-bandwidth": {"title": "CDN Bandwidth", "unit": "(MB)"}
    }
    
    report_data = {}
    for key in metrics:
        _, data_curr = fetch_kinsta_metric(key, DATES[2], DATES[3])
        _, data_prev = fetch_kinsta_metric(key, DATES[0], DATES[1])
        
        curr_vals = []
        prev_vals = []
        for i in range(7):
            c = float(data_curr[i]['value']) if i < len(data_curr) else 0
            p = float(data_prev[i]['value']) if i < len(data_prev) else 0
            
            if "bandwidth" in key:
                curr_vals.append(format_bytes_to_mb(c))
                prev_vals.append(format_bytes_to_mb(p))
            else:
                curr_vals.append(int(c))
                prev_vals.append(int(p))
                
        report_data[key] = {"curr": curr_vals, "prev": prev_vals}

    pdf = KinstaReport(site_name=site_display_name)
    
    for key, info in metrics.items():
        chart_file = f"{key}_chart.png"
        generate_chart(X_AXIS_LABELS, report_data[key]["curr"], report_data[key]["prev"], 
                       f"{info['title']} Trends", "Units", chart_file, is_bar=("bandwidth" in key))
        pdf.add_metric_page(info["title"], chart_file, report_data[key]["prev"], report_data[key]["curr"], info["unit"])

    # Executive Summary
    pdf.add_page()
    pdf.set_font("Helvetica", "B", 20)
    pdf.set_text_color(83, 51, 237)
    pdf.cell(0, 15, "Executive Summary", align="C", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
    
    curr_visits = sum(report_data['visits']['curr'])
    prev_visits = sum(report_data['visits']['prev'])
    curr_bw = sum(report_data['bandwidth']['curr'])
    prev_bw = sum(report_data['bandwidth']['prev'])

    try:
        summary_prompt = (
            f"Analyze Kinsta performance for site {site_display_name}. "
            f"Current Period ({CURR_RANGE}): {curr_visits} visits, {curr_bw:.2f}MB server bandwidth. "
            f"Previous Period ({PREV_RANGE}): {prev_visits} visits, {prev_bw:.2f}MB server bandwidth. "
            f"Compare these periods and identify trends. Language: {REPORT_LANG}. Max 4 sentences."
        )
        response = client.models.generate_content(model=MODEL_ID, contents=summary_prompt)
        summary = response.text
    except Exception as e:
        summary = f"Analytical insights unavailable. Error: {str(e)}"

    pdf.set_y(40)
    pdf.set_font("Helvetica", "", 12)
    pdf.set_text_color(0)
    pdf.multi_cell(0, 8, summary)
    
    report_filename = f"Kinsta_Report_{datetime.now().strftime('%Y-%m-%d')}.pdf"
    pdf.output(report_filename)
    print(f"Report generated: {report_filename}")

if __name__ == "__main__":
    main()

このコードでは、以下の処理を行っています。

  • forループで metrics配列を順に処理し、Kinsta APIに2回リクエストを送信。1回目は現在の週、2回目は前の週のデータを取得する。
  • データが帯域幅に関するものである場合は、format_bytes_to_mb()関数を使って生データをMBに変換
  • report_data()関数で取得したデータを保存し、その後KinstaReportがサイトごとにPDFを作成
  • 次のfor ループでは、グラフ用のPNG画像を生成し、指標ごとに新しいページを作成
  • 次のセクションでは、エグゼクティブサマリーを生成。対象期間の総訪問数と合計メガバイト数を計算し、Gemini 2.5 Flashに動的なプロンプトを送信。最後に、そのレスポンスを使ってPDFの最終ページを完成させる。
  • スクリプトは、現在の日付を含むファイル名でドキュメントを保存
  • 最後の条件により、この処理はスクリプトがメインプログラムとして実行された場合にのみ実行

いよいよ、アプリケーションをビルドして実行してみます。

アーティファクトを取得

これで、アプリケーションを実行できるようになりました。GitHubプロジェクトページで「Actions」タブをクリックします。左側のメニューから、作成したアクション名を探します。この例では、generate_report.ymlファイルで指定した「Generate Kinsta Analytics Report」です。

Actionsタブに表示されるワークフローの一覧
Actionsタブに表示されるワークフローの一覧

次に、右側にある「Run workflow」メニューをクリックし、緑色の「Run workflow」をクリックします(現在利用できるのはmainブランチのみ)。

GitHubワークフローを実行
GitHubワークフローを実行

次のページには、現在のワークフローが表示されます。クリックすると、実行中の処理一覧を確認できます。

ブランチからワークフローを使う
ブランチからワークフローを使う

Run Report Script」セクションでは、実行された処理の一覧を確認できます。一方、「Upload Report」セクションには、生成されたアーティファクトのダウンロードリンクが表示されます。このリンクをクリックすると、PDF形式のレポートをダウンロードできます。

Upload Reportセクションに生成されたPDFレポートへのリンクが表示される
Upload Reportセクションに生成されたPDFレポートへのリンクが表示される

同じリンクは、ワークフローの「Summary」ページ下部にある「Artifacts」セクションからも確認できます。

Run Report ScriptとUpload Reportアクション
Run Report ScriptとUpload Reportアクション

以下は、Google AIによって生成された「エグゼクティブサマリー」を含む、完成したレポート全体です。

サイト訪問数とサーバー帯域幅のレポートページ
サイト訪問数とサーバー帯域幅のレポートページ
CDN転送量とエグゼクティブサマリーのレポートページ
CDN転送量とエグゼクティブサマリーのレポートページ

次のステップは拡張性を高めて配信を自動化

ここで紹介した内容は、Kinsta APIとGitHub Actionsのような高度な自動化ツールを組み合わせることで実現できることのほんの一例です。さらにAIを連携させることで、生の数値データを、クライアントにそのまま共有できる詳細なレポートへと変換できます。

レポートシステムは、以下のような方法でさらに改善できます。

  • YAMLファイルにschedule: '0 9 * * 1'を追加し、毎週月曜日の午前9時にレポートを生成するよう設定できる。
  • smtplibのようなライブラリやSendGridなどのサービスを連携させ、レポートをクライアントに直接送信できる。
  • 数十〜数百のサイトを管理する制作会社であれば、サイトIDのリストをループ処理し、1回の実行ですべてのレポートを生成可能。
  • Kinsta APIを使って、地域別データ、HTTPコードの内訳、サーバーログなど、レポートに含めたい追加データを取得することで、内容をさらに充実させることができる。これらのデータをAIで分析すれば、攻撃の可能性があるリクエスト(400番台コード)や、想定外の地域からのトラフィック急増などを検出可能。
  • プロンプトを調整することで、AIによる分析結果をより詳細で包括的なものに。
  • 自社やクライアントのロゴを入れて、PDFテンプレートをカスタマイズすることもできる。

レポート作成を自動化することで、チームの作業負担を軽減できます。また、一貫性と正確性の高いレポートを継続的に提供することで、クライアントからの信頼とロイヤリティの向上にもつながります。

Kinstaでクライアント向けレポートを自動化しませんか?ビジネス要件に適したプランを選んで、Kinsta APIを使った構築を行ってみてください。

Carlo Daniele Kinsta

ウェブデザインとフロントエンド開発をこよなく愛し、WordPress歴は10年以上。イタリアおよびヨーロッパの大学や教育機関とも共同研究を行う。WordPressに関する記事を何十件も執筆しており、イタリア国内外のウェブサイトや雑誌に掲載されている。詳しい仕事情報はXとLinkedInで公開中。