The Broadcast Channel API lets multiple browser tabs or windows on the same origin exchange messages without a server round-trip. In WordPress this is useful for syncing cart state, invalidating admin caches, or showing a “logged out” warning across all open tabs when a session expires.
Problem: A WordPress admin page opens multiple browser tabs — for example, a split-screen comparison or a background processing tab — and needs to synchronise state (a completed import, a settings change) between tabs without polling a server endpoint.
Solution: Use the BroadcastChannel API to post messages between same-origin tabs. Create a channel with the same name in each tab, post a message with channel.postMessage(), and listen with channel.onmessage to react instantly when another tab reports a state change.
The examples below open a broadcast channel in a WordPress front-end script, post a cart-update message from the WooCommerce store, and receive it in the admin dashboard tab to update a live counter.
// cart-channel.js — enqueued on every front-end page
const cartChannel = new BroadcastChannel( 'woo_cart' );
// Post a message whenever the cart changes (hook into WooCommerce's jQuery events)
document.addEventListener( 'wc_cart_hash_updated', () => {
cartChannel.postMessage( {
type: 'CART_UPDATED',
count: parseInt( document.querySelector( '.cart-count' )?.textContent ?? '0', 10 ),
timestamp: Date.now(),
} );
} );
// admin-bar.js — also enqueued on front-end (or admin-bar on back-end pages)
const cartListener = new BroadcastChannel( 'woo_cart' );
cartListener.addEventListener( 'message', ( e ) => {
if ( e.data?.type === 'CART_UPDATED' ) {
const badge = document.querySelector( '#wp-admin-bar-my-account .cart-badge' );
if ( badge ) badge.textContent = e.data.count;
}
} );
// Always close the channel when the page unloads to avoid memory leaks
window.addEventListener( 'beforeunload', () => {
cartChannel.close();
cartListener.close();
} );
Use a broadcast channel to force re-login across all tabs when a WordPress session expires:
// session-monitor.js
const sessionChannel = new BroadcastChannel( 'wp_session' );
// On every authenticated REST request, check the response status
async function apiFetch( url, options = {} ) {
const response = await fetch( url, options );
if ( response.status === 401 ) {
// Broadcast to all other tabs
sessionChannel.postMessage( { type: 'SESSION_EXPIRED' } );
handleSessionExpired();
}
return response;
}
// All tabs listen for session expiry
sessionChannel.addEventListener( 'message', ( e ) => {
if ( e.data?.type === 'SESSION_EXPIRED' ) {
handleSessionExpired();
}
} );
function handleSessionExpired() {
sessionChannel.close();
// Show a non-dismissible overlay
document.body.insertAdjacentHTML( 'beforeend',
''
);
}
NOTE: Broadcast Channel only works between same-origin contexts (same protocol, host, and port). For cross-origin communication use postMessage with explicit origin checks, or a SharedWorker if you need persistent state.