Summary
LifterLMS sets a wp_llms_session_<COOKIEHASH> cookie on the first page view of every anonymous visitor, including on pages with nothing to do with LifterLMS (home page, blog posts, marketing pages, 404s). Full-page caches refuse to store any response carrying a Set-Cookie header (otherwise one visitor's session would be served to everyone), so the practical effect is that activating LifterLMS disables anonymous full-page caching site-wide.
Reproduction Steps
- Install LifterLMS on a site with a full-page cache (Surge, Cloudflare, Varnish, WP Super Cache, W3TC, host-level cache).
- As a logged-out visitor, request any front-end URL (home page, a blog post, a 404).
- Inspect the response headers.
Expected Behavior
An anonymous page view that never touches the LifterLMS session (no coupon applied, no notice queued) should not emit a Set-Cookie: wp_llms_session_... header and should stay cache-eligible.
Actual Behavior
Every anonymous front-end response carries Set-Cookie: wp_llms_session_<hash>=... plus a no-cache Cache-Control, so the page cache stores nothing for logged-out traffic. Captured on a live site:
set-cookie: wp_llms_session_<hash>=...; path=/; secure; HttpOnly
cache-control: private, max-age=0, no-cache
Root Cause
LLMS_Session::init_cookie() (includes/class.llms.session.php) eagerly mints a session and emits the cookie for any visitor without an existing one ($set_cookie = true), even though nothing has used the session. The cookie's only purposes are preserving an applied coupon during checkout and storing notice messages, both of which write via LLMS_Session::set().
Proposed Fix
Make the cookie lazy: defer emission until the first session write. Same philosophy already shipped for the llms-tracking cookie in #2330 / #2331. A grep of core + all first-party add-ons confirms every session writer goes through LLMS_Session::set() (core checkout + AJAX coupons, llms_add_notice(), Advanced Coupons coupon-from-URL, Gifts voucher count, Groups seat count) and none relies on eager creation, so this is safe default-on. The llms_session_should_init filter stays as the escape hatch.
This issue has been recreated:
Summary
LifterLMS sets a
wp_llms_session_<COOKIEHASH>cookie on the first page view of every anonymous visitor, including on pages with nothing to do with LifterLMS (home page, blog posts, marketing pages, 404s). Full-page caches refuse to store any response carrying aSet-Cookieheader (otherwise one visitor's session would be served to everyone), so the practical effect is that activating LifterLMS disables anonymous full-page caching site-wide.Reproduction Steps
Expected Behavior
An anonymous page view that never touches the LifterLMS session (no coupon applied, no notice queued) should not emit a
Set-Cookie: wp_llms_session_...header and should stay cache-eligible.Actual Behavior
Every anonymous front-end response carries
Set-Cookie: wp_llms_session_<hash>=...plus a no-cacheCache-Control, so the page cache stores nothing for logged-out traffic. Captured on a live site:Root Cause
LLMS_Session::init_cookie()(includes/class.llms.session.php) eagerly mints a session and emits the cookie for any visitor without an existing one ($set_cookie = true), even though nothing has used the session. The cookie's only purposes are preserving an applied coupon during checkout and storing notice messages, both of which write viaLLMS_Session::set().Proposed Fix
Make the cookie lazy: defer emission until the first session write. Same philosophy already shipped for the
llms-trackingcookie in #2330 / #2331. A grep of core + all first-party add-ons confirms every session writer goes throughLLMS_Session::set()(core checkout + AJAX coupons,llms_add_notice(), Advanced Coupons coupon-from-URL, Gifts voucher count, Groups seat count) and none relies on eager creation, so this is safe default-on. Thellms_session_should_initfilter stays as the escape hatch.This issue has been recreated: