2026年5月22日
2026年5月22日
WordPressにInstagramの投稿を表示する方法(Instagram APIとの連携、2026年版)
WordPress のサイトに Instagram の投稿を一覧表示するには、Meta が提供する Instagram の API を使います。以前よく使われていた「Instagram Basic Display API」は 2024年12月4日で提供が終わり、現在(2026年10月時点)は「Instagram API with Instagram Login」などの、プロアカウント向けの API を使う必要があります。
この記事では、まず前提となる条件を整理し、プラグインで連携する方法と、自分でコードを書いて連携する方法を説明します。
連携の前に確認すること
- プロアカウントが必要: 現在の Instagram API が扱えるのは、ビジネスアカウントとクリエイターアカウント(プロアカウント)です。個人アカウントの投稿は API で取得できないため、Instagram アプリの設定でプロアカウントに切り替えておきます。
- 旧 API の情報は使えない:
instagram.com/developerでアプリを作る手順や、Basic Display API の「Client ID」「Sandbox Users」を使う手順は、現在は使えません。 - URL の埋め込みも単独では動かない: WordPress 本体は 5.5.2 で Instagram の oEmbed(URL を貼るだけで埋め込む機能)の対応を外しています。投稿 URL を本文に貼っても、プラグインなしでは埋め込み表示になりません。
方法1:プラグインで連携する
コードを書かずに投稿の一覧を表示したい場合は、公式ディレクトリのプラグインを使うのが手軽です。たとえば「Smash Balloon Social Photo Feed」(スラッグ instagram-feed)は、2026年11月時点で有効インストール数100万以上、更新も続いています。
- 管理画面の「プラグイン」→「新規プラグインを追加」で名前を検索し、インストールして有効化します。
- プラグインの設定画面から Instagram アカウントを接続します(Instagram のログイン画面に移動し、連携を許可します)。
- 表示用のブロックやショートコードを、投稿・固定ページ・ウィジェットに配置します。
接続の手順や無料版でできる範囲は、プラグインの版によって変わります。導入時は、プラグインの説明ページとサポート情報で最新の手順を確認してください。プラグインによっては、トークンの管理のために開発元のサーバーを経由する仕組みのものもあります。
方法2:Instagram APIを自分で呼び出す
自分のアカウントの投稿だけを表示するなら、プラグインを使わずに API を直接呼ぶこともできます。流れは次のとおりです。
- Meta の開発者向け管理画面(App Dashboard)でアプリを作り、アクセストークンを発行する
- トークンを WordPress のオプションに保存する
- API から投稿を取得してキャッシュし、HTML にして表示する
- トークンの有効期限(60日)が切れないよう、定期的に更新する
ステップ1:アプリを作ってトークンを発行する
Meta for Developers にログインし、App Dashboard で新しいアプリを作ります。公式ドキュメントでは、アプリの種類として「ビジネス(Business)」を選ぶよう案内されています。
アプリに Instagram の機能を追加したら、左のメニューの「Instagram」→「API setup with Instagram business login」を開き、対象の Instagram アカウントの横にある「Generate token」をクリックします。Instagram にログインすると、アクセストークンが表示されます。
- App Dashboard で発行したトークンは「長期トークン」で、有効期限は60日です。
- 自分以外の人のアカウントを扱うアプリにする場合は、Advanced Access の申請とアプリレビューが必要になることがあります。
画面の名前や配置は変わることがあるため、うまく見つからないときは Instagram API with Instagram Login の公式ドキュメント の「Get started」を確認してください。
ステップ2:トークンをWordPressに保存する
トークンはテーマやプラグインのファイルに直接書かず、データベースのオプションに保存します。WP-CLI が使える場合は次のコマンドで保存できます(--autoload=no で、すべてのページで読み込まれないようにします)。
wp option add my_ig_token 'ここに発行したトークン' --autoload=no
トークンはデータベースに平文で保存されるため、データベースのバックアップファイルの扱いにも注意してください。トークンが漏れた疑いがあるときは、App Dashboard で発行し直します。
ステップ3:投稿を取得して表示するプラグインを作る
wp-content/plugins/my-instagram-feed/my-instagram-feed.php として次のファイルを作り、管理画面で有効化します。API のバージョン(v27.0)は、2026年10月時点の公式ドキュメントの例に合わせています。
<?php
/**
* Plugin Name: My Instagram Feed
* Description: Instagram API with Instagram Login で自分の投稿を表示する。
*/
const MY_IG_API = 'https://graph.instagram.com/v27.0';
/**
* Instagram API に GET リクエストを送り、JSON を配列で返す。
*/
function my_ig_get( $path, array $query = array() ) {
$token = get_option( 'my_ig_token' );
if ( ! $token ) {
return new WP_Error( 'my_ig_no_token', 'アクセストークンが保存されていません。' );
}
$query['access_token'] = $token;
$url = add_query_arg( array_map( 'rawurlencode', $query ), MY_IG_API . $path );
$response = wp_remote_get( $url, array( 'timeout' => 10 ) );
if ( is_wp_error( $response ) ) {
return $response;
}
$code = (int) wp_remote_retrieve_response_code( $response );
$data = json_decode( wp_remote_retrieve_body( $response ), true );
if ( 200 !== $code || ! is_array( $data ) ) {
$message = isset( $data['error']['message'] ) ? $data['error']['message'] : 'HTTP ' . $code;
return new WP_Error( 'my_ig_http', $message );
}
return $data;
}
/**
* 自分のアカウントの Instagram ユーザーID を返す(取得後はオプションに保存)。
*/
function my_ig_user_id() {
$id = get_option( 'my_ig_user_id' );
if ( $id ) {
return $id;
}
$me = my_ig_get( '/me', array( 'fields' => 'user_id,username' ) );
if ( is_wp_error( $me ) ) {
return $me;
}
// 応答が data 配列で包まれている場合にも対応する
$row = isset( $me['data'][0] ) ? $me['data'][0] : $me;
if ( empty( $row['user_id'] ) ) {
return new WP_Error( 'my_ig_no_user', 'ユーザーIDを取得できませんでした。' );
}
update_option( 'my_ig_user_id', $row['user_id'], false );
return $row['user_id'];
}
/**
* 最近の投稿を取得する(1時間キャッシュ)。
*/
function my_ig_recent_media( $limit = 12 ) {
$cache_key = 'my_ig_media_' . (int) $limit;
$items = get_transient( $cache_key );
if ( false !== $items ) {
return $items;
}
$user_id = my_ig_user_id();
if ( is_wp_error( $user_id ) ) {
error_log( 'my_ig: ' . $user_id->get_error_message() );
return array();
}
$result = my_ig_get(
'/' . $user_id . '/media',
array(
'fields' => 'id,media_type,media_url,permalink,thumbnail_url,timestamp',
'limit' => (int) $limit,
)
);
if ( is_wp_error( $result ) ) {
error_log( 'my_ig: ' . $result->get_error_message() );
set_transient( $cache_key, array(), 5 * MINUTE_IN_SECONDS );
return array();
}
$items = isset( $result['data'] ) ? $result['data'] : array();
set_transient( $cache_key, $items, HOUR_IN_SECONDS );
return $items;
}
/**
* 投稿の一覧を HTML にする。
*/
function my_ig_render_feed( $atts = array() ) {
$atts = shortcode_atts( array( 'limit' => 12 ), $atts );
$items = my_ig_recent_media( min( 50, max( 1, (int) $atts['limit'] ) ) );
if ( ! $items ) {
return '';
}
$html = '<ul class="my-ig-feed">';
foreach ( $items as $item ) {
// 動画はサムネイル、画像とカルーセルは media_url を使う
$src = ( 'VIDEO' === $item['media_type'] )
? ( isset( $item['thumbnail_url'] ) ? $item['thumbnail_url'] : '' )
: ( isset( $item['media_url'] ) ? $item['media_url'] : '' );
if ( ! $src || empty( $item['permalink'] ) ) {
continue;
}
$html .= sprintf(
'<li><a href="%1$s" target="_blank" rel="noopener"><img src="%2$s" alt="%3$s" loading="lazy" width="320" height="320"></a></li>',
esc_url( $item['permalink'] ),
esc_url( $src ),
esc_attr__( 'Instagramの投稿', 'my-ig' )
);
}
$html .= '</ul>';
return $html;
}
add_shortcode( 'my_instagram_feed', 'my_ig_render_feed' );
/**
* 長期トークンを更新する(WP-Cron で週1回)。
*/
function my_ig_refresh_token() {
$token = get_option( 'my_ig_token' );
if ( ! $token ) {
return;
}
$url = add_query_arg(
array(
'grant_type' => 'ig_refresh_token',
'access_token' => rawurlencode( $token ),
),
'https://graph.instagram.com/refresh_access_token'
);
$response = wp_remote_get( $url, array( 'timeout' => 10 ) );
if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
error_log( 'my_ig: トークンを更新できませんでした。' );
return;
}
$data = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! empty( $data['access_token'] ) ) {
update_option( 'my_ig_token', $data['access_token'], false );
update_option( 'my_ig_token_expires', time() + (int) $data['expires_in'], false );
}
}
add_action( 'my_ig_refresh_token_event', 'my_ig_refresh_token' );
register_activation_hook(
__FILE__,
function () {
if ( ! wp_next_scheduled( 'my_ig_refresh_token_event' ) ) {
wp_schedule_event( time() + DAY_IN_SECONDS, 'weekly', 'my_ig_refresh_token_event' );
}
}
);
register_deactivation_hook(
__FILE__,
function () {
wp_clear_scheduled_hook( 'my_ig_refresh_token_event' );
}
);
表示したい場所に「ショートコード」ブロックを置き、次のように入力します。limit で表示件数を変えられます。
[my_instagram_feed limit="9"]
一覧の見た目はテーマの CSS で整えます。たとえば3列のグリッドにする場合は次のようにします。
.my-ig-feed { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; list-style: none; padding: 0; }
.my-ig-feed img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; }
コードのポイント
- 取得する項目:
fieldsでid・media_type・media_url・permalink・thumbnail_url・timestampを指定しています。media_typeはIMAGE・VIDEO・CAROUSEL_ALBUMのいずれかで、thumbnail_urlは動画にだけ付きます。 - media_url が無い場合: 著作権のある音源を使った動画などでは
media_urlが返らないことが公式リファレンスに記載されています。この例では動画にサムネイルを使い、画像の URL が無い投稿は飛ばしています。 - キャプション: 2026年10月時点のリファレンスでは、
captionは Facebook ログイン版の API でのみ取得できる項目として記載されているため、この例では取得していません。画像の代替テキストは固定の文言にしています。 - キャッシュ: 結果をトランジェントで1時間保存し、ページを表示するたびに API を呼ばないようにしています。取得に失敗したときも5分間は空の結果を保存し、API への連続アクセスを避けています。
- ストーリーズ: 投稿一覧(
/media)にストーリーズは含まれません。
ステップ4:トークンの期限切れを防ぐ
長期トークンの有効期限は60日です。refresh_access_token に grant_type=ig_refresh_token を付けて呼ぶと、その時点から60日有効なトークンが返ります。更新できるのは、発行から24時間以上たっていて、まだ期限が切れていない長期トークンです。
上のコードは、プラグインの有効化時に WP-Cron へ週1回の更新を登録しています。WP-Cron はサイトへのアクセスをきっかけに動くため、アクセスの少ないサイトや、DISABLE_WP_CRON でサーバーの cron に切り替えている場合は、実際に実行されているかを確認してください。WP-CLI では次のコマンドで予定と実行を確認できます。
wp cron event list --hook=my_ig_refresh_token_event
wp cron event run my_ig_refresh_token_event
期限が切れてしまった場合は更新できないため、ステップ1の画面でトークンを発行し直し、ステップ2のコマンドで wp option update my_ig_token '新しいトークン' として保存し直します。
うまく表示されないとき
- 何も表示されない:
wp-content/debug.log(WP_DEBUG_LOGを有効にした場合)にmy_ig:で始まるエラーが出ていないか確認します。 - トークンのエラー(期限切れ・無効): トークンを発行し直して保存します。保存後は
wp transient delete --allなどでキャッシュを消すと、すぐに反映を確認できます。 - 別のアカウントのトークンに変えた: 保存済みのユーザーIDが古いままなので、
wp option delete my_ig_user_idで消してから表示し直します。 - 個人アカウントのまま: プロアカウントに切り替えてから、トークンを発行し直します。
まとめ
- Basic Display API は2024年12月4日に終了し、現在はプロアカウント向けの Instagram API を使う。
- コードを書かずに表示するなら、公式ディレクトリのプラグインで連携するのが手軽。
- 自作する場合は、App Dashboard で長期トークンを発行し、オプションに保存して
graph.instagram.comから投稿を取得する。 - 取得結果はキャッシュし、60日で切れるトークンは
refresh_access_tokenで定期的に更新する。
関連記事: