GMO NIKKOのS.Tです。
FacebookのグラフAPIでレポート取得を毎日行っていますが、
レポートが反映される深夜から取得を開始しても業務開始時間に間に合わない事が増えてきたので高速化を行いました。
概要 – グラフAPI
詳細はリンクの概要を見ていただきたいのですが、下準備としてアクセストークンを用意する必要があります。
同期リクエスト(通常のリクエスト)
下記のようにリクエストとレスポンスの例を紹介していきます。
GET送信で<バージョン>にAPIのバージョン番号、<アカウントID>に取得したいアカウントIDを指定します。
このアカウントIDはキャンペーンIDや広告セットID、広告IDも指定可能です。(アカウントID以外のIDはact_は不要)
fields=に取得したい項目を指定します。
レスポンスが多い場合は分割されてpagingに続きのURLが送られてくるので終わるまでリクエストを繰り返す必要があります。
ページングについては説明すると長くなるので下記を参照ください。
ページ分割された結果 – グラフAPI
1 |
https://graph.facebook.com/v<バージョン>/act_<アカウントID>/insights?fields=impressions&access_token=XXXXX |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "data": [ { "date_start": "YYYY-MM-DD", "date_stop": "YYYY-MM-DD", "impressions": "XXXXXXX", } ], "paging": { "cursors": { "before": "MAZDZD", "after": "MAZDZD" } } } |
図ですが、縦軸が時間経過、左がリクエスト送信プログラム、右がFacebookです。
通常はリクエストを送信したあと、レスポンスが返ってくるまで処理を返さないので待ち時間が発生します。
数件であればこれで問題ないですが、何万何十万となると影響がかなり出てきます。
順番待ちが発生して時間内に終わらないので
プログラムを同時に10個動かして擬似的に並列処理を行っていましたが、
graph.facebook.com:443エラーで弾かれることがあり、遅れることがかなり増えていました。
バッチリクエスト
バッチリクエスト – グラフAPI
次にバッチリクエストを試しました。
ドキュメントによると「1つのバッチにつき50個に制限されています。」とあるので下記ソースのようにアカウントID1~50まで指定します。(長くなるのでアカウントID2まで表示)
わかりやすく表示していますが実際は[]の範囲はJSONエンコードしてPOST送信します。
デフォルトではヘッダー情報も返ってきますがいらないので「include_headers=false」を指定します
レスポンスもJSONで返ってくるのでデコードする処理が増えます。
レスポンスもJSONで返ってくるのでデコードする処理が増えます。
1 2 3 4 5 6 7 8 9 10 11 12 |
https://graph.facebook.com/v<バージョン>/ ?batch= [ { "method":"GET", "relative_url":" act_<アカウントID1>/insights?fields=impressions" }, { "method":"GET", "relative_url":" act_<アカウントID2>/insights?fields=impressions" } ]&access_token=XXXXX&include_headers=false |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
[ { "code": 200, "body": "{ \"data\": [ { \"impressions\": \"XXXXX\", \"date_start\": \"YYYY-MM-DD\", \"date_stop\": \"YYYY-MM-DD\" } ], \"paging\": { \"cursors\": { \"before\": \"MAZDZD\", \"after\": \"MAZDZD\" } } }" }, { "code": 200, "body": "{ \"data\": [ { \"impressions\": \"XXXXX\", \"date_start\": \"YYYY-MM-DD\", \"date_stop\": \"YYYY-MM-DD\" } ], \"paging\": { \"cursors\": { \"before\": \"MAZDZD\", \"after\": \"MAZDZD\" } } }" } ] |
通常のリクエストと変わりませんが50件ずつリクエストするので、
効率は良くなっているのは確かですが、Facebookの処理が完了するまで返さないので
効率は良くなっているのは確かですが、Facebookの処理が完了するまで返さないので
合計処理時間はそこまで差はありませんでした。
非同期リクエスト
制限とベストプラクティス – マーケティングAPI
というわけで非同期リクエストに行き着きました。
通常のリクエストと同じですがこちらはPOST送信します。
するとreport_run_id (ジョブID)が返ってくるのでこれを使ってリクエスト状況を管理します。
同時にFacebookでレポートの作成が始まります。
1 |
https://graph.facebook.com/v<バージョン>/act_<アカウントID>/insights?fields=impressions&access_token=XXXXX |
1 2 3 |
{ "report_run_id": “XXXXXXXXXXXXXXX" } |
report_run_idだけを指定して下記のようにGET送信するとジョブステータスが返ってくるので定期的にFacebookの処理状況を確認します。
1 |
https://graph.facebook.com/v<バージョン>/<ジョブID>&access_token=XXXXX |
1 2 3 4 5 6 7 8 9 10 |
{ "id": “XXXXXXXXXXXXXXX", "account_id": “XXXXXXXXXXXXXXXX", "time_ref": XXXXXXXXXX, "time_completed": XXXXXXXXXX, "async_status": "Job Completed", "async_percent_completion": 100, "date_start": “YYYY-MM-DD", "date_stop": “YYYY-MM-DD" } |
ステータスが「Job Completed」になっていたら今度は/insightsをつけてGET送信すると目的のレポートが返ってきます。
POST送信時に指定したfieldsの内容が反映されます。
1 |
https://graph.facebook.com/v<バージョン>/<ジョブID>/insights&access_token=XXXXX |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "data": [ { "date_start": "YYYY-MM-DD", "date_stop": "YYYY-MM-DD", "impressions": "XXXXXXX", } ], "paging": { "cursors": { "before": "MAZDZD", "after": "MAZDZD" } } } |
全体の流れですが、レポート作成リクエストだけ一気に投げてしまい別処理で定期的にジョブチェックも同時に行います。
バッチリクエストと併用もできるので50件ずつ非同期リクエストすることも可能です。
完了していたらレポートを取得します。
Facebookに処理を委ねるのでエラーで弾かれる確率も低く待ち時間も発生しないので効率よく処理できます。
Facebookに処理を委ねるのでエラーで弾かれる確率も低く待ち時間も発生しないので効率よく処理できます。
ただしリクエスト状況をこちらで管理する必要があるので手間は増えます。
まとめ
今までは同期リクエストの疑似並列処理で遅い時は30日分のレポート取得だけで10時間以上かかっていましたが、
非同期処理に変更したところ2時間程度になりました。
不要な処理を削除した影響もあると思いますが、処理時間が安定しているので
graph.facebook.com:443エラーで弾かれることがなくなったのが大きいと思います。