How Notifications Work in WordPress (Pings, Trackbacks) – xmlrpc.php File

In this article, we will talk about pings (trackback, pingback) in WordPress, how they are structured, how they differ, and how to effectively use them.

Trackbacks and pingbacks are ways of communication between WordPress sites. They have existed since the early days of WordPress, but very few users are aware of these functions.

Trackbacks and Pingbacks

In WP, there are two types of notifications about someone referencing your article (this someone can be your site when you reference an article from another site):

Pingback

Automatic notification. Does not send any content.

This is when your site automatically notifies the "other site" upon publishing a post, that the post content contains a link to the "other site". Upon such notification, your site automatically sends a ping, and the other site receives this ping as a comment with the type comment_type = pingback.

Trackback

Manual notification. Sends an excerpt from the post content.

With this notification, you need to manually specify the URL of the article to which you want to send the notification, and the other site receives this notification as a comment with the type comment_type = trackback.

To send a Trackback, you can do it from the post editing page.

How Trackbacks and Pingbacks Differ?

From the above description, it is evident that both essentially do the same thing, but they still have several differences:

  1. Trackbacks are sent manually, while Pingbacks are sent automatically.

  2. Pingbacks do not send any content, whereas trackbacks are accompanied by an excerpt from the content.

  3. Different technologies are used for sending and receiving requests.

Configuring Trackbacks and Pingbacks?

In WP, you can enable/disable receiving/sending notifications on the Settings → Discussion page:

How Notifications (Pings) Work

There are two possible scenarios here:

1) Your site sends a ping request to another site

Pingback

Upon post publication, WP checks whether it needs to notify the sites mentioned in the post. That is, it checks if the default_pingback_flag option is enabled. If it is, it gathers links from the post and performs the following operations for each link:

  • It visits the link and checks for x-pingback: in the HTTP header. If it's present, it sends a notification to the URL specified in this header. The notification is an HTTP request with POST parameters to the specified URL.

    For WP, this URL points to the xmlrpc.php file. There, the extensive wp_xmlrpc_server{} class operates. The class separates requests that require authentication from those that do not. For such ping notifications, no authentication is required. Therefore, for example, if you disable xmlrpc via a filter:

    // Disables XML-RPC methods that require authentication
    add_filter( 'xmlrpc_enabled', '__return_false' );

    Trackbacks will still work!

  • If the x-pingback: header is not found, WP continues searching: it retrieves the HTML and looks for the rel="pingback" meta tag. If found, it does the same: sends a notification to the URL specified in the meta tag.

    By default, WP does not add this meta tag to the HEAD of the theme; usually, the theme adds it automatically. So, it needs to be added manually if necessary. It looks like this:

    <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">

Trackback

Upon post publication/update, the field trackback_url is checked:

If specified, it will be added to the to_ping field of the wp_posts table, which stores links to sites that need to be notified. The notification operation will occur later via cron read below. In short, the function do_trackbacks() will be triggered for each post.

2) Your site receives a ping request from another site

In the site settings (image above), sending notifications from your site and receiving notifications are separate options, meaning they are independent of each other and work on their own. That is, you can disable pings but leave trackbacks, or vice versa.

Pingback

Notifications come to the /xmlrpc.php file, where they are processed:

  • First, it checks the default_ping_status option - whether receiving notifications on the site is allowed at all.

  • Then, it finds the mentioned post and checks if notifications are open for it. This is done by the get_default_comment_status() function, specifically checking the value of the ping_status field of the post, which can be: open or closed.

  • If notifications are open, a comment with the type comment_type = 'pingback' is published for the specified post.

Trackback

The file /wp-trackback.php processes trackbacks.

A trackback comment has the type comment_type = 'trackback'.

The Purpose of the xmlrpc.php File

The xmlrpc.php file allows remote management of the site. I don't know if anyone uses it today.

For such management, there are special programs, for example, "Windows Live Writer," "Open Live Writer," and others. Using them, you can remotely publish posts and upload photos to the site. For example, you can publish posts on various sites from your computer (you need to know the login and password of a user with publishing rights).

Spam Through Notifications (Pings)

Since sending notifications only requires sending a request, spammers love this. It is very simple: take the domain of the site, append /xmlrpc.php to it, and send the prepared POST request. Moreover, the request will be the same for all sites, making it very easy to spam in this way.

So, if notifications with a link to the site of the sender are displayed in the comments on your site, the spammer will receive a backlink to their site. For this reason, many people disable notifications.

However, such disabling only stops processing requests. But if spammers start sending numerous requests, it can affect the server (create unnecessary load), resulting in something like an unintentional DDoS attack. However, as far as I know, this is rare.

In the event of such a load from spammers, you can completely close access to the /xmlrpc.php file via the .htaccess file.

# Close access to the file
<FilesMatch "xmlrpc.php">
Order Deny,Allow
Deny from all
</FilesMatch>

For nginx, this is done as follows:

location = /xmlrpc.php {
   deny all;
}

Such closure completely disables all notification capabilities; there is nothing more to do.

I emphasize once again! The following disabling of xmlrpc does not disable notification processing but disables the ability to manage the site remotely!

// Disables XML-RPC methods that require authentication
add_filter( 'xmlrpc_enabled', '__return_false' );

Notifications for Post Types

For pages (post type page), notification processing from other sites is completely disabled in the code.

For other post types, notifications can be enabled or disabled separately on the post editing page:

When registering a post type, in the supports parameter of the register_post_type() function, you need to specify support for trackbacks:

'supports' => array( 'title', 'editor', 'trackbacks' ),

Otherwise, the ping_status for new posts will default to closed, and notifications with a link to this post type will not be processed.

Should You Disable Pings in WordPress

I think you shouldn't, it's still interesting and may even be useful to know who is referencing your site's articles and which articles they are referencing.

However, it is essential to check if there is a backlink to your site in the referenced article mentioned in the notification. By default, WordPress does not do this, and it's a shame!

To enable such checking, you can install my anti-spam plugin Kama Spamblock

Or use the following code in the functions.php file:

## Check the link to this site when processing trackbacks (pings)
add_action( 'preprocess_comment', 'trackbacks_check_protect', 0 );

function trackbacks_check_protect( $commentdata ){

   if( ! in_array( $commentdata['comment_type'], [ 'trackback', 'pingback' ] ) ){
	  return;
   }

   $external_html = wp_remote_retrieve_body( wp_remote_get( $commentdata['comment_author_url'] ) );

   // Stop if there is no link to us
   if( ! preg_match('~<a[^>]+href=[\'"](https?:)?//'. preg_quote( parse_url( home_url(), PHP_URL_HOST ) ) .'~si', $external_html) ){
	  die( 'no backlink...' );
   }

}

How it works (step by step in the code)

Pings from your site's articles are sent by the cron, the scheme is as follows:

Step 1 (creating a cron task)

The function _publish_post_hook() is hooked to the publish_post hook:

add_action( 'publish_post', '_publish_post_hook', 5, 1 );

Thus, when a post is published/updated, the function _publish_post_hook() is triggered, which adds special meta-fields and a cron task:

...
	if ( get_option('default_pingback_flag') ) {
		add_post_meta( $post_id, '_pingme', '1' );
	}
	add_post_meta( $post_id, '_encloseme', '1' );

	if ( ! wp_next_scheduled( 'do_pings' ) ) {
		wp_schedule_single_event( time(), 'do_pings' );
	}
...
Step 2 (cron)

Next, when the cron task is executed, the function do_all_pings() is triggered:

add_action( 'do_pings', 'do_all_pings', 10, 1 );

This function triggers the do_all_pings hook, to which by default 4 functions are attached:

add_action( 'do_all_pings', 'do_all_pingbacks', 10, 0 );
add_action( 'do_all_pings', 'do_all_enclosures', 10, 0 );
add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 );
add_action( 'do_all_pings', 'generic_ping', 10, 0 );
do_all_pingbacks() Performs all pingbacks.
do_all_enclosures() Performs all enclosures.
do_all_trackbacks() Performs all trackbacks.
generic_ping() Sends pings to all of the ping site services.

Since WP 5.6, the function code has been split into these 4 functions. Before that, the code performed many different operations at once. The old description of the code (which shows what each function above does):

  1. Gathers all posts with set meta-fields and triggers the function for each of them:

    <enclosure url="http://example.com/file.mp3" length="123456789" type="audio/mpeg" />
  2. Also gathers all published posts status=publish AND to_ping != '' (usually, to_ping contains links from the content that need to be notified that they were used in the post) and triggers the function for each post:

  3. Sends pings to sites that need to be pinged (specified in the settings). The function responsible for this operation is generic_ping().

How to disable/prohibit XML-RPC requests

First of all, I would like to reiterate that the file xmlrpc.php handles requests that do not require authorization (pings) and those that do (publishing content on the site).

Therefore, it is not recommended to completely disable this file, only the part of the logic that requires authorization can be disabled. This can be done with one line using the xmlrpc_enabled hook:

// Disables XML-RPC methods that require authorization
add_filter( 'xmlrpc_enabled', '__return_false' );