年別アーカイブ 2026年8月7日

Cloudflare AI Searchがエージェント検索を簡素化、公開エンドポイントと価格プレビュー発表

Cloudflare AI Searchがエージェント検索を簡素化、公開エンドポイントと価格プレビュー発表

Cloudflareは2026年8月6日、AI Searchに大規模な機能拡張を発表した。従来はWorkers AIやVectorize、R2、Browser Runといった複数のプリミティブを組み合わせて独自の検索パイプラインを構築する必要があった。今回のアップデートによりAI Searchがこれらの処理を自動化し、開発者やエージェントが、まるで自前の検索エンジンを持っているかのような感覚で扱えるようになった。

新機能として、複数のWebサイトやファイルを横断して検索できる公開エンドポイントの提供、サイトマップ不要のクロール機能、カスタムドメインによるブランディング、EmDash CMS向けの検索プラグインなどが追加された。さらにプレビュー価格モデルも発表され、デフォルトの埋め込み・リランキングモデルを利用すれば、これらの処理が無料になる予測可能な料金体系が示されている。エージェントが信頼できる情報源から回答を引き出せるインフラが、これまでより格段に手軽になった。

AI Searchの主な機能強化点

AI Searchの主な機能強化点
従来の構成(Before)
開発者 手動組み合わせ → Workers AI → Vectorize → R2 → Browser Run
それぞれの設定を個別に管理し、データパイプラインを自前で構築する必要があった
↓
AI Searchで統合(After)
開発者 データソース指定 → AI Search が自動処理
クローリング 埋め込み リランキング 検索API
1コマンドでセットアップし、即座に検索エンドポイントが利用可能

AI Searchを導入する前は、ベクトル化したデータの格納先やクローリングの仕組み、リランキングのパイプラインなどを開発者が自前で組み上げる必要があった。しかし今回の強化により、それらの低レベルなサービスを意識せずに済む。結果としてエージェントが信頼できる最新情報を引き出せるインフラが、数分で立ち上がるようになった。

インデックス作成の簡素化

これまでAI SearchでWebサイトをインデックスに追加する際は、サイトマップが必須だった。しかし新たに追加された「Discover」パースオプションを使えば、サイトマップがなくてもページ内のリンクを辿って自動的にコンテンツを収集できる。Cloudflareアカウントに登録されたゾーンであれば、特定のページから始まる全サイトデータを取り込めるようになった。

さらに、HTMLやPDFなどの非構造化データから構造化データまで、幅広いファイル形式に対応した取り込みが可能になった。これにより社内Wikiや製品マニュアルといった多様なデータソースをエージェントの検索対象に加えやすくなっている。

公開検索/MCPエンドポイント

ネームスペースに対して公開URLを有効化すると、/search と /mcp のエンドポイントが即座に利用できるようになる。/search は通常のREST APIとして、/mcp はモデルコンテキストプロトコル(MCP)に対応した形で提供される。どちらも認証不要で、複数のインスタンスにまたがる横断検索を1つのリクエストで実行できる。

外部のエージェントやアプリケーションに検索機能を提供したい場合、このエンドポイントをそのまま公開するだけで済む。Cloudflare以外の顧客に自社データへアクセスしてもらうシナリオでも、認証が不要で、URLを渡すだけのシンプルな共有が可能になっている。

EmDashとの統合とbotポリシー

Cloudflareが公開しているOSSのCMS「EmDash」向けに、AI Searchプラグインが提供された。これを導入すると、EmDashで構築したサイト内にセマンティック検索を組み込める。実際にCloudflare BlogやDeveloper Docsもこの仕組みで動いている。

また、AI Searchのクローラは独自のユーザーエージェント「Cloudflare-AI-Search」を使い、各サイトのrobots.txtに従う。ブラウザベースのクローリング機能を使う場合でも、このポリシーは変わらない。サイト運営者がクロールを拒否すれば収集が停止されるため、著作権や利用規約上の配慮が十分になされている。

Cloudflare Dev Stack MCPの実装事例

Cloudflare Dev Stack MCPの実装事例

Cloudflare自身がAI Searchをどう活用しているかを示す好例が、新しく公開された「Cloudflare Dev Stack MCP」だ。これはCloudflareのエコシステム全体(ドキュメント、ブログ、APIリファレンス、コミュニティなど)を横断検索し、コーディングエージェントへ最新の引用付き回答を返す仕組みである。古いトレーニングデータではなく、常にフレッシュな情報を基にコードを生成できる。

インスタンス作成とクロール

CloudflareはDocs、Blog、API Docs、コミュニティ、Astro、Viteなど計10以上のサイトに対して、それぞれ個別のAI Searchインスタンスを作成した。各インスタンスはドメインが異なるが、Cloudflareが所有するサイトデータであるため、統一的な方法でクロールできる。

npx wrangler ai-search instance create cloudflare-community \
  --namespace dev-stack \
  --source https://community.cloudflare.com \
  --type web-crawler \
  --parse-type discover

上記のコマンドでは、--parse-type discover を指定することでサイトマップなしにページを発見するクロールを実行している。この内部ではBrowser Runの/crawl機能が使用され、リンクを辿って再帰的にページを見つけ出す。

Workerを使ったマルチインスタンス統合

10個のインスタンスにまたがる横断検索を実現するため、CloudflareはWorkerを用いたMCPサーバを構築した。wrangler.jsonにAI Searchネームスペースのバインディングを追加し、1つのツール呼び出しで全インスタンスを同時に検索する。

{
  "ai_search_namespaces": [
    { "binding": "AI_SEARCH", "namespace": "cloudflare-stack" }
  ]
}
context.registerTool(
  'search_dev_stack',
  {
    description: 'Search current docs across the Cloudflare stack.',
    inputSchema: z.object({ query: z.string() }),
  },
  async ({ query }) => {
    const res = await context.env.AI_SEARCH.search({
      query,
      ai_search_options: {
        instance_ids: ['developers-cloudflare-com', 'astro', /* ... */],
        retrieval: { max_num_results: 10 },
        reranking: { enabled: true },
      },
    })
    return { content: [{ type: 'text', text: format(res.chunks) }] }
  }
)

この方式により、エージェントが単一のツール呼び出しで全ドキュメントを検索でき、結果にはどのインスタンスから取得されたかのメタデータが付与される。複数の検索先を順に叩く必要がなく、応答速度も一括で処理される。

コード不要の公開エンドポイントも選択可能

Workerを書かずに済ませたい場合、ネームスペースの公開URLを有効化するだけで、すべてのインスタンスにクエリを投げる/searchおよび/mcpエンドポイントが得られる。設定画面からワンクリックで有効化でき、即座に利用を開始できる。Cloudflare自身のMCPサーバもこの公開エンドポイントを活用している。

Workerを使う場合(カスタム制御)
開発者 Worker実装 → MCPサーバ 経由で検索
既存アプリやエージェントに検索を組み込む場合に適する
↓
公開エンドポイント(ノーコード)
管理者 ワンクリック有効化 → /search /mcp エンドポイント公開
すぐにURLを共有でき、ブラウザやエージェントから直接呼び出せる

コードを書く場合は細かいチューニングやMCPツールとしての統合が可能で、コードを書かない場合は設定画面上の操作だけで外部共有が完了する。どちらの選択肢も提供されている点が、利用者のスキルや要件に応じた柔軟な導入を後押しする。

公開エンドポイントとカスタムドメインで検索を共有

公開エンドポイントとカスタムドメインで検索を共有

AI Searchでは、公開エンドポイントに独自のカスタムドメインを割り当てられる。デフォルトのCloudflare管理URLではなく、search.example.com/mcpといったブランド化されたエンドポイントを用意できるため、サービス提供時の信頼感が高まる。

さらに、検索を限定公開したいケースではCloudflare Accessを介した認証ゲートを追加できる。これによりエンドポイントへのアクセスを許可された人物やエージェントだけに制限し、認証情報を持たない第三者からの不正なクエリを防げる。社内データや顧客限定の検索サービスを安全に運用できる設計になっている。

デフォルト公開URL(無設定)
https://xxx.ai-search.cloudflare.com/search 認証なし
短時間の試験や内部検証には十分だが、ブランド観点では不十分
↓
カスタムドメイン + Access制御(推奨)
search.example.com/mcp → Cloudflare Access でログイン必須
ブランド力とセキュリティを両立し、顧客向け公開に最適

このカスタムドメイン機能は、SaaSプロダクトやエージェントサービスを展開する事業者にとってとくに有用だ。自社ブランドのURLで検索APIを提供することで、サービス全体の統一感が生まれ、導入先からの信頼獲得につながる。

プレビュー価格モデルでコストを予測可能に

プレビュー価格モデルでコストを予測可能に

AI Searchは現在ベータ版として無料提供されているが、正式版に向けたプレビュー価格が公開された。課金開始前には十分な通知が行われる予定だ。料金設計の中心にある考え方は「予測可能でスケーラブル」であり、埋め込みとリランキングをデフォルトモデル利用時に無料化することで、トークン数の見積もりに頭を悩ませる必要をなくしている。

料金の主な内訳

  • インジェスト(テキスト): $0.75 / 1Mトークン。月間無料枠5Mトークン。
  • 画像処理アドオン: +$0.50 / 1Mトークン。画像の埋め込みに使用される。
  • ストレージ: $2.00 / GB・月。月間無料枠10GB。
  • セマンティック検索(ハイブリッド+ベクトル): $0.75 / 1,000クエリ。無料枠2,000クエリ。
  • 全文検索: $0.10 / 1,000クエリ。同上の無料枠と共有。
  • 埋め込みとリランキング: 指定モデル利用時は無料。それ以外はWorkers AIの従量課金。

無料枠はインジェスト5Mトークンと検索2,000クエリがそれぞれ一つのプールとしてまとめられており、用途を気にせず使い切れる。埋め込みやリランキングのコストが気にならないため、データ更新や再インデックスの頻度を高めやすい。これは頻繁に情報が変わるナレッジベースをエージェントに与えたい開発者にとって大きなメリットだ。

2万ドキュメント規模の試算例

以下は、2万件の文書(約2,000万トークン)と1,000枚の画像をインジェストし、月間3万回のセマンティッククエリを実行した場合の想定コストである。ワーカーズ有料プランが前提で、埋め込みとリランキングにはデフォルトモデルを使用する。

  • インジェスト(テキスト): 18.1Mトークン × $0.75/1M = $13.58
  • 画像アドオン: 1.1Mトークン × $0.50/1M = $0.55
  • ストレージ: 約1.2GB → 無料枠内で$0
  • 検索: 28,000クエリ × $0.75/1k = $21.00
  • 埋め込み・リランキング: $0
  • 合計: 約$35.13

初月にインジェスト費用がかかるが、2か月目以降は主に検索クエリ分だけ(この例では約$21)で運用できる。ドキュメントの大幅な増加がなければ、ランニングコストを低く抑えられる構造だ。

初月のコスト内訳イメージ
インジェスト $13.58 + $0.55 → 検索$21
埋め込み・リランキングは無料
↓
2か月目以降の月額
検索のみ 約$21.00
インジェスト費用が不要で、クエリ数に応じた変動

このように、AI Searchのコストは初回のデータ登録が大部分を占め、その後は利用量に比例した検索料金のみになる。大規模なデータベースを抱える場合でも、固定費ではなく使った分だけ支払うモデルのため、予算計画が立てやすい。

AI Searchの導入方法

AI Searchの導入方法

AI SearchはCloudflareダッシュボードから有効化し、すぐに使い始められる。もっとも簡単な導入は、次のwranglerコマンドでインスタンスを作成する方法だ。

npx wrangler ai-search create my-search \
  --namespace my-namespace \
  --source https://my-website.com \
  --type web-crawler \
  --hybrid-search

この1行でWebクローラー型のインスタンスが立ち上がり、ハイブリッド検索(セマンティック+キーワード)が有効になる。クロールが完了すれば、/searchエンドポイントで検索APIとして利用できる。さらに/mcpエンドポイントを使えば、ChatGPTやClaudeなどのモデルが直接ツールとして呼び出せる。

既存のアプリに組み込む場合はWorker経由でバインドし、エージェントと連携させればよい。カスタムドメインやCloudflare Accessを設定すれば、プライベートな検索サービスとしても公開できる。詳しい手順は公式ドキュメントを参照してほしい。

この記事のポイント

  • Cloudflare AI Searchは、複数サービスの組み合わせを自動化し、データ検索基盤をワンストップで提供する。
  • 公開/MCPエンドポイントやカスタムドメインにより、エージェントへの組み込みや外部共有が容易になった。
  • サイトマップ不要のクロールやEmDash CMSとの統合で、あらゆるデータソースを取り込める。
  • プレビュー価格ではデフォルトモデルの埋め込み・リランキングが無料で、予測しやすいコスト構造が示された。
  • wranglerコマンド1行でセットアップが完了し、すぐにエージェント向け検索エンジンとして利用開始できる。
ShopMagicで重複カラムエラーが出る原因とデータベース接頭辞の修正

ShopMagicで重複カラムエラーが出る原因とデータベース接頭辞の修正

ShopMagic 4.8.6以前のバージョンで、データベースアップグレード中に「カラムが重複しています(Duplicate column name ‘note_context’)」というエラーが発生する場合、原因はプラグイン内部のマイグレーションファイルでテーブル接頭辞が wp_ に固定されていることだ。バージョン4.8.7へのアップデートで修正されるが、すぐにアップデートできない場合は、データベースのオプション値を直接編集する緊急回避策でエラーを止められる。

なぜShopMagicで重複カラムエラーが発生するのか

なぜShopMagicで重複カラムエラーが発生するのか

ShopMagicには、プラグインが更新されるたびにデータベースのテーブル構造を自動調整する「マイグレーション」機能が備わっている。今回の問題は、マイグレーションファイル Version_42.php の17行目付近で発生する。このファイルは、note_context というカラムが既に存在するかどうかを確認するために SHOW COLUMNS クエリを実行するが、その際に対象テーブルを wp_shopmagic_automation_outcome_logs と決め打ちしてしまっている。

サイトのデータベース接頭辞(wp-config.php の $table_prefix)がデフォルトの wp_ であれば問題は出ない。しかし、セキュリティや複数サイト運用の都合で接頭辞を abc123_ などに変更している場合、wp_shopmagic_automation_outcome_logs というテーブルは存在しないため、SHOW COLUMNS が失敗する。その結果、プラグインは「カラムが存在しない」と誤認し、note_context を追加しようとする。しかし実際には正しい接頭辞のテーブルに既に存在するため、ALTER TABLE が「カラムが重複しています」というエラーで失敗する。

さらに深刻なのは、このエラーによってマイグレーションチェーン全体が止まってしまう点だ。Version 42が失敗として記録されないため、後続のVersion 43から48のマイグレーションがいっさい実行されない。これにより、マーケティングリストやトラッキングメール関連のテーブルが不足し、気付かないうちに一部機能が不完全になる可能性がある。また、エラーはページが読み込まれるたびに繰り返し発生し、デバッグログを大量に汚染する。

カスタム接頭辞サイトでのエラー発生フロー
【Before】 SHOW COLUMNS FROM wp_shopmagic_… を実行
↓ テーブルが存在しないため失敗
↓
【エラー】 プラグインが「カラム不在」と誤認し、ALTER TABLEで note_context を追加しようとする
↓ しかしカラムは既に存在する
↓
【After】 修正後は $table_name を使って正しい接頭辞のテーブルを確認するため、エラーは発生しない
■ エラー発生時の流れ ■ 修正後の動作

データベースエラーを解消するアップデート手順

根本的な解決策は、ShopMagicをバージョン4.8.7以降にアップデートすることだ。このバージョンでは、マイグレーションファイル内のハードコードされた wp_ が削除され、動的に正しいテーブル接頭辞を参照するように修正されている。

管理画面から自動アップデートする

WordPress管理画面の「プラグイン」→「インストール済みプラグイン」で、ShopMagicに利用可能なアップデートが表示されていれば、「今すぐ更新」をクリックする。アップデート後、データベースのアップグレードが正常に走り、エラー通知が消えていることを確認する。

手動でアップデートする

自動アップデートが利用できない場合は、公式リポジトリまたは有料版の提供元から最新のZIPファイルをダウンロードし、管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から上書きインストールする。既存の設定やデータが失われることはないが、不安な場合は事前にサイト全体のバックアップを取得しておく。

アップデートできない場合の緊急回避策

アップデートできない場合の緊急回避策

何らかの理由ですぐにプラグインをアップデートできない場合、データベースのオプション値を直接書き換えることでエラーの無限ループを止められる。この方法は、マイグレーションVersion 42が「未完了」として記録されているために毎回実行される状態を、「完了」とマークするものだ。Version 42が実際に行うべきテーブル変更(カラム追加)はエラーを起こしながらも既に成功しているため、安全性は高い。

緊急回避の手順
STEP 1 必ずデータベース全体のバックアップを取る
↓
STEP 2 phpMyAdminなどで wp_options テーブルを開く(接頭辞は環境に合わせる)
↓
STEP 3 option_name が shopmagic_db の行を探し、編集する
↓
STEP 4 option_value を WPDesk\ShopMagic\migrations\Version_42 に変更して保存する
注意: phpMyAdmin上ではバックスラッシュのエスケープ処理が自動で行われるため、入力時は WPDesk\ShopMagic\migrations\Version_42 とシングルバックスラッシュで入力する。保存後に LENGTH(option_value) が38(35ではない)であることを確認すれば、正しく保存されている。

変更を保存して管理画面を再度読み込むと、ShopMagicはVersion 42のマイグレーションが完了したと認識し、続けてVersion 43から48の未実行マイグレーションを順次処理する。これにより、不足していたテーブルが自動的に作成され、エラー通知も消える。なお、マイグレーション44では既存のオプトインメールデータを作成済みのマーケティングリストテーブルにコピーする処理が含まれるため、データ量によってはページの読み込みに時間がかかることがある。

よくある質問

エラーが解消された後、不足していたテーブルは自動的に作られるのか

アップデートまたはオプション値の書き換え後、ページを読み込んだタイミングで自動的に不足テーブルが作成される。Version 43から48のマイグレーションが順次実行され、マーケティングリストテーブルやトラッキングメールテーブルなどが生成される。特別な操作は不要だ。

データベース接頭辞をデフォルトのwp_に変更すれば直るのか

接頭辞の変更はサイト全体に影響を与える大掛かりな作業であり、推奨しない。テーブル名の一括置換やwp-config.phpの編集、シリアライズ化データの再計算などが必要になる。このエラーはプラグイン側の問題であり、ShopMagicをアップデートするだけで解決するため、そちらを優先する。

この問題はShopMagic以外のプラグインでも起きるのか

プラグインが内部でデータベース接頭辞をwp_に決め打ちしている場合、全く同じメカニズムでエラーが発生する。ただし、多くのプラグインはWordPressの$wpdb->prefixを用いて動的に接頭辞を取得するため、一般的な問題ではない。カスタム接頭辞を使用しているサイトで特定のプラグインだけがエラーを起こす場合、同様のハードコードが原因である可能性を疑うとよい。

phpMyAdminから直接オプション値を変更するのが不安だ

WP-CLIが利用できる環境であれば、wp option update shopmagic_db 'WPDesk\ShopMagic\migrations\Version_42' --format=plain というコマンドで安全に同じ変更が行える。phpMyAdminを使う場合でも、該当行の編集後すぐに管理画面を開き、エラー通知が消えたことを確認すれば問題ない。

この記事のポイント

  • エラーの直接原因は、マイグレーションファイル内でテーブル接頭辞が wp_ に固定されていること
  • カスタム接頭辞を使うサイトでは、毎回のページ読み込みでエラーが繰り返される
  • ShopMagicをバージョン4.8.7以降にアップデートすれば根本解決する
  • アップデートできない場合、shopmagic_db オプションを手動で進める緊急回避策がある
  • 回避策を取ったあと、後続のマイグレーションが自動実行され不足テーブルも作成される
OpenAIが解説、GPT-Liveのリアルタイム音声AI基盤 6か月で会話応答を実現へ

OpenAIが解説、GPT-Liveのリアルタイム音声AI基盤 6か月で会話応答を実現へ

OpenAIが2026年8月、新たな音声AIシステム「GPT‑Live」の設計を解説するブログ記事を公開した。同社の音声AIは、従来のターンベースからフルデュプレックスへと進化し、人が会話で無意識に行う「間」の制御を大幅に改善したという。わずか6か月で実用化にこぎつけたその裏側には、ストリーミング推論、状態管理、プロトコル最適化といった多層的な技術的挑戦があった。

本記事では、このブログで語られたGPT‑Liveのシステム設計に焦点を当てる。なぜ従来の音声応答では違和感が残ったのか、そしてどのようにして「息の合った」会話をスケールさせたのかを、具体的な設計上の工夫とともに紹介する。

ターンベースの限界、なぜ音声AIは「間」に弱いのか

ターンベースの限界、なぜ音声AIは「間」に弱いのか

人間同士の会話では、わずか0.5秒以下の間で話者交替が行われる。しかし従来の音声AIはテキスト向けLLMの流れを引き継ぎ、音声をテキストに変換し、推論してから音声を合成するという逐次処理が基本だった。スピーチトゥスピーチモデルの登場で音声を直接扱えるようになったが、依然として「発話が終わったか」を判断する小さなターン検出器に依存していた。

この検出器はジレンマを抱える。早すぎる判断はユーザの言葉を遮り、遅すぎる判断は応答の間延びを生む。しかも検出器の判断後に大規模なLLMが起動するため、応答までの遅延は避けられなかった。

OpenAIのブログ記事では、この課題を「誰がいつ話すかを決める小さなモデルに会話のリズムを委ねることは非効率だった」と指摘している。

従来のターンベースモデル(Before)
ユーザ発話 音声入力 → ターン検出器 判断待ち → LLM推論 応答生成
※検出器の誤判定による遮断や遅延が発生
↓
GPT‑Liveのフルデュプレックス(After)
ユーザ発話 音声ストリーム ⇄ 同時送受信 ⇄ 音声モデル 即時応答
※検出器不要、発話中も相手の音声を聞きながら応答を生成

上の図のように、GPT‑Liveはターン検出器を音声パスから完全に排除した。音声の送受信を同時に行うフルデュプレックス方式により、会話の流れが途切れず、より自然なやり取りを実現している。

GPT‑Liveの中核、フルデュプレックスと非同期委任の仕組み

GPT‑Liveでは、音声そのものを処理する経路と、より深い思考やツール実行を担う経路を意図的に分離している。会話のリアルタイム性を支える「メディア高速パス」と、大規模なフロンティアモデルGPT‑5.5を呼び出す「アプリケーション低速パス」だ。音声モデルは常に会話を続けながら、必要に応じて非同期RPCでGPT‑5.5に委任する。これにより、たとえ委任先の応答に時間がかかっても、音声の流れが止まることはない。

この分離設計は、機能拡張の面でも恩恵が大きい。アプリケーション側のツールやポリシーを変更しても、音声応答の核となるメディアパスに影響を与えずに済む。今後、ChatGPTのデスクトップアプリでコンピュータ操作やエージェント連携といった新機能を追加する際も、音声体験の即時性を犠牲にしない基盤がすでに整っている。

システム全体の流れ
クライアント 音声入出力 → 音声モデル フルデュプレックス推論
メディア高速パス
途切れのない音声フレーム配送
アプリケーションサーバ 非同期RPC → GPT‑5.5 ツール・推論
アプリケーション低速パス
深い思考やツール実行をバックグラウンドで処理
重要な設計方針
音声モデルは会話を途切れさせず、必要に応じてフロンティアモデルに委任する。委任の結果が遅れても、音声パスには影響しない。

途切れない音声を保つ、推論基盤の最適化

途切れない音声を保つ、推論基盤の最適化

フルデュプレックスの会話をスケールさせるには、ステートフルな推論と動的なコンテクスト管理が欠かせない。音声セッションは長時間に及び、その間コンテクストが増え続ける。モデルインスタンスも需要に応じて増減するため、途切れのない体験を維持するには高度なハンドオフ機構が必要になる。

GPT‑Liveは、モデルインスタンス間のシームレスな切り替えを導入した。切り替えが必要な場合、既存のインスタンスと並行して新しいインスタンスを立ち上げ、現在のセッションコンテクストを事前に読み込ませる。両方のインスタンスで推論を並行して行い、新しいインスタンスの準備が整った時点で切り替える。この一連の処理はメディアパスの外側で実行されるため、会話が中断される心配はない。

同様に、コンテクストがモデルの上限を超えた場合も、同じ並行ハンドオフの考え方で対応する。従来は推論を止めてコンテクストを圧縮し、KVキャッシュを再構築する必要があったが、GPT‑Liveでは圧縮作業と新インスタンスの準備をバックグラウンドで行う。元のインスタンスが会話を続けている間に、圧縮済みコンテクストを持った代替インスタンスが準備され、問題なく切り替えられる。この仕組みにより、長時間の通話でも音声が途切れず、ユーザはコンテクストの上限を意識することがない。

従来の対応(Before)
長い会話でコンテクストが上限に達すると、推論を止めて圧縮処理を実行。KVキャッシュが破棄され、再構築に遅延が発生。
STEP 1 コンテクスト上限到達
↓
STEP 2 推論一時停止 圧縮処理
※この間音声が途切れる
↓
GPT‑Liveの動的コンパクション(After)
既存のインスタンスが会話を続ける裏で、新しいインスタンスを準備し、圧縮済みコンテクストを事前投入。準備完了後に切り替える。
STEP 1 代替インスタンス生成
↓
STEP 2 圧縮コンテクストを事前読込
↓
STEP 3 並行推論で追いついたら切替
※会話は一切止まらない

起動遅延を1回のUDPパケットに、プロトコル改善の舞台裏

起動遅延を1回のUDPパケットに、プロトコル改善の舞台裏

音声AIの応答速度は、会話の開始ボタンを押した瞬間から問われる。GPT‑Liveでは、WebRTCをベースにメディアパスを確立し、モデルへの音声入力を開始するまでの時間を極限まで削り取った。そのために生み出されたのが、WARP(WebRTC Abridged Roundtrip Protocol)とInstant Connectという2つの新技術だ。

標準的なWebRTCでは、メディアとデータの開始までにICE、DTLS、SCTP、データチャネルの確立と、最大6回のネットワーク往復が必要だった。OpenAIのエンジニアは、DTLSハンドシェイクをICEに便乗させるSPEDや、SCTPのネゴシエーションを事前共有するSNAPなどを考案し、これらの手順を1往復に圧縮した。さらにInstant Connectにより、SDPパラメータの事前共有を実現。ユーザがボタンを押した瞬間、最初のUDPパケットでセッションが成立し、即座に音声ストリームが流れ始める。

従来のWebRTCハンドシェイク(Before)
メディアとデータの開始までに最大6往復の通信が必要。
1往復目 ICE疎通確認
↓
2往復目 DTLSハンドシェイク
↓
3往復目 SCTPアソシエーション
↓
4〜6往復目 データチャネル確立
※接続完了まで数百ミリ秒
↓
WARPとInstant Connectによる最適化(After)
事前にSDPネゴシエーションを行い、1つのUDPパケットでセッション開始。
1パケット送信 ICE+DTLS+SCTP+データチャネルを一回の往復で確立
※接続時間を大幅短縮、実質ワンラウンドトリップ

これらのプロトコル改良は、OpenAIだけでなくWebRTCコミュニティにも公開されており、すでにlibwebrtcやPionに実装が進んでいる。IETFのTSVWGワーキンググループを通じて標準化も目指されているという。

本番さながらのテストが教えた教訓

本番さながらのテストが教えた教訓

理論上の性能がいくら優れていても、実際の音声トラフィックの前では想定外のボトルネックが顔を出す。OpenAIはGPT‑Liveの本格提供前に、サイレントシャドーテストと呼ばれる手法を採用した。ChatGPT Voiceの実際のユーザセッションの一部を、既存のAdvanced Voice Modeと並行して、新しいシステムに読み取り専用で流し込むのだ。

このテストで最初に判明したのは、GPUの処理能力だけを見ていては不十分だという事実だった。音声セッションは継続的にフレームを送り続けるため、CPU側のストリームハンドラやキュー、ネットワーク経路もGPUと同等にスケールしなければならない。サイレントテストにより、負荷試験では見落とされがちなCPU飽和が検出され、レイテンシの蓄積を防ぐ対策が取られた。

一般的な負荷テスト(Before)
  • GPUあたりのリクエスト数だけを見る
  • 長時間接続や再接続のパターンを検証できない
  • 地理的な遅延差が考慮されない
※本番で想定外のボトルネックが発生しがち
↓
GPT‑Liveのサイレントシャドーテスト(After)
  • 実際のユーザーの音声セッションを読み取り専用で流す
  • CPU側のストリーム処理やネットワーク経路も含めて検証
  • 地域別の遅延や長時間の状態圧縮の挙動を観測
※本番と同等の負荷と多様性で問題を早期発見できる

また地理的な要素も無視できない教訓をもたらした。ユーザに近い場所に推論リソースを配置しなければ、起動時やストリーミング中の遅延が増加する。OpenAIは地域別の容量とトラフィック誘導を定常的に検証し、エンドツーエンドの応答性を部品ごとに可視化する監視体制を整えた。さらに、メトリクスの粒度を上げ、ダッシュボードが不健全なエンジンを埋もれさせないように改善。段階的なロールアウトやパスの隔離など、本番品質を支える運用技術も同時に鍛え上げられた。

この記事のポイント

  • GPT‑Liveはターン検出器を排除したフルデュプレックス方式で、発話中の同時送受信を実現
  • 音声モデルとフロンティアモデルを非同期に分離し、深い思考を会話の遅延なく組み込む設計
  • ステートフル推論と動的コンパクションにより、長時間の会話でも途切れない音声を維持
  • WebRTCのハンドシェイクを1往復に圧縮するWARPやInstant Connectで、起動遅延を極限まで低減
  • 本番トラフィックを使ったサイレントテストで、実際の運用に耐えるシステムへと練り上げた
WooCommerce納品書印刷でFTPエラーが起きた時の原因と直し方

WooCommerce納品書印刷でFTPエラーが起きた時の原因と直し方

WooCommerceのマイアカウント画面から「納品書を印刷」や「領収書を印刷」をクリックした瞬間に「このサイトで重大なエラーが発生しました」と表示されてページが落ちる場合、原因はプラグインがFTPの認証情報なしにファイルシステムへアクセスしようとしたことにある。PHP 8環境で発生しやすいこの問題は、WP_Filesystem()の呼び出し方を修正すれば直る。

エラーの原因は何か

エラーの原因は何か

この問題は「Print Invoice & Delivery Notes for WooCommerce」などの納品書プラグインが、フロントエンドからWP_Filesystem()を呼び出す際にFTPの認証情報を渡していないことが根本原因だ。WP_Filesystem()はWordPressがサーバー上のファイルを操作するためのAPIで、通常は管理画面から操作するときに使われる。しかしプラグインのコードがこのAPIをバックグラウンドで実行しようとしたとき、必要なFTP接続情報が揃わず、接続オブジェクトがnullのままになってしまう。

PHP 8では関数の引数の型チェックが厳格化されたため、nullの接続オブジェクトをftp_nlist()などの関数に渡すと即座に致命的なTypeErrorが発生する。これが「Uncaught TypeError: ftp_nlist(): Argument #1 ($ftp) must be of type FTP\Connection, null given」というエラーの中身だ。

エラー発生時の状態
プラグインが WP_Filesystem() を引数なしで呼び出す
↓
FTP認証情報がないため接続オブジェクトが null になる
↓
PHP 8の型チェックで TypeError が発生し画面がクラッシュ
↓
修正後の正しい流れ
まず request_filesystem_credentials() で認証情報を取得
↓
取得した認証情報を WP_Filesystem( $credentials ) に渡す
↓
FTP接続が正常に行われ、ファイル操作が完了する
■ エラー発生時 ■ 修正後

上の図で見るとわかるように、修正前は認証情報の取得ステップが丸ごと抜け落ちている。WordPressが用意している標準的な手順は「まず認証情報を集め、それからファイルシステムを初期化する」という2段階だ。プラグインがこの流れを省略したことで、FTP接続が確立されないまま後続の処理が走り、致命的エラーに至っている。

自分のサイトでエラーが発生しているか確認する方法

自分のサイトでエラーが発生しているか確認する方法

まずはエラーの詳細を把握するためにWordPressのデバッグモードを有効にしよう。wp-config.phpに以下の行を追加する。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

この設定をすると、エラーの内容が/wp-content/debug.logに記録されるようになる。ページが真っ白になる現象は本番環境では特に厄介だが、ログを見ればスタックトレースが残っているため原因を特定できる。スタックトレースの中にwp-admin/includes/class-wp-filesystem-ftpext.phpやwoocommerce-delivery-notesというパスが見つかれば、今回のケースに該当する可能性が高い。

プラグインのコードを修正してエラーを止める手順

プラグインのコードを修正してエラーを止める手順

根本的な修正はプラグイン本体のコードを書き換えることだが、これはプラグインが更新されるたびに変更が上書きされてしまう一時しのぎの対策だ。それでも今すぐエラーを止めたい場合には有効なので、まずは直接修正する手順を説明する。

修正対象のファイルとコードの場所

対象ファイルはプラグインディレクトリ内の includes/helpers/class-utils.php にある get_filesystem() メソッドだ。このメソッドが WP_Filesystem() を引数なしで呼び出している箇所が問題の中心になる。

// 修正前のコード
public static function get_filesystem() {
    global $wp_filesystem;
    if ( ! $wp_filesystem ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        WP_Filesystem(); // ← 引数がないためFTP接続に失敗する
    }
    return $wp_filesystem;
}

修正後のコード

以下のように書き換える。request_filesystem_credentials() であらかじめ認証情報を取得し、それを WP_Filesystem() に渡す形にする。さらに、request_filesystem_credentials() が認証情報を問い合わせるHTMLフォームを出力してしまうのを防ぐために、出力バッファリングで囲んでおく。

// 修正後のコード
public static function get_filesystem() {
    global $wp_filesystem;
    if ( ! function_exists( 'WP_Filesystem' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
    }
    if ( ! $wp_filesystem ) {
        ob_start(); // バッファリング開始
        $credentials = request_filesystem_credentials( '' );
        ob_end_clean(); // バッファを捨てる(フォーム出力を抑制)
        WP_Filesystem( $credentials ); // 認証情報を渡す
    }
    return $wp_filesystem;
}
STEP 1 FTPまたはサーバーのファイルマネージャーでプラグインファイルにアクセス
↓
STEP 2 includes/helpers/class-utils.php をテキストエディタで開く
↓
STEP 3 get_filesystem() メソッドを見つけてコードを差し替え
↓
STEP 4 ファイルを保存してアップロードし、動作を確認

この修正を施すと、wp-config.phpに定義されたFTP定数(FTP_HOST、FTP_USER、FTP_PASS)や、WordPressがデータベースに保存している認証情報が自動的に使われるようになる。結果としてFTP接続が正常に確立され、exists()などのファイル操作メソッドが問題なく動作する。

プラグイン更新で修正が消えないようにする恒久対策

プラグイン更新で修正が消えないようにする恒久対策

プラグインのコアファイルを直接編集する方法は、アップデートがあるたびに上書きされてしまうため本番運用には不向きだ。より持続的な対策として、以下のいずれかの方法を選ぶとよい。

子テーマのfunctions.phpでフックを使って上書きする

プラグインが提供しているフィルターフックやアクションフックを利用し、テンプレートのレンダリング時にファイルシステムアクセスが発生する処理を迂回する方法だ。ただし、このプラグインではフックが十分に用意されていない可能性が高いため、テーマのCSSやテンプレートの上書きだけで対応しきれないこともある。

プラグインのIssueトラッカーやサポートフォーラムに修正を依頼する

今回の修正はすでにWordPress.orgのサポートフォーラムにも報告されている。プラグインの開発者がこの修正を取り込めば、次回以降のアップデートで公式に問題が解決される。開発者の対応を待つ間は、前述のファイル直接編集でしのぎつつ、アップデートのたびに修正を再適用する運用になる。

プラグイン全体をフォークして独自バージョンを使う

どうしても自前で管理したい場合は、プラグインのコードをコピーして別のプラグインとしてインストールし直す方法もある。ただし今後のアップデートやセキュリティパッチの追従をすべて自分で行う必要があるため、開発リソースに余裕がある場合に限った選択肢だ。

同じエラーが別のプラグインで出る場合の一般的な対処法

同じエラーが別のプラグインで出る場合の一般的な対処法

今回のエラーは「Print Invoice & Delivery Notes for WooCommerce」に限らず、フロントエンドから WP_Filesystem() を不用意に呼び出しているあらゆるプラグインで発生しうる。バックアップ系、インポート系、PDF生成系のプラグインで似たような「ftp_nlist()」を含むTypeErrorが出た場合は、以下の共通チェックポイントで原因を絞り込める。

  • スタックトレースの2〜3行目に表示されているプラグインのパスを特定する
  • 該当プラグインのファイルシステム呼び出し部分を探す(WP_Filesystem() または $wp_filesystem を grep する)
  • 認証情報の取得が行われているか確認する(request_filesystem_credentials() の有無)
  • PHPのバージョンを確認する(PHP 8.0未満では暗黙の型変換でエラーが表面化しないことがある)
エラーパターンの見分け方
パターンA 管理画面では動くがフロントエンドでだけ落ちる → FTP認証情報の未取得が原因
パターンB PHP 7.xでは問題なかったがPHP 8に上げたら発生 → 型チェック厳格化の影響
パターンC 特定のサーバー環境(ftpext方式)でのみ発生 → ファイルシステム方式の不一致

特に「ftpext」というファイルシステム方式を使用しているサーバー環境で顕著に発生する。多くのレンタルサーバーでは「direct」方式が使われるため問題が起きにくいが、FTP経由でファイル操作を行う設定になっているとこのエラーに遭遇しやすい。

よくある質問

エラーが出ているのに管理画面にはアクセスできるのはなぜか

管理画面ではWordPressがWP_Filesystem()を呼び出す前に自動的に認証情報を収集する仕組みが働くため、正常に動作する。フロントエンドではその仕組みが起動しないため、プラグインが自前で認証情報を取得しない限り接続に失敗する。これが「管理画面では動くのにマイアカウント画面では落ちる」という現象の理由だ。

出力バッファリングをしないとどうなるのか

request_filesystem_credentials() は認証情報が不足している場合にFTPのホスト名やユーザー名を入力するHTMLフォームを画面に直接出力してしまう。フロントエンドのページに突然フォームが表示されると、サイトのレイアウトが崩れたり、ユーザーを混乱させたりする。出力バッファリングでこのフォーム出力を捕捉して破棄することで、見た目に影響を与えずに認証情報だけを取得できる。

wp-config.phpにFTP定数を設定するだけで直らないのか

FTP定数(FTP_HOST、FTP_USER、FTP_PASS)を定義していても、プラグインがWP_Filesystem()を引数なしで呼び出している限り、WordPressは認証情報を探しに行かない。定数はあくまで「情報の置き場所」であり、「その情報を取りに行く処理(request_filesystem_credentials())」が実行されなければ意味がない。コードの修正が不可欠な理由はここにある。

PHP 8にアップグレードした直後から発生したのだが関係あるのか

大いに関係がある。PHP 8.0から関数の引数と戻り値の型が厳密にチェックされるようになり、それまで暗黙的に許容されていたnullの受け渡しがTypeErrorとして検出されるようになった。PHP 7.x時代は同じコードでも警告で済んでいたか、あるいはエラーが発生しても表面的に無視されていた可能性が高い。

この修正でセキュリティ上の問題は起きないのか

起きない。request_filesystem_credentials()はWordPressのコア関数であり、管理画面で日常的に使われている安全な方法だ。認証情報はwp-config.phpの定数やデータベースに保存された情報から取得され、フロントエンドの訪問者にFTPのパスワードが表示されることはない。出力バッファリングでフォームの表示を抑制するのも、余計な情報を露出させないための適切な処置だ。

この記事のポイント

  • WooCommerceの納品書印刷で重大エラーが発生するのは、プラグインがWP_Filesystem()を認証情報なしで呼び出しているのが原因
  • PHP 8の厳格な型チェックにより、FTP接続オブジェクトがnullのまま関数に渡されてTypeErrorが起きる
  • プラグインのclass-utils.phpにあるget_filesystem()メソッドを修正すれば即座に直る
  • request_filesystem_credentials()で認証情報を先に取得し、出力バッファリングでフォーム表示を防ぐのが正しい修正手順
  • プラグインのアップデートで修正が消えるため、恒久対応は開発者による公式修正を待つかフォークしての運用が必要
AppleがOpenAIを提訴、訴訟内容に事実誤認か? メールが示す真実

AppleがOpenAIを提訴、訴訟内容に事実誤認か? メールが示す真実

2026年8月3日、OpenAIが公式ブログでAppleの訴訟内容に反論する記事を公開した。Appleが起こした訴訟には事実誤認が含まれており、OpenAIはメールやiMessageのやり取りを公開して真相を明らかにしている。

この訴訟は、元Apple社員がOpenAIへ転職した際の機密情報持ち出し疑惑に端を発する。しかしOpenAI側は、Apple側の情報管理の不備や誤解によるものであると主張。一方的な提訴に疑問を投げかけている。

Appleの提訴と事実のギャップ

Appleの提訴と事実のギャップ

Appleは2026年7月末、OpenAIと元自社社員3名を相手取り訴訟を起こした。主な主張は、元従業員が退職時に機密情報を持ち出し、OpenAIの製品開発に流用したというものだ。訴状では、OpenAIに対して仮差止命令(Preliminary Injunction)も求めている。

しかしOpenAIのブログ記事によれば、これらの主張の多くは事実と異なる。同社は自社の法務責任者(General Counsel)であるChe Chang氏とAppleの外部弁護士、社内法務チーム間のメールのやり取りを全文公開し、Appleの説明が実際の経緯を隠蔽していると批判した。

Appleの主張(訴訟で提示)
  • 2026年2月にOpenAIへ連絡したが返答なし
  • OpenAIの法務責任者と協議を行った
  • 元従業員が退職後に機密情報にアクセスした
↓
実際の経緯(OpenAIが指摘)
  • 外部弁護士が中国人姓を混同し、誤った人物にメール送信。OpenAIが指摘するまで気づかず。
  • 協議は行われておらず、後にAppleも認める
  • Apple社員が元同僚に業務上の問い合わせをしていた(残留アクセスの問題)
出典 OpenAIブログ(2026年8月3日)より作成

このように、Appleが公式の法的手続きで述べた内容と、公開された文書が示す事実には大きな隔たりがある。特にコミュニケーションの行き違いは、大企業間の訴訟プロセスとして異例の稚拙さと言える。

訴訟の背景

問題となっているのは、Appleの元社員であるChang Liu氏、Tang Tan氏らがOpenAIに転職したことだ。Appleは彼らが自社の設計や製造プロセスに関する極秘情報を不正に保持し、OpenAIのAIハードウェア開発に利用したと主張している。Tang Tan氏はAppleに24年以上在籍し、最も革新的なリーダーの一人として知られていた人物だ。

OpenAIによる反論のポイント

OpenAIの反論は主に3つに集約される。

  • AppleがOpenAIに連絡しなかったとされる点について、実際にはAppleの外部弁護士がChe Chang氏(姓が異なる別人)に誤ってメールを送っていた。OpenAIから指摘を受けて初めて謝罪した。
  • 「法務責任者と協議した」という主張は虚偽であり、後に取り下げた。
  • Chang Liu氏が退職後にAppleの機密情報にアクセスしたという疑惑は、むしろApple社員が業務上の問い合わせを元同僚に行っていた事実を示すiMessageの記録で反証される。

残留アクセス問題が浮き彫りにした情報管理の甘さ

残留アクセス問題が浮き彫りにした情報管理の甘さ

訴訟でAppleが「Chang Liu氏が退職後に機密情報へ不正アクセスした」と主張する一方、OpenAIはその主張を覆すiMessageのスクリーンショットを公開した。それによると、Appleの社員が退職直後のChang Liu氏に連絡を取り、ファイルの所在確認や作業の補助を依頼していたのだ。

Chang Liu氏とApple社員のiMessage

公開されたメッセージでは、2026年1月22日が最終出社日だったChang Liu氏に対し、元同僚が「この文書はどこにあるか」「以前のプロジェクトの資料を探してほしい」といった内容を送っている。つまり、Apple内部で情報の引継ぎが不十分だったために、退職者に頼らざるを得なかった状況が浮かび上がる。

「残留アクセス」の実態

OpenAIはこの点を「残留アクセス(residual access)」という言葉で説明する。これは退職後も社内システムやファイルへのアクセス権が適切に削除されていない状態を指す。Appleの情報管理プロセスに問題があるからこそ、退職者が意図せず情報を見られてしまう状況が生まれているとOpenAIは指摘する。この指摘は、AI業界に限らず多くの企業にとって、退職者のアクセス権管理という普遍的な課題を投げかけるものだ。

誤送信メールが示すコミュニケーションの混乱

誤送信メールが示すコミュニケーションの混乱

訴訟の根幹にある「AppleはOpenAIに連絡したが無視された」という主張も、電子メールの証拠によって崩れている。OpenAIが全文公開したメールのやり取りは、Appleの外部弁護士事務所Weil Gotshalのパートナー弁護士Gabriel Gross氏と、OpenAIのChe Chang氏、Apple社内法務チームの間で交わされたものだ。

弁護士のメール誤送信と虚偽報告

2026年2月23日、Gross氏はChe Chang氏宛てにAppleを代理する内容のメールを送信した。しかしこのメールは本来、同じく元Apple社員の「Wang」氏に送る予定だったものだ。Chinese surname(中国系の姓)の混同により誤って別人物に届いた。

さらにGross氏は、同日にChang氏と電話で話したと記したが、Chang氏はそれを否定し「私は彼を知らないし話していない。虚偽だ」とApple社内法務にメールで抗議した。翌24日、Gross氏は誤りを認め謝罪。「Wang氏と話した後に返信しようとして誤ってあなたとのメールチェーンに返信してしまった」と説明した。

問題解決の意思と5か月の沈黙

この一連の混乱のなかで、Gross氏は「問題を解決する(resolving any issues)」と述べており、Apple側に訴訟の具体的な主張を事前に伝えることはなかった。その後、5か月もの間何の連絡もないまま、突然訴訟が提起された。OpenAIは「提訴前にこうした問題を提起してくれれば喜んで協力したのに」とコメントしている。

OpenAIの姿勢と今後の展望

OpenAIの姿勢と今後の展望

OpenAIは今回の訴訟について、「Appleの仮差止命令の申し立ては虚偽の情報に基づいており、まったく不要なものだ」と断じている。同社はAppleの機密情報を望んでおらず、保有もしていないと断言する。

また、将来的にAppleと協調して問題解決にあたる用意があることを示しつつも、訴訟の場で事実を歪曲する行為には強く反発している。AI業界全体としては、優秀な人材の移動に伴う知的財産の取扱いに関するルール整備が急務であるとの見方も出ている。

この記事のポイント

  • AppleがOpenAIを提訴した内容には、事実誤認が複数含まれているとOpenAIが反論した
  • メールの誤送信や虚偽の申し立てなど、コミュニケーションの混乱が訴訟の背景にある
  • 退職者の残留アクセス問題は、Apple自身の情報管理の甘さに起因する可能性が高い
  • OpenAIは機密情報の利用を否定し、建設的な対話を求めている
  • AI業界では人材流動性が高まるなか、知的財産管理の再考が求められる
WordPressで「Duplicate entry」データベースエラーが出た時の原因と直し方

WordPressで「Duplicate entry」データベースエラーが出た時の原因と直し方

プラグイン更新後に debug.log へ「WordPress database error Duplicate entry」が大量出力される問題は、テーブルに一意キーを追加する際、既存データに空の値や重複が存在するために起きている。このエラーそのものはサイトの表示を直ちに壊すわけではないが、ログファイルが急激に肥大化してサーバーのディスク容量を圧迫するため、早期の対処が必要だ。

なぜこのエラーが発生するのか

なぜこのエラーが発生するのか

プラグインのバージョンアップで、データベースのテーブル構造(スキーマ)が変更されることがある。今回のように wp_blc_links テーブルに url_hash カラムを追加し、さらにそのカラムへ UNIQUE KEY(一意キー制約)を設定しようとした場合、既存のレコードの中に同一のハッシュ値が重複していると「Duplicate entry」エラーが発生する。

とりわけ問題になるのが、ハッシュ値が空文字列(空の値)のまま残っているレコードだ。空文字列どうしも「同じ値」とみなされるため、一意キー制約に違反してエラーとなる。これは Broken Link Checker に限らず、データベースのスキーマ変更をともなうあらゆるプラグインで起こりうる。

エラーメッセージの後半に「for key 'wp_blc_links.url_hash'」と表示されているなら、url_hash 列の重複が原因と特定できる。この情報を手がかりに、次の対処へ進む。

まずはログの肥大化を止める

まずはログの肥大化を止める

このエラーはサイトの表示に影響を与えないケースが多いが、放置すると debug.log が一晩で数百 MB に膨れ上がる。ディスク容量が尽きればサイト全体が停止するため、真っ先にログ出力を食い止める必要がある。

プラグインを前のバージョンに戻す

最も確実なのは、問題が発生しなかった旧バージョンへ差し戻す方法だ。プラグインの公式ページにある「以前のバージョン」セクションからダウンロードし、手動でアップロードして上書きする。WordPress 管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から ZIP ファイルを指定すればよい。

プラグインを一時的に無効化する

旧バージョンの入手が難しい場合や、そもそもこのプラグインがサイト運営に必須でなければ、無効化するだけでログ出力は止まる。「プラグイン」→「インストール済みプラグイン」から該当プラグインを無効化するだけだ。無効化しても、これまでに収集されたリンク切れのデータはデータベースに残るため、後で有効化すれば以前の状態から再開できる。

Before(エラー発生中)
プラグイン v2.4.9 有効化された状態
debug.log へ毎秒数百件の重複エラーが記録される
→ 数時間で数百 MB に肥大化
↓
After(対処後)
プラグイン 旧バージョン または無効化
debug.log へのエラー出力が停止
→ ログファイルは正常サイズを維持
■ エラー出力が続く状態  ■ 対処後(ログ出力停止)

上図は、プラグインのバージョンを戻すか無効化する前後でのログ出力の変化を表している。どちらの方法でも、エラーの無限出力はすぐに止められる。

データベースの重複を手動で修正する

データベースの重複を手動で修正する

プラグインの新バージョンを使い続けたい場合や、修正パッチのリリースを待たずに根本解決したい場合は、データベースを直接操作して重複レコードを削除する方法がある。ただし、操作を誤るとサイト全体に影響が出るため、必ず事前にデータベースのバックアップを取得しておく。

phpMyAdmin から重複行を特定して削除する

レンタルサーバーの管理画面から phpMyAdmin を開き、該当の WordPress データベースを選択する。wp_blc_links テーブル(接頭辞は環境により異なる)を表示し、「SQL」タブで次のクエリを実行すると、url_hash が空のレコードと重複しているレコードを確認できる。

SELECT url_hash, COUNT(*) 
FROM wp_blc_links 
GROUP BY url_hash 
HAVING COUNT(*) > 1;

このクエリで表示される行が、一意キー制約に違反する重複レコードだ。続けて、重複しているレコードのうち不要なものを削除する。url_hash が空文字列のレコードをすべて削除してしまえば、多くのケースでエラーは解消する。

DELETE FROM wp_blc_links WHERE url_hash = '';

削除後、プラグインを最新バージョンにアップデートするか、一度無効化してから再度有効化すれば、テーブルのスキーマ変更が正常に完了する。エラーログへの出力も止まるはずだ。

WP-CLI が使える環境での対処

サーバーに SSH 接続でき、WP-CLI がインストールされているなら、コマンドラインからより安全に操作できる。まずは重複を確認する。

wp db query "SELECT url_hash, COUNT(*) FROM wp_blc_links GROUP BY url_hash HAVING COUNT(*) > 1;"

問題が確認できたら、同様に空ハッシュのレコードを削除する。

wp db query "DELETE FROM wp_blc_links WHERE url_hash = '';"

操作後はプラグインを再有効化し、debug.log からエラーが消えたことを確認する。WP-CLI を使う最大の利点は、誤って操作しても wp db export で事前にバックアップを取りやすく、復旧が容易な点だ。

再発防止と注意点

再発防止と注意点

プラグインのアップデートは自動更新に任せず、可能であればステージング環境で事前にテストする運用が望ましい。とくにデータベースのスキーマ変更をともなうアップデート(変更履歴に「database」「schema」「table」「column」といった単語が見られるもの)は要注意だ。

また、debug.log が常に有効になっている環境では、定期的にログファイルのサイズを確認し、不要になったら削除する習慣をつけておくと、ディスク容量の急激な枯渇を防げる。wp-config.php で WP_DEBUG_LOG を true にしている場合は、開発やトラブル解決時以外は false に戻しておくのも有効な対策だ。

よくある質問

重複レコードを削除してもプラグインの機能に影響はないのか

空のハッシュ値を持つレコードは、もともと正常にリンクチェックが機能していないデータだ。削除しても、プラグインは次回のクロール時に改めてリンクを検査して正しいハッシュ値を再生成するため、実害はない。むしろ重複が解消されることで、後続のアップデートも正常に完了するようになる。

このエラーを放置するとどうなるのか

エラーそのものはサイトのフロントエンド表示に影響しない場合が多いが、debug.log がサーバーのディスク容量を圧迫し、最悪の場合「ディスクフル」でサイト全体がダウンする。また、プラグインのスキーマ変更が完了しないため、以降のアップデートが正常に適用されず、プラグインの一部機能が動作しない状態が続く可能性もある。

Broken Link Checker 以外のプラグインでも同じエラーは起こるのか

起こる。UNIQUE KEY を追加するデータベーススキーマの変更を行うプラグインであれば、同種のエラーが発生しうる。SEO プラグインやセキュリティプラグインの大規模アップデートでも見られるため、エラーメッセージに表示されるテーブル名とカラム名を手がかりにして、同じ手順で対処できる。

phpMyAdmin を使えない場合はどうすればよいか

「WP Data Access」や「Advanced Database Cleaner」のようなデータベース操作ができるプラグインを一時的にインストールして、SQL クエリを実行する方法がある。あるいは、サーバー会社のサポートに依頼して重複レコードの削除を代行してもらうのも一つの手だ。

修正パッチがリリースされるまでのつなぎ対策は

プラグインを旧バージョンに固定し、WordPress 管理画面の「プラグイン」→「インストール済みプラグイン」で該当プラグインの自動更新をオフにしておく。公式の変更履歴を定期的にチェックし、修正が含まれたバージョンがリリースされたら手動でアップデートすればよい。

この記事のポイント

  • 「Duplicate entry」エラーは、一意キー制約の追加時に既存データの重複が原因で発生する
  • 緊急対応として、プラグインを旧バージョンに戻すか一時的に無効化する
  • データベースから重複レコードを削除すれば、最新バージョンでも正常動作する
  • 事前のバックアップ取得と、ステージング環境でのテストが再発防止に有効
WooCommerceチェックアウトでPayPalボタンが表示されない原因と修正手順

WooCommerceチェックアウトでPayPalボタンが表示されない原因と修正手順

独自テーマを使った WooCommerce サイトのチェックアウトページで PayPal ボタンが表示されない場合、主な原因は DOM の準備完了前に async で読み込まれた JavaScript がコンテナ要素を取得できずに失敗することだ。また、PayPal JS SDK の読み込み完了後に buttons メソッドが存在しない問題は、コンストラクタの引数順序の誤りやスクリプトの初期化タイミングの競合で発生する。これらの問題を順に切り分けて修正すれば、数分でボタンが復活する。

PayPalボタンが表示されない原因を特定する

PayPalボタンが表示されない原因を特定する

まずコンソールに出力されているエラーを把握する。大半のケースで、Error: Document is ready and element #paypal-button-container does not exist(日本語環境では同様のエラーメッセージが英語で表示される)という致命的なエラーが記録されている。これは PayPal JS SDK が #paypal-button-container という要素を DOM から見つけられず、ボタンの描画を中止したことを意味する。同時に、スクリプトがチェックアウトページではなく商品カテゴリページで動作してしまう現象や、CORS(クロスオリジンリクエスト)がブロックされたというエラーも散見される。

以下のフローで問題を切り分けると、原因に早くたどり着ける。

STEP 1 チェックアウトページのソースを開き #paypal-button-container が実在するか確認する
↓
STEP 2 PayPalManager が読み込まれているか console.log でオブジェクトを確認する
↓
STEP 3 init() 後の this.paypal.buttons が undefined でないか検証する
↓
STEP 4 スクリプトがチェックアウトページ以外で実行されていないか調べる

この4つのチェックポイントをもとに、次のセクションで具体的な修正を加えていく。

async読み込みによるDOM参照の競合を解決する

async読み込みによるDOM参照の競合を解決する

WordPress 7.0 では、wp_enqueue_script に 'strategy' => 'async' を指定すると、スクリプトが非同期で読み込まれる。この設定自体は高速化に有効だが、DOM の構築が完了する前に document.querySelector('#paypal-button-container') が実行されると、要素がまだ存在しないために null が返ってしまう。

解決策はシンプルだ。PayPal ボタンの初期化処理全体を DOMContentLoaded イベントの中に包み、DOM の準備完了を待つ。具体的には index.js の setupPayment() を次のように修正する。

document.addEventListener('DOMContentLoaded', async function() {
    const paypalManager = new PayPalManager(
        clientIdHere,
        '.checkoutForm',
        '#paypal-button-container',
        orderEndPoint,
        emailEndPoint
    );
    await paypalManager.init();
    await paypalManager.renderButtons(paypalManager.buttonContainer);
});

こうすれば、DOMContentLoaded が発火した時点でコンテナ要素が確実に存在するため、null エラーが解消する。なお、async ストラテジーはそのままでも問題ないが、より確実な制御を求めるなら defer に切り替えてもよい。ただし defer も DOM 構築の完了前に実行される可能性があるため、イベントリスナーを組み合わせるのが最も安全だ。

Before(エラー)
async 読み込み → 即座に querySelector が走り、container は null
After(修正)
DOMContentLoaded の後で初期化 → container を確実に取得
■ エラー状態 ■ 修正後

コンストラクタの引数順序と初期化タイミングを修正する

コンストラクタの引数順序と初期化タイミングを修正する

コンソールに出力されたオブジェクトを見ると、buttonContainer が null、orderEndPoint と emailEndPoint の値が意図したものと逆になっているケースが多い。これは PayPalManager のコンストラクタを呼び出す際の引数の順序がずれているか、引数が不足しているときに起こる。

典型的なミスは、最初の引数(clientId)を空にしてしまったり、セレクタ文字列を間違った順番で渡してしまうことだ。次のように constructor と new の呼び出し側を一致させる必要がある。

// paypal_manager.js の constructor 定義(本来の正しい順序の例)
constructor(clientId, formSelector, containerSelector, orderEndPoint, emailEndPoint) {
    this.clientId = clientId;
    this.formSelector = formSelector;
    this.containerSelector = containerSelector;
    this.buttonContainer = null;
    this.orderEndPoint = orderEndPoint;
    this.emailEndPoint = emailEndPoint;
    this.paypal = null;
}
// index.js でのインスタンス化(すべての引数を順序通りに正しく与える)
const paypalManager = new PayPalManager(
    'your-client-id',          // clientId
    '.checkoutForm',           // formSelector
    '#paypal-button-container',// containerSelector
    'https://api-m.sandbox.paypal.com/v2/checkout/orders', // orderEndPoint
    '/wp-json/auto-parts/v3/send_order_email'               // emailEndPoint
);

このコードのように引数を明示的に記述すれば、プロパティの食い違いが一掃される。また、init() 内で this.paypal.buttons が undefined になる問題は、loadScript() の完了を await で待つ処理が正しく記述されていれば解決する。paypal-js パッケージの loadScript は Promise を返すので、必ず await loadScript(...) の形で使う。

チェックアウトページにだけスクリプトを読み込む方法

チェックアウトページにだけスクリプトを読み込む方法

症状のひとつに「スクリプトが商品カテゴリページでは動くのにチェックアウトページで動かない」という現象があった。これは wp_enqueue_scripts フックがすべてのページで実行されるために、意図しないページで PayPal のコードが動き出し、逆にチェックアウトページでは何らかの理由でコンテナが存在したにもかかわらず失敗していることを示す。

第一に、スクリプトの読み込みをチェックアウトページに限定する。WordPress の条件分岐タグ is_checkout() を使い、functions.php を次のように変更する。

function mainModules() {
    if ( is_checkout() && ! is_order_received_page() ) {
        wp_enqueue_script(
            'paypal-checkout',
            get_theme_file_uri('/build/index.js'),
            array(),
            '1.0.0',
            array( 'strategy' => 'async' )
        );
    }
}
add_action('wp_enqueue_scripts', 'mainModules');

この条件を追加すれば、商品一覧やカテゴリページで PayPal 関連の JavaScript エラーがコンソールに表示されなくなり、意図したページだけが初期化を行う。また、キャッシュプラグインが原因で古いスクリプトが配信されている可能性があるため、修正後にキャッシュをクリアすることも忘れずに行う。

CORSエラーの対処と無視できる場合

CORSエラーの対処と無視できる場合

コンソールに記録される Cross-Origin Request Blocked エラーは、PayPal のロガー API(https://www.sandbox.paypal.com/xoplatform/logger/api/logger)へ送信されるリクエストがオリジン間制限に引っかかったものだ。このエラーは、PayPal ボタンの描画が失敗した後に二次的に発生するケースがほとんどで、サイトの主要機能には影響しない。

ボタンが正しく表示されるようになれば、多くの場合この CORS エラーは自然に消える。もし修正後も CORS エラーが出続けるなら、PayPal の Sandbox アプリケーション設定で許可されたオリジンに本番ドメインが登録されているか確認する。通常は無視して問題ないが、セキュリティ上の懸念がある場合は、PayPal のビジネスサポートにオリジン制限の解除を依頼できる。

よくある質問

asyncとdeferのどちらを選ぶべきか

両者とも非同期読み込みだが、defer は HTML のパース完了後に実行順序を保ちながら実行される。PayPal ボタンのような DOM 操作が絡むスクリプトは、defer と DOMContentLoaded の組み合わせが扱いやすい。ただし、パフォーマンスを優先するなら async のままイベントリスナーで制御する形で問題ない。

PayPal SDK の読み込みに時間がかかる場合の改善策

@paypal/paypal-js の loadScript は PayPal の CDN からスクリプトを取得する。自前でキャッシュすることは難しいが、async 読み込みによってページ全体のレンダリングをブロックしないようにできる。どうしても速度が遅い場合は、チェックアウトページ遷移時にローディングスピナーを表示し、init() が完了するまでユーザーに待機を伝える UI を実装するとよい。

コンソールのCORSエラーを完全に消す方法はあるか

PayPal 側のロガーAPIのオリジンを制御することはできないため、完全に消すことは難しい。実害がないため無視するのが一般的だ。もしどうしても気になる場合は、エラーハンドリングで該当のリクエストをキャッチして無視するか、PayPal のサポートに問い合わせてロガー機能を無効化できないか相談する。

WordPressのバージョンが7.0でなくてもこの問題は起きるか

async ストラテジーは WordPress 6.6 以降で導入されたため、それ以前のバージョンでは異なる方法で非同期読み込みを行っている可能性がある。しかし、DOM の準備完了前に要素を取得できない問題は、wp_enqueue_script の設定にかかわらず生じるため、同じ修正が有効だ。

子テーマで上書きする場合の注意点

親テーマの functions.php で定義された wp_enqueue_scripts フックを子テーマで解除するには、remove_action を使うか、子テーマ側のフックで wp_dequeue_script を使って親のスクリプトを外した後、新たに読み込む。ペイパルマネージャーの JavaScript ファイルは通常、テーマのビルドフォルダにあるため、ファイル自体を子テーマにコピーして上書きする方法が確実だ。

この記事のポイント

  • PayPalボタンが表示されない根本原因は、DOMの準備完了前にスクリプトがコンテナ要素を取得できないこと
  • async読み込みの対策として、DOMContentLoadedイベントの内側で初期化を行う
  • コンストラクタ引数の順序ずれで、buttonContainerがnullになったりエンドポイントが入れ替わる
  • is_checkout() 条件を使ってチェックアウトページにだけスクリプトを読み込む
  • 二次的に発生するCORSエラーはボタン描画が成功すれば消えることが多く、実害がなければ無視できる
GoogleサーチコンソールにAI検索レポート登場。見るべきポイントと活用術

GoogleサーチコンソールにAI検索レポート登場。見るべきポイントと活用術

Google は 2026 年 6 月 3 日、Search Console に生成 AI 専用のパフォーマンスレポートを追加した。AI Overviews(AI 概要)や AI Mode(AI モード)といった検索体験の一部として、自社サイトの URL がどの程度表示されたかを切り分けて確認できるようになっている。

これまで「AI 検索に自社のコンテンツが出ているのかどうか」は、通常の検索パフォーマンスの数字に埋もれてわからなかった。今回の分離によって、どのページが生成 AI の回答元として使われているのかを確認できるようになったが、あくまで「表示回数」ベースのデータであり、クリックや引用のされ方までは把握できない点に注意が必要だ。

この記事では、新レポートで何が読み取れるのか、従来の検索表示回数とどう違うのか、そして実際にサイト改善に役立てるための診断フローを解説する。

AI検索レポート、ついに独立

AI検索レポート、ついに独立

生成AI専用レポートの概要

この新しい Search レポートは、AI Overviews と AI Mode からの表示回数のみを集計する。Discover 向けの生成 AI 機能は別レポートとして提供されている。また、Labs の実験的機能は対象外だ。

レポートでは、URL 単位、国別、デバイス別、日付別に表示回数をセグメントできる。ただし現時点では、以下の指標は含まれていない。

  • 検索クエリ
  • クリック、クリック率(CTR)
  • 平均掲載順位
  • 引用の位置(回答内でリンクがどの順序で表示されたか)
  • 回答の基となった文章の特定
  • コンバージョンや収益データ

Google は「今後、追加指標の要望をサイト運営者とともに検討する」と述べており、機能拡張の可能性はある。また、AI Overviews や AI Mode にコンテンツを含めるかどうかを制御する新しい設定も Search Console でテスト中だ。デフォルトは「含める」で、オプトアウトすると従来の検索結果には影響なく、生成 AI の回答からも自社コンテンツが除外される。

まずは「どの部分が使われているか」を把握するために

現時点のレポートが答えられるのは「サイトのどのページが生成 AI の表示に使われているのか、どのくらいの頻度か」という問いだ。それ以上の詳細は得られないが、この可視化だけでもこれまでにない手がかりになる。

AI表示回数は従来の表示回数とは異なる

AI表示回数は従来の表示回数とは異なる

表示回数の数え方の基本

Google の定義では、AI 表示回数とは「生成 AI の機能内でユーザーにリンクが表示された回数」を指す。集計方法はレベルによって異なり、グラフのプロパティ全体では、1 つの回答内に同じサイトの異なる URL が複数出ても 1 回とカウントされることがある。一方、ページテーブルでは各 URL が個別に 1 回ずつ計上されるケースもある。

つまり、ページレベルの表示回数を足し上げた合計が、必ずしもプロパティ合計と一致しない。これは集計単位の違いによるもので、数値に矛盾があるわけではない。

従来の検索との違いと混同禁止

従来の検索結果での表示回数は、検索結果リスト内の 1 つの掲載としてユーザーが認識しやすい。一方、AI Overviews や AI Mode の表示は、合成された回答文の一部として現れる。リンクが目立つ場合もあれば、折りたたまれた引用リストの中に埋もれている場合、フォローアップの質問の後に出現する場合もある。

また、AI Overviews ではリンクがスクロールされるか展開されるまで表示回数としてカウントされない。AI Mode ではフォローアップの質問が新しいクエリとして扱われ、後続の回答で表示されたリンクが追加の表示回数を生む。

これらの違いから、生成 AI の表示回数と通常の検索表示回数を合算して「総検索可視性」のように扱うのは全くの誤りだ。CTR のブレンド計算も同様に意味をなさない。レポート画面で数字が並んでいても、それらは性質の異なる指標であることを肝に銘じたい。

このレポートで診断できること

このレポートで診断できること

このレポートの真価は、表示回数の総数ではなく、どのページが生成 AI 検索で使われているかを通常の検索パフォーマンスと比較できる点にある。

AI 表示回数と通常検索表示の4象限
高オーガニック表示・低AI表示
通常検索では上位だが、生成AIにはあまり使われないページ。情報が回答として抽出しにくい可能性
低オーガニック表示・高AI表示
通常検索では控えめだが、AIには頻出。有用な定義や統計など、抽出しやすいコンテンツが多い
高オーガニック表示・高AI表示
いずれも良好。ページの質が高く、合成にも向く可能性。強みのトピックとして要分析
低オーガニック表示・低AI表示
検索上もAI上も見えていない。コンテンツの根本的な見直し候補
■ 高(上) ■ 低(下) ■ 問題あり ■ 好材料

これは概念図だが、レポートの表示回数を通常の Search Console の検索パフォーマンスと並べて分類すると、上記の4パターンに整理できる。それぞれ次のような特徴がある。

高オーガニック表示・低AI表示のページ

通常検索ではよく見られていても、生成 AI の回答にはあまり使われないページだ。必ずしも問題とは限らない。クエリ自体が AI 応答を引き起こさないケースもある。しかし、次のような点を確認すると原因が見えてくる。

  • 具体的な質問に直接答えているか
  • 見出し構造が整理されているか
  • 重要な情報がテキストとして HTML 上に露出しているか(タブや画像、JavaScript に隠れていないか)
  • AI 応答が発生しやすいクエリにマッチする内容か

通常のランキングで上位に上がる能力があっても、合成に使えるクリーンな回答を提供できなければ、AI 表示にはつながりにくい。

低オーガニック表示・高AI表示のページ

こちらの方が注目に値する。通常の検索では目立たずとも、生成 AI で高い頻度で表示されるページがある。定義や統計、比較、説明が明快なコンテンツがこれにあたる。

こうしたページを分析すると、以下の共通点が見えてくることが多い。

  • セクションの冒頭付近で直接的な回答を提示している
  • 見出しの階層が明確で情報が取り出しやすい
  • 独自の調査や一次情報を含んでいる
  • 有益な表やリストがある
  • トピックの範囲が絞られており、曖昧な表現が少ない

1 つの成功パターンを見つけたからといって、それを再生産すればうまくいくとは限らないが、サイト内で「Google が使いやすい」と判定している構造や表現のヒントになる。

ページ改修の効果を追う

コンテンツを大幅に修正した後に、AI 表示回数がどう変化するかをウォッチするのにも有用だ。たとえば以下のような改修が効果を持つ可能性がある。

  • 明確な要約や定義を冒頭に追加
  • 古い情報を更新し、鮮度を高める
  • 重複したページを統合
  • 見出しを書き直して情報の抽出を助ける
  • 画像や動画に頼っていた重要情報を HTML テキストに移す
  • 独自の証拠や専門家のコメントを加える

ただし、1 つの見出しを変えた翌週に数字が上がったからといって「AI 検索のアルゴリズムを解明した」と騒ぐのは禁物だ。需要や競合、AI 機能の出現頻度そのものが変動する。持続的な増加が確認できて初めて意味のあるシグナルとなる。

データを分析する実践ワークフロー

データを分析する実践ワークフロー

エクスポートと分類、従来データとの比較

分析は次の 6 ステップを踏むと整理しやすい。

  1. AI 表示回数の上位ページをエクスポート
    意味のある期間を選ぶ。リリース直後の数日で判断しない。
  2. 同じ URL・期間で通常の検索パフォーマンスをエクスポート
    通常の検索表示回数、クリック、CTR、平均順位、可能なら上位クエリを加える。比較することで、AI と通常検索で差があるページを特定できる。
  3. ページを属性で分類
    ページタイプ、トピック、検索意図、テンプレート、著者、公開日、最終改訂日、ファネルステージなどを付与。URL と表示回数を並べただけでは分析にならない。
  4. 外れ値を調査
    AI 表示回数が極端に高いページや低いページを探す。テンプレートやトピック、著者によってなぜ差が生まれるのかを実際に HTML 構造や本文を見て確認する。この段階で初めて手を動かす必要がある。
  5. アナリティクスのデータを別に確認
    AI 経由のトラフィックやコンバージョンが特定できれば、表示回数がどの程度実際の訪問につながっているかを評価する。ただし Search Console と Analytics では計測方法が異なるため、数字のズレに一喜一憂しない。
  6. 日次の変動ではなくトレンドを追う
    新しいデータは暫定的な数値の可能性もある。週次や月次で傾向を見るほうが建設的だ。1 日で上がった下がったに右往左往しない。

経営ダッシュボードに載せるべきではない指標

経営ダッシュボードに載せるべきではない指標

「AI」とラベルされた大きな数字が現れると、ダッシュボードの一番上に大きく表示したくなるものだ。しかし、生成 AI の表示回数はあくまで特定の状況でのリンク出現を示しており、ビジネス成果に直結するとは限らない。

以下のような報告は避けるべきだ。

  • 生成 AI 表示回数と通常検索表示回数を合算した「総視認性」
  • 両者をブレンドしたクリック率
  • 自社の AI 表示回数だけを元にした「AI シェア」
  • 表示回数に紐づけたコンバージョンの推測
  • 1 つの最適化施策が効いたかのように見せるための表示回数の増加報告
  • ページレベルの合計をプロパティ全体の露出と誤認させる表示

代わりに、ダッシュボードに盛り込むべきは「生成 AI 表示回数の推移」「表示回数がついたページ数」「表示されているトピック・ページタイプ」「AI 可視ページと通常検索パフォーマンスとの関係」「期間中に実施した改修」「AI 経由の識別可能なトラフィックやコンバージョン(分けて報告)」「追加調査が必要な仮説」といった項目だ。

この記事のポイント

  • Search Console の新レポートで、AI Overviews と AI Mode の表示回数が通常検索と分離された
  • 表示回数はクリックや引用位置の情報を含まず、あくまで「リンクが表示された」という指標である
  • 従来の検索表示回数とは性質が異なり、合算やブレンド分析は誤解を招くため厳禁
  • 通常検索との比較で、コンテンツの抽出しやすさや構造の課題を発見できる
  • 分析の際は長期的なトレンドとページ属性の分類が不可欠で、数字の上下だけで施策の成否を判断しない
WordPressで投稿が突然崩れる原因と直し方(HTMLが壊れる場合の対処)

WordPressで投稿が突然崩れる原因と直し方(HTMLが壊れる場合の対処)

WordPressで投稿を更新した直後や新規投稿を公開した際に、レイアウトが崩れたりHTMLタグがむき出しで表示される場合、原因の大半はビジュアルエディタとテーマ・プラグインの競合、または外部からのHTMLコード貼り付け時に生じた不正なタグの混入だ。自動整形機能(wpautop)の誤作動が引き金になるケースも多い。本記事では、投稿が崩れる代表的な原因を整理し、投稿を元どおりに戻す手順を具体的に示す。

投稿のHTMLが崩れる原因はどこにあるのか

投稿のHTMLが崩れる原因はどこにあるのか

WordPressの投稿が崩れる場合、問題は大きく3つのレイヤーに分かれる。エディタ内部での表示崩れ、データベースに保存される時点での変換ミス、そしてフロントエンドでレンダリングされる際のテーマやプラグインの干渉だ。

原因① 外部エディタからのHTML貼り付け

WordやGoogleドキュメント、他のCMSからコピーしたテキストには、不要なスタイル指定や不正なHTMLタグが混入している。WordPressのエディタがこれらを正しく処理できず、表示が崩れる。

↓
原因② wpautop自動整形の誤作動

WordPressは本文の改行を自動で<p>タグや<br>タグに変換する。この機能がカスタムHTMLやショートコードと衝突し、不要なタグを挿入してレイアウトを破壊することが多い。

↓
原因③ テーマ・プラグインの競合

使用中のテーマやプラグインが、WordPressの標準機能であるTinyMCEエディタやブロックエディタの動作を妨害している。特定のプラグインがJavaScriptエラーを起こし、エディタの表示や保存処理が不完全になる。

実際のトラブルでは、これらの要因が複合的に絡み合っている。投稿が完全に壊れてしまう前に、まずはどのレイヤーで破損が起きているのかを段階的に絞り込む必要がある。

テキストエディタでHTMLを直接確認し修復する手順

テキストエディタでHTMLを直接確認し修復する手順

最初に試すべきは、WordPress標準の「テキスト」エディタ(クラシックエディタ利用時)またはブロックエディタの「コードエディタ」モードを使って、投稿に含まれるHTMLを直接目視することだ。不正なタグやスタイル指定が混入していれば、この段階で発見できる。

Before(崩れた状態)

<span style=”font-size: 12pt; font-family: ‘MS Gothic’;”><span lang=”EN-US”>テキストが</span></span><span lang=”EN-US”>途中で切れる</span>

↓
After(修正後)

<p>テキストが途中で切れずに表示される</p>

■ 不要なspanタグ混入  ■ pタグで整形し直し

管理画面の投稿編集画面を開き、画面右上の「オプション」(縦三点リーダー)から「コードエディター」を選択する。クラシックエディタの場合は「テキスト」タブをクリックする。ここで表示されるHTMLソースに、意図しない<span>タグやインラインスタイル、閉じタグの不足がないかを確認する。

もしWordなどからの貼り付けが原因なら、「形式を選択して貼り付け」または「プレーンテキストとして貼り付け」機能を使い、装飾なしで再貼り付けを行う。ブロックエディタには貼り付け時に「ブロックとして貼り付け」「プレーンテキストとして貼り付け」などの選択肢が表示されるため、常にプレーンテキストを選ぶのが安全だ。

テーマとプラグインを切り分けて競合を特定する

テーマとプラグインを切り分けて競合を特定する

HTMLに問題が見当たらない、あるいは修正しても再発するなら、次はテーマとプラグインの切り分けに進む。この作業はサイトの表示に一時的な影響を与えるため、可能であればメンテナンスモードを有効にするか、深夜帯などアクセスの少ない時間帯に実施する。

STEP 1 すべてのプラグインを無効化する
↓
STEP 2 WordPress標準テーマ(Twenty Twenty-Fiveなど)に切り替える
↓
STEP 3 問題の投稿を再編集して表示を確認する
↓
STEP 4 プラグインを1つずつ再有効化し、問題が再発するものを特定する

この手順で問題が解消された場合、原因は無効化したプラグインかテーマにある。問題が消えたら、プラグインを1つずつ再有効化していき、どのタイミングで投稿の崩れが再発するかを観察する。競合が見つかったプラグインは、代替プラグインを探すか、開発元にサポートを依頼する。

wpautopフィルターを停止して自動整形を無効化する

wpautopフィルターを停止して自動整形を無効化する

カスタムHTMLやショートコードを多用するサイトでは、WordPressの自動整形機能(wpautop)が不要な<p>タグや<br>タグを挿入し、投稿を壊してしまうことがある。この機能はfunctions.phpに1行追加するだけで停止できる。

remove_filter('the_content', 'wpautop');

上記のコードを、使用中のテーマ(できれば子テーマ)のfunctions.phpの末尾、<?php タグの内側に追加する。この設定を加えると、本文全体の自動整形が無効になり、HTMLを書いたとおりに表示されるようになる。ただし、これにより通常の投稿でも改行が反映されなくなるため、本文はすべてHTMLでマークアップする必要が出てくる点に注意が必要だ。

どうしても特定の投稿だけwpautopを無効化したい場合は、専用のプラグインを利用する方法もある。たとえば「Toggle wpautop」のような軽量プラグインを使えば、投稿ごとに自動整形のオンオフを切り替えられる。

ブロックエディタの「カスタムHTMLブロック」で安全にコードを埋め込む

ブロックエディタの「カスタムHTMLブロック」で安全にコードを埋め込む

ブロックエディタでHTMLコードを埋め込む場合、通常の段落ブロックに直接コードを書き込むと、エディタが予期せぬ変換を行うことがある。これを回避するには、必ず「カスタムHTML」ブロックを使用する。

段落ブロック → HTMLが自動変換されて壊れる
カスタムHTMLブロック → コードがそのまま保持される

ブロックエディタで「+」ボタンを押し、「カスタムHTML」ブロックを追加する。その中にHTMLやショートコードを記述すれば、エディタによる自動変換の影響を受けずに済む。すでに崩れてしまった投稿も、一度このブロックにコードを移し替えることで、表示が安定することが多い。

ブラウザのキャッシュとサーバーキャッシュをクリアする

ブラウザのキャッシュとサーバーキャッシュをクリアする

投稿を修正してもブラウザ上で崩れたままに見える場合、キャッシュが古い状態を表示し続けている可能性がある。最初にブラウザのキャッシュをクリアし、ハードリロード(Ctrl+Shift+RまたはCmd+Shift+R)を試す。

WordPress側でキャッシュ系プラグインを使用している場合は、管理画面から全キャッシュを削除する。サーバーレベルでVarnishやNginx FastCGI Cache、CloudflareなどのCDNキャッシュが有効になっている場合は、それらもパージする。特にCloudflareを使用している場合、「キャッシュ」→「キャッシュの消去」から「すべてを消去」を実行すると確実だ。

よくある質問

ブロックエディタで「コードエディタ」が見つからない

ブロックエディタの画面右上にある「オプション」アイコン(縦三点リーダー)をクリックすると、メニューの中に「コードエディター」が表示される。もし表示されない場合は、管理画面の「ユーザー」→「プロフィール」で「ビジュアルエディターを使用しない」のチェックが入っていないか確認する。

functions.phpを編集したらサイトが真っ白になった

PHPの文法ミスが原因だ。FTPやレンタルサーバーのファイルマネージャーでfunctions.phpを開き、追加したコードを削除または修正する。functions.phpの編集前には必ずバックアップを取り、できればCode Snippets系のプラグインを使うほうが安全だ。

テーマやプラグインの競合がまったく特定できない

「このサイトで重大なエラーが発生しました」というメッセージが表示されているなら、WordPressのデバッグモードを有効にして具体的なエラー内容を確認する。wp-config.phpにdefine('WP_DEBUG', true);を追加すると、エラーの詳細が画面に表示される。また、ブラウザの開発者ツール(F12キー)のConsoleタブでJavaScriptエラーが出ていないかも併せてチェックする。

特定のプラグインだけが原因だとわかったが手放せない

そのプラグインの設定画面で、エディタ関連の機能(ビジュアルエディタの拡張やカスタムボタンの追加など)を個別に無効化できるか確認する。無効化できない場合は、プラグインのバージョンを最新に更新するか、開発元のサポートフォーラムで同様の症状が報告されていないか調べる。

WordやGoogleドキュメントから毎回貼り付ける運用を安全にしたい

貼り付けの際にCtrl+Shift+V(Cmd+Shift+V)のショートカットでプレーンテキストとして貼り付ける習慣をつける。ブロックエディタでは、貼り付け直後に表示されるツールバーから「プレーンテキストとして貼り付け」を選択する。どうしても書式を保持したい場合は、「Markdownで貼り付け」や「外部ドキュメントのインポート」に対応した専用プラグインの利用を検討する。

この記事のポイント

  • 投稿の崩れはHTML混入、wpautop誤作動、テーマ・プラグイン競合の3層で起きる
  • コードエディタでHTMLを直視し、不要タグや不正なインラインスタイルを取り除く
  • 全プラグイン無効化+標準テーマで原因を特定し、1つずつ再有効化して競合を絞り込む
  • カスタムHTML埋め込みはカスタムHTMLブロックを使い、段落ブロックへの直書きを避ける
  • 修正後はブラウザキャッシュ、プラグインキャッシュ、CDNキャッシュをすべてクリアする
Supabase Evals公開、AIエージェントのコード品質を自動評価する基盤

Supabase Evals公開、AIエージェントのコード品質を自動評価する基盤

Supabaseが2026年7月31日、AIコーディングエージェント向けの評価フレームワーク「Supabase Evals」をオープンソースで公開した。Claude CodeやCodex、OpenCodeといった主要エージェントを使い、実際のSupabaseプロジェクト開発を自動で試行し、その成否を定量的に測る仕組みだ。

このフレームワークは、エージェントがデータベーススキーマの構築やEdge Functionsのデバッグ、RLSポリシーの修正といったタスクをどれだけ正確にこなせるかを評価する。公開されたベンチマーク結果は誰でも閲覧でき、エージェントの得意分野や弱点が数値で把握できる。

なぜSupabaseがこの基盤を作ったのか。AIを使ってSupabase上にアプリを構築する開発者が急増する中、エージェントの「実力」を正確に把握し、改善につなげる必要があった。本記事ではその仕組みと、初期の評価で明らかになったエージェントの弱点、そして今後の展望を解説する。

Supabase Evalsが目指すもの

Supabase Evalsが目指すもの

Supabase Evalsは、AIコーディングエージェントがSupabaseを使った開発タスクを実行する際のパフォーマンスを評価するためのフレームワークだ。ベンチマークテストとリグレッション(回帰)テストの2つのスイートを持ち、エージェントの実力を多角的に測る。

具体的には、エージェントがCLIやMCPサーバー、各種ドキュメントを活用しながらスキーマ設計やEdge Functionsの作成、RLSポリシーの修正などを行う。その結果を「ユーザーが特定のデータにアクセスできるか」「Edge Functionが期待通りのレスポンスを返すか」といった決定論的なチェックと、LLMによる判定(LLM-as-a-judge)でスコア化する。

この基盤は、Supabaseが公開する公式ベンチマークのほか、日次で動作する内部のリグレッションスイートにも利用されている。これにより、新しい機能がエージェントの動作を悪化させていないかを継続的に監視できる。

なぜ今、AIエージェント評価基盤が必要なのか

なぜ今、AIエージェント評価基盤が必要なのか

AIコーディングエージェントを使った開発は日常化しつつある。SupabaseのCLIやMCPサーバー、エージェントスキル、ドキュメントを介してエージェントがプロジェクトを構築するケースが増えてきた。しかし、各エージェントがどこでつまずき、どの機能がうまく使えていないのかを体系的に把握する手段が不足していた。

Supabaseの公式ブログ記事によれば、エージェントが苦手とするパターンを特定し、それを修正した上で再発防止(リグレッション)を確認するサイクルを回すことが目的だ。単一のツールだけではなく、Supabaseが提供するすべてのインターフェースを横断的に評価できる点が特徴である。

従来は開発者自身が手動でコードを書く前提だったため、エージェントに特化したテスト基盤は存在しなかった。Evalsの登場により、AI時代の開発者体験を数値で議論できる土台が整ったと言える。

評価の仕組みとベンチマーク/リグレッションの二層構造

評価の仕組みとベンチマーク/リグレッションの二層構造
ベンチマークシナリオ(幅広さ重視)
少ないシナリオ数でSupabaseの主要な領域をカバーする。結果は公開され、複数のエージェント構成で比較される。
↓
リグレッションシナリオ(深さ重視)
既知の障害パターンに焦点を当て、頻繁に実行される。公開スコアには影響せず、品質管理の内部指標として使われる。
↓
実行環境
ホスト型SupabaseスタックとローカルCLIプロジェクトをコンテナ内で生成する。エージェントは実際のMCPサーバーやCLIを操作する。
↓
判定方法
決定論的チェック(データアクセス可否など)とLLMによる意味評価を併用する。エージェントには一度のリトライが許される。

このフレームワークでは、エージェントが実際のSupabase環境で作業するため、机上の空論ではない実用的な評価が可能だ。テスト結果はWebアプリで可視化され、誰でも確認できる。

初期ベンチマークが明らかにしたAIエージェントの弱点

初期ベンチマークが明らかにしたAIエージェントの弱点

スキル読み込みの効果は想定以上に限定的、ただしドキュメント参照は改善

Supabase Evalsのベンチマーク結果では、エージェントがスキル(エージェント向けの最適化ガイド)を読み込んでいない状態でも、多くのシナリオをクリアできることがわかった。ビルド段階では、Opus 5とKimi K3がスキルなしで100%のスコアを達成している。

スキル読み込みの効果は限定的だが、Sonnet 5は78%から100%へ、GPT-5.6 Solは89%から100%へ、GPT-5.4 miniは78%から89%へと改善した。特に、スキルを有効にするとSupabaseドキュメントの参照頻度が一貫して増え、古い事前学習知識を上書きする必要があるエッジケースで差がついた形だ。

宣言的スキーマを使わず、マイグレーションを手書きする傾向

Supabaseには宣言的スキーマという、データベースの構造を一つのファイルで管理できる仕組みがある。本来は複数のマイグレーションファイルをつなぎ合わせるより効率的だが、エージェントは既に宣言的スキーマが使われているプロジェクトでも、手書きのマイグレーションを作成しようとする傾向があった。

この問題を受け、Supabaseはエージェントスキルの中で「どのワークフローを選ぶべきか」の指針を明確に改訂し、Evalsを使って修正が正しく反映されたことを確認した。

新しいライブラリ「@supabase/server」の発見率が低い

Supabaseは最近、Edge Functionsを安全に書くためのボイラープレートを簡略化する@supabase/serverパッケージをリリースした。しかし、エージェントは依然としてsupabase-jsを使い、手動で認証を検証する方法を選んでしまう。

このためSupabaseは「どのパッケージを選ぶべきか」を解説する専用ガイドを公開し、エージェントの判断材料として提供している。

Postgresベストプラクティススキルの有効化が不安定

Evalsは、エージェントがセッション中にどのスキルを読み込んだかを追跡している。主要な「supabase」スキルはほぼ常に読み込まれるのに対し、Postgresのベストプラクティスを教えるスキルは当初、約1割のシナリオでしか有効化されなかった。

スキルの説明文を具体的なトリガーで書き直した結果、有効化率は60%まで向上したが、それでもOpenAIモデルの方がより安定してスキルを活用する傾向が見られる。

ドキュメント参照の頻度に大きなばらつき

Evalsの実行中、エージェントがSupabaseドキュメントを読む頻度も測定している。CodexベースのエージェントはClaude Codeよりもドキュメントをチェックする傾向があり、最も高性能なOpenAIモデルは毎シナリオ約8ページを読むのに対し、Claude Codeは約2ページにとどまる。

しかもClaude Codeはスキルを読み込んでいても、40%未満のシナリオでしかドキュメントを確認しない。Supabaseはエージェントが必要な情報を確実に見つけられるよう、改善を進めている。

AIエージェント時代のSupabase開発体験を支える展望

AIエージェント時代のSupabase開発体験を支える展望

Supabase Evalsはまだ出発点に過ぎない。今後はエッジケースのカバレッジを広げ、エージェントやプロダクトの進化に合わせて新しいシナリオを追加していく計画だ。スコアリングの精度と安定性も引き続き強化される。

また、内部のリグレッションシナリオのなかで信頼性が確認されたものは、順次公開ベンチマークへと格上げされる方針である。さらに、エージェントがタスクに失敗した際にフィードバックを提出できるCLIコマンドやMCPツールも開発中で、これにより次の改善優先度をデータドリブンに決定できるようになる見込みだ。

AIコーディングエージェントを本格的にプロダクト開発に組み込むチームにとって、Supabase Evalsは「エージェントが何を得意とし、どこでつまずくのか」を数値で判断する貴重な羅針盤になる。公開されたベンチマークはsupabase.com/evalsで誰でも確認できる。

この記事のポイント

  • SupabaseがAIコーディングエージェント向け評価フレームワーク「Supabase Evals」をOSS公開
  • 実際のSupabase環境でエージェントを動作させ、ベンチマークとリグレッションの2層でスコア化
  • 初期のベンチマークでは、スキル無しでも高スコアの一方、宣言的スキーマの無視や新ライブラリの未発見など弱点が判明
  • ドキュメント参照頻度のばらつきやスキル活性化の不安定さも浮き彫りに
  • 今後はエッジケースの拡充やエージェントからのフィードバック収集機能の追加を予定