Visitor Tracker in WordPress Want a lightweight way to see how many people are on your site right now—and get a subtle pop-up when someone new arrives? This tutorial gives you a clean PHP snippet you can drop into a snippets plugin. It tracks all visitors, updates counts in real time, and shows a floating pop-up and sticky counter button to administrators.
// Hook to add the visitor tracking and popup for admins
add_action('wp_footer', 'admin_visitor_tracker');
function admin_visitor_tracker() {
if (!current_user_can('administrator')) {
return;
}
// Generate a temporary session ID
if (!session_id()) {
session_start();
}
$session_id = session_id();
// Update visitor data
$visitors = get_transient('online_visitors') ?: array();
$visitors[$session_id] = time();
set_transient('online_visitors', $visitors, 300); // Store for 5 minutes
// Output HTML and JavaScript
?>
#visitor-popup, #visitor-count-button {
position: fixed;
right: 20px;
background: white;
color: #333;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 9999;
font-size: 14px;
font-family: Arial, sans-serif;
transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
}
#visitor-popup {
display: none;
bottom: 80px;
transform: translateY(20px);
opacity: 0;
}
#visitor-count-button {
bottom: 20px;
cursor: pointer;
opacity: 0;
transform: translateY(20px);
display: none;
}
#visitor-count-button:hover {
background-color: #f0f0f0;
}
New visitor entered
Online visitors: 0
Online: 0
jQuery(document).ready(function($) {
var lastCount = 0;
var updateAfterPopup = false; // Flag to update the button count after popup
function updateVisitorCount() {
$.ajax({
url: '',
type: 'POST',
data: {
action: 'update_visitor_count',
nonce: ''
},
success: function(response) {
if (response.count > lastCount) {
updateAfterPopup = true; // Set flag to update after popup
$('#visitor-count-button').animate({opacity: 0, transform: 'translateY(20px)'}, 500, function() {
$(this).css('display', 'none');
$('#visitor-popup').css({display: 'block', opacity: 0, transform: 'translateY(20px)'})
.animate({opacity: 1, transform: 'translateY(0)'}, 500)
.delay(5000)
.animate({opacity: 0, transform: 'translateY(20px)'}, 500, function() {
$(this).css('display', 'none');
$('#visitor-count-button').css({display: 'block', opacity: 0, transform: 'translateY(20px)'})
.animate({opacity: 1, transform: 'translateY(0)'}, 500, function() {
if (updateAfterPopup) {
$('#button-visitor-count').text(response.count); // Update button count after popup is hidden
updateAfterPopup = false; // Reset flag
}
});
});
});
} else {
$('#button-visitor-count').text(response.count); // Update button count immediately if no new visitor
}
$('#popup-visitor-count').text(response.count); // Always update popup count
lastCount = response.count;
}
});
}
// Update immediately and then every 5 seconds
updateVisitorCount();
setInterval(updateVisitorCount, 5000);
// Clear session when leaving the page
$(window).on('beforeunload', function() {
$.ajax({
url: '',
type: 'POST',
async: false,
data: {
action: 'remove_visitor',
nonce: ''
}
});
});
});
$time) {
if ($current_time - $time > 300) {
unset($visitors[$id]);
}
}
set_transient('online_visitors', $visitors, 300);
$count = count($visitors);
wp_send_json(array('count' => $count));
}
// AJAX handler to remove visitor when leaving
add_action('wp_ajax_remove_visitor', 'remove_visitor');
add_action('wp_ajax_nopriv_remove_visitor', 'remove_visitor');
function remove_visitor() {
check_ajax_referer('visitor_tracker_nonce', 'nonce');
$session_id = session_id();
$visitors = get_transient('online_visitors') ?: array();
if (isset($visitors[$session_id])) {
unset($visitors[$session_id]);
set_transient('online_visitors', $visitors, 300);
}
wp_send_json_success();
}
// Track all visitors, not just admins
add_action('wp_head', 'track_visitor');
function track_visitor() {
if (!session_id()) {
session_start();
}
$session_id = session_id();
$visitors = get_transient('online_visitors') ?: array();
$visitors[$session_id] = time();
set_transient('online_visitors', $visitors, 300);
}
If you want editors to see the counter too, replace current_user_can('administrator') with a capability like edit_pages or check multiple roles before returning.
Powered by Webspires © Boost My Croco 2025. All Rights Reserved.