スクリプトの使い方

使い方はとても簡単で、Google AdWordsの管理画面で「一括処理>スクリプト」を選択し、新しいスクリプトを追加します。追加するスクリプトに下記のプログラムコードを貼付けます。タイトルに分かりやすい名前をつけて、「プレビュー」を押して問題なく動作するか確認しましょう。正しく動作していることが確認できたら、保存して、スクリプトファイルを閉じます。スクリプトの一覧画面で、「スケジュールを作成」でお好みの時間にスクリプトが実行されるように設定すれば完了です。

スクリプトの設定項目

スクリプトの冒頭部分に下記のようなコードがあります。

var config = {
  '対象アカウントのラベル': '日次レポート送信', // MCCアカウントの場合のみ
  '送信先メールアドレス': 'your-mailaddress@example.com'
};

ここの部分で、スクリプトの動作を設定します。下記を参考に、自分のアカウント構成に合わせて設定を書き換えてください。

対象アカウントのラベル

処理対象のアカウントのラベルを指定します. MCCアカウントの場合は設定が必要です. MCCのアカウント一覧画面で, ここに指定したラベルを保持するアカウントが処理の対象となります. MCCアカウントでない場合はそのままで構いません.

送信先メールアドレス

日次レポートを送信するメールアドレスを指定します. 複数のメールアドレスは指定できないので, 複数人に送信したい場合は別途メーリングリストを作成し, メーリングリストのアドレスを指定するといいでしょう.

スクリプトファイル

var config = {
  '対象アカウントのラベル': '日次レポート送信', // MCCアカウントの場合のみ
  '送信先メールアドレス': 'ここを送信先のメールアドレスに変更'
};
var API_VERSION = 'v201609';

function main() {
  procAccountWithLabel('対象アカウントのラベル', function(account) {
    var stat = {
      "YESTERDAY": {
        "Search": getReportData(account, "YESTERDAY", "Search Network"),
        "Display": getReportData(account, "YESTERDAY", "Display Network")
      },
      "THIS_MONTH": {
        "Search": getReportData(account, "THIS_MONTH", "Search Network"),
        "Display": getReportData(account, "THIS_MONTH", "Display Network")
      }
    };
    var view_data = view(account, stat);
    sendmail({
      "to": config['送信先メールアドレス'],
      "subject": view_data["subject"],
      "htmlBody": view_data["body"]
    });
  });
}

function sendmail(context) {
  MailApp.sendEmail(context);
  Logger.log("メールを送信しました。送信先:" + context["to"] + ', 件名:' + context['subject']);
}

function getReportData(account, during, network) {
  var results = {"Impressions": 0, "Clicks": 0, "Cost": 0, "Conversions": 0, "ConversionValue": 0};
  var rows = AdWordsApp.report(
    "SELECT AdNetworkType1, Impressions, Clicks, Cost, Conversions, ConversionValue "
    + "FROM CAMPAIGN_PERFORMANCE_REPORT "
    + "DURING " + during, {
      apiVersion: API_VERSION
   } ).rows();
  while (rows.hasNext()) {
    var row = rows.next();
    if (row["AdNetworkType1"] === network) {
      try {
        results["Impressions"] += toInteger(row["Impressions"]);
        results["Clicks"] += toInteger(row["Clicks"]);
        results["Cost"] += toInteger(row["Cost"]);
        results["Conversions"] += toInteger(row["Conversions"]);
        results["ConversionValue"] += toInteger(row["ConversionValue"]);
      } catch (ex) {}
    }
  }
  return results;
}

function view(account, data) {
  var row = function (title, value, is_top) {
    var th_style = 'border-bottom: #e3e3e3 1px solid; border-left: #e3e3e3 1px solid; text-align: left; background: #f7f7f7; padding: 10px; font-weight: normal;';
    var td_style = 'border-bottom: #e3e3e3 1px solid; border-right: #e3e3e3 1px solid; text-align: right; padding: 10px;';
    if (is_top) {
      th_style += 'border-top: #be1309 4px solid;';
      td_style += 'border-top: #b3b3b3 4px solid;';
    }
    return '<tr><th width="180" style="' + th_style + '">' + title + '</th><td width="120" align="right" style="' + td_style + '">' + value + '</td></tr>';
  };
  var table = function (title, dataset) {
    var body = [];
    body.push("<td width='420'>");
    body.push("<section>");
    body.push('<h3>■' + title + '</h3>');
    body.push('<table style="border-collapse: collapse;">');
    body.push(row('インプレッション数', formatter(dataset['Impressions'], '000,000') + '回', true));
    body.push(row('クリック数',formatter(dataset['Clicks'], '000,000') + '回'));
    body.push(row('費用', formatter(dataset['Cost'], '000,000') + '円'));
    body.push(row('コンバージョン数', formatter(dataset['Conversions'], '000,000') + '回'));
    body.push(row('クリック率', formatter(getRatio(dataset['Clicks'], dataset['Impressions'], true), '000,000.00') + '%'));
    body.push(row('クリック単価', formatter(getRatio(dataset['Cost'], dataset['Clicks'], false), '000,000.00') + '円'));
    body.push(row('コンバージョン率', formatter(getRatio(dataset['Conversions'], dataset['Clicks'], true), '000,000.00') + '%'));
    body.push(row('コンバージョン単価', formatter(getRatio(dataset['Cost'], dataset['Conversions'], false), '000,000.00') + '円'));
    body.push(row('売上金額', formatter(dataset['ConversionValue'], '000,000') + '円'));
    body.push(row('ROAS', formatter(getRatio(dataset['ConversionValue'], dataset['Cost'], true), '000,000.00') + '%'));
    body.push('</table>');
    body.push("</section>");
    body.push("</td>");
    return body.join('');
  };
  var d = new Date();
  d.setDate(d.getDate() - 1);
  var subject = account.getName() + '(' + account.getCustomerId() + ') の広告配信レポート(' + Utilities.formatDate(d, 'JST', 'yyyy年MM月dd日') + ')';
  var body = [];
  body.push('<h1>' + subject + '</h1>');
  body.push('<h2>昨日のデータ</h2>');
  body.push("<table>");
  body.push("<tr>");
  body.push( table('検索広告', data['YESTERDAY']['Search']) );
  body.push( table('ディスプレイ広告', data['YESTERDAY']['Display']) );
  body.push("</tr>");
  body.push("</table>");
  body.push("<hr style='clear: both;' />");
  body.push('<h2>今月のデータ</h2>');
  body.push("<table>");
  body.push("<tr>");
  body.push( table('検索広告', data['THIS_MONTH']['Search']) );
  body.push( table('ディスプレイ広告', data['THIS_MONTH']['Display']) );
  body.push("</tr>");
  body.push("</table>");

  return { "subject": subject, "body": body.join('\n') };
}

function procAccountWithLabel(labelKey, callback) {
  if (isMccAccount() == true) {
    var accountIterator = MccApp.accountLabels().withCondition("Name = '" + config[labelKey] + "'").get().next().accounts().get();
    var accounts = [];
    while (accountIterator.hasNext()) {
      var account = accountIterator.next();
      MccApp.select(account);
      callback(account);
    }
  } else {
    callback(AdWordsApp.currentAccount());
  }
}

function isMccAccount() {
  try {
    var account = MccApp.accounts();
    return true;
  } catch (ex) {
    return false;
  }
}

function toInteger(value) {
  try {
    return parseInt(value.split(",").join(""), 10)
  } catch (ex) {
    Logger.log(value);
    return 0;
  }
}

function getRatio(bunshi, bunbo, is_percent) {
  if (bunbo == 0) { return "--" ; }
  if (is_percent) {
    return 100 * bunshi / bunbo;
  } else {
    return bunshi / bunbo;
  }
}

function formatter(value, type) {
  value = value + '';
  if (value == '--') return value;
  if (type == '000,000') {
    if (value.indexOf('.') > 0) {
      value = value.split('.')[0];
    }
    return value.replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,' );
  } else if (type == '000,000.00') {
    var values = value.split('.');
    var result = '';
    result = values[0].replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,' );
    result += '.';
    if (values.length == 1) { values.push('00'); }
    result += (values[1] + '00').substr(0, 2);
    return result;  
  }
  return value;
}