2026年7月16日

2026年7月16日

WooCommerceのセッションが正常に機能しない(カートが消える・保持されない)場合の原因と修正

WooCommerceでカートの中身が消える、ページを移動すると商品数が0に戻る、チェックアウトで「セッションの有効期限が切れました」と出る、といった症状の多くは、セッション用のCookieが正しく保存・送信されていないことが原因です。中でも多いのは、キャッシュがカートやチェックアウトのページ、Cookieのやり取りまでキャッシュしてしまうケースです。この記事では、WooCommerceのセッションの仕組み、ブラウザでの確認方法、原因を可能性の高い順に並べた確認と対処を説明します。

WooCommerceのセッションの仕組み

WooCommerceは、PHP標準のセッション($_SESSION)ではなく、独自のセッション処理を使っています。おおまかな流れは次のとおりです。

  1. 訪問者が商品をカートに入れると、wp_woocommerce_session_ で始まる名前のCookieがブラウザに保存される
  2. カートの中身などのデータは、データベースの {接頭辞}woocommerce_sessions テーブル(標準では wp_woocommerce_sessions)に保存される
  3. 次のページ表示でブラウザがCookieを送り、WooCommerceがそのCookieに対応するデータをテーブルから読み出す

あわせて woocommerce_items_in_cart と woocommerce_cart_hash というCookieも使われ、キャッシュプラグインやサーバーが「この訪問者はカートに商品を入れている」と判断する手がかりになります。

つまり、セッションが機能しないときは「Cookieが保存されない」「Cookieが送られない」「Cookieは届いているがキャッシュされたページが返っている」「テーブルの読み書きに失敗している」のどれかが起きています。

まずブラウザで症状を確認する

設定を変える前に、どこで途切れているのかを見ます。シークレットウィンドウで、ログアウトした状態で試すと、ログイン中の挙動と区別できます。

  1. ブラウザの開発者ツールを開き、「アプリケーション」(Firefoxでは「ストレージ」)タブでCookieの一覧を表示する
  2. 商品をカートに入れ、wp_woocommerce_session_ で始まるCookieが作られるかを確認する
  3. 「ネットワーク」タブでカートページを再読み込みし、レスポンスヘッダーを確認する

Cookieが作られない場合は、レスポンスに Set-Cookie ヘッダーがあるかを見ます。Cookieはあるのにカートが空と表示される場合は、レスポンスヘッダーに x-cache: HIT、cf-cache-status: HIT、age など、キャッシュから返されたことを示す値がないかを確認します。ヘッダー名はキャッシュの種類やサーバー会社によって異なります。

あわせて、wp-config.php で WP_DEBUG_LOG を有効にし、wp-content/debug.log に Cannot modify header information - headers already sent という警告が出ていないかも見ておきます。この警告は後述の原因4の手がかりになります。

原因と対処(可能性が高い順)

1. キャッシュがカート・チェックアウトを保存している

もっとも多い原因です。WooCommerce自体は、カート・チェックアウト・マイアカウントのページでキャッシュしないよう指示する仕組み(DONOTCACHEPAGE 定数やキャッシュ無効化のヘッダー)を持っており、主要なキャッシュプラグインの多くはこれを認識します。ただし、次のような場所のキャッシュはこの指示を無視することがあります。

  • サーバー会社が提供するサーバーキャッシュ(nginxのFastCGIキャッシュ、Varnish、LiteSpeedのサーバー設定など)
  • Cloudflareなどで、HTML全体をキャッシュするルールを設定しているCDN
  • キャッシュプラグインで、除外設定を独自に書き換えている場合

対処として、キャッシュの設定で次の2点を除外します。

  • URLの除外:カート、チェックアウト、マイアカウントのページ(日本語サイトではスラッグを変えていることが多いので、実際のURLを確認する)
  • Cookieによる除外:woocommerce_items_in_cart、wp_woocommerce_session_、wordpress_logged_in_ を持つ訪問者にはキャッシュを返さない

nginxのFastCGIキャッシュを自分で設定している場合の例です。設定を変える前に元のファイルを保存し、nginx -t で構文を確認してから再読み込みしてください。

set $skip_cache 0;

# カート・チェックアウト・マイアカウント(実際のスラッグに合わせて変更)
if ($request_uri ~* "/(cart|checkout|my-account)/") {
    set $skip_cache 1;
}

# カートに商品がある訪問者・ログイン中のユーザー
if ($http_cookie ~* "woocommerce_items_in_cart|wp_woocommerce_session_|wordpress_logged_in_") {
    set $skip_cache 1;
}

fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache     $skip_cache;

CDNでHTMLをキャッシュしている場合も、同じ考え方でパスとCookieの除外ルールを設定します。設定画面の名称はサービスやプランで変わるため、各サービスのドキュメントで「Cookieによるキャッシュのバイパス」に当たる機能を確認してください(2026年10月現在)。設定を変えたら、プラグイン・サーバー・CDNのすべての層でキャッシュを削除してから再確認します。

2. URLやドメインが混在している

www あり・なし、http と https が混在していると、Cookieが別のサイトのものとして扱われ、ページ移動のたびにセッションが切れたように見えます。

  • 「設定」→「一般」の「WordPressアドレス(URL)」と「サイトアドレス(URL)」が同じ表記か
  • 商品ページからカートへ移動したとき、URLの www や https が変わっていないか
  • wp-config.php で COOKIE_DOMAIN を独自に定義していないか(定義している場合、実際のドメインと合っているか)

URLを統一したら、.htaccess やサーバー設定で、表記の違うURLから正規のURLへリダイレクトします。

3. リバースプロキシの裏でHTTPSが正しく判定されていない

ロードバランサーやCDNでHTTPSを終端し、WordPressのサーバーにはHTTPで届く構成では、WordPressが「今はHTTPSではない」と判断してしまうことがあります。すると、Cookieの属性やリダイレクトが食い違い、セッションが保持されません。プロキシが X-Forwarded-Proto ヘッダーを渡している場合は、wp-config.php の先頭付近で次のように判定を補います。

// 信頼できるプロキシ経由の場合だけ使う
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
	$_SERVER['HTTPS'] = 'on';
}

このヘッダーは外部から偽装できるため、プロキシを通らない直接のアクセスを受け付けない構成で使ってください。サーバー会社によっては、この設定をすでに入れていることもあります。

4. 出力が先に送られてCookieを保存できない

Cookieは、ページの本文より前にヘッダーとして送る必要があります。テーマやプラグインのファイル先頭に空白や文字が紛れていたり、PHPの警告が画面に出力されていたりすると、Cookieを送れなくなります。デバッグログの headers already sent の警告には、出力が始まったファイルと行番号が書かれているので、そのファイルを修正します。functions.php の末尾の ?> の後ろにある改行が原因になることもあるため、PHPだけのファイルでは閉じタグを書かないのが安全です。

5. セッションテーブルの不具合

wp_woocommerce_sessions テーブルが壊れている、または移行時に作られていない場合も、セッションを保存できません。WooCommerceの「ステータス」画面のシステムレポートで、データベースのテーブル一覧にこのテーブルがあるかを確認できます。古いセッションが溜まりすぎている場合は、「ステータス」→「ツール」にあるお客様のセッションを削除する項目で整理できます(項目名はバージョンで変わることがあります)。実行するとカートに商品を入れている訪問者のカートも消えるため、アクセスの少ない時間帯に、データベースのバックアップを取ってから行ってください。

期限切れセッションはWooCommerceが定期処理(WP-Cron)で削除するため、WP-Cronが止まっているとテーブルが肥大化します。

6. プラグインやカスタムコードの競合

カート関連の拡張プラグインや、自作コードで WC()->session を早すぎるタイミング(WooCommerceの初期化前)に使っていると、セッションが正しく扱われません。ステージング環境で、WooCommerceとデフォルトテーマ(Storefrontなど)以外を一時的に無効化し、症状が消えるかを確かめます。消えた場合は、1つずつ有効に戻して原因を特定します。

セッションの有効期限を調整したい場合

WooCommerceのセッションには有効期限があり、標準ではおおむね2日程度で切れます(既定値はバージョンや、ログイン状態によって異なる場合があります)。「翌日に戻るとカートが空になる」ことへの対策として期限を延ばしたい場合は、フィルターで変更できます。

// mu-plugin または子テーマの functions.php
add_filter( 'wc_session_expiring', function () {
	return 6 * DAY_IN_SECONDS; // 延長処理を始める時点
} );
add_filter( 'wc_session_expiration', function () {
	return 7 * DAY_IN_SECONDS; // 有効期限
} );

wc_session_expiring は wc_session_expiration より短い値にします。期限を延ばすと、セッションテーブルに残るデータ量が増える点に注意してください。また、セッションにはカートの内容や入力途中の住所などの個人データが含まれる場合があるため、保存期間を変えたときはプライバシーポリシーの記載と矛盾しないかも確認します。

まとめ

  • WooCommerceのセッションは、wp_woocommerce_session_ のCookieとデータベースのセッションテーブルの組み合わせで動いている
  • まず開発者ツールでCookieの保存とレスポンスヘッダー(キャッシュの有無)を確認する
  • もっとも多い原因はキャッシュ。カート・チェックアウト・マイアカウントのURLと、セッション関連のCookieをすべてのキャッシュ層で除外する
  • ドメイン表記の混在、プロキシ裏のHTTPS判定、出力の先行、テーブルの不具合、プラグインの競合を順に確認する
  • 設定変更の前にバックアップを取り、ステージング環境で試してから本番に反映する

お気軽にご相談ください

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