MCC配下のアカウントサマリーレポート

更新履歴

2024/02/26 V202402に対応

スクリプトの概要

Yahoo!広告スクリプトでは、Googleスプレッドシートに各種レポートを直接出力することが可能です。
本スクリプトは、MCCアカウントに、Yahoo! 検索広告用とYahoo! ディスプレイ広告用でそれぞれ分けて設定することを想定したもので、MCC配下の各アカウントの主要な指標の月単位のレポートをGoogleスプレッドシートに出力します。
集計する月単位の期間は以下の3つより選択可能です。ただし、月初に「今月(今日を含まない)」で実行された場合は先月分のレポートを出力します。
・今月(今日を含まない)
・先月
・先々月

ご注意

このスクリプトでは、配信設定がオンになっているアカウントの実績のみが出力されます。
また、レポートのヘッダーは出力されません。

レポートに出力する項目のカスタマイズ

本スクリプトでは、デフォルトで以下の項目をレポートに出力します。
・アカウントID
・アカウント名
・インプレッション数
・クリック数
・クリック率
・コスト
・平均クリック単価
・コンバージョン数
・コンバージョン率
・コンバージョン単価
・インプレッションシェア

この中で不要な項目がある場合、以下配列内から削除してください。

検索広告の場合


const   REPORT_FIELDS_YSA   =   ['ACCOUNT_ID',   'ACCOUNT_NAME',   'IMPS',   'CLICKS', 'CLICK_RATE',     'COST',     'AVG_CPC',     'CONVERSIONS',     'CONV_RATE',     'COST_PER_CONV', 'IMPRESSION_SHARE'];
また、加えたい項目がある場合は、以下のCSVをご参照いただき、上記配列に対象の項目を追加してください。
https://ads-developers.yahoo.co.jp/reference/ads-search-api/v13/ReportDefinitionService/reports/v13/ACCOUNT.csv

ディスプレイ広告の場合


const   REPORT_FIELDS_YDA   = ['ACCOUNT_ID',   'ACCOUNT_NAME',   'IMPS',   'CLICKS', 'CLICK_RATE',     'COST',     'AVG_CPC',     'CONVERSIONS',     'CONV_RATE',     'COST_PER_CONV', 'IMPRESSION_SHARE'];
ディスプレイ広告にも、検索広告と同様に加えたい項目がある場合は以下のCSVをご参照ください。
https://ads-developers.yahoo.co.jp/reference/ads-display-api/v13/ReportDefinitionService/reports/v13/AD.csv

必要な設定

スクリプト一覧画面右上の「外部ツール連携」より、Googleアカウントとの連携を事前に完了しておいてください。

ご注意

Yahoo!広告スクリプトの実行処理時間には10分以内と言う制限があるため、MCCに紐づくアカウント数が多すぎる場合はレポート出力処理が完了せずに実行が中断されてしまいます(タイムアウト)。これにより、MCC配下の全てのアカウントのレポート出力が完了しない場合は、MCCを分ける、コードをカスタマイズする、といった対策をお客様側で行っていただき、タイムアウトを回避していただきますようお願いいたします。

サンプルコード

検索広告


/*
■スクリプト内容
MCCに紐づく検索広告アカウントに対して、「今日を含まない今月(実行日が1日なら前月)分」、「先月分」「先々月分」のいずれかのレポートをスプレッドシートに出力します。
■利用方法
1.当スクリプトを、検索広告のスクリプトとしてください。
2.各定数を以下のように設定してください。
・SPREAD_SHEET_ID:スプレッドシートID
・SPREAD_SHEET_NAME:シート名
・MONTHS_AGO:何か月前の分のレポート取得するか、0-2の整数で指定。今月分(昨日まで)なら0。先月分なら1、先々月分なら2。
(0の指定時、スクリプト起動した日が1日のときは先月分のレポートを取得し、1日以外のときは、今月分のレポートを取得します)
・REPORT_FIELDS_YSA:レポート出力するフィールド名を配列で記載。(フィールド名は以下を確認してください)
 https://ads-developers.yahoo.co.jp/reference/ads-search-api/v13/ReportDefinitionService/reports/v13/ACCOUNT.csv
■制限事項
このスクリプトでは、配信設定がオンになっているアカウントの実績のみが出力されます。
*/
const SPREAD_SHEET_ID = 'スプレッドシートID';
const SHEET_NAME = 'シート名';
let MONTHS_AGO = 0;
const REPORT_FIELDS_YSA = [
  'ACCOUNT_ID', //アカウントID
  'ACCOUNT_NAME', //アカウント名
  'IMPS', //インプレッション数
  'CLICKS', //クリック数
  'CLICK_RATE', //クリック率
  'COST', //コスト
  'AVG_CPC', //平均クリック単価
  'CONVERSIONS', //コンバージョン数
  'CONV_RATE', //コンバージョン率
  'COST_PER_CONV', //コンバージョン単価
  'IMPRESSION_SHARE', //インプレッションシェア
];
const mccAccountId = AdsUtilities.getCurrentAccountId();
function main() {
  if (MONTHS_AGO < 0 || MONTHS_AGO > 2 || Number.isInteger(MONTHS_AGO) == false) {
    throw new Error('MONTHS_AGOを、0-2の整数で指定してください');
  }
  writeToSpreadsheet();
}
//YSAレポートをスプレッドシートに書き込み
function writeToSpreadsheet() {
  //MCC内のYSA用のaccountIdsを取得する
  let accountIds = getAccountIds();
  if (accountIds.length == 0) return;
  //deliveryStatusがActiveのアカウントIDを抜き出す
  accountIds = getAccountIdsActive(accountIds);
  if (accountIds.length == 0) return;
  //レポートを取得する
  let reportData = getSearchReport(accountIds);
  //レポート書き込みシート
  let sh = SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheetByName(SHEET_NAME);
  //レポートが表頭を入れて1より大きければ、スプレッドシートに結果を貼り付け
  if (reportData.length > 1) {
    sh.clear();
    sh.getRange(1, 1).setValues(reportData);
  }
}
//MCC内のYSA用のaccountIdsを取得する
function getAccountIds() {
  let accountIds = [];
  let num = 0;
  while (true) {
    const accountLinks = Search.AccountLinkService.get({
      mccAccountId: mccAccountId,
      accountStatuses: ['SERVING'],
      numberResults: 500,
      startIndex: num * 500 + 1,
    }).rval;
    if (accountLinks.totalNumEntries == 0) break;
    for (let i = 0; i < accountLinks.values.length; i++) {
      accountIds.push(accountLinks.values[i].accountLink.accountId);
    }
    num++;
    if (num * 500 >= accountLinks.totalNumEntries) break;
  }
  return accountIds;
}
//deliveryStatusがActiveのアカウントIDを抜き出す
function getAccountIdsActive(accountIds) {
  let accountIdsActive = [];
  let num = 0;
  while (true) {
    const accounts = Search.AccountService.get({
      accountIds: accountIds.slice(num * 200, Math.min((num + 1) * 200, accountIds.length)),
    }).rval;
    for (let i = 0; i < accounts.values.length; i++) {
      let account = accounts.values[i].account;
      if (account.deliveryStatus == 'ACTIVE') {
        accountIdsActive.push(account.accountId);
      }
    }
    num++;
    if (num * 200 >= accountIds.length) break;
  }
  return accountIdsActive;
}
//YSAのレポートを取得
function getSearchReport(accountIds) {
  let reportData = [];
  //レポート取得の開始日と終了日を取得する
  let dateString = getDateString();
  for (let i = 0; i < accountIds.length; i++) {
    //レポートを取得する
    const reports = AdsUtilities.getSearchReport({
      accountId: accountIds[i],
      dateRange: {
        startDate: dateString.startDateString,
        endDate: dateString.endDateString,
      },
      reportType: 'ACCOUNT',
      fields: REPORT_FIELDS_YSA,
      reportDateRangeType: 'CUSTOM_DATE',
    }).reports[0].rows;
    //レポートをreportDataにマージする
    reportData = reportData.concat(reports);
  }
  return reportData;
}
//レポートの開始日と終了日を取得する
function getDateString() {
  let jstNow = new Date(Date.now() + ((new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000));
  let day = Utilities.formatDate(jstNow, 'GMT', 'd');
  if (MONTHS_AGO == 0 && day == 1) {
    MONTHS_AGO = 1;
  }
  let startDateString;
  let endDateString;
  if (MONTHS_AGO == 0) {
    jstNow.setDate(jstNow.getDate() - 1);
    endDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
    jstNow.setDate(1);
    startDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
  } else {
    jstNow.setDate(1);
    jstNow.setMonth(jstNow.getMonth() - MONTHS_AGO);
    startDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
    jstNow.setMonth(jstNow.getMonth() + 1);
    jstNow.setDate(jstNow.getDate() - 1);
    endDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
  }
  return { startDateString: startDateString, endDateString: endDateString };
}

ディスプレイ広告


/*
■スクリプト内容
MCCに紐づくディスプレイ広告アカウントに対して、「今日を含まない今月(実行日が1日なら前月)分」、「先月分」、「先々月分のレポート」のいずれかを、スプレッドシートに出力します。
■利用方法
1.当スクリプトを、ディスプレイ広告のスクリプトとしてください。
2.各定数を以下のように設定してください。
・SPREAD_SHEET_ID:スプレッドシートID
・SHEET_NAME:シート名
・MONTHS_AGO:何か月前の分のレポート取得するか、0-2の整数で指定。今月分(昨日まで)なら0。先月分なら1、先々月分なら2。
(0の指定時、スクリプト起動した日が1日のときは先月分のレポートを取得し、1日以外のときは、今月分のレポートを取得します)
・REPORT_FIELDS_YDA:レポート出力するフィールド名を配列で記載。(フィールド名は以下を確認してください)
 https://ads-developers.yahoo.co.jp/reference/ads-display-api/v13/ReportDefinitionService/reports/v13/AD.csv
■制限事項
このスクリプトでは、配信設定がオンになっているアカウントの実績のみが出力されます。
*/
const SPREAD_SHEET_ID = 'スプレッドシートID';
const SHEET_NAME = 'シート名';
let MONTHS_AGO = 0;
const REPORT_FIELDS_YDA = [
  'ACCOUNT_ID', //アカウントID
  'ACCOUNT_NAME', //アカウント名
  'IMPS', //インプレッション数
  'CLICKS', //クリック数
  'CLICK_RATE', //クリック率
  'COST', //コスト
  'AVG_CPC', //平均クリック単価
  'CONVERSIONS', //コンバージョン数
  'CONV_RATE', //コンバージョン率
  'COST_PER_CONV', //コンバージョン単価
  'IMPRESSION_SHARE', //インプレッションシェア
];
const mccAccountId = AdsUtilities.getCurrentAccountId();
function main() {
  if (MONTHS_AGO < 0 || MONTHS_AGO > 2 || Number.isInteger(MONTHS_AGO) == false) {
    throw new Error('MONTHS_AGOを、0-2の整数で指定してください');
  }
  writeToSpreadsheet();
}
//YDAレポートをスプレッドシートに書き込み
function writeToSpreadsheet() {
  //MCC内のYDA用のaccountIdsを取得する
  let accountIds = getAccountIds();
  if (accountIds.length == 0) return;
  //deliveryStatusがActiveのアカウントIDを抜き出す
  accountIds = getAccountIdsActive(accountIds);
  if (accountIds.length == 0) return;
  //レポートを取得する
  let reportData = getDisplayReport(accountIds);
  //レポート書き込みシート
  let sh = SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheetByName(SHEET_NAME);
  //レポートが表頭を入れて1より大きければ、スプレッドシートに結果を貼り付け
  if (reportData.length > 1) {
    sh.clear();
    sh.getRange(1, 1).setValues(reportData);
  }
}
//MCC内のYDA用のaccountIdsを取得する
function getAccountIds() {
  let accountIds = [];
  let num = 0;
  while (true) {
    const accountLinks = Display.AccountLinkService.get({
      mccAccountId: mccAccountId,
      accountStatuses: ['SERVING'],
      numberResults: 500,
      startIndex: num * 500 + 1,
    }).rval;
    if (accountLinks.totalNumEntries == 0) break;
    for (let i = 0; i < accountLinks.values.length; i++) {
      accountIds.push(accountLinks.values[i].accountLink.accountId);
    }
    num++;
    if (num * 500 >= accountLinks.totalNumEntries) break;
  }
  return accountIds;
}
//deliveryStatusがActiveのアカウントIDを抜き出す
function getAccountIdsActive(accountIds) {
  let accountIdsActive = [];
  let num = 0;
  while (true) {
    const accounts = Display.AccountService.get({
      accountIds: accountIds.slice(num * 500, Math.min((num + 1) * 500, accountIds.length)),
    }).rval;
    for (let i = 0; i < accounts.values.length; i++) {
      let account = accounts.values[i].account;
      if (account.deliveryStatus == 'ACTIVE') {
        accountIdsActive.push(account.accountId);
      }
    }
    num++;
    if (num * 500 >= accountIds.length) break;
  }
  return accountIdsActive;
}
//YDAのレポートを取得
function getDisplayReport(accountIds) {
  let reportData = [];
  //レポート取得の開始日と終了日を取得する
  let dateString = getDateString();
  for (let i = 0; i < accountIds.length; i++) {
    Logger.log('対象アカウントID:' +accountIds[i]);
    //レポートを取得する
    let reports = AdsUtilities.getDisplayReport({
      accountId: accountIds[i],
      dateRange: {
        startDate: dateString.startDateString,
        endDate: dateString.endDateString,
      },
      fields: REPORT_FIELDS_YDA,
      reportDateRangeType: 'CUSTOM_DATE',
    }).reports[0].rows;
    //レポートをreportDataにマージする
    reportData = reportData.concat(reports);
  }
  return reportData;
}
//レポートの開始日と終了日を取得する
function getDateString() {
  let jstNow = new Date(Date.now() + ((new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000));
  let day = Utilities.formatDate(jstNow, 'GMT', 'd');
  if (MONTHS_AGO == 0 && day == 1) {
    MONTHS_AGO = 1;
  }
  let startDateString;
  let endDateString;
  if (MONTHS_AGO == 0) {
    jstNow.setDate(jstNow.getDate() - 1);
    endDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
    jstNow.setDate(1);
    startDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
  } else {
    jstNow.setDate(1);
    jstNow.setMonth(jstNow.getMonth() - MONTHS_AGO);
    startDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
    jstNow.setMonth(jstNow.getMonth() + 1);
    jstNow.setDate(jstNow.getDate() - 1);
    endDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd');
  }
  return { startDateString: startDateString, endDateString: endDateString };
}