• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

meta marketing api

date: 2025-11-22 excerpt: meta marketing apiで広告インサイトや動画を取得したメモ

tag: metafacebookmarketing api


meta marketing apiのメモ

概要

  • meta marketing apiを使って広告インサイトや動画素材を取得したときの手順を整理する
  • アプリIDやアクセストークンや広告アカウントIDは全てダミー値や環境変数として扱う

ライブラリのインストール

  • pythonの公式SDKとしてfacebook-businessを使う
  • 併せてpandasとrequestsもインストールしておく
$ pip install facebook-business pandas requests

アクセストークンの取得

  • graph api explorerからUser Tokenを発行し必要なpermissionを付与する
  • ここで得られるアクセストークンは1〜2時間程度でexpireする短期トークン
  • より長い期限(最大で半年程度)のトークンが必要な場合はfb_exchange_tokenを使ってlong lived tokenに交換する
import requests

app_id = "<APP_ID>"
app_secret = "<APP_SECRET>"
short_lived_token = "<SHORT_LIVED_USER_ACCESS_TOKEN>"

url = (
    "https://graph.facebook.com/v21.0/oauth/access_token?"
    "grant_type=fb_exchange_token&"
    f"client_id={app_id}&"
    f"client_secret={app_secret}&"
    f"fb_exchange_token={short_lived_token}"
)

resp = requests.get(url)
print(resp.text)

準備

  • meta for developersでアプリを作成しmarketing apiに必要な権限を付与する
  • graph api explorerなどから一時的なユーザアクセストークンを発行し必要に応じてlong lived tokenに変換する
  • 実務ではAPP_IDやAPP_SECRETやACCESS_TOKENを環境変数やsecret managerから読み込むようにする
from facebook_business.api import FacebookAdsApi

app_id = "<APP_ID>"
app_secret = "<APP_SECRET>"
access_token = "<ACCESS_TOKEN>"

FacebookAdsApi.init(app_id, app_secret, access_token)

広告アカウントとキャンペーンの取得

  • 広告アカウントはact_<AD_ACCOUNT_ID>形式で指定する
  • キャンペーン一覧やインサイトはAdAccountオブジェクトから取得する
from facebook_business.adobjects.adaccount import AdAccount

account = AdAccount("act_<AD_ACCOUNT_ID>")
campaigns = account.get_campaigns()
for c in campaigns:
    print(c["id"], c.get("name"))

キャンペーンインサイトの取得

  • get_insightsでキャンペーン単位の指標を取得できる
  • 期間指定にdate_presetやtime_rangeを使いlevel="campaign"などで粒度を変える
from facebook_business.adobjects.adsinsights import AdsInsights
import pandas as pd

insights = account.get_insights(
    fields=[
        AdsInsights.Field.campaign_id,
        AdsInsights.Field.campaign_name,
        AdsInsights.Field.impressions,
        AdsInsights.Field.clicks,
        AdsInsights.Field.spend,
        AdsInsights.Field.date_start,
        AdsInsights.Field.date_stop,
    ],
    params={
        "date_preset": "maximum",
        "level": "campaign",
        "time_increment": 1,
    },
)

rows = []
for row in insights:
    rows.append(
        {
            "campaign_id": row["campaign_id"],
            "campaign_name": row.get("campaign_name"),
            "date_start": row["date_start"],
            "date_stop": row["date_stop"],
            "impressions": int(row["impressions"]),
            "clicks": int(row["clicks"]),
            "spend": float(row["spend"]),
        }
    )
df_campaign = pd.DataFrame(rows)

配信済み広告からクリエイティブと動画をひも付ける

  • どの動画クリエイティブが実際に配信されたかを知るために以下の順番でひも付ける
    • AdAccount.get_insights(level="ad")で配信実績のある広告IDを列挙
    • Ad(ad_id)からcreative_idを取得
    • AdCreative(creative_id)からvideo_idを取得
    • AdVideo(video_id)から動画のメタ情報やダウンロードURLを取得
from facebook_business.adobjects.ad import Ad
from facebook_business.adobjects.adcreative import AdCreative
from facebook_business.adobjects.advideo import AdVideo

ad_insights = account.get_insights(
    fields=["ad_id", "ad_name", "campaign_id", "campaign_name", "impressions"],
    params={"date_preset": "maximum", "level": "ad"},
)

served_ads = []
for row in ad_insights:
    if int(row["impressions"]) == 0:
        continue
    served_ads.append(
        {
            "ad_id": row["ad_id"],
            "ad_name": row.get("ad_name"),
            "campaign_id": row["campaign_id"],
            "campaign_name": row.get("campaign_name"),
            "impressions": int(row["impressions"]),
        }
    )
df_ads = pd.DataFrame(served_ads)
unique_ad_ids = sorted(df_ads["ad_id"].unique())
ad_creatives = []
creative_ids = set()

for ad_id in unique_ad_ids:
    ad = Ad(ad_id).api_get(fields=["id", "name", "creative", "campaign_id"])
    creative = ad.get("creative")
    if not creative or "id" not in creative:
        continue
    cid = creative["id"]
    creative_ids.add(cid)
    ad_creatives.append(
        {
            "ad_id": ad_id,
            "creative_id": cid,
            "ad_name": ad.get("name"),
            "campaign_id": ad.get("campaign_id"),
        }
    )
df_ad_creative = pd.DataFrame(ad_creatives)
creative_video_rows = []
video_ids = set()

for cid in creative_ids:
    creative = AdCreative(cid).api_get(
        fields=[
            "id",
            "name",
            "video_id",
            "object_story_spec",
        ]
    )

    video_id = None

    if creative.get("video_id"):
        video_id = creative["video_id"]
    else:
        oss = creative.get("object_story_spec") or {}
        video_data = oss.get("video_data") or {}
        if "video_id" in video_data:
            video_id = video_data["video_id"]
        else:
            link_data = oss.get("link_data") or {}
            video_id = link_data.get("video_id")

    if not video_id:
        continue

    video_ids.add(video_id)
    creative_video_rows.append(
        {
            "creative_id": cid,
            "video_id": video_id,
            "creative_name": creative.get("name"),
        }
    )

df_creative_video = pd.DataFrame(creative_video_rows)
df_link = (
    df_ad_creative
    .merge(df_creative_video, on="creative_id", how="inner")
    .merge(
        df_ads[["ad_id", "campaign_id", "campaign_name", "impressions"]],
        on=["ad_id", "campaign_id"],
        how="left",
    )
)

動画ファイルのダウンロード

  • AdVideo(video_id)からsourceフィールドを取得しrequestsでダウンロードする
  • 実運用ではS3などオブジェクトストレージへの保存やレート制限を考慮する
from pathlib import Path
import requests
from facebook_business.adobjects.advideo import AdVideo

video_id = "<VIDEO_ID>"
video = AdVideo(video_id).api_get(
    fields=["id", "title", "length", "permalink_url", "source"]
)

source_url = video.get("source")
out_dir = Path("video_downloads")
out_dir.mkdir(parents=True, exist_ok=True)
out_path = out_dir / f"{video_id}.mp4"

resp = requests.get(source_url, stream=True)
resp.raise_for_status()
with out_path.open("wb") as f:
    for chunk in resp.iter_content(chunk_size=1024 * 1024):
        if chunk:
            f.write(chunk)

権限まわりの注意

  • ページ権限や広告アカウントへのアクセス承認が適切に行われていないとcampaignやvideo情報を取得できない
  • metaビジネスマネージャで対象のビジネスと広告アカウントにアプリやユーザを招待し必要な権限を付与する
  • 権限が足りない場合はapiレスポンスにエラーコードが返るのでドキュメントを見ながら不足している権限を特定する


metafacebookmarketing api Share Tweet