How To Implement Pingback
on....because it drove me insane when I was writing the new Four Island. There didn't appear to be any information on it anywhere. Or at least, any complete information.
Finally, however, I found the Pingback Specification, which, at the bottom of the page, includes a nice little step-through of Pingback at work.
To summarize, there are two parts of the Pingback process. The server and the client. The client sends Pingbacks and the server receives them.
When writing a blog post, the client should scan it for external links and, if any are found, attempt to read the pages they link to. If they contain a
<LINK REL="pingback" HREF="....">
tag, then that means that the page in question supports pingback. So, if one is found, the client uses XML-RPC to connect to the server URL specified in the HREF attribute of the tag mentioned above. Then, it calls the methodpingback.ping
with two parameters, the first being the URL of the local post, the second being the URL of the post being linked to. From there, it's the server's job.When the server receives the Pingback, it checks to see the both URLs actually exist and that the linking blog post actually links to the second URL. If it does, the server adds a comment to the blog post in question saying that it's been linked to and providing a link to the linking blog post.
Ok, that probably sounded complicated. It is, a little. So, that's why we're going to do this step by step, starting with the client. Let's examine the specification process again:
- First, the client scans the post being submitted for external links.
We can accomplish this with a simple screen scraper which is a script that combs through an HTML page and picks up useful information. We'll be using a simple one to pick up all of the links, and then to sift out the ones that aren't external: (Note that I am assuming that the contents of the post are located in $postText)
preg_match_all('|<a\s[^>]*href="([^"]+)"|i', $postText, $matches); foreach ($matches[1] as $link) { if ($all_links[$link]) { continue; } $all_links[$link] = true; if (preg_match('/^https{0,1}:/i', $link)) { // We've got an external link! } }
- Then, the client attempts to download any links it finds.
This is easy as well. For this I'll be using cURL. Note that this code goes in place of the comment
// We've got an external link!
.$c = curl_init(); curl_setopt($c, CURLOPT_URL, $link); curl_setopt($c, CURLOPT_RETURNTRANSFER, true); curl_setopt($c, CURLOPT_HEADER, false); $page_data = curl_exec($c); curl_close($c);
- If they contain a
<LINK REL="pingback" HREF="....">
tag, then that means that the page in question supports pingback.Checking for the tag is again, easy. We do it with a simple regular expression:
if (preg_match('/<LINK REL="pingback" HREF="([^"]+)">/i', $page_data, $server)) { // It has the <LINK> tag! }
- Finally, the client sends an XML-RPC request to the server located in the tag.
For this, we need XML-RPC for PHP. It's a very easy to use XML-RPC library. Somewhere in your page, you need to include it's client libraries (in lib/xmlrpc.inc). When that's done, we have our client-side Pingback code:
$client = new xmlrpc_client($server[1]); $msg = new xmlrpcmsg("pingback.ping", array( new xmlrpcval(PERMALINK, 'string'), new xmlrpcval($link, 'string'))); $client->send($msg);
Make sure to replace PERMALINK with some method of generating the URL of the current post.
That's the client-side part of Pingback, the sending side. Now for the server side.
Before we begin, we have to remember that the client finds the server by looking for a tag in the blog post's page header. You should include this now into your global header file:
<LINK REL="pingback" HREF="http://yourdomain.com/xmlrpc.php">
Now it's time to make that xmlrpc.php.
- The server has to be able to receive XML-RPC requests. Because of this, it needs to include XML-RPC for PHP's server-side library (lib/xmlrpcs.inc) as well as the client-side. Then, it needs to define the
pingback.ping
method.$s = new xmlrpc_server(array( "pingback.ping" => array("function" => "ping"))); function ping($xmlrpcmsg) { }
- The server then needs to verify that both URLs actually exist.
How to implement this part is up to you as I'm not writing your entire blog, but the code to extract the URLs passed as arguments to the pingback.ping method is as follows:
$from = $xmlrpcmsg->getParam(0)->scalarVal(); $to = $xmlrpcmsg->getParam(1)->scalarVal();
- Finally, the server posts a comment to the blog post in question notifying people that someone has sent it a pingback.
Once again, this is mostly up to you as I don't know the specifics of your blog. However, when the comment has been successfully added, the XML-RPC server needs to return with a response to the client:
return new xmlrpcresp(new xmlrpcval( "YAY! Your Pingback has been registered!", "string"));
YAY! You're Pingback implementation is nearly done! There's only a little bit left now. With the server, it has to response with an appropriate error if there's some problem such as the source URL not existing. Here's a list of them:
- From doesn't actually link to To:
return new xmlrpcresp(0, 17, "Source uri does have link to target uri");
- To URL doesn't exist:
return new xmlrpcresp(0, 32, "Target uri does not exist");
- To URL doesn't support pingback:
return new xmlrpcresp(0, 33, "Target uri cannot be used as target");
I really hope someone finds this tutorial useful because when I wanted to implement Pingback support on my blog, as I said before, it was very difficult to find any good information about it.
EDIT: Wow. One of the most popular posts on the site and it was posted, of all days, June 17th. Very strange.
Comments