Creating A UserOnline Page
Go to WP-Admin -> Pages -> Add New Type any title you like in the post’s title area If you ARE using nice permalinks, after typing the title, WordPress will generate the permalink to the page. You will see an ‘Edit’ link just beside the permalink. Click ‘Edit’ and type in useronline in the text field and click ‘Save’. Type [page_useronline] in the post’s content area Click ‘Publish’ If you ARE NOT using nice permalinks, you need to go to WP-Admin -> WP-UserOnline -> Settings (the Settings tab) and under ‘UserOnline URL’, you need to fill in the URL to the UserOnline Page you created above.
To Display Most Number Of Users Online
Use: <?php if ( function_exists( 'get_most_users_online' ) ) : ?> <p>Most Users Ever Online Is <?php echo get_most_users_online(); ?> On <?php echo get_most_users_online_date(); ?></p> <?php endif; ?>
To Display Users Browsing Site
Use: <?php if ( function_exists( 'get_users_browsing_site' ) ) : ?> <div id="useronline-browsing-site"><?php echo get_users_browsing_site(); ?></div> <?php endif; ?>
To Display Users Browsing A Page
Use: <?php if ( function_exists( 'get_users_browsing_page' ) ) : ?> <div id="useronline-browsing-page"><?php echo get_users_browsing_page(); ?></div> <?php endif; ?>
Every visitor shows the same IP address
Your site is behind a reverse proxy or CDN — Cloudflare, a load balancer, nginx in front of Apache — so the address PHP sees is the proxy’s, not the visitor’s.
The real address is in the X-Forwarded-For header, but WP-UserOnline ignores that header by default: any client can send it with any value, so trusting it blindly lets a visitor forge their address. Opt in only if a proxy you control actually sets it, by adding this to wp-config.php above the /* That's all, stop editing! */ line:
define( 'WP_USERONLINE_TRUST_PROXY', true );
If you need to decide at runtime — say, only trust it for requests arriving from your load balancer — use the filter instead:
add_filter( 'wp_useronline_trust_proxy', function () { return isset( $_SERVER['REMOTE_ADDR'] ) && '10.0.0.1' === $_SERVER['REMOTE_ADDR']; } );
With neither set, the plugin records REMOTE_ADDR — correct on a plain host, and the proxy’s address behind one.
Both the constant and the filter were renamed in 4.0.0, from USERONLINE_TRUST_PROXY and useronline_trust_proxy . The old names do nothing at all now, so if your site was already opted in, rename them or every visitor will start showing the proxy’s address.
Who can see the users online screen?
Anyone with manage_options , which in practice means administrators. Before 4.0.0 the screen was open to anyone who could list_users , which on many sites included editors. To put it back that way, filter the capability — the context tells the Users Online tab from the other two, and each tab checks its own, so this does not open the settings at the same time:
add_filter( 'wp_useronline_capability', function ( $capability, $context ) { return 'useronline' === $context ? 'list_users' : $capability; }, 10, 2 ); Can I change where an IP address links to?
Yes. Each address in the detailed listing links to a lookup at ipinfo.io , which answers for IPv4 and IPv6 alike. Before 4.0.1 it went to a service that could not read an IPv6 address at all. To send it somewhere else, filter the URL — the address arrives raw as the second argument, so encode it however the service you pick wants it:
add_filter( 'wp_useronline_ip_lookup_url', function ( $url, $ip ) { return 'https://who.is/whois-ip/ip-address/' . rawurlencode( $ip ); }, 10, 2 );
Return an empty string to drop the link entirely and show the address as plain text, which is what to do if you would rather not hand a visitor’s address to a third party:
add_filter( 'wp_useronline_ip_lookup_url', '__return_empty_string' ); Can I change the list of search bots?
Yes. wp_useronline_bots filters the whole list, whose keys are the names shown in the users online list and whose values are the case-insensitive fragment looked for in the user agent:
add_filter( 'wp_useronline_bots', function ( $bots ) { $bots['My Crawler'] = 'mycrawler'; return $bots; } ); My own code renders the counters and they never refresh
The refresh script loads only when something on the page has already rendered a counter or a listing, and it is enqueued from wp_footer — the one pass. Markup fetched over admin-ajax.php or the REST API into a page that shows none of its own reaches neither: the fetch has no footer to enqueue into, and the page rendered nothing to ask. The numbers then sit at whatever they were when the markup was built.
Say so from the page that will hold them:
add_filter( 'wp_useronline_needs_scripts', '__return_true' );
Code that runs during the page itself can call WP_UserOnline_Template::request_scripts() instead, which is the same request every built-in render path makes.
The plugin will not activate
WP-UserOnline 4.0 and later requires WordPress 6.8 and PHP 8.2. WordPress checks both and refuses to activate the plugin on anything older, telling you which one is short.
To see what your host is running, look at Tools -> Site Health -> Info -> Server , or install WP-ServerInfo .
If you cannot upgrade, WP-UserOnline 3.0.0 is the last release supporting WordPress 6.0 and PHP 7.4.