広告運用で「人と機械の共生」をやりました

こんにちは。SDGデータサイエンスDivの18新卒の島です。エンジニア新卒リレー2番手となります。 「人と機械の共生」というのは弊社が掲げているテーマの一つです。
今回はちょっと前に担当した、Google Adsの広告自動運用についてご紹介したいと思います。
どんなものかというと

リスティング広告の入札キーワードを”自動”でいい感じにする

というやつです。なにこれすごいですね。

  • リスティング広告について

Google Adsのリスティング広告では、人間がキーワードを入札し、単価を設定、CTRやCPA(Cost Per Action)などのたくさんの指標を見ながら運用を行います。

そのプロジェクトではGoogle Ads Scriptを用いることで、運用作業の効率化を行い、キーワードの自動入札・単価調整・自動停止などを行っています。結果的に現状の売上の一部をほぼ自動で生み出しています(!)

Google Ads Scriptとは

JavaScriptみたいな文法(ほぼGoogle App Script)でGoogle Adsをコントロールできるスクリプトです。
簡単なスケジューラなどもあり、自前でサーバーを用意しなくてもかなり細かいところまで自動化できます。

どんなものか見てみる

配信結果レポートの取得

Ads ScriptにはAWQLというSQLっぽい言語があり、それを使うことでそれぞれのレポートを取得できます。
レポートには非常にたくさんの種類が存在し、それぞれに「Attribute(キャンペーンとかアドグループとか入札単価), Segment(日付とかユーザー層), Metric(コンバージョンなど)」の情報が載っています。
以下では「特定のキャンペーンの7日分の配信結果」を取得しています。

function fetchCampaignPerfomanceReport(CampaignId){
  var query = (
    " SELECT Date, CampaignId, CampaignName, Impressions, Clicks, ・・・ " +
    " FROM CAMPAIGN_PERFORMANCE_REPORT " +
    " WHERE" +
    " CampaignStatus = ENABLED" +
    " AND CampaignId = " + CampaignId +
    " DURING LAST_7_DAYS");
  
  return AdsApp.report(query).rows();
}

では次に「キャンペーンの中の特定のラベルがついているキーワード7日間の配信結果」を取得して見ましょう。

function fetchKeywordPerfomanceReportByCampaign(CampaignId, labelId){
  var query = (
    " SELECT Date, CampaignId, CampaignName, Impressions, Clicks, ・・・ " +
    " FROM KEYWORDS_PERFORMANCE_REPORT " +
    " WHERE " +
    " Labels CONTAINS_ANY " + "[" + labelId + "]" +
    " AND CampaignId = " + CampaignId +
    " DURING LAST_7_DAYS");
  
  return AdsApp.report(query).rows();
}

(AWQLではlabelsでwhereするときにIDを指定するけど、クエリで返ってくるLabel要素はラベルそのものの名前が返ってくるなど、書き方にちょっと癖があるので注意。)

キーワードの停止

ではサンプルのご紹介、以下のスクリプトは「特定のキーワードに対して入札の停止」を行います。

// AWQLでキーワードの配信結果を取得
var query = (" SELECT Date, CampaignId, CampaignName, Impressions, Clicks, ・・・ " +
             " FROM KEYWORDS_PERFORMANCE_REPORT " +
             " WHERE " +
             " Status = ENABLED " +
             " DURING LAST_7_DAYS");
var reports = AdsApp.report(query).rows();
// 停止対象のキーワードを入れる配列
var keywordToBePaused = [];
while (reports.hasNext()) {
  var report = reports.next();
  // キーワードイテレータ取得!
  var keywordIterator = AdsApp.keywords()
                              .withIds([[report['AdGroupId'], report['Id']]])
                              .get();
  while (keywordIterator.hasNext()) {
    // keyword取得!
    var keyword = keywordIterator.next();
    if(/* 社外秘のスーパーロジック*/(report)) {
      keywordToBePaused.push(keyword);
    }
  }
    
  for (i = 0; i < keywordToBePaused.length; i++) {
    var keyword = keywordToBePaused[i];
    // これだけでキーワードが停止します!
    keyword.pause();
  }                        
}        

流れを説明すると

  1. 特定のキーワードレポートを取得
  2. ループの中でそれぞれのキーワードの結果を社外秘のスーパーロジックでチェックし、当てはまるものを配列に追加
  3. 停止対象のキーワードを全て停止

といった感じです! 実際はもっとごちゃごちゃした感じでロジックが並んでますが、最小限だとこんなイメージになります!
(停止するキーワードを一度配列に入れてるのは、レポートの取得とキーワードのコントロールは別々に行った方がいいというベストプラクティスに従っています。)

開発に携わって

今回、Google Ads Scriptの開発に携わるにあたり

  • 自身の広告運用の知識の無さ(指標の意味はわかるけど、何を重視すればいいかわからない・・・)
  • キーワードの「ラベル」で状態を管理することでの「抜け、漏れ」(日予算で停止したキーワードってどうやって再開しよう・・・)
  • 運用者とのルール策定、検証フロー(スプレッドシートへの出力、Slackでの通知)
  • 溢れる英語力の無さ(ドキュメントは基本英語、サポートも日本語より英語の方がいい)

など様々な問題に直面しました。しかし、検証、MTGなどを通じてPDCAをできるだけ細かく丁寧に行うことで実際に広告運用の一部を自動化することができました。関係者の皆さんにこの場をお借りして、感謝申し上げます。ありがとうございました!

まとめ

今回のプロジェクトでは、「人と機械の共生」を(小さい形ですが)実践できました。
メインのロジックは紹介できませんが、人間が得意なことと機械が得意なことをそれぞれ活かせるつくりになっています。

新卒エンジニアがここまで実際の広告運用に関われるのは、なかなか少ないと思います。自分で資料を作成して、フローチャートを作って、実装して、結果を確認して改善する。仕事の中では基本的なことばかりですが、コミュニケーションから開発まで自分で行えたのは大きな自信に繋がりました。 広告運用の熱さとエンジニアリングのエモみを体感できる最高のプロジェクトでした!

あと2週間で社会人生活2年目がスタートしますが、エンジニアの枠を飛び越えてどんどんチャレンジしていきたいと思います!

There’s always more information out there. (引用:Googleが掲げる10の事実より)

株式会社アドウェイズ
サービスデベロップメントグループ
データサイエンスDiv
島裕生