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万以上、更新も続いています。

  1. 管理画面の「プラグイン」→「新規プラグインを追加」で名前を検索し、インストールして有効化します。
  2. プラグインの設定画面から Instagram アカウントを接続します(Instagram のログイン画面に移動し、連携を許可します)。
  3. 表示用のブロックやショートコードを、投稿・固定ページ・ウィジェットに配置します。

接続の手順や無料版でできる範囲は、プラグインの版によって変わります。導入時は、プラグインの説明ページとサポート情報で最新の手順を確認してください。プラグインによっては、トークンの管理のために開発元のサーバーを経由する仕組みのものもあります。

方法2:Instagram APIを自分で呼び出す

自分のアカウントの投稿だけを表示するなら、プラグインを使わずに API を直接呼ぶこともできます。流れは次のとおりです。

  1. Meta の開発者向け管理画面(App Dashboard)でアプリを作り、アクセストークンを発行する
  2. トークンを WordPress のオプションに保存する
  3. API から投稿を取得してキャッシュし、HTML にして表示する
  4. トークンの有効期限(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 '新しいトークン' として保存し直します。

うまく表示されないとき

  1. 何も表示されない: wp-content/debug.log(WP_DEBUG_LOG を有効にした場合)に my_ig: で始まるエラーが出ていないか確認します。
  2. トークンのエラー(期限切れ・無効): トークンを発行し直して保存します。保存後は wp transient delete --all などでキャッシュを消すと、すぐに反映を確認できます。
  3. 別のアカウントのトークンに変えた: 保存済みのユーザーIDが古いままなので、wp option delete my_ig_user_id で消してから表示し直します。
  4. 個人アカウントのまま: プロアカウントに切り替えてから、トークンを発行し直します。

まとめ

  • Basic Display API は2024年12月4日に終了し、現在はプロアカウント向けの Instagram API を使う。
  • コードを書かずに表示するなら、公式ディレクトリのプラグインで連携するのが手軽。
  • 自作する場合は、App Dashboard で長期トークンを発行し、オプションに保存して graph.instagram.com から投稿を取得する。
  • 取得結果はキャッシュし、60日で切れるトークンは refresh_access_token で定期的に更新する。

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲