Using the Bing API to Send Pings to Ping-O-Matic

bing basic search before

Those who use WordPress may be familiar with Ping-O-Matic for keeping blog search engines updated whenever a new post is written.

I discovered that Bing had more of my posts indexed than any other search engine. I could manually submit the link for each post to Ping-O-Matic, but that would be no fun. Instead, I decided to automate the process.

The Bing Search API is free for use up to 5000 queries per month. All you need is a Microsoft account to get a key from the Microsoft Azure Marketplace.

Once you have the key, you can set up two files: the first is called bing_basic.html, and the second is bing_basic.php. These files are a mashup from the Bing Search API guide and a function created for sending pings to Ping-O-Matic.

bing_basic.html:

<html>
	<head>
		<title>Bing Search Tester (Basic)</title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	</head>
	<body>
		<h1>Bing Search Tester (Basic)</h1>
		<form method="POST" action="bing_basic.php">
			<label for="service_op">Service Operation</label>
			<input name="service_op" type="radio" value="Web" CHECKED /> Web <input name="service_op" type="radio" value="Image" /> Image 
			<label for="query">Query</label>
			<input name="query" type="text" size="60" maxlength="60" value="" />
			
			<input name="bt_search" type="submit" value="Search" />
		</form>
		<h2>Results</h2> {RESULTS}
	</body>
</html>

bing_basic.php:

<?php

/*
--------------------------------------------
 $title contains the title of the page you're sending
 $url is the url of the page
 $debug true print out the debug and show xml call and answer
--------------------------------------------
 the output is an array with two elements:
 status: ok / ko
 msg: the text response from pingomatic
--------------------------------------------
*/
function pingomatic($title,$url,$debug=false) {
    $content='<?xml version="1.0"?>'.
        '<methodCall>'.
        ' <methodName>weblogUpdates.ping</methodName>'.
        '  <params>'.
        '   <param>'.
        '    <value>'.$title.'</value>'.
        '   </param>'.
        '  <param>'.
        '   <value>'.$url.'</value>'.
        '  </param>'.
        ' </params>'.
        '</methodCall>';

    $headers="POST / HTTP/1.0\r\n".
    "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)\r\n".
    "Host: rpc.pingomatic.com\r\n".
    "Content-Type: text/xml\r\n".
    "Content-length: ".strlen($content);

    if ($debug) nl2br($headers);

    $request=$headers."\r\n\r\n".$content;
    $response = "";
    $fs=fsockopen('rpc.pingomatic.com',80, $errno, $errstr);
    if ($fs) {
        fwrite ($fs, $request);
        while (!feof($fs)) $response .= fgets($fs);
        if ($debug) echo "<xmp>".$response."</xmp>";
        fclose ($fs);
        preg_match_all("/<(name|value|boolean|string)>(.*)<\/(name|value|boolean|string)>/U",$response,$ar, PREG_PATTERN_ORDER);
        for($i=0;$i<count($ar[2]);$i++) $ar[2][$i]= strip_tags($ar[2][$i]);
        return array('status'=> ( $ar[2][1]==1 ? 'ko' : 'ok' ), 'msg'=>$ar[2][3] );
    } else {
        if ($debug) echo "<xmp>".$errstr." (".$errno.")</xmp>";
        return array('status'=>'ko', 'msg'=>$errstr." (".$errno.")");
    }
}

/****
* Simple PHP application for using the Bing Search API
*/
$acctKey = 'YourAccountKey';
$rootUri = 'https://api.datamarket.azure.com/Bing/Search';

// Read the contents of the .html file into a string.
$contents = file_get_contents('bing_basic.html');
if ($_POST['query'])
{
// Here is where you'll process the query.
// The rest of the code samples in this tutorial are inside this conditional block.
// Encode the query and the single quotes that must surround it.
$query = urlencode("'{$_POST['query']}'");
// Get the selected service operation (Web or Image).
$serviceOp = $_POST['service_op'];
// Construct the full URI for the query.
$requestUri = "$rootUri/$serviceOp?\$format=json&Query=$query";
// Encode the credentials and create the stream context.
$auth = base64_encode("$acctKey:$acctKey");
$data = array(
'http' => array(
'request_fulluri' => true,
// ignore_errors can help debug – remove for production. This option added in PHP 5.2.10
'ignore_errors' => true,
'header' => "Authorization: Basic $auth")
);
$context = stream_context_create($data);
// Get the response from Bing.
$response = file_get_contents($requestUri, 0, $context);
// Decode the response.
$jsonObj = json_decode($response);
$resultStr = '';
// Parse each result according to its metadata type.
foreach($jsonObj->d->results as $value) {
	$pingresults = pingomatic($value->Url,$value->Description);
	//$arrlength = count($pingresults);
	//$resultStr .= $arrlength . "
\n";
	//for($x = 0; $x < $arrlength; $x++) {
	$resultStr .= $pingresults['status'] . "
\n";
	$resultStr .= $pingresults['msg'] . "
\n";
	//}
	switch ($value->__metadata->type) {
		case 'WebResult':
			$resultStr .=
				"<a href=\"{$value->Url}\">{$value->Title}</a>
{$value->Description}
";
				 break;
				 case 'ImageResult':
				 	$resultStr .=
				 		"<h4>{$value->Title} ({$value->Width}x{$value->Height}) " . "{$value->FileSize} bytes)</h4>" . "<a href=\"{$value->MediaUrl}\">" . "<img src=\"{$value->Thumbnail->MediaUrl}\"></a>
";
				 		 break;
				 	}
				 }
// Substitute the results placeholder. Ready to go.
$contents = str_replace('{RESULTS}', $resultStr, $contents);
}
echo $contents;
?>

Put both files into the same folder on your website. When you open bing_basic.php in your browser, it should look something like this:

bing basic search before

In my case, I wanted to get all the pages that Bing had indexed. I entered “site:deepinthecode.com” into the Query box and clicked Search.

After a moment, the page refreshed with the following results:

bing basic after searching

The “ok” status shows that the ping was received properly and the line below shows the status message. Following those lines are the hyperlinked post titles and the beginning of each post.

Had the ping not been received, the status would be “ko”, and the message would (hopefully) be descriptive of why the ping did not take.

The function in the PHP file can be modified for use with APIs other than the one for Ping-O-Matic, though I haven’t had time to make any changes there yet to see how well it will work with other sites.