読者です 読者をやめる 読者になる 読者になる

NO AD NO LIFE

ベンチャー企業の広告エンジニアのブログ

作りながら学ぶ広告サーバ - DSP その1

広告 DSP

はじめに

今回は,近年の広告業界に定着したRTB(Real Time Bidding)について説明しようと思います.

残念ながら筆者はRTBの広告サーバを作ったことがないのですが,GW休みで暇なので詳細まで皆さんと一緒に勉強していきたいので,実際にRTBのシステムを作りながら解説していこうと思います.

RTBの広告サーバだけでなく広告サーバ共通で気を付けるポイントもあるので,その辺りにも触れていきます.(大雑把な話は以下のエントリにまとめていますので,興味のある方はご覧下さい)

inchom.hatenadiary.jp

今回は,RTBシステムの広告主側プラットフォームであるDSP (Demand Side Platform)について説明していきます.

(注意)共通標準であるOpenRTBの仕様をベースに開発を進めるので,現状動いているシステムのRTBの仕様とは異なっていたり,一部私の認識が間違っている箇所もあるかもしれません,そういった場合はコメント等いただけたらと思います.

RTBシステムとは?

RTBシステムとは,広告枠の売買を目的としたシステムです. 具体的には,ユーザがメディアのページを表示しようとしたときに,そのページに表示する広告枠に対して入札を行い,最も高くその広告枠を買った広告サーバの広告を表示するシステムです.

ユーザがメディアのページを表示を開始してから表示が完了するまでの1秒足らずの間に入札を行いますから,一般的な入札のように人が落札している時間なんてありません.(熟練の広告運用担当者はそれをやっているという噂はありますがw)

ではどのように実現しているのでしょうか? RTBシステムの概要図を使って説明します.

f:id:inchom:20160430184724p:plain

  1. ユーザが広告タグが張ってあるメディアのページを踏みます
  2. メディアのページから広告リクエストがSSP(Supply Side Platform)に対して飛びます
  3. SSP複数DSPに対して広告枠の入札リクエスト(RTBリクエスト)を送ります
  4. DSPは広告枠の情報から入札するかを決めて,入札する場合は入札価格を含めてRTBレスポンスを返します
  5. SSPは最も高く入札したDSPに対して落札通知を行います
  6. 落札通知を受け取ったDSPは広告の表示情報(広告マークアップ)を送ります*1
  7. SSPはメディアに対して広告表示情報を返します
  8. ユーザに広告が表示されます

上記2-8までの手順がメディアのページを表示するまでの間に行われます. このように,広告枠が1インプレッション単位で逐次入札されるため,Real Time Biddingと呼ばれます.

上記を実現する仕組みがRTBシステムです.

DSPとは?

DSPとは,SSPから送られた広告枠の入札リクエストに対して,自分の広告と広告枠の情報を考慮して入札すべきかどうか判断するプラットフォームです.

DSPは一般的に以下のような機能を持ちます.

広告枠入札機能

SSPから与えられた広告枠情報から広告枠を入札する機能です.収益性の高い広告枠を安価に入札することが目的になります. そのため,メディアやデバイス,ユーザと配信可能な広告との親和性を考慮して,可能な限りクリックやコンバージョンしやすい広告枠をできるだけ安く入札することになります. 以前紹介したターゲティングの技術も積極的に使われます. 一般的に50msec程度の応答性能を求められるため,大量のデータを高速に処理できるシステム設計.データ設計が重要になります.

広告入稿機能

広告主や代理店が広告を入稿する機能です. 予算や単価,ターゲティング用の設定などを行うことができます. 初期の広告サーバはこのような機能は持たずメールベースで入稿する(エンジニアがDBに入れる)ケースもあります.使いやすいUI/UXにする必要があるため,作り込むと非常に時間がかかる機能です.

広告効果レポート機能

広告主や代理店が入稿した広告の効果を閲覧する機能です. 1コンバージョンあたりに使われた予算を示すCPAやクリック率やコンバージョン率を表示することができます. レポートは大容量のログデータを高速に処理するための基盤作りやUI/UX設計が必要になるため,こちらも時間のかかる機能になります.

全ての機能を作ろうとすると時間的に終わらないので,今回はコアの機能である広告入札機能に焦点を当てて開発していきますが,データ設計やインフラ設計はその他の機能を考慮したものにします.

DSPの開発

前置きが長かったですが,これから実際にDSPを作っていきたいと思います.

ベースとなるRTBの仕様は,OpenRTB v2.3を参照します.こちらに仕様のPDFがあります.

開発は,以下の手順で進めていきます.

  • システム設計
  • データ設計
  • 実装
  • システム構築

全てやっているとかなり長くなってしまうため,今回は,データ設計まで説明します.

システム設計

一般的な広告サーバの設計方針に併せて以下のようなことを意識しながら設計を行っていきます.

  • 大量リクエストを高速に処理できる
  • 停止しない
  • 障害復旧が早い
  • 収益性の高い広告を選択できる

今回は,AWSの上で動くシステムを前提としました.

f:id:inchom:20160501102805p:plain

DSP API Server

広告枠の入札を行うサーバです. このAPIサーバはロードバランサに接続され,リクエストが増えるとAPIサーバを増やして対応することを想定しています.(一般的なAPIサーバと同じです)

Redis

配信可能な広告データを持ちます. 処理性能を考慮してオンメモリ型のKVSであるRedisを参照します. Redisに対してWriteをしないようにすることで,リクエストが大量に増加した場合も,Redis Slaveを増やすことで対応できるためスケールするようになります.これによって大量リクエストを高速に処理できるになります.

ただ,Redisのマスターサーバが単一障害点になり得るため,AaroSpikeのような分散KVSを使ったり,LevelDBやKyoto TycoonなどのFile型KVSを各APIインスタンスが保持する方法でもよいかと思います.(今回は実装コストを考慮してRedisを採用しています.ElastiCacheを使えばフェイルオーバーをしてくれるため,無停止ではないにしろ障害復旧は早い設計にしています)

S3

配信ログを保存します. APIサーバ側から送られてくる配信ログ(入札,クリック,コンバージョンログなど)を定期的に受け取り,保存します. ログ集計のためBackendサーバ側から定期的に読み込まれます.

DSP Backend Server

配信可能な広告データの更新,配信レポートの更新を行います. 配信可能な広告データの更新には,MySQLに存在する広告データを取得し,S3の配信ログ(あるいは配信レポート)を読み込んで予算超過しているものを排除して,Redisにある配信可能広告リストを更新します.

配信レポートの更新には,S3の配信ログを集計して広告主や代理店が必要とする広告配信結果をMySQLに保存します.

処理速度の観点から配信量が増えるとS3から直接読み込むのは難しくなると思われるため,懐に余裕があればRedshiftやBigQueryを間に挟んだ方がよいかと思います.

MySQL

広告主や代理店から入稿された広告情報,また,広告の配信結果を保持します. 広告情報は,クリエイティブの情報や予算や単価などを保持します. 広告の配信結果は,キャンペーン別,クリエイティブ別,セグメント別などでインプレッション数,クリック数,CTR,CVR,CPAなどを保持します.

CDN (Cloud Front)

S3に保存された広告のクリエイティブを保持します. 今回はCloud Frontにしていますが,配信量が増えるとシステムコストとして効いてくるのがこの部分のため,実際には他のCDNとコストや安定性などから検討するのがよいかと思います.

データ設計

DSPで使用するデータの設計を行っていきます.今回は,広告入札機能の実装がメインであるため,DSP API Serverで扱うデータ型を決めていきます.

DSP API Serverで扱うデータ型には以下のものがあります.

  • RTBの応答に使うデータ型
  • DSP API Serverで内部的に扱うデータ型

RTBの応答に使われるデータ型は,OpenRTBの仕様に従う形になります. そのため,内部的に扱うデータ型のみ仕様を決めます.

DSP API Serverで内部的に扱うデータ

DSP API Serverで内部的に扱うデータは仕様を極力小さくするため以下に絞りました.

  • 広告配信候補リスト
  • 広告データ

詳細を下で説明します.

予算消化を厳密に管理するためには予算上限や消化予算などのデータを持たせた方がよいですが,今回は実装コストやシステムの複雑性を考慮して,広告配信候補リストにあるものは配信可能というようにしています.(集計バッチが高頻度動くことを期待している)

広告配信候補リスト

Indexと呼ばれる,どの枠にどの広告を出すかを持つデータです.

詳細は,広告の基本 - 広告サーバの機能 - NO AD NO LIFE広告配信候補リストの作成の部分で触れています.

Indexは,配信可能な広告データのリストを所持しています. Indexはリスト型であるためMessagePackでパッキングした後のデータを入れておきます.RedisのSET型を使うこともできますが,RedisにロックインされないためにKey => Valueの形式を保つようにしています.

(Key => Value)

index:<view> => Index
項目 内容
view どの広告クリエイティブの種類かを示す.バナーやネイティブ,動画などを判別する. banner, banner_rect, native

ここで定義した項目は最低限のものなので,実際にはさらに細かく作っていく必要があります.

広告データ

広告データは,広告の入札,表示,クリック等をするために必要な情報です.

項目 内容
CampaignID 広告キャンペーンID 123
CreativeID 広告クリエイティブID 1234
Price 単価 30
NURL 落札通知を受けるURL
IURL 広告の画像URL.広告の品質・安全性のチェックに使われる
AdM 広告マークアップ
Adomain ブロックするドメイン
PeCPM eCPMの期待値

ここで定義されているBidPriceを見て,最低入札単価を満たしているものがあれば,対象の広告枠に入札するようにします. また,PeCPMにeCPMの期待値を入れておき,広告効果を考慮した入札ができるようにしておきます.

その他のデータ

FQやリタゲ用のデータなども将来的には必要だと思いますが,時間的に実装できないので排除しています.

おわりに

今回は,RTBシステムについての概要,DSPの概要,システム設計,データ設計について説明しました. 次回は,実装,システム構築を行っていきたいと思います.

*1:広告の表示情報は4のRTBレスポンスに含めることができるので,その場合は送る必要はありません.