環境
Ruby 2.6.6
Rails 6.0.4.7
Gem facebookbusiness(Metaが出している公式のSDK)
(※ ググるとgem ‘facebook_ads’などが出てくるが、そちらではないことに注意)
API version v14.0(2022年8月最新)
やりたいこと
- Meta for DeveloperのAppにアクセス許可を渡しているすべての広告アカウントを取得する
- それぞれの広告アカウントの、昨日のパフォーマンス(インプレッション、クリック、コストなど)を取得する
ビジネスのちょっとした背景
ウチの会社はweb広告に力を入れていて、すべての事業のfacebook 広告アカウントを足すと使っていないものも含めて80アカウントくらいある…。(広告代理店かってくらい)
以前は各アカウントの担当者が毎日毎日手作業でgoogle spreadsheetに情報を入力して、ピボットやシートの連携で集計して、目視で確認して…とだいぶ作業が煩雑になっていた。それを、facebookのapiを叩いてspreadsheetの入力まで自動化してしまおうというのが今回の背景。
この記事ではfacebookの情報を呼び出すところまでを解説する。
前提
1. Meta for DeveloperのAppを作っていること
access tokenやapp secretをまだ生成していない場合は作っておいてください。この辺は日本語でもたくさん記事が転がっているので困らないはず。
2. Facebookの広告管理の構造について理解していること
ユーザーがいて、広告アカウントがあって、その中にキャンペーンがあって、広告セットがあって…などなど、基本的な構造や、imp、click、costなどPPC広告の基礎用語なんかは理解しておくとよい。
このあたりを前提知識として、facebookのAPIの概念から実際の叩き方をお伝えしてく。
そもそもFacebookのAPIってどんなの?
・キーワードは「ノード」と「エッジ」
詳しくは公式ドキュメントに任せるが、ざっくり云えば、、、
ノード:「ユーザー」とか「広告アカウント」といったオブジェクト(のインターフェース)
Javascriptを知っている人であれば、DOMのノードと同じような概念として馴染めると思う。
エッジ:オブジェクトとオブジェクトを紐付けるもの
DBのリレーションとかJOINのような概念。例えば、広告アカウントにある(複数の)キャンペーンを呼び出したい場合、AdAccount.campaigns
のように書いて呼び出せるが、このドット以下の部分がエッジ。このエッジによってオブジェクトに紐づくオブジェクトを連鎖的に呼び出すことが可能になっている。
・Rubyでは、「facebookbusiness」というGemを使って叩くことができる
上記のノードやエッジといったものを、httpリクエスト⇔レスポンスという形ではなく、オブジェクトとメソッドのように扱えるようにしたものがこのGem。
ちなみに、facebook側の自動Gemアップデートによって常に最新のAPIバージョンが叩かれるようになっているので、基本的にメンテナンスはaccess_tokenの張替えだけでいい。
下準備
まずはGemを用意してインストールしておく。
gem 'facebookbusiness'
初期設定
require 'facebookbusiness'
class FacebookAPI
def initialize
# facebook APIの初期設定
FacebookAds.configure do |config|
config.access_token = '<発行したアクセストークン>'
config.app_secret = '<発行したアプリ・シークレット>'
end
end
end
※トークンなどは適宜クレデンシャルに突っ込んでおくこと。ちなみに、アクセストークンには「短期」(1〜2時間で切れる)と「長期」(2ヶ月)のものが存在する。以前は長期アクセストークンから無期限のトークンを発行できたが、現在はできない模様。
1:自分のアカウント情報を取得する
user = FacebooAd::User.get('me')
#<FacebookAds::User {:id=>"me"}>
ここでのポイントは2つ
1)「me」というのは特別なノードとして扱われている
普通.get(id)でUserの情報にアクセスするが、「me」というノードを指定することで、リクエスト時にくっついてくるアクセストークンやアプリシークレットを見てAPI側が勝手に引っ張ってきてくれる。
2)この段階ではまだAPIを叩いていない
ただgetと書いただけではAPIは叩かれず、具体的な情報を取ってくる必要があるメッセージを送ったタイミングでAPIが叩かれることになる。
user = FacebooAd::User.get('me')
user.name
# "寺尾 たくみ"
このname
のように、オブジェクトが保有してる情報をフィールドと呼ぶ。これは公式ドキュメントでも確認できるし、gemの中身を見れば、、、、
module FacebookAds
class User < AdObject
field :about, 'string'
field :age_range, 'AgeRange'
field :birthday, 'string'
field :cover, 'UserCoverPhoto'
field :currency, 'Currency'
field :education, { list: 'object' }
field :email, 'string'
field :favorite_athletes, { list: 'Experience' }
field :favorite_teams, { list: 'Experience' }
field :first_name, 'string'
field :gender, 'string'
field :hometown, 'Page'
field :id, 'string'
...
...
...
end
end
こんなふうにズラーッと並んでいるので、この一覧からほしい情報を検索してもいい。恐れずにgemをgit cloneしよう。
また、ほとんどのオブジェクトはAdObjectというクラスを継承しているので、いろんな便利メソッドが使える。
user = FacebookAds::User.get('me')
user.load! # 今すぐAPIを叩いて自身のインスタンスを書き換える
user
#<FacebookAds::User {:id=>"<自分のアカウントID>"}>
user = FacebookAds::User.get('me',['name', 'id']) # argにほしいフィールドを配列でもたせる
user.load!
user.inspect
#<FacebookAds::User {:id=>"<自分のアカウントID>", :name=>"寺尾 たくみ"}>
user.to_hash
#{:id=>"<自分のアカウントID>", :name=>"寺尾 たくみ"}
恐れずにgemをgit cloneしよう。
2:自分のアカウントに紐づく広告アカウントを取得する
今回欲しいのは、Userに紐づくすべての広告アカウント。ここでgemのエッジを確認する。
class User < AdObject
### 略 ###
has_edge :accounts do |edge|
edge.get 'Page' do |api|
api.has_param :is_place, 'bool'
api.has_param :is_promotable, 'bool'
end
...
end
### 略 ###
has_edge :adaccounts do |edge|
edge.get 'AdAccount'
end
end
アカウントっぽいものは2つあるが、上のものはおそらくfacebookページ。広告アカウントは下の方のadaccounts
になっていることがわかった。
user = FacebookAds::User.get('me')
user.adaccounts
#<#<Class:0x0000aaaaf8eaea18>:0x0000aaaafa39f210
@name=:adaccounts,
@node=#<FacebookAds::User {:id=>"me"}>,
@options={},
@should_delegate=false>
この段階では、ノード(=オブジェクト)がUserで、エッジの名前である@nameがadaccountsであるプレーンなオブジェクトになっている。
user.adaccounts.all # allですべて取り出す
#[#<FacebookAds::AdAccount {:account_id=>"xxx", :id=>"yyy"}>,
#<FacebookAds::AdAccount {:account_id=>"xxx", :id=>"yyy"}>,
#<FacebookAds::AdAccount {:account_id=>"xxx", :id=>"yyy"}>,
#<FacebookAds::AdAccount {:account_id=>"xxx", :id=>"yyy"}>]
allの中身を確認するにはさすがにAPIを叩かないといけないので、ppを取った結果は上記のようにAdAccountというオブジェクトとそのフィールド(id)を取得している。
3:広告アカウントのデータを取得する
広告アカウントのオブジェクトが取得できたところで、次はそのアカウントがどんなパフォーマンスだったのかデータを呼び出したい。(インプレッション、クリック、コストなど)
このデータはAdInsightsという別のオブジェクトのフィールドになっているので、広告アカウントからエッジを使ってAdInsightsに接続する。
user.adaccounts.each do |account|
fields = %w[account_id account_name impressions inline_link_clicks spend]
account.insights(fields: fields).each do |insight|
insight.inspect
end
end
#<FacebookAds::AdsInsights {:account_id=>"xx", :account_name=>"なまえ", :impressions=>"1000", :inline_link_clicks=>"100", :spend=>"10000", :date_start=>"2022-07-06", :date_stop=>"2022-08}>
ポイントは、エッジにもフィールドの指定ができること。これでデータが無事呼べたので、、、
insight.impressions
# 1000
insight.spend
# 10000
など、好きに使うといい。ただし、取ってこれてない値を参照しようとするとAdObjectが持っている#load!でコケるので注意。特に数値系は値が0だと取ってこれないので、安牌を取るなら…
insight[:impressions]
# 1000
insight.[:spend]
# 10000
insight[:conversions]
# nil
このようにシンボルで呼び出してやるといい。
4:パラメータをつけて条件を絞る
先程呼び出したデータは、デフォルトで1ヶ月間?の集計データを呼んでいる。が、こちらとしては昨日の集計だけ呼んで、毎日バッチを回して管理したい…。そこで、パラメータをつけて絞り込みをかける。
AdInsightsオブジェクトはAPIの中でもinsights APIが担当しているので、そのドキュメントのリファレンスを参照しなければならないことに注意。
・Graph API
・Insights API
・Marketing API
と3つのAPIに分かれているので、自分がほしいオブジェクトのAPIを探してリファレンスを見るべし。
fields = %w[account_id account_name impressions inline_link_clicks spend]
target_date = '2022-08-05'
time_range = { 'since': target_date, 'until': target_date }
account.insights({ fields: fields, time_range: time_range}).each do |insights|
insights.inspect
end
今回はtime_rangeで昨日だけのデータを呼び出した。フィールドとセットで設定する場合は、中括弧でこれらを挿入する。
おわりに
faceboookのAPI、特に広告アカウントの情報を取ってくるものについては国内の情報がほとんどない...。この記事がfacebookのAPIに挑む方の手助けになれば幸いです。