実現したいこと
この度はお世話になります。もしYahoo広告スクリプトにお詳しい方、わかる方がいらっしゃいましたらご教示いただけますでしょうか。
●やりたいこと
Yahooのビジネスアカウントで、YahooのMCC配下にあるYSA、YDAの情報を取得し、スプレッドシートに出力をしたい
※取得したいのはレポートではなく、MCCで管理しているアカウントの情報となります
●今回作成したコードの参考サイト
Yahooサイトにある、サンプルライブラリ
発生している問題・分からないこと
タイムアウトになり、データをスプレッドシートへ出力できない
エラーメッセージ
error
1Exceeded maximum execution time
該当のソースコード
const SPREAD_SHEET_ID = 'スプレッドシートのID'; const SHEET_NAME = 'YSA'; let MONTHS_AGO = 0; const REPORT_FIELDS_YSA = [ 'ACCOUNT_ID', //アカウントID 'CLICKS', //クリック数 'COST', //コスト ]; 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, 'JST', '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, 'JST', 'yyyyMMdd'); jstNow.setDate(1); startDateString = Utilities.formatDate(jstNow, 'JST', 'yyyyMMdd'); } else { jstNow.setDate(1); jstNow.setMonth(jstNow.getMonth() - MONTHS_AGO); startDateString = Utilities.formatDate(jstNow, 'JST', 'yyyyMMdd'); jstNow.setMonth(jstNow.getMonth() + 1); jstNow.setDate(jstNow.getDate() - 1); endDateString = Utilities.formatDate(jstNow, 'JST', 'yyyyMMdd'); } return { startDateString: startDateString, endDateString: endDateString }; }
試したこと・調べたこと
上記の詳細・結果
●ラインタイム:V202402
●ためしたこと
(1)上記の『該当のソースコード』で、出力項目数を以下3つに絞ってみました
'ACCOUNT_ID', //アカウントID
'CLICKS', //クリック数
'COST', //コスト
(2)
サンプルコード:startDateString = Utilities.formatDate(jstNow, 'GMT', 'yyyyMMdd'); と
なっていましたが、 'GMT' を'JST'に変更してみました。
(3)インプレッション数が0より大きいものを抽出するようにコードを修正
●結果 『●ためしたこと』 の結果はすべてタイムアウトでした。
補足
●下記が、インプレッション数が0より大きいものを出力させるコードです。
MONTHS_AGO=Oは今月で言えば、3/1~昨日までを抽出してくれます。
インプレッション数は今月は300件ほどなので、タイムエラーになるとは考えづらいです。
const SPREAD_SHEET_ID = 'スプレッドシートのID'; const SHEET_NAME = 'YSA'; let MONTHS_AGO = 0; const REPORT_FIELDS_YSA = [ 'ACCOUNT_ID', //アカウントID 'ACCOUNT_NAME', //アカウント名 'IMPS', //インプレッション数 'CLICKS', //クリック数 'COST', //コスト ]; 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; // インプレッション数が0以上のレポートのみを取得 const filteredReports = reports.filter(report => parseInt(report.IMPS) > 0); // レポートをreportDataにマージする reportData = reportData.concat(filteredReports); } return reportData; } //レポートの開始日と終了日を取得する function getDateString() { let jstNow = new Date(Date.now() + ((new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000)); let day = Utilities.formatDate(jstNow, 'JST', '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, 'JST', 'yyyyMMdd'); jstNow.setDate(1); startDateString = Utilities.formatDate(jstNow, 'JST', 'yyyyMMdd'); } else { jstNow.setDate(1); jstNow.setMonth(jstNow.getMonth() - MONTHS_AGO); startDateString = Utilities.formatDate(jstNow, 'GMJSTT', 'yyyyMMdd'); jstNow.setMonth(jstNow.getMonth() + 1); jstNow.setDate(jstNow.getDate() - 1); endDateString = Utilities.formatDate(jstNow, 'JST', 'yyyyMMdd'); } return { startDateString: startDateString, endDateString: endDateString }; }
0 コメント