Next.jsのSSGとInstagram apiで投稿一覧ページを作成する

自分のインスタグラムの投稿が多くなり何を投稿したか探すのが億劫になってきたのでキーワードで投稿を検索できるサイトを勉強がてら簡単に作成しました。
使用技術はNext.js13系(SSG) + Chakra ui + Vercelです

作った投稿一覧サイト↓
https://saunabouya-search.vercel.app/

インスタグラムのapiを取得できるようにする

これがなかなか面倒でした。。。
必要な手順を以下に列挙していきます。

  • Instagramをプロアカウントを切り替える
  • PCでFacebookにログイン
  • Facebookページを作成
  • FacebookページとInstagramプロアカウントの紐づける
  • Facebook for DevelopersからFacebook アプリを作成
  • Instagram Graph APIを追加
  • InstagramグラフAPIエクスプローラーからアクセストークンを取得
  • 無期限トークンとビジネスアカウントIDを取得

詳しくは以下のリンクを参考にしてください。。
https://www.teijitaisya.com/instagram-graph-api/#index_id4

Next.jsの環境構築

以下のコマンドでNext.jsを立ち上げます。

npx create-next-app insta-post --ts
cd insta-post
npm run dev

環境変数

先ほど取得した無期限トークンとビジネスアカウントIDを.envに記載します。

NEXT_PUBLIC_INSTAGRAM_ACCESS_TOKEN=無期限トークンを入力
NEXT_PUBLIC_INSTAGRAM_BUSINESS_ID=インスタグラムのビジネスアカウントIDを入力

インスタグラムの投稿apiを取得する

インスタグラムの投稿は一度のリクエストで最大25件までしか取れません。
今回SSGで一度に全ての投稿を取得したかったので26件目以降も一度に取得するようにする必要がありました。


インスタグラムのapiではリクエストの結果に以下のようなページングのパラメーターが含まれているのでこちらを使用して26件目以降の投稿を取得します。
以下は公式ドキュメントに記載されているパラメータの例です

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/{your-user-id}/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/{your-user-id}/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}

https://developers.facebook.com/docs/graph-api/results?locale=ja_JP
https://developers.facebook.com/docs/instagram-api/guides/content-publishing?locale=ja_JP

pages/api/instagram.tsにインスタグラムの投稿apiを取得するメソッドを作成します。
getInstagramPostsメソッドにはデフォルト引数を渡しておき
リクエストのパラメーターにafterのキーがある場合のみGETパラメーターを末尾に追加するようにします。

import axios from "axios";

const accessToken = process.env.NEXT_PUBLIC_INSTAGRAM_ACCESS_TOKEN;
const businessId = process.env.NEXT_PUBLIC_INSTAGRAM_BUSINESS_ID;

export async function getInstagramPosts(param = '') {
  let after = ''
  if(param !== '') {
    after = `&after=${param}`
  }
  const response = await axios.get(
    `https://graph.facebook.com/v16.0/${businessId}/media?access_token=${accessToken}&fields=caption%2Clike_count%2Cmedia_url%2Cmedia_type%2Cvideo_url%2Cpermalink%2Ctimestamp%2Cusername${after}`
  );
  return response.data;
}

getStaticPropsで投稿データを取得

先ほども書きましたがインスタグラムの投稿は一度のリクエストで最大25件までしか取れません。
なのでページ送りのパラメータが存在する限りリクエストを続けてすべての投稿を取得し、concatメソッドで一つの配列として結合します。

import { getInstagramPosts } from "@/pages/api/instagram";

export const getStaticProps = async () => {
  let data:any = []; //妥協...
  let after = '';
  let hasNextPage = true;

  while (hasNextPage) {
    try {
      const response = await getInstagramPosts(after);
      data = data.concat(response.data);
      after = "after" in response.paging.cursors ? response.paging.cursors.after : '',
      hasNextPage = !!after;
    } catch (error) {
      console.error('Error fetching data:', error);
      hasNextPage = false;
    }
  }
  return {
    props: {
      data: data
    }
  };
};

余談なのですが最初objectのキーがない場合以下のようにundefinedを代入しておりビルド時に怒られてしまいました。。
なのでキーが存在しない場合は空文字を代入します。

after = "after" in response.paging.cursors ? response.paging.cursors.after : undefined,
`undefined` cannot be serialized as json. please use `null` or omit this value.

まとめ

今回はSSG + vercelでインスタグラムの投稿一覧ページを作成しました。
SSGなので新規でインスタグラムのフィードを投稿した際、最新の投稿が一覧には反映されていないというデメリットはありますが個人的にはなかなか使い勝手がいいのではと思っています。
結局インスタグラムのapiを取得できるようにデベロッパーアカウントを作るところが一番苦労しました。笑

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。