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側で作った表示(ビュー)を、読み取り専用のままページに載せます。
- Airtableでベースを開き、載せたいビューを選びます。不要な列はビューの設定で非表示にしておきます。
- 画面右上の「Share and sync」(共有と同期)を開き、「Embed this view」を選びます。
- プレビュー画面で背景色などを選び、表示されたiframeのコードをコピーします。
- 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(他人に配布する連携アプリの場合)を使います。
https://airtable.com/create/tokensを開き、「Create token」を押して名前を付けます。- 「Add a scope」でスコープを選びます。読み取りだけなら
data.records:read、レコードの作成もするならdata.records:writeを追加します。 - 「Add a base」で、連携に使うベースだけを選びます。すべてのベースを許可しないでください。
- 作成されたトークンは一度しか表示されないので、安全な場所に控えます。
あわせて、ベース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と入力値のサニタイズ、迷惑送信対策を組み合わせます。