Lazy Load for Comments ships with a small, stable extension surface so you can customise its behaviour without modifying its core files. Anything documented on this page is part of the public API — it will keep working across minor releases. Anything not documented here is internal and may change without notice.
All examples below can be dropped into your theme's functions.php or a small companion plugin.
Lazy Load for Comments 2.x is built with namespaced PHP classes under FoxeLabs\LazyComments\… and a Composer classmap autoloader. Every subsystem lives in its own dedicated class so it can be reasoned about, tested and replaced independently.
These classes lived under DuckDev\LazyComments\ before 2.1.0, when the plugin moved to the Foxe Labs brand. Every old name is still resolvable — the plugin registers an autoloader that aliases DuckDev\LazyComments\* to its current equivalent on first use — so add-ons and custom templates written against the old names keep working. They are deprecated, raise a _doing_it_wrong() notice and will be removed in a future version, so new code should use FoxeLabs\LazyComments\.
Hook, filter, option and setting names all start with lazy_load_for_comments_ and were not affected. The Composer package was renamed duckdev/lazy-load-for-comments → foxelabs/lazy-load-for-comments.
The recommended way to extend the plugin is:
Hook into lazy_load_for_comments_init so your code only runs when the plugin is loaded.
Reach the long-lived services through the global helper lazy_load_for_comments_settings() or the service locator on Core::instance().
Use the documented filters and actions for everything you can — they are guaranteed-stable.
Fires once the plugin is fully booted and every subsystem (admin, front-end, REST, compatibility) has registered its hooks. Addons should use this action so they only initialise when Lazy Load for Comments is active.
add_action( 'lazy_load_for_comments_init', 'my_addon_init' );function my_addon_init( $core ) { // The plugin is loaded; the settings, REST routes and front-end // controller are all wired up. Safe to register your own hooks. $settings = $core->settings();}
add_action( 'lazy_load_for_comments_activated', 'my_addon_on_activate' );function my_addon_on_activate() { // First run — seed your addon's own options here.}
Fires right after the plugin is deactivated. Use it to undo whatever the activation hook set up. Do not delete user data here — full cleanup belongs in your addon's own uninstall.php.
Decides whether the comments should be lazy-loaded for the current request. The plugin already runs its own eligibility checks (load method, single post, minimum comment count, bot detection) — this filter lets you add your own conditions on top.
Gives fine-grained control over whether the current user can manage the plugin and use its REST API. Runs after the capability check, so you can override the result on a per-user basis.
add_filter( 'lazy_load_for_comments_has_access', 'my_restrict_access' );function my_restrict_access( $has_access ) { // Only allow user ID 1 to manage the plugin. return get_current_user_id() === 1;}
The settings live in a single WordPress option (lazy_load_for_comments_settings), managed by FoxeLabs\LazyComments\Settings. The recommended way to read and write them from PHP is the global helper:
When a block-theme renders the core/comments block, the parsed block markup is cached per-post in a transient so the REST endpoint can re-render it on demand without walking the active template tree again.
php
use FoxeLabs\LazyComments\Cache\BlockCache;// Read.$key = BlockCache::key( $post_id ); // transient key for a post$block = BlockCache::get( $post_id ); // serialized block, or false// Write.BlockCache::set( $post_id, $serialized_block );// Invalidate.BlockCache::flush_all(); // every cached entry
BlockCache::flush_all() is automatically called on switch_theme — a different theme renders the comments block differently, so any cached markup is no longer trustworthy.
The settings UI exposes a "Clear cache" button that calls the DELETE /lazy-load-for-comments/v1/cache REST endpoint, which in turn calls BlockCache::flush_all().
Returns the rendered comments HTML for a post. Used by the front-end script to fetch the comments on click or scroll.
Query args:post_id(int, required)
Permission: public (no nonce, no capability check) — the response only contains markup WordPress would have served inline. The route is full-page-cache friendly.
Nonce: the front-end script only sends an X-WP-Nonce header when the visitor is logged in, so the comment form renders for the right user. Logged-out visitors send no nonce at all. This matters behind a full-page cache: a nonce baked into cached HTML expires after 12–24 hours, and WordPress rejects a stale X-WP-Nonce with a 403 in rest_cookie_check_errors() before the route's own permission check runs. If that happens anyway — for example when a logged-in visitor is served a page cached for logged-out visitors — the script retries the request once without the header.
If you need the placeholder markup outside the normal classic / block-theme render paths — for example, in a custom block or shortcode — call the renderer directly:
php
use FoxeLabs\LazyComments\Front\Renderer;echo Renderer::placeholder();
The returned HTML contains the mount point the front-end script attaches to. Make sure your custom output is reachable on a single-post view where lazy_load_for_comments_can_lazy_load returns true, otherwise the script will not enqueue.
Lazy Load for Comments is hosted on WordPress.org, so its translations are loaded automatically from translate.wordpress.org the first time a __()-style call uses the plugin's text domain. There is no need to call load_plugin_textdomain() yourself.
If you want to ship custom strings for your addon, register them under your own text domain rather than lazy-load-for-comments.
Need help?
If you think something is missing or need help extending Lazy Load for Comments, feel free to contact us.
Developer Docs
Lazy Load for Comments ships with a small, stable extension surface so you can customise its behaviour without modifying its core files. Anything documented on this page is part of the public API — it will keep working across minor releases. Anything not documented here is internal and may change without notice.
All examples below can be dropped into your theme's
functions.phpor a small companion plugin.Architecture overview
Lazy Load for Comments 2.x is built with namespaced PHP classes under
FoxeLabs\LazyComments\…and a Composer classmap autoloader. Every subsystem lives in its own dedicated class so it can be reasoned about, tested and replaced independently.Namespace changed in 2.1.0
These classes lived under
DuckDev\LazyComments\before 2.1.0, when the plugin moved to the Foxe Labs brand. Every old name is still resolvable — the plugin registers an autoloader that aliasesDuckDev\LazyComments\*to its current equivalent on first use — so add-ons and custom templates written against the old names keep working. They are deprecated, raise a_doing_it_wrong()notice and will be removed in a future version, so new code should useFoxeLabs\LazyComments\.Hook, filter, option and setting names all start with
lazy_load_for_comments_and were not affected. The Composer package was renamedduckdev/lazy-load-for-comments→foxelabs/lazy-load-for-comments.The recommended way to extend the plugin is:
lazy_load_for_comments_initso your code only runs when the plugin is loaded.lazy_load_for_comments_settings()or the service locator onCore::instance().Actions
Actions let you run a custom function at a specific, predefined point in the plugin's execution.
lazy_load_for_comments_initFires once the plugin is fully booted and every subsystem (admin, front-end, REST, compatibility) has registered its hooks. Addons should use this action so they only initialise when Lazy Load for Comments is active.
Parameters
$core(Core) — the singleton instance ofFoxeLabs\LazyComments\Core.Example
lazy_load_for_comments_activatedFires right after the plugin is activated (or reactivated). Use it to run one-time setup tasks for your addon.
Example
lazy_load_for_comments_deactivatedFires right after the plugin is deactivated. Use it to undo whatever the activation hook set up. Do not delete user data here — full cleanup belongs in your addon's own
uninstall.php.Example
Filters
Filters let you modify a value before the plugin uses it. A filter callback receives the value, modifies it, and returns the modified version.
lazy_load_for_comments_can_lazy_loadDecides whether the comments should be lazy-loaded for the current request. The plugin already runs its own eligibility checks (load method, single post, minimum comment count, bot detection) — this filter lets you add your own conditions on top.
Parameters
$can(bool) — result of the built-in checks. Returntrueto lazy-load,falseto render the comments inline as WordPress normally would.Example
lazy_load_for_comments_rendered_htmlModifies the comments HTML that the REST API returns to the browser before it is injected into the page.
Parameters
$html(string) — the rendered comments HTML.$post(WP_Post) — the post the comments belong to.Example
lazy_load_for_comments_default_settingsModifies the plugin's default settings. Addons can use it to change the fallback value of any existing key.
Parameters
$defaults(array) — associative array of setting keys and their default values. The supported keys are:load_method'scroll''scroll','click','off'.button_textLoad Commentsbutton_style'theme''theme'to inherit the theme's button styling,'custom'for the plugin's own style.button_class''show_loadertrueminimum_count1disable_for_botstruecache_enabledtrueExample
lazy_load_for_comments_capabilityChanges the user capability required to access and manage the plugin's settings page. The default is
manage_options.Parameters
$capability(string) — capability slug.Example
lazy_load_for_comments_has_accessGives fine-grained control over whether the current user can manage the plugin and use its REST API. Runs after the capability check, so you can override the result on a per-user basis.
Parameters
$has_access(bool) — result of the default capability check.Example
Settings API
The settings live in a single WordPress option (
lazy_load_for_comments_settings), managed byFoxeLabs\LazyComments\Settings. The recommended way to read and write them from PHP is the global helper:Every write goes through the same sanitisation pipeline that the REST API uses, so unsafe values are coerced or rejected automatically.
Cache management API
When a block-theme renders the
core/commentsblock, the parsed block markup is cached per-post in a transient so the REST endpoint can re-render it on demand without walking the active template tree again.BlockCache::flush_all()is automatically called onswitch_theme— a different theme renders the comments block differently, so any cached markup is no longer trustworthy.The settings UI exposes a "Clear cache" button that calls the
DELETE /lazy-load-for-comments/v1/cacheREST endpoint, which in turn callsBlockCache::flush_all().REST API
The plugin registers two routes under the
lazy-load-for-comments/v1namespace.GET /lazy-load-for-comments/v1/commentsReturns the rendered comments HTML for a post. Used by the front-end script to fetch the comments on click or scroll.
post_id(int, required)X-WP-Nonceheader when the visitor is logged in, so the comment form renders for the right user. Logged-out visitors send no nonce at all. This matters behind a full-page cache: a nonce baked into cached HTML expires after 12–24 hours, and WordPress rejects a staleX-WP-Noncewith a403inrest_cookie_check_errors()before the route's own permission check runs. If that happens anyway — for example when a logged-in visitor is served a page cached for logged-out visitors — the script retries the request once without the header.{ "html": "<ol class=\"commentlist\">…</ol>" }{ "html": "" }— post missing or not publicly viewable.DELETE /lazy-load-for-comments/v1/cacheClears every cached comments-block transient.
FoxeLabs\LazyComments\Utils\Permission::has_access()— defaults tomanage_options, filterable vialazy_load_for_comments_capabilityandlazy_load_for_comments_has_access.{ "success": true, "message": "Comments cache cleared." }Placeholder helper
If you need the placeholder markup outside the normal classic / block-theme render paths — for example, in a custom block or shortcode — call the renderer directly:
The returned HTML contains the mount point the front-end script attaches to. Make sure your custom output is reachable on a single-post view where
lazy_load_for_comments_can_lazy_loadreturnstrue, otherwise the script will not enqueue.Translations
Lazy Load for Comments is hosted on WordPress.org, so its translations are loaded automatically from translate.wordpress.org the first time a
__()-style call uses the plugin's text domain. There is no need to callload_plugin_textdomain()yourself.If you want to ship custom strings for your addon, register them under your own text domain rather than
lazy-load-for-comments.Need help?
If you think something is missing or need help extending Lazy Load for Comments, feel free to contact us.