Account summary report under MCC

Updates

February 24, 2024: Added support for V202402.

Script overview

Yahoo! JAPAN Ads Script can output various reports directly to Google Sheets.
This script sets up MCC accounts for each Search Ads and Display Ads. It outputs the key metrics of the monthly report for accounts under MCC in Google Sheets.
The following three monthly durations are available: The report will show the previous month's data when scripts with "This month (excluding today)" run at the beginning of the month.
・This month (excluding today)
・Last month
・Month before last

Note

This script outputs the results of accounts whose delivery settings are turned on.
Also, the report header is not output.

Customize columns to show in reports

This script outputs the following columns as a default.
・Account ID
・Account Name
・Impressions
・Clicks
・CTR
・Cost
・Avg. CPC
・Conversions
・Conv. Rate
・Cost Per All Conv.
・Impression Share

Remove unnecessary columns from the following array.

For Search Ads


const   REPORT_FIELDS_YSA   =   ['ACCOUNT_ID',   'ACCOUNT_NAME',   'IMPS',   'CLICKS', 'CLICK_RATE',     'COST',     'AVG_CPC',     'CONVERSIONS',     'CONV_RATE',     'COST_PER_CONV', 'IMPRESSION_SHARE'];
When you want to add columns, refer to the following CSV file and add them to the preceding array.
https://ads-developers.yahoo.co.jp/reference/ads-search-api/v13/ReportDefinitionService/reports/v13/ACCOUNT.csv

For Display Ads


const   REPORT_FIELDS_YDA   = ['ACCOUNT_ID',   'ACCOUNT_NAME',   'IMPS',   'CLICKS', 'CLICK_RATE',     'COST',     'AVG_CPC',     'CONVERSIONS',     'CONV_RATE',     'COST_PER_CONV', 'IMPRESSION_SHARE'];
To add columns to Display Ads, refer to the following CSV file:
https://ads-developers.yahoo.co.jp/reference/ads-display-api/v13/ReportDefinitionService/reports/v13/AD.csv

Before you begin

Connect with your Google account in advance. Click "External tool connection" in the upper right corner of the script list.

Note

Yahoo! JAPAN Ads Script has a 10-minute limit. If too many accounts are associated with the MCC, the report output will stop (timeout). If the report output isn't complete for all accounts under the MCC, avoid timeouts by separating the MCC accounts, customizing the code, etc.

Sample codes

Search Ads


/*
■Script summary
This script outputs any of the search account reports of "This month (excluding today)", "Last month" or "Month before the last".
If you run the script with "This month (excluding today)" on 1st day of the month, it will output "Last month" report.
■How to use
1. This script is for Yahoo! JAPAN Ads Search Ads accounts.
2. Set each constant as follows
・SPREAD_SHEET_ID: Spreadsheet ID
・SPREAD_SHEET_NAME: Sheer name
・MONTHS_AGO: Choose 0 for "This month (excluding today)", 1 for "Last month" and 2 for "Month before the last".
・REPORT_FIELDS_YSA: Edit this array according to the fields you would like to check. 
You can check available fields names from the link below.
https://ads-developers.yahoo.co.jp/reference/ads-search-api/v13/ReportDefinitionService/reports/v13/ACCOUNT.csv
■Limitation
This script outputs the results of accounts whose delivery settings are turned on.
*/
/*
■Script summary
This script outputs any of the search account reports of "This month (excluding today)", "Last month" or "Month before the last".
If you run the script with "This month (excluding today)" on 1st day of the month, it will output "Last month" report.
■How to use
1. This script is for Yahoo! JAPAN Ads Search Ads accounts.
2. Set each constant as follows
・SPREAD_SHEET_ID: Spreadsheet ID
・SPREAD_SHEET_NAME: Sheer name
・MONTHS_AGO: Choose 0 for "This month (excluding today)", 1 for "Last month" and 2 for "Month before the last".
・REPORT_FIELDS_YSA: Edit this array according to the fields you would like to check. 
You can check available fields names from the link below.
https://ads-developers.yahoo.co.jp/reference/ads-search-api/v13/ReportDefinitionService/reports/v13/ACCOUNT.csv
■Limitation
This script outputs the results of accounts whose delivery settings are turned on.
*/
const SPREAD_SHEET_ID = 'SpreadsheetID';
const SHEET_NAME = 'Sheet name';
let MONTHS_AGO = 0;
const REPORT_FIELDS_YSA = [
  'ACCOUNT_ID',
  'ACCOUNT_NAME',
  'IMPS', 
  'CLICKS',
  'CLICK_RATE',
  'COST',
  'AVG_CPC',
  'CONVERSIONS',
  'CONV_RATE', 
  'COST_PER_CONV',
  'IMPRESSION_SHARE',
];
const managerAccountId = AdsUtilities.getCurrentAccountId();
function main() {
  if (MONTHS_AGO < 0 || MONTHS_AGO > 2 || Number.isInteger(MONTHS_AGO) == false) {
    throw new Error('Specify MONTHS_AGO as an integer between 0 to 2');
  }
  writeToSpreadsheet();
}
function writeToSpreadsheet() {
  let accountIds = getAccountIds();
  if (accountIds.length == 0) return;
  accountIds = getAccountIdsActive(accountIds);
  if (accountIds.length == 0) return;
  let reportData = getSearchReport(accountIds);
  let sh = SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheetByName(SHEET_NAME);
  // Paste the reportData into spreadsheet if the report has more than 2 rows.
  if (reportData.length > 1) {
    sh.clear();
    sh.getRange(1, 1).setValues(reportData);
  }
}
//Get account IDs for search ads linked to MCC
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;
}
//Identify account IDs whose deliveryStatus is active.
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;
}
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.concat(reports);
  }
  return reportData;
}
//Get the start and end dates of the report
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 };
}

Display Ads


/*
■Script summary
This script outputs any of the search account reports of "This month (excluding today)", "Last month" or "Month before the last".
If you run the script with "This month (excluding today)" on 1st day of the month, it will output "Last month" report.
■How to use
1. This script is for Yahoo! JAPAN Ads Display Ads accounts.
2. Set each constant as follows
・SPREAD_SHEET_ID: Spreadsheet ID
・SPREAD_SHEET_NAME: Sheer name
・MONTHS_AGO: Choose 0 for "This month (excluding today)", 1 for "Last month" and 2 for "Month before the last".
・REPORT_FIELDS_YDA: Edit this array according to the fields you would like to check. 
You can check available fields names from the link below.
https://ads-developers.yahoo.co.jp/reference/ads-display-api/v13/ReportDefinitionService/reports/v13/AD.csv
■Limitation
This script outputs the results of accounts whose delivery settings are turned on.
*/
const SPREAD_SHEET_ID = 'SpreadsheetID';
const SHEET_NAME = 'Sheet name';
let MONTHS_AGO = 0;
const REPORT_FIELDS_YDA = [
  'ACCOUNT_ID',
  'ACCOUNT_NAME',
  'IMPS',
  'CLICKS', 
  'CLICK_RATE',
  'COST',
  'AVG_CPC',
  'CONVERSIONS',
  'CONV_RATE',
  'COST_PER_CONV',
  'IMPRESSION_SHARE',
];
const managerAccountId = AdsUtilities.getCurrentAccountId();
function main() {
  if (MONTHS_AGO < 0 || MONTHS_AGO > 2 || Number.isInteger(MONTHS_AGO) == false) {
    throw new Error('Specify MONTHS_AGO as an integer between 0 to 2');
  }
  writeToSpreadsheet();
}
function writeToSpreadsheet() {
  let accountIds = getAccountIds();
  if (accountIds.length == 0) return;
  accountIds = getAccountIdsActive(accountIds);
  if (accountIds.length == 0) return;
  let reportData = getDisplayReport(accountIds);
  let sh = SpreadsheetApp.openById(SPREAD_SHEET_ID).getSheetByName(SHEET_NAME);
  // Paste the reportData into spreadsheet if the report has more than 2 rows.
  if (reportData.length > 1) {
    sh.clear();
    sh.getRange(1, 1).setValues(reportData);
  }
}
//Get account IDs for display ads linked to MCC
function getAccountIds() {
  let accountIds = [];
  let num = 0;
  while (true) {
    const accountLinks = Display.AccountLinkService.get({
      managerAccountId: managerAccountId,
      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;
}
//Identify account IDs whose deliveryStatus is active.
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;
}
function getDisplayReport(accountIds) {
  let reportData = [];
  let dateString = getDateString();
  for (let i = 0; i < accountIds.length; 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.concat(reports);
  }
  return reportData;
}
//Get the start and end dates of the report
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 };
}