はじめに
GASでYouTubeアナリティクスを使って動画がショート動画かを判別する。
動画の種類ごとにシートを分けてスプレッドシートに出力する。
この記事ではYouTube Analytics APIについて解説していきます。
自分のチャンネルで投稿しているすべての動画に対して特定の期間の動画情報を取得する方法、トラフィックソースの取得は以下の記事にまとめています。
目的
動画の種類を判別しシートを分けてスプレッドシートで管理したい。
コーディング
まずは実際のコードをご覧ください。
エラー処理等は割愛しています。
以下の項目で解説していきます。
/**
* チャンネルが投稿したすべての動画から必要な情報をスプシに出力
*/
function getAndOutputChannelInfo() {
// チャンネルが投稿した動画のプレイリストIDを取得
const channel = YouTube.Channels.list(
'contentDetails', {
mine: true
});
const {contentDetails} = channel.items[0];
// プレイリストID
const playListId = contentDetails.relatedPlaylists.uploads;
// チャンネル内のすべての動画のIDを取得する
const videoIds = getVideoIds(playListId);
// creatorContentType(動画の種類)を取得
const contentTypeList = YouTubeAnalytics.Reports.query({
ids: 'channel==MINE',
dimensions: 'video,creatorContentType',
startDate: new Date(Date.now() - 365*24*60*60*1000).toLocaleDateString('sv-SE'), // 365日前の日付
endDate: new Date().toLocaleDateString('sv-SE'), // 今日の日付
maxResults: 25,
filters: `video==${videoIds.join(',')}`,
metrics: 'views',
sort: '-views'
});
// creatorContentTypeからショート動画か判別
const shortVideoIds = [];
const videoOnDemandIds = [];
for (let contentType of contentTypeList.rows) {
if (contentType[1] && contentType[1] === 'shorts') {
shortVideoIds.push(contentType[0]);
} else if (contentType[1] && contentType[1] === 'videoOnDemand') {
videoOnDemandIds.push(contentType[0]);
}
}
// 動画の情報を取得し必要なデータを抽出
const outputVideosData = createOutputData(videoOnDemandIds);
// ショート動画の情報を取得し必要なデータを抽出
const outputShortVideosData = createOutputData(shortVideoIds);
// スプシに出力
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const videoSheet = spreadSheet.getSheetByName('動画');
const shortVideoSheet = spreadSheet.getSheetByName('ショート動画');
exportSpreadsheet(videoSheet, outputVideosData);
exportSpreadsheet(shortVideoSheet, outputShortVideosData);
}
/**
* チャンネル内のすべての動画のIDを取得する
*/
function getVideoIds(id, pageToken) {
const playlistItemsInfo = YouTube.PlaylistItems.list([
'contentDetails'
], {
'playlistId': id,
'maxResults': 50,
pageToken,
});
let videoIds = playlistItemsInfo.items.map(item => item.contentDetails.videoId);
const nextPageToken = playlistItemsInfo.nextPageToken;
if (nextPageToken) {
videoIds = [...videoIds, ...getVideoIds(id, nextPageToken)];
}
return videoIds;
}
/**
* 動画情報を取得する
*/
function getVideos(ids) {
let videos = [];
for(let i = 0, l = ids.length; i < l; i++) {
const videoInfo = YouTube.Videos.list([
'snippet',
'statistics',
], {
'id': ids[i].join(','),
});
videos = [...videos, ...videoInfo.items];
}
return videos;
}
/**
* 第1引数のarrayを第2引数指定したnumberで区切って返す
*/
function sliceByNumber(array, number) {
const length = Math.ceil(array.length / number);
return new Array(length).fill().map((_, i) =>
array.slice(i * number, (i + 1) * number)
)
}
/**
* スプシ出力用のデータを作成
*/
function createOutputData(ids) {
// 詳細データを取得
const videos = getVideos(sliceByNumber(ids, 50));
// 詳細データを追加
const videoInfos = [];
videos.map((item) => {
videoInfos.push([
item.id, // 動画ID
item.snippet.title, // 動画タイトル
Utilities.formatDate(new Date(item.snippet.publishedAt), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm'), // 投稿日
item.statistics.viewCount || 0, // 再生回数
item.statistics.likeCount || 0, // 高評価の数
item.statistics.commentCount || 0, // コメントの数
`https://www.youtube.com/watch?v=${item.id}` // 動画URL
])
});
return videoInfos;
}
/**
* スプシに出力
*/
function exportSpreadsheet(sheet, outputData) {
sheet.getRange(1, 1, 1, 7).setValues([['動画id', 'タイトル', '投稿日', '再生回数', '高評価', 'コメント', '動画URL']]);
sheet.getRange(2, 1, outputData.length, 7).setValues(outputData);
}
動画がショート動画か判別
前回の記事とおおまかに違う部分は以下のみですので、こちらを解説していきます。
// creatorContentType(動画の種類)を取得
const contentTypeList = YouTubeAnalytics.Reports.query({
ids: 'channel==MINE',
dimensions: 'video,creatorContentType',
startDate: new Date(Date.now() - 365*24*60*60*1000).toLocaleDateString('sv-SE'), // 365日前の日付
endDate: new Date().toLocaleDateString('sv-SE'), // 今日の日付
maxResults: 25,
filters: `video==${videoIds.join(',')}`,
metrics: 'views',
sort: '-views'
});
// creatorContentTypeからショート動画か判別
const shortVideoIds = [];
const videoOnDemandIds = [];
for (let contentType of contentTypeList.rows) {
if (contentType[1] && contentType[1] === 'shorts') {
shortVideoIds.push(contentType[0]);
} else if (contentType[1] && contentType[1] === 'videoOnDemand') {
videoOnDemandIds.push(contentType[0]);
}
}
まずYouTube Data APIでは判別ができないので、YouTube Analytics APIのcreatorContentTypeを取得しています。
creatorContentTypeの種類は以下のようになっています。
| type | 説明 |
|---|---|
| LIVE_STREAM | ライブ配信 |
| SHORTS | ショート |
| STORY | ストーリーズ |
| VIDEO_ON_DEMAND | 他のディメンション値のいずれにも該当しない動画 |
| UNSPECIFIED | コンテンツ タイプが不明 |
取得項目の内容からdimensionsにはvideoとcreatorContentTypeを設定しています。
startDateとendDateは必須項目ですが本記事では期間を一年以内に投稿した動画を対象にしています。
お好きな期間に変更してください。
YouTube Analytics APIの詳細は以下のリファレンスをご覧ください。
あとは動画とショートそれぞれの配列から詳細データを取得し、
// 動画の情報を取得し必要なデータを抽出
const outputVideosData = createOutputData(videoOnDemandIds);
// ショート動画の情報を取得し必要なデータを抽出
const outputShortVideosData = createOutputData(shortVideoIds);
シートを分けて出力しています。
// スプシに出力
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const videoSheet = spreadSheet.getSheetByName('動画');
const shortVideoSheet = spreadSheet.getSheetByName('ショート動画');
exportSpreadsheet(videoSheet, outputVideosData);
exportSpreadsheet(shortVideoSheet, outputShortVideosData);
最後に
細かい解説は省いていますが、ソースに必要なコメントは残しているので、順を追って理解することができるかと思います。
YouTube Data APIよりYouTube Analytics APIのほうがとっつきにくい感じはありました。
動画がショート動画かどうかの判別方法は、はじめ調べてもすぐに分からずリファレンスを読み漁りました。
誰かのお役に立てると幸いです。

