Setup

WP-Cron is the built-in tool in WordPress that allows you to schedule automated tasks.

The main issue: Out of the box, WP-Cron only works on page load, and therefore depends on site traffic.

If the site doesn’t get enough traffic, the task will only be performed when the next user visits the site, even if it was already supposed to run.

For example, if you want a particular task to be performed at 7:00 am but no page loading occurs at this time, the task will only be executed at the next visit.

Another issue is with site performance. Since WP-Cron checks for cron jobs on every page load, this can lead to poorer performance, especially on high-traffic sites.

A solution for these issues might be a combination of the built-in WP-Cron tool and the server-side cron jobs system.

The server-side system can perform tasks at any given time regardless of the number of visitors.

So we can set the cron jobs using the built-in WP-Cron solution, but actively run the /wp-cron.php file only through the server-side cron jobs system instead of on each page load.

For this setup we will schedule /wp-cron.php through the server-side system.

In addition, we would like to prevent WP-Cron from running on page load.

This can be done by adding following line to the wp-config.php file just before the “That’s all, stop editing! Happy blogging.” line:

define( 'DISABLE_WP_CRON', true );

General structure of a cron job

/**
 * Schedules the cron job.
 */
add_action(
	'init',
	function() {
        // Create the event which will execute the automated task.
		add_action(
			'notesontech_refresh_feed_event',
			'notesontech_refresh_feed_run'
		);

        // Schedule the event.
		if ( ! wp_next_scheduled( 'notesontech_refresh_feed_event' ) ) {
			wp_schedule_event(
				strtotime( '07:00:00' ),
				'daily',
				'notesontech_refresh_feed_event'
			);
		}
	}
);

/**
 * Executes the cron job.
 */
function notesontech_refresh_feed_run() {
    // This is the actual task the we want to automate.
}

We have two main parts here.

The first part is the action that is triggered after WordPress has finished loading (init).

Within it, we create an action for the event. This even will be triggered when the task is scheduled. It will then trigger the actual task.

We also schedule the next time this task will be executed (using wp_schedule_event) if it’s not already scheduled.

The second part is the actual task - the cron job.

In the example above, the notesontech_refresh_feed_run function will be performed every day (note the daily value in the second recurrence parameter) at 7:00 am GMT (note the strtotime( '07:00:00' ) value in the first timestamp parameter).

Timestamp

This is the first parameter in the wp_schedule_event function. It defines when to run the event next.

We can set a specific time when the task should run using strtotime( '07:00:00' ) (change 07:00:00 to the desired time).

Alternatively, if we just want the automated task to run and a specific time is not important, we can use time() as the first parameter to run the next event immediately.

In this case, the task will be executed for the first time after this new code is deployed. Then, it will repeat itself according to the set recurrence.

Recurrence

The second parameter in the wp_schedule_event function. It defines how often the event should be performed.

Supported default values are hourly, twicedaily, daily, and weekly.

Custom recurrence

We can also create another recurrence option if it’s not part of the default values.

Suppose we want to create a “Twice Hourly” recurrence to run a task every 30 minutes:

/**
 * Adds custom cron schedules.
 *
 * @param array $schedules Existing schedules.
 * @return array Array of default and custom schedules.
 */
function notesontech_add_custom_cron_schedules( $schedules ) {

	// Every 30 minutes.
	$schedules['twicehourly'] = array(
		'interval' => HOUR_IN_SECONDS / 2,
		'display'  => __( 'Twice Hourly', 'textdomain' ),
	);

	return $schedules;
}

add_filter( 'cron_schedules', 'notesontech_add_custom_cron_schedules' );

Specific date

Finally, let’s say we want to perform a task on a specific date.

For example, on the 15th of each month.

A simple way to achieve this is by setting a standard task with a daily recurrence.

Then, in the actual task, check the date as the first thing.

If the date is not 15, we stop the execution (return).

This way, the automated task is being triggered daily, but actually runs only on the 15th of each month.

In the following example, the cron job will be executed on the 15th of each month at 7:00 am GMT.

/**
 * Schedules the cron job.
 */
add_action(
	'init',
	function() {
        // Create the event which will execute the automated task.
		add_action(
			'notesontech_refresh_feed_event',
			'notesontech_refresh_feed_run'
		);

        // Schedule the event.
		if ( ! wp_next_scheduled( 'notesontech_refresh_feed_event' ) ) {
			wp_schedule_event(
				strtotime( '07:00:00' ),
				'daily',
				'notesontech_refresh_feed_event'
			);
		}
	}
);

/**
 * Executes the cron job.
 */
function notesontech_refresh_feed_run() {

	// Run the cron job every day ("daily" interval) and check the date.
	// Only execute the cron job on the 15th of each month.
	if ( 15 !== (int) gmdate( 'd' ) ) {
		return;
	}

    // Continue with the automated task.
}

References