

A full-screen loader with a frosted background and the top progress bar, styled to match the site.
PagePulse shows clear, good-looking feedback whenever visitors wait: while a page loads, when they follow a link, submit a form, add a product to the cart, or when your own scripts fetch data. It is built to be safe on real sites: it never delays navigation, never changes how forms submit, never leaves a page covered, and never loads files a page does not need.
PagePulse improves perceived loading. It does not make your pages load faster, and it is designed not to make them slower: no jQuery, CSS-only animations, a deferred script, and only the CSS of the loaders you use.
mailto:/tel:, new tabs, Ctrl/⌘-clicks, in-page anchors, the dashboard or the login page.data-pagepulse attributes or the JavaScript API.fetch()/XMLHttpRequest is opt-in.[pagepulse_skeleton] shortcode and a Skeleton placeholder block: text, image, card, avatar, table, product, list and custom shapes, with wrapped content revealed when loading finishes. Optional shimmer placeholders for images.33 loaders in four groups, every one pure CSS (with a little SVG) and configurable in colour, size, speed, direction and intensity:
The seven transitions of PagePulse 0.1 are kept (slide top-bottom, slide bottom-top, fade, clip top/bottom, clip left/right, animated slides) plus zoom fade and none.
Settings PagePulse has an overview, the animation library, loading triggers, a live builder with desktop/mobile preview and contrast check, ten presets plus your own, advanced settings, tools (frontend preview, compatibility diagnostics, recent errors, export/import, restore defaults, safe mode, temporary disablement) and developer documentation. The builder and its preview load only in the dashboard.
aria-busy, buttons aria-busy and aria-disabled, progress bars role="progressbar" with real values only.Tested with WordPress 5.8, 6.1 and 7.1 on PHP 7.4 and 8.4; block and classic themes (Twenty Twenty-Five, Twenty Twenty-One, Storefront, Astra); Gutenberg, Elementor, WooCommerce (block and classic shop, classic cart), Contact Form 7, WPForms, Ninja Forms and the AJAX Loading plugin (1.1, and the 2.x event contract). The Gravity Forms integration (AJAX iframe mode) follows that plugin’s documented events. Caching and optimisation plugins are supported (see FAQ). PagePulse stays out of page-builder editing canvases (Elementor, Beaver Builder, Divi, Bricks, Oxygen).
When AJAX Loading is active, it loads the content and PagePulse shows the transition. PagePulse listens to AJAX Loading’s lifecycle events (wp_ajax_load_start, wp_ajax_load_complete, wp_ajax_load_error, wp_ajax_load_cancel in 2.x; History.js state changes in 1.x), keeps a single overlay (AJAX Loading’s own indicator and 1.x page dimming are not shown at the same time) and respects PagePulse’s link exclusions. Neither plugin requires the other. Turn the integration off under Loading triggers Page navigation.
window.PagePulse (no dependencies):
const h = PagePulse.show({ type: 'dots', text: 'Saving…' }); h.hide();
PagePulse.element.show('.product-container');
PagePulse.element.hide('.product-container');
PagePulse.button.show('#save', { text: 'Saving…' });
PagePulse.progress.set(60); // measured progress only
PagePulse.track(fetch(url), { target: '#results' });
Loaders are reference counted (finishing one operation never hides a loader another operation still needs) and every loader times out on its own. Data attributes (data-pagepulse, data-pagepulse-target…), DOM events (pagepulse:start/pagepulse:end in, pagepulse:show/hide/timeout… out) and PHP hooks (pagepulse_should_load, pagepulse_frontend_config, pagepulse_animations, pagepulse_presets, pagepulse_overlay_markup…) are documented on the Developers tab and in DEVELOPERS.md.
PagePulse loads no remote files, sets no cookies and sends nothing to third parties. “Only on the first page of a visit” uses the browser’s sessionStorage. Debug mode records PagePulse’s own JavaScript errors for administrators only.
edit_css capability).Clear your page cache after changing settings.
Mark an element and call the API:
<div class="product-container" data-pagepulse="true" data-pagepulse-loader="dots">…</div>
<button data-pagepulse-target=".product-container">Load more</button>
The button shows a loader on .product-container until its content changes (or the maximum time). Without code, add a rule under Loading triggers Element loading: while the page loads, after a click until the content changes or during matching AJAX requests.
[pagepulse_skeleton type="card" count="3" /]
[pagepulse_skeleton type="product" count="4" columns="4" until="load"]…your content…[/pagepulse_skeleton]
Types: text, image, card, avatar, table, product, list, custom. Options: count, lines, rows, columns, width, height, until (load, delay, manual), delay, max, label, class. Use the self-closing form (/]) when a page mixes standalone and wrapping skeletons. Standalone placeholders are replaced by your script (PagePulse.skeleton.replace(el, html)) or removed after max milliseconds.