Why use Uptime Robot for monitoring websites in WordPress?
Monitoring our website’s uptime is essential to ensure its reliability, especially for critical systems. In this post, we’ll see how I use the Uptime Robot API—a popular and robust third-party tool—to automate uptime tracking directly in WordPress.
Why Uptime Robot?
We chose Uptime Robot because:
- Popular and robust: Uptime Robot has a proven track record of reliability. It’s trusted by thousands of users worldwide and simply works.
- Third-party reliability: Using a third-party tool ensures that even if our systems are down, we can still monitor and access the status page.
- Why not self-host? While tools like Uptime Kuma are great alternatives, self-hosted solutions could fail alongside our systems, leaving us unable to track status when we need it most.
- Notifications: We can trigger instant notifications like an email when our site is down!
- Free Tier and API: Uptime Robot’s free tier offers generous features, including an API that we leverage here. The API is read-only, so there are no security concerns about unwanted modifications.
Data retention
By default, Uptime Robot’s free tier retains uptime history for 90 days. However, by using this WordPress solution:
- We will use posts as data storage: Each day’s uptime data is saved as a new WordPress post, allowing unlimited retention (or as much as our hosting storage permits).
- We control our data, and it’s always available for reference.
Using WordPress posts instead of a custom post type
Why store uptime data in standard posts?
- This solution is designed for a dedicated status site (e.g.,
status.oursite.com
) that has no other content. - Posts provide a simple and effective structure to display uptime information dynamically without the overhead of custom post types.
How it works
- Fetches site status and 24-hour uptime percentage every 5 minutes using WP-Cron.
- Each day, a new post is created with:
- Title: Current date in
dd-mm-yyyy
format. - Tags: Status values like success, outage, or unknown.
- Custom Field: Uptime percentage for the last “day”.
- Title: Current date in
- Uptime Robot status returned value –> stored status
2
=success
8
and9
=outage
0
and1
=unknown
- Unlimited Data Retention:
- Posts ensure our uptime data remains stored indefinitely without expiration
TLDR – the code
Below is an extract of the custom plugin I created:
// Schedule the cron job when the plugin is activated
register_activation_hook(__FILE__, function() {
// Schedule the 'check_uptime_status' event to run every 5 minutes if not already scheduled
if (!wp_next_scheduled('check_uptime_status')) {
wp_schedule_event(time(), 'five_minutes', 'check_uptime_status');
}
});
// Clear the cron job when the plugin is deactivated
register_deactivation_hook(__FILE__, function() {
// Remove the scheduled 'check_uptime_status' event
wp_clear_scheduled_hook('check_uptime_status');
});
// Add a custom cron interval for 5 minutes
add_filter('cron_schedules', function($schedules) {
// Define a new schedule 'five_minutes' with an interval of 300 seconds (5 minutes)
$schedules['five_minutes'] = [
'interval' => 300, // 5 minutes
'display' => __('Every 5 Minutes', 'uptime-robot-connector')
];
return $schedules;
});
// Main function to check the uptime status and update WordPress posts
add_action('check_uptime_status', function() {
$api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // Uptime Robot API key
$uptime_url = "https://api.uptimerobot.com/v2/getMonitors"; // Uptime Robot API endpoint
// Make an API request to UptimeRobot to fetch monitor data with a 30-second timeout
$response = wp_remote_post($uptime_url, [
'timeout' => 30, // API request timeout
'body' => [
'api_key' => $api_key,
'format' => 'json',
'custom_uptime_ratios' => '1' // Request uptime percentage for the last day
]
]);
// Check for API errors or invalid responses
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
error_log('Uptime Robot API error: ' . print_r($response, true)); // Log the error
return; // Exit the function if there's an error
}
// Decode the API response into a PHP array
$data = json_decode(wp_remote_retrieve_body($response), true);
// Check if the response contains valid monitor data
if (empty($data['monitors']) || !isset($data['monitors'][0]['custom_uptime_ratio'])) {
error_log('Uptime Robot API returned invalid data: ' . print_r($data, true)); // Log invalid data
return; // Exit the function if data is invalid
}
// Retrieve the site status from the API response
$site_status = $data['monitors'][0]['status'];
// Map the Uptime Robot status to custom labels
$status_label = match ($site_status) {
2 => 'success', // Site is up
9 => 'outage', // Site is down
8 => 'incident', // Site seems down (store as "incident")
0 => 'unknown', // Site is paused (store as "unknown")
1 => 'unknown', // Site is not checked yet (store as "unknown")
default => 'unknown' // Default to "unknown"
};
// Retrieve the uptime percentage for the last day
$uptime_percentage = (float) $data['monitors'][0]['custom_uptime_ratio'];
// Generate today's date in 'dd-mm-yyyy' format
$today = date('d-m-Y');
// Check if a WordPress post with today's date as the title already exists
$existing_post = get_page_by_title($today, OBJECT, 'post');
if (!$existing_post) {
// Create a new post if it doesn't exist
$post_id = wp_insert_post([
'post_title' => sanitize_text_field($today), // Set the post title to today's date
'post_content' => '', // Leave post content empty
'post_status' => 'publish', // Set post status to 'publish'
'post_author' => 1, // Replace with the desired author ID
'tags_input' => [sanitize_text_field($status_label)], // Add the status as a tag
]);
// Add the uptime percentage as a custom field if the post was created successfully
if ($post_id) {
add_post_meta($post_id, 'uptime_percentage', $uptime_percentage);
}
} else {
// If the post already exists, update its tags and uptime percentage
$post_id = $existing_post->ID;
// Update the post's tags with the new status label
wp_set_post_tags($post_id, [sanitize_text_field($status_label)], false);
// Check if the 'uptime_percentage' custom field exists; if not, create it
if (!get_post_meta($post_id, 'uptime_percentage', true)) {
add_post_meta($post_id, 'uptime_percentage', $uptime_percentage);
} else {
// Update the existing 'uptime_percentage' custom field
update_post_meta($post_id, 'uptime_percentage', $uptime_percentage);
}
}
// Calculate the previous scheduled time for the cron job (5 minutes ago)
$previous_scheduled_time = wp_next_scheduled('check_uptime_status') - 300; // Subtract 5 minutes
// Update the post's modified date to match the previous scheduled time
global $wpdb;
$wpdb->update(
$wpdb->posts, // WordPress posts table
[
'post_modified' => date('Y-m-d H:i:s', $previous_scheduled_time), // Local modified time
'post_modified_gmt' => gmdate('Y-m-d H:i:s', $previous_scheduled_time) // GMT modified time
],
['ID' => $post_id], // Target the specific post ID
['%s', '%s'], // Data types for the values
['%d'] // Data type for the where clause
);
});