2026年5月29日

2026年5月29日

WordPressとAirtableを連携する方法(埋め込み・API読み取り・フォーム送信)

AirtableはスプレッドシートのようにWeb画面で編集できるデータベースサービスです。WordPressと組み合わせると、Airtableで管理している一覧をサイトに表示したり、サイトのフォームから届いた内容をAirtableに記録したりできます。この記事では、目的別に3つの連携方法と、それぞれの手順・注意点を説明します。

連携方法は目的で選ぶ

やりたいこと 方法 コード
Airtableの表をそのままページに見せたい 共有ビューをiframeで埋め込む 不要
Airtableのデータをサイトのデザインに合わせて表示したい Web APIで読み取り、WordPress側で整形して表示 PHP
サイトのフォーム送信内容をAirtableに記録したい Web APIでレコードを作成 PHP
Airtableのレコードを投稿として自動で作成・更新したい 通知を受けて投稿を同期 PHP(別記事)

コードを書かずに済ませたい場合は、ZapierやMakeといった連携サービスや、Airtableの内容をWordPressへ取り込むプラグインもあります。対応範囲や料金は製品ごとに異なり変更もあるため、各公式サイトで確認してください(2026年10月時点)。

方法1:共有ビューをiframeで埋め込む

いちばん手軽な方法です。Airtable側で作った表示(ビュー)を、読み取り専用のままページに載せます。

  1. Airtableでベースを開き、載せたいビューを選びます。不要な列はビューの設定で非表示にしておきます。
  2. 画面右上の「Share and sync」(共有と同期)を開き、「Embed this view」を選びます。
  3. プレビュー画面で背景色などを選び、表示されたiframeのコードをコピーします。
  4. WordPressの投稿編集画面で「カスタムHTML」ブロックを追加し、コピーしたコードを貼り付けて保存します。

コピーされるコードは次のような形です(shrXXXXXXXXXXXXXX は共有ビューごとのID)。

<iframe class="airtable-embed" src="https://airtable.com/embed/shrXXXXXXXXXXXXXX" frameborder="0" width="100%" height="533" style="background: transparent; border: 1px solid #ccc;"></iframe>

注意点は次のとおりです。

  • 埋め込みは読み取り専用ですが、ビューに表示されている列は閲覧者全員に見えます。個人情報や社内向けの列は、ビュー側で非表示にしてください。閲覧者はセルの内容をコピーすることもできます。
  • 共有リンクを作り直すと、これまでの埋め込みは表示されなくなります。その場合は新しいコードを貼り直します。
  • iframe内のAirtableのロゴ表示は消せません。
  • 「カスタムHTML」ブロックのiframeがそのまま保存されるのは、unfiltered_html 権限を持つユーザー(通常のサイトでは管理者と編集者、マルチサイトではネットワーク管理者)だけです。投稿者権限で貼るとiframeが取り除かれます。

Airtableのフォーム(フォームビュー)も、同じ「共有」メニューから埋め込みコードを取得してWordPressに載せられます。WordPress側にデータを保存しないので、問い合わせ受付を手早く作りたいときに向いています。

方法2・3の準備:パーソナルアクセストークン

Web APIを使う場合はトークンが必要です。以前使われていた「APIキー」は2024年2月1日に廃止され、現在はパーソナルアクセストークン(個人で使う場合)かOAuth(他人に配布する連携アプリの場合)を使います。

  1. https://airtable.com/create/tokens を開き、「Create token」を押して名前を付けます。
  2. 「Add a scope」でスコープを選びます。読み取りだけなら data.records:read、レコードの作成もするなら data.records:write を追加します。
  3. 「Add a base」で、連携に使うベースだけを選びます。すべてのベースを許可しないでください。
  4. 作成されたトークンは一度しか表示されないので、安全な場所に控えます。

あわせて、ベースID(app で始まる値)とテーブル名またはテーブルID(tbl で始まる値)を控えます。どちらもベースを開いたときのURLやAPIドキュメント画面で確認できます。テーブル名は変更されるとコードが動かなくなるため、テーブルIDを使うほうが安全です。

トークンはテーマファイルやデータベースではなく wp-config.php に定数として書きます。値はダミーです。

// wp-config.php(「編集が必要なのはここまでです」の行より上に追記)
define( 'AIRTABLE_PAT', 'patXXXXXXXXXXXXXX.xxxxxxxxxxxxxxxx' );
define( 'AIRTABLE_BASE_ID', 'appXXXXXXXXXXXXXX' );
define( 'AIRTABLE_TABLE', 'tblXXXXXXXXXXXXXX' );

以下のコードは、子テーマの functions.php ではなく、独立したプラグイン(wp-content/plugins/ に置くファイル)にまとめることをおすすめします。テーマを変えても連携が止まりません。ステージング環境で試してから本番に入れてください。

方法2:レコードを読み取って表示する

Airtableの「List records」APIは GET https://api.airtable.com/v0/{ベースID}/{テーブル} で、1回の応答で最大100件を返します。続きがあるときは応答に offset が入るので、それを付けて次のページを取得します。

AirtableのAPIには、ベースごとに毎秒5リクエストという上限があり、超えると429エラーが返って30秒待つ必要があります(2026年10月時点)。ページを表示するたびにAPIを呼ぶと上限に達しやすいため、取得結果はWordPressのトランジェントに保存して使い回します。

<?php
/**
 * Plugin Name: My Airtable Connector
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Airtableのレコードを全件取得し、10分間キャッシュする。
 *
 * @return array|WP_Error レコードの配列、または失敗時のWP_Error。
 */
function my_airtable_get_records() {
	$cache_key = 'my_airtable_records';
	$cached    = get_transient( $cache_key );
	if ( false !== $cached ) {
		return $cached;
	}

	$base_url = sprintf(
		'https://api.airtable.com/v0/%s/%s',
		rawurlencode( AIRTABLE_BASE_ID ),
		rawurlencode( AIRTABLE_TABLE )
	);

	$records = array();
	$offset  = '';

	do {
		$args = array( 'pageSize' => 100 );
		if ( '' !== $offset ) {
			$args['offset'] = $offset;
		}

		$response = wp_remote_get(
			add_query_arg( $args, $base_url ),
			array(
				'timeout' => 15,
				'headers' => array( 'Authorization' => 'Bearer ' . AIRTABLE_PAT ),
			)
		);

		if ( is_wp_error( $response ) ) {
			return $response;
		}
		$code = wp_remote_retrieve_response_code( $response );
		if ( 200 !== $code ) {
			error_log( 'Airtable list records: HTTP ' . $code );
			return new WP_Error( 'airtable_http', 'Airtable returned HTTP ' . $code );
		}

		$data    = json_decode( wp_remote_retrieve_body( $response ), true );
		$records = array_merge( $records, isset( $data['records'] ) ? $data['records'] : array() );
		$offset  = isset( $data['offset'] ) ? $data['offset'] : '';
	} while ( '' !== $offset );

	set_transient( $cache_key, $records, 10 * MINUTE_IN_SECONDS );
	return $records;
}

/**
 * 本文で [airtable_list] と書いた場所に一覧を表示する。
 */
add_shortcode( 'airtable_list', function () {
	$records = my_airtable_get_records();
	if ( is_wp_error( $records ) || empty( $records ) ) {
		return '';
	}

	$html = '<ul class="airtable-list">';
	foreach ( $records as $record ) {
		$fields = isset( $record['fields'] ) ? $record['fields'] : array();
		$name   = isset( $fields['Name'] ) ? $fields['Name'] : '';
		if ( '' === $name ) {
			continue;
		}
		$html .= '<li>' . esc_html( $name ) . '</li>';
	}
	$html .= '</ul>';

	return $html;
} );

ポイントは次のとおりです。

  • 認証は Authorization: Bearer トークン ヘッダーで行います。トークンをURLに含めないでください。
  • Airtableから来た値は外部データとして扱い、出力時に esc_html() などでエスケープします。
  • 値が空のフィールドは、APIの応答に含まれません。isset() で存在を確かめてから使います。
  • 失敗したときは空文字を返し、ページ全体が壊れないようにしています。エラーログにはHTTPステータスだけを書き、トークンは出力しません。
  • 表示したい列やレコードを絞るときは、fields[](取得する列)や view(ビュー名)、filterByFormula(条件式)を add_query_arg() の配列に加えます。Airtableで公開用のビューを作り、view で指定すると管理しやすくなります。

キャッシュの有効期間(例では10分)の間は、Airtable側で更新しても表示に反映されません。すぐに反映したいときは delete_transient( 'my_airtable_records' ); を実行します。

方法3:フォームの送信内容をAirtableに記録する

レコードの作成は POST https://api.airtable.com/v0/{ベースID}/{テーブル} に、fields を含むJSONを送ります。次の例は、WordPressの admin-post.php で受け付けたフォームの内容を1件のレコードとして登録します。

<?php
/**
 * Airtableにレコードを1件作成する。
 *
 * @param array $fields フィールド名 => 値 の配列。
 * @return true|WP_Error
 */
function my_airtable_create_record( array $fields ) {
	$url = sprintf(
		'https://api.airtable.com/v0/%s/%s',
		rawurlencode( AIRTABLE_BASE_ID ),
		rawurlencode( AIRTABLE_TABLE )
	);

	$response = wp_remote_post(
		$url,
		array(
			'timeout' => 15,
			'headers' => array(
				'Authorization' => 'Bearer ' . AIRTABLE_PAT,
				'Content-Type'  => 'application/json',
			),
			'body'    => wp_json_encode( array( 'fields' => $fields ) ),
		)
	);

	if ( is_wp_error( $response ) ) {
		return $response;
	}
	$code = wp_remote_retrieve_response_code( $response );
	if ( 200 !== $code ) {
		error_log( 'Airtable create record: HTTP ' . $code );
		return new WP_Error( 'airtable_http', 'Airtable returned HTTP ' . $code );
	}
	return true;
}

/**
 * フォームの受け付け(ログインしていない訪問者用と、ログイン中のユーザー用)。
 */
add_action( 'admin_post_nopriv_my_airtable_form', 'my_airtable_handle_form' );
add_action( 'admin_post_my_airtable_form', 'my_airtable_handle_form' );

function my_airtable_handle_form() {
	if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'my_airtable_form' ) ) {
		wp_die( 'Invalid request', 400 );
	}

	$name  = isset( $_POST['your_name'] ) ? sanitize_text_field( wp_unslash( $_POST['your_name'] ) ) : '';
	$email = isset( $_POST['your_email'] ) ? sanitize_email( wp_unslash( $_POST['your_email'] ) ) : '';

	$result = 'error';
	if ( '' !== $name && is_email( $email ) ) {
		$sent   = my_airtable_create_record(
			array(
				'Name'  => $name,
				'Email' => $email,
			)
		);
		$result = is_wp_error( $sent ) ? 'error' : 'ok';
	}

	$back = wp_get_referer() ? wp_get_referer() : home_url( '/' );
	wp_safe_redirect( add_query_arg( 'sent', $result, $back ) );
	exit;
}

フォーム側のHTMLは、送信先を admin-post.php にし、action と nonce を含めます。

<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
	<input type="hidden" name="action" value="my_airtable_form">
	<?php wp_nonce_field( 'my_airtable_form' ); ?>
	<p><label>お名前 <input type="text" name="your_name" required></label></p>
	<p><label>メールアドレス <input type="email" name="your_email" required></label></p>
	<p><button type="submit">送信</button></p>
</form>

実装上の注意は次のとおりです。

  • fields のキーは、Airtableのフィールド名と一字一句同じにします(大文字小文字も区別されます)。存在しない名前を送ると422エラーになります。
  • 単一選択などのフィールドに、まだ選択肢にない値を送るとエラーになります。値を自動で変換・追加させたい場合は、送信するJSONに "typecast": true を加えます。
  • トークンには data.records:write のスコープと、そのベースの編集権限が必要です。
  • 公開フォームは迷惑送信の対象になりやすく、送信が続くとAirtableのリクエスト上限に達することがあります。CAPTCHAやハニーポットなどの対策を組み合わせてください。
  • Contact Form 7などのフォームプラグインを使っている場合は、そのプラグインが用意している送信後のフックから my_airtable_create_record() を呼ぶ形にできます。フック名は各プラグインのドキュメントで確認してください。

投稿を自動同期したい場合

Airtableのレコードを正本にして、WordPressの投稿を自動で作成・更新したい場合は、Airtableのオートメーションから変更を通知し、WordPress側の独自RESTエンドポイントで受け取る構成にします。手順は次の記事で詳しく説明しています。

うまくいかないときの確認ポイント

  • 401・403が返る:トークンの値、スコープ(data.records:read / data.records:write)、トークンに対象ベースを追加したかを確認します。古いAPIキー(key で始まる値)はもう使えません。
  • 404が返る:ベースIDやテーブル名・IDの誤りを疑います。テーブル名に日本語や空白を含む場合は、テーブルIDに置き換えて試します。
  • 422が返る:フィールド名の不一致や、フィールドの種類に合わない値を送っている可能性があります。
  • 429が返る:リクエストが多すぎます。キャッシュ時間を延ばす、呼び出し回数を減らすなどして調整し、30秒以上空けてから再試行します。
  • 埋め込みが表示されない:投稿者権限でiframeが削除されていないか、共有リンクを作り直していないかを確認します。

まとめ

  • 表をそのまま見せるだけなら、共有ビューの埋め込みコードを「カスタムHTML」ブロックに貼る方法が手軽です。見せたくない列はビュー側で非表示にします。
  • APIを使う場合は、パーソナルアクセストークンを必要なスコープと対象ベースに絞って発行し、wp-config.php に置きます。
  • 読み取りは wp_remote_get() で行い、トランジェントでキャッシュしてリクエスト上限(ベースごとに毎秒5回)に備えます。
  • 書き込みは wp_remote_post() でJSONを送り、nonceと入力値のサニタイズ、迷惑送信対策を組み合わせます。

お気軽にご相談ください

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