Instagram Graph APIを使ってみた(Rails)

# 概要
おはこんばんにちわ。お疲れ様です。

RailsでInstagram Graph APIを導入したので備忘録ついでにそっと置いておこうと思います。

# 環境
- Rails 6
- faraday 1.8.0

# 始めに
Instagramには複数のAPIがありますが今回は表題にもある通り<font color="Red">**Instagram Graph API**</font>について解説します。

今回Railsでアカウント名を保存してそのアカウントの投稿内容を表示するということをやりました。

すなわち、1つのAPIキーから複数のアカウント情報を取得するということをやりましたので紹介します。

# Instagram Graph APIとは
グラフAPIの公式ドキュメントを雑に置いておきます。

[Meta for Developers](https://developers.facebook.com/docs/graph-api/)

ざっくりいうといろんなアカウントのいろんな情報が取れます。
しかもなんと**無料で！！！**

ただ感想としては**設定が面倒だしよくわからん**と思ってました。

そんなAPIですが早速やっていきましょう。

# 必要なもの
APIを使うために必要なものは以下になります。
- Instagram ビジネスID
- アクセストークン

**以上！！**

しかし、これを取得するまでの道のりが長かったです...

# 下準備
ここからは**自分で必要なものを用意したい方**
または開発するときに**自由に操作できるInstagramのアカウントが欲しい**(Instagramのプロアカウントを作成したい)方向けです。

必要ない方は<strong>[実装](#実装)</strong>まで飛ばしていただいて大丈夫です。

ただ開発するうえで投稿など自由に使えるアカウントは用意した方がはるかにやりやすいと思いますので是非やってみましょう。

### 1.Facebookアカウントを作る
え..そこから？
そうなんです。Facebookアカウントは<font color="Red">**必須**</font>なんです。
なのでとりあえず作成しましょう。
ついでに**Instagramアカウント**も作成してください。

### Facebookページを作る

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/f479f83f-f002-c605-2981-4c86bc905fa5.png' width=50%/><img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/0e0225ec-6e59-b25f-96f0-75025962756a.png' width=50%/>



1→2とクリックして画面が変わったら左側の**新しいページを作成**をクリック

名前は適当に(短すぎると拒否られる)、カテゴリも適当に入力すると選択できるので選んで下の**Facebookページを作成**をクリック

作成が完了するといろいろ入力が求められるが全部スキップでいいです。


### FacebookページとInstagramアカウントと連携
![スクリーンショット 2023-12-04 202341.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/8538cf67-9891-c956-9b46-7e287e963eb9.png)

Facebookページから黄丸部分をクリックしていき画面の指示に従ってInstagramのログインまでします。

![スクリーンショット 2023-12-04 204902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/4b80988b-a1fd-26c2-c44b-659d36666e09.png)

そのままInstagramのアカウントを**プロアカウント**に設定する流れが出てきますので設定していきます。
今回はアカウントが作れればいいので適当に選んでいきます。

![スクリーンショット 2023-12-04 204110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/74fb2712-a833-3529-08eb-2acd5f016275.png)

最後にこんな画面が出てくれば成功です。

Instagramのアカウントの種類をプロアカウント→個人用アカウントに変更できますが**連携が切れる**ため**再設定**が必要になります。

プロアカウントの作成のみでいい場合は以上になりますので<strong>[実装](#実装)</strong>まで飛ばしましょう。

### アプリ作成

[こちら](https://developers.facebook.com/)にアクセスしヘッダーの**利用を開始する**をクリックした後
アカウントを作成します。

SMS認証があるのでスマホを用意した方がいいかもしれないですね。
電話番号入力時に国のコードを選んで(日本なら+81)初めの**0**を抜いた番号を入力してください。

最後はかっこつけて**開発者**にでもしておきましょう。

![スクリーンショット 2023-12-04 211107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/33534b2c-eac3-d7f5-700d-7140608304fb.png)

こんな画面が出てきたら**アプリを作成**をクリックします。

![スクリーンショット 2023-12-04 211615.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/0f4279ea-a98b-fc38-9ec6-fa742ae51b81.png)

APIを使用するために**その他**の次に**ビジネス**を選択して次へ

![スクリーンショット 2023-12-04 212531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/e81044e8-670f-9775-175a-962da3e3899b.png)

アプリ名は何でもいいので適当につけてください。
メールアドレスは入力されているものでも大丈夫です。
**ビジネスアカウント**の部分はここまでに作成したものを選択して下さい。

![スクリーンショット 2023-12-04 211734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/840c8c8b-9511-655d-a091-c3adb9dc6015.png)

作成が完了するとこんな感じの画面が出てくると思います。
左上に付けたアプリ名が出ていればOKです。

### アクセストークン取得
やっとこさアクセストークンの取得です。

アクセストークンには３種類あります。
有効期限１時間、有効期限２ヶ月、無制限

今後何も気にしなくてもいいように**無制限**を取りに行きます。
そのためには全部取得しにいかなければ...orz

ヘッダー部分の**ツール**から**グラフAPIエクスプローラー**をクリックします。

右側の**アクセス許可**の許可を追加をクリックするとドロップダウンメニューが出てくるので
そこから必要なものを選択していきます。

| other | Events Groups Pages |
|--|--|
|instagram_basic<br/>instagram_manage_comments<br/>instagram_manage_insights<br/>instagram_manage_messages<br/>instagram_content_publish<br/>read_insights|business_management<br/>pages_show_list<br/>pages_read_engagement|

![スクリーンショット 2023-12-04 220232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/5f7dfdd1-d50e-4660-e4a3-015b3c330001.png)


画像の様になっていれば大丈夫です。

その後上にある**Generate Access Token**をクリックします。

アカウントについて中央に画面が出現するのでそのまま青いボタンをクリックして進みます。

![スクリーンショット 2023-12-04 220515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/bc05961f-b53d-a265-73aa-be0f43f12791.png)

オプトインについては画像の様に”～のみにオプトイン”をすべてにおいて選択し、チェックを入れて**続行**をクリックします。

アクセストークンに文字列が出現したらこれが１段階目のアクセストークンになります。
念のためコピーをとっておきましょう。

![スクリーンショット 2023-12-04 225742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/cadde105-c02c-4a5f-ee18-fd81307ed22c.png)

水色の**i**をクリックしてアクセストークンツールを開くをクリックします。

![スクリーンショット 2023-12-04 221744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/bc486b49-6e7e-c0d1-f70b-64074555dc84.png)

赤丸部分が有効期限になります。

下にスクロールし**アクセストークンを延長**をクリックして
アカウントのパスワードを入力し
緑色で<font color="green">アクセストークン</font>が表示されたら
**コピー**をとっておき、横の**デバッグ**をクリックします。

すると先ほどの赤丸部分が２ヶ月になっていると思いますのでそうなっていれば成功です。

最後にもう一度ツール→**グラフAPIエクスプローラー**を開きます。

先ほどの緑色で表示されたアクセストークンを**Generate Access Token**の上のフォームに上書きして
**送信**の欄に**me/accounts**と入力し送信を押します。

![スクリーンショット 2023-12-04 231242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/3d2fccf4-b353-b18d-a386-f5e771e1b3e0.png)

画像の様な画面が取得されましたら成功です。
”access_token：”の後ろに続く長い文字列が欲しかった<font color="Red">**無制限アクセストークン**</font>になります。

ついでに２つ目に必要な<font color="Red">**Instagram ビジネスID**</font>を取得します。

先ほど”me/accounts”と入力したところに
<strong>me?fields=accounts{instagram_business_account}</strong>と入力し送信します。

![スクリーンショット 2023-12-04 232612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/05cdd262-b86c-1e6e-84c3-d6defdbd49a7.png)

一番上の”id:”に続く数字が<font color="Blue">青字</font>で表示されていれば成功です。

ちなみに先ほどのアクセストークンについてはアクセストークンデバッカーで確認すると、

![スクリーンショット 2023-12-04 233609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/de74e351-2d2b-0b29-6277-0ac67228cad2.png)

有効期限の欄が受け取らないになっているはずですので
そうなっていれば長い長い下準備は完了です。

# 実装

あともうひと踏ん張り！

<strong>[必要なもの](#必要なもの)</strong>を用意出来たらあとはサクッと行っちゃいましょう！


今回は投稿データとURLを取りに行きます。

先に結果から

```model.rb
require "faraday"

class InstagramGraphApi
  def fetch_instagram(account_name)
    #必要な情報は.envに定義
    instagram_business_id = ENV['ID']
    access_token = ENV['ACCSESS_TOKEN']
    #投稿の取得数
    limit = "3"
    #取得したい情報によってオプションを設定
    options = "{thumbnail_url,media_url,media_type,permalink}"

    if account_name.present?
      #取得制限があるためキャッシュを使って抑制する
      #引数をキーにして１時間保持
      data = Rails.cache.fetch(account_name, expires_in: 1.hours) do
        url = "https://graph.facebook.com/v18.0/#{instagram_business_id}?fields=business_discovery.username(#{account_name}){media.limit(#{limit})#{options}}&access_token=#{access_token}"
          
        response = Faraday.get(url)
        if response.success?
          JSON.parse(response.body)
        else
          Rails.logger.error("データ取得に失敗しました。")
          return
        end
      end
    end
  end
end
```

データを整理して

```controller.rb
#@instagram_account_nameにはアカウントの種類がプロアカウントの
#アカウント名を入れる
if @account_name.present?
  api = InstagramGraphApi.new
  @response = api.fetch_instagram(@account_name) 

  if @response.present? && @response['business_discovery']['media'].present?
    posts = []
    @response['business_discovery']['media']['data'].each do |data|
      #1投稿ごとのリンク先とサムネイルを格納して配列に押し込む
      insta = {}
      insta['link_url'] = data['permalink']
      #投稿が動画の時はサムネイル画像、画像の時は画像データが取れる
      insta['thumbnail'] = data['media_type'] == 'VIDEO' ?  data['thumbnail_url'] : data['media_url']
      posts.push(insta)
    end

    @instagram = posts
  end
end
```
表示！
```view.html.haml
- @instagram.each do |insta|
  = link_to insta['link_url'], target: '_blank', rel: "noopener noreferrer" do
    = image_tag insta['thumbnail'], loading: 'lazy'
```

注意点としては対象のアカウントが<font color="Red">**プロアカウント**</font>でなければならないということです。
プロアカウントすなわち**ビジネスアカウント**もしくは**クリエイターアカウント**に設定されている必要があります。
個人用アカウントでは取得できません。

もし実装前にデータが取得できるか確認したい場合は、
```
https://graph.facebook.com/v18.0/<ビジネスID>?fields=business_discovery.username(<取得したいアカウント名>){media.limit(3){thumbnail_url,media_url,media_type,permalink}}&access_token=<アクセストークン>
```

**<>**含めてそれぞれ値を入れてからブラウザのURLに入れてもらえば結果が出ます。

![スクリーンショット 2023-12-05 212248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193405/26db897a-2359-73d4-c551-078317303b56.png)

こんな感じに成功すれば左の様に
失敗すれば右の様に返ってきます。

optionsに関しては[**ここ**](https://developers.facebook.com/docs/instagram-basic-display-api/reference/media/)に書いてあるものを
使ってます。

レート制限に関しては[**これ**](https://developers.facebook.com/docs/graph-api/overview/rate-limiting)です。

制限に引っ掛かると取得できなくなるので注意してください。
(まあ開発中は不意に制限かかったことないけど)

制限解放には**１時間**かかります。(Youtubeに比べれば全然いいね)

# 感想と最後に

**準備が大変！！**
これにつきますね

前置きが長すぎて実装はあっさりしてしまいました。

あとは皆さんの環境やコードに合わせてカスタマイズしていただければと思います。

長くなりましたが、ここまで読んでいただきありがとうございました。
それではまた次の記事で会いましょう

# 参考文献
偉大なる先人の知恵
参考にさせていただいたものを載せておきます。

https://tabiato.co.jp/biz/blog/instagram-graph-api-setup/#Instagram_API