そこまで有益ではない記事
API を利用するまで
ご存じの通り、YouTube の所有者は Google です。
Google API は基本的には OAuth 2.0 による認可を経て、API を利用するためのトークン(以下、アクセストークン)を取得し、
リクエスト毎にアクセストークンを投げることで API の利用を可能にします。
ちなみに、Google API では OAuth 2.0 を利用しないフローの 1 つにサービスアカウントがありますが、
YouTube Analytics/Reporting API はサービスアカウントフローを利用できません。
https://developers.google.com/youtube/reporting/guides/authorization?hl=ja
サービス アカウント向け OAuth 2.0 フローは、ユーザー情報にアクセスしないサーバー間のやり取りをサポートします。
YouTube Reporting API と YouTube Analytics API は、このフローをサポートしていません。
準備
まずは普通にチャンネルを取得します。
GCP にアクセスし、プロジェクトを作成します。
次に、以下の URL から YouTube Analytics/Reporting API を有効にします。
https://console.cloud.google.com/apis/library/youtubeanalytics.googleapis.com?hl=ja
https://console.cloud.google.com/apis/library/youtubereporting.googleapis.com?hl=ja
更に、認証情報 > 同意画面を構成 より、OAuth 同意画面を作成します。
User Type は可能な限り内部をおすすめしますが、今回は外部にし、テストユーザーに 1 つ追加します。
スコープは以下を追加しました。
https://www.googleapis.com/auth/yt-analytics.readonly
https://www.googleapis.com/auth/yt-analytics-monetary.readonly
https://www.googleapis.com/auth/youtube
https://www.googleapis.com/auth/youtubepartner
次に、 認証情報 > OAuth クライアント ID の作成 をします。
ウェブアプリケーションを指定し、
承認済みのリダイレクト URI に http://localhost:8000/callback.php を指定しました。
この時、認証情報を json でダウンロードし、client_secret.json にリネームします。
認証
PHP 用のクライアントライブラリを composer でインストールします。
$ composer require google/apiclient:^2.12.1
php ファイルを作成し、まずは認証をするための URL を発行します。
同じディレクトリに client_secret.json を設置します。
// youtube.php require 'vendor/autoload.php'; use Google_Client as Client; $client = new Client(); $client->setAuthConfig(__DIR__ . '/client_secret.json'); $client->setScopes([ 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner', ]); $client->setRedirectUri('http://localhost:8000/callback.php'); $client->setAccessType('offline'); print_r($client->createAuthUrl() . "\n");
Google_Client の createAuthUrl() で認証 URL を作成します。
認証 URL にはクエリパラメータが付与されており、セットしたクライアント ID やスコープ等のデータが付属しています。
作成された URL をブラウザ上で開き、通常通り認証します。
スコープは基本的には全て選択します。
認証が完了すると、事前に指定したリダイレクト URL
http://localhost:8000/callback.php)にクエリパラメータが付与された URL にリダイレクトされます。
現時点では当然 404 なはずです。
この時のリダイレクト URL には認可コード(Authorization Code)とブラウザ上で選択したスコープが付与されています。
アクセストークンの取得
まず、リダイレクト URL に指定した callback.php を作成します。
いろいろ不要なパラメータがありそうなんですが特に検証はしてないです。
require 'vendor/autoload.php'; use Google_Client as Client; $client = new Client(); $client->setAuthConfig(__DIR__ . '/client_secret.json'); $client->setScopes([ 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner', ]); $client->setRedirectUri('http://localhost:8000/callback.php'); $client->setAccessType('offline'); print_r($client->fetchAccessTokenWithAuthCode($_GET['code']));
次に PHP のビルドインサーバをローカルに立てます。
下記のコマンドを実行します。
// t オプションで指定したディレクトリのファイルを実行できるようにする $ php -S localhost:8000 -t .
この状態で先ほど 404 を踏んだリダイレクト URL(クエリパラメータ付き)に GET リクエストします。
$ curl http://localhost:8000/callback.php?code=xxx&scope=xxx
fetchAccessTokenWithAuthCode() の戻り値は単純な array で、内容は以下のようになっています。
これでアクセストークン(およびリフレッシュトークン)を取得できました。
access_token: string expires_in: int refresh_token: string scope: "https://www.googleapis.com/auth/youtubepartner https://www.googleapis.com/auth/yt-analytics-monetary.readonly https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/youtube" token_type: "Bearer" created: int
ここで取得したアクセストークンには期限があり、expires_in で指定された時間分だけ利用ができます。
期限が切れた場合、リフレッシュトークンを利用して再度アクセストークンを取得する必要があります。
print_r($client->fetchAccessTokenWithRefreshToken({{ 先ほど取得したリフレッシュトークン
}}));
リフレッシュトークンは通常無期限で使用できますが、以下のルールで失効する場合があります。
https://developers.google.com/identity/protocols/oauth2?hl=ja#expiration
リフレッシュトークンはアクセスタイプが offline かつ初回の認証時でなければ発行されない
2 回目以降の認証ではどう頑張ってもリフレッシュトークンが発行されません。
もし誤ってリフレッシュトークンを発行できなかった、または発行したけど紛失した場合は以下の URL から一度権限を削除する必要があります。
https://myaccount.google.com/u/0/permissions
API の利用
use Google_Client as Client; use Google_Service_YouTubeAnalytics; $client = new Client(); $client->setAuthConfig(__DIR__ . '/client_secret.json'); $client->setAccessToken({{ 先ほど取得したアクセストークン }}); $client->setScopes([ 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/yt-analytics-monetary.readonly', 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtubepartner', 'https://www.googleapis.com/auth/adsense.readonly', ]); $client->setRedirectUri('http://localhost:8000/callback.php'); $client->setAccessType('offline'); $analytics = new Google_Service_YouTubeAnalytics($client); $result = $analytics->reports->query([ 'ids' => 'channel=={{ チャンネル ID }}', 'startDate' => '2023-06-18', 'endDate' => '2023-06-30', 'metrics' => 'views,comments', 'dimensions' => 'day', ]);
雑多
アクセストークンの期限が切れているかどうかをどのようにチェックするか
一応、Google_Client には isAccessTokenExpired() といういかにも期限切れかどうかを判定するメソッドが用意されているのですが、
実装を見ると、Google_Client インスタンスの token 配列に expires_in が含まれていて、かつ現在が期限内かどうかを確かめるという、
簡単に言えばサーバに直接見に行くものではないので正直あまり使えないものになっています。
(実際にアプリで運用するならアクセストークンを取得しない場合のリクエストの方が大半だろうし)
API にリクエストが飛ぶメソッドを実行したタイミングで、try-catch 使って例外捕まえるのが一番楽な気がしてます。
期限切れの際は 401 エラーが返却されることだけ分かっています。
use Google\Service\Exception as GoogleServiceException; try { $result = $analytics->reports->query([ 'ids' => 'channel=={{ チャンネル ID }}', 'startDate' => '2023-06-18', 'endDate' => '2023-06-30', 'metrics' => 'views,comments', 'dimensions' => 'day', ]); } catch (GoogleServiceException $e) { // これもうちょっといい特定方法ないのか if ($e->getCode() === 401) { print_r($e->getErrors()[0]); } exit; }
Analytics API と Reporting API の違い
あんまり調べてない。
Analytics は即時にコメント数とか再生数のデータを json で取得できて、
Reporting はデータを CSV で出力するためのジョブを発行して、後ほど CSV ファイルのダウンロード URL を取得できる、ということらしいです。たぶん CSV は日次発行です。
あと、metrics 等を見ると Reporting API の方が取得できるデータの種類が充実しているように見えます。
PHP 用 API クライアントは 各 API へどのメソッドで HTTP リクエストを飛ばすのか
YouTube Analytics だと $analytics->reports->query() だったり、
Google Adsense だと $adsense->accounts_reports->generate() だったりでバラバラです。
基本的に各 API のリファレンス通りだったりするので、ブラウザでそれらを読むのもいいですし、
vendor/google/apiclient-services/src 直下の各 API に相当するクラスのコンストラクタを見るのが一番直感的だったりもします。