ASP.NET CoreでMetaグラフAPIを使用して広告データを取得する

# はじめに
3年目エンジニアです。
今回、運用しているMeta広告のデータをAPIを使用して自動で取得する処理を作成したので振り返りがてら
同じような処理を作成している人の目に留まればと思います。

※すべてを網羅しているわけではないので不足項目があれば優しく教えてください
# 必要な情報
・アクセストークン（今回はOAuth2.0、JavaScriptSDKを使用した自動発行は行わないので長期アクセストークンでできるだけ長く使えるように）

・広告セットId（広告セットごとのデータ取得を行う為）

・広告配信への理解（これは書いてる自分があまりにも理解がなく苦戦したので補足程度）
# MetaForDevelopers への登録、アクセストークン発行
MetaForDevelopers登録ページ
https://www.facebook.com/business/tools/business-manager

まず広告を管理しているFaceBookアカウントでMetaForDevelopersへの登録をして、アクセストークンを発行します。

ここら辺の内容は調べればいくらでも出てくるので参考URLだけ添付しておきます
https://di-acc2.com/marketing/sns-tech/18499/

アクセストークンのアクセス許可は行いたい処理に応じて選択する必要があります。
今回は広告データの参照のみなので以下３項目を設定
・ads_management
・ads_read
・business_management

# 広告データ取得
開始日終了日を指定して期間内の広告データを取得するURL
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{adSetId}/" +
    $"insights?time_range={{'since':'{startDay}','until':'{endDay}'}}&" +
    $"fields=date_start,date_stop,campaign_id,campaign_name,reach,conversions,frequency,spend,impressions,clicks,video_play_actions,ctr,cpm,cpc,ad_name,adset_name&access_token={accessToken}";
```

:::note
補足
日ごとのデータを取得したい場合はURLに「time_increment=1」を追加すると取得できます
:::

このURLを使えば大体の階層のデータでも取得できます。

・キャンペーン単位のデータ取得
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{campaignId}/" +
    $"insights?time_range={{'since':'{startDay}','until':'{endDay}'}}&" +
    $"fields=date_start,date_stop,campaign_id,campaign_name,reach,conversions,frequency,spend,impressions,clicks,video_play_actions,ctr,cpm,cpc,ad_name,adset_name&access_token={accessToken}";
```
広告クリエイティブ単位のデータ取得
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{adCreativeId}/" +
    $"insights?time_range={{'since':'{startDay}','until':'{endDay}'}}&" +
    $"fields=date_start,date_stop,campaign_id,campaign_name,reach,conversions,frequency,spend,impressions,clicks,video_play_actions,ctr,cpm,cpc,ad_name,adset_name&access_token={accessToken}";
```

# 広告セットのターゲティングを取得する
次は広告のターゲティングを取得します。
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{adSetId}?fields=targeting&access_token={accessToken}";
```
#### 年齢
```
{
  "targeting": {
    "age_max": 30,
    "age_min": 18,
```
これらを組み合わせたものが年齢範囲になります

#### 性別
```
{
  "targeting": {
    "genders": [
      2
    ],
```
1は男性、2が女性、それ以外はすべての性別になります

#### 地域

:::note warn
注意
地域ターゲティングは指定方法によって帰ってくるJsonが変わるので注意が必要
:::
・国単位のターゲティング
countriesの項目が国情報、国内にしか配信しないことがほどんどだと思うのでcountriesがあったら自国をターゲティングだ！くらいの気持ちでいいと思います
```
{
  "targeting": {
    "geo_locations": {
      "countries": [
        "JP"
      ]
    },
```



・県単位のターゲティング
regions内のnameが県のデータ
```
  "targeting": {
    "geo_locations": {
      "regions": [
        {
          "key": "",
          "name": "都道府県",
          "country": "JP"
        }
      ],
```

・市町村単位のターゲティング
cities内のregionとnameを組み合わせると〇〇県 〇〇市のような形式になる
```
{
  "targeting": {
    "geo_locations": {
      "cities": [
        {
          "country": "JP",
          "distance_unit": "",
          "key": "",
          "name": "市町村",
          "region": "都道府県",
          "region_id": ""
        },
```
・場所単位のターゲティング
places内のnameが場所なので、nameとradiusを組み合わせることで〇〇から半径〇〇圏内という形式になる
```
"targeting": {
    "geo_locations": {
      "places": [
        {
          "key": "",
          "name": "場所名",
          "distance_unit": "",
          "latitude": 35.116433339447,
          "longitude": 138.91786247492,
          "radius": 1,
          "primary_city_id": ,
          "region_id": ,
          "country": "JP"
        },
```
・緯度経度単位でのターゲティング
そのまま使用する場合は、latitudeとlongitudeとradiusを使用して、緯度,経度から半径〇〇圏内のようになります
```
{
  "targeting": {
    "geo_locations": {
      "custom_locations": [
        {
          "distance_unit": "",
          "latitude": 緯度,
          "longitude": 経度,
          "radius": 1,
          "primary_city_id": ,
          "region_id": ,
          "country": "JP"
        }
      ],
```
:::note info
補足
緯度経度ではなく住所にしたい人はReverseGeoCodingを使用して住所に変換して使用してください
自分はGoogleMapAPIを使用して緯度経度を住所に変更して表示するようにしています
:::

# 画像、動画の取得
以下URLで広告画像のURLと広告動画のIdを取得できます
※今回は広告セットのIdを使用て配下の広告クリエイティブすべてのデータを取得
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{adSetId}/adcreatives?fields=image_url,video_id&access_token={accessToken}";
```

#### 動画
取得した動画Idは以下のような形でHtmlに挿入して画面に表示しています
※もっといいい方法があるかも
```
<iframe src="@($"https://www.facebook.com/plugins/video.php?width=560&href=https%3A%2F%2Fwww.facebook.com%2F{広告セットId}%2Fvideos%2F{広告動画Id}")"
        allow="autoplay" clipboard-write; encrypted-media; picture-in-picture; web-share; allowfullscreen; frameborder="0" scrolling="no">
</iframe>
```
#### 画像
画像は取得したURLを以下のように埋め込むだけ
```
<image src="画像URL"></image>
```

:::note alert
注意
広告画像のデータは様々な項目に格納されているらしく、先ほどのURLでは画像URLの取得ができないケースが存在します
:::

その場合、以下URLを使用して画像のhashを取得します
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/{adCreativeId}?fields=asset_feed_spec,object_story_spec,status&access_token={accessToken}";
```
・asset_feed_spec
```
{
  "asset_feed_spec": {
    "images": [
      {
        "adlabels": [
          {
            "name": "",
            "id": ""
          }
        ],
        "hash": "画像hash"
      }
    ],
```
・object_story_spec
```
{
  "object_story_spec": {
    "page_id": "",
    "instagram_actor_id": "",
    "link_data": {
      "link": "",
      "message": "",
      "name": "",
      "image_hash": "画像hash"
    }
  },
```
上記で取得した画像hashを使用して広告画像のURLを取得します
※広告アカウントIdはターゲティングを取得した際のURLに含めることで取得可能
```
var requestUrl = $"{MetaGraphApiURL}{ApiVersion}/act_{accountId}/adimages?fields=url,height,width&hashes=['{hash}']&access_token={accessToken}";
```

取得したurlをHTMLに埋め込むことで広告画像の表示が可能です

# さいごに
今回は広告からデータを取得するのみですが、MetaグラフAPIを使用することで広告画像のアップなど他にも様々なことが実装可能です。

これから実装する方、すでに実装した方に少しでも役に立てればと思います！

最後まで見ていただきありがとうございました。