WordPress 404 Plugin built on Bing Wrapper
Update: We have added a link to a short youtube video on how to install the plugin. It explains each the options as well.
Over at my personal blog, I recently posted about the new Bing Search API wrapper I wrote for Microsoft. In the post, I said that I would talk about some of the uses of the wrapper. This post is the the first of two I have planned.
php|architect, The Accidental Businessman and Postcards From My Life are all three WordPress blogs. Personally, I have three others as well because it’s just so easy to setup and get running that I really have to have some serious requirements that absolutely cannot be met within WordPress to consider another option.
These days, being more of a market-teer than a code monkey, I worry about thinks like my site being “sticky”, people being able to find my site, and generally the things that programmers laugh at but are important to the rest of us that build out sites.
One of the things I’ve always hated about WordPress is the stock 404 error message. Out of the box, WordPress just tells users “I’m sorry, I can’t find what you are looking for.” Granted it is better than the stock Apache 404 page but it isn’t much more helpful. Having just finished working on the Bing Search Wrapper for PHP, the best use case I could think of for the wrapper was to solve this particular problem. This is how I helped Microsoft’s Interoperability team to put together the Bing 404 Plugin for WordPress.
Quick Start
Ok, if you are in a hurry you can either watch this video or follow the 4 steps below.
- Install the Bing 404 Plugin from the wordpres.org repository
- Get a Bing App ID
- Configure the plugin and give it your App Id
- Test it out by trying to go to an invalid URL on your blog.
All told, it should take you about 5 minutes, 2 if yo have the App Id already.
All the gory details
The goal of the plugin was to give useful 404 page. However, the definition of useful is different for different people. To be specific, I wanted to see if we could find what the user was looking for on the site and if not, then at the very least I wanted to suggest a few of the most popular articles on the blog. To further narrow the search, I wanted to be able to plug in “standard” search terms for which to search.
Abbreviated Workflow
Get the URL, strip off the domain. Everything else is considered the query.
If the url that led them to the 404 page is http://phparch.com/bing-rocks/
then I want to strip off http://phparch.com/
and be left with /bing-rocks/
. Granted it is not very useful by itself but it gives us a hint at what the user was looking for.
Get the standard search terms.
Just in case the query string doesn’t return enough results (or any at all) we have the option of specifying some generic terms. In the case of phparch.com
, we specify php, because that is what most people will be looking for here.
Run both queries, combine the arrays and pop off the top x results
In the setup, you can specify how many entries you want displayed on your page. If the query using the user’s original query string returns enough results, we use only those. However, if that doesn’t return enough to flesh out the entire x, the results of the second query to Bing, using the specified default keywords, will round out the list. Both queries honor the localized domain option so if you put in your domain name there, it will limit the results of both queries to results from your domain.
Code
Counting comments and all, the entire plugin (sans the API library) is 500+ lines. I am not going to paste them all in here but I will show the heart of the plugin and a couple of the bits of magic that allow it to work.
/**
* perform the actual search
*
* This is the heart of the plugin. This function is called from the 404.php
* template. No parameters are necessary. It returns the properly formatted
* HTML to either display a list of potential links or an error message.
*
* @return string html to output.
*/
function bing404_search_bing() {
include 'Msft/Exception.php';
include 'Msft/Bing/Exception.php';
include 'Msft/Bing/Search/Exception.php';
include 'Msft/Bing/Search.php';
/*
* Create the Bing Search object.
*/
$search = new Msft_Bing_Search( get_option( 'b4_apiKey' ) );
$search->setWebCount( get_option( 'b4_count' ) );
$search->setSource( 'Web' );
$search->setAdult( get_option( 'b4_adult' ) );
/*
* If requested, make this a site specific search
*/
if ( $localsite = get_option( 'b4_site' ) ) {
$search->setSite( $localsite );
}
/*
* If set, set the local market
*/
$localMarket = get_option( 'b4_market' );
if ( !empty( $localMarket ) && $localMarket != 'NONE' ) {
$search->setMarket( $localMarket );
}
/*
* Build the query to execute
*/
$queryTerms = str_replace( '/', ' ', html_entity_decode( urldecode( $_SERVER['REQUEST_URI'] ) ) );
$localQuery = get_option( 'b4_query' );
/*
* Try to pull the site-wide from cache. Otherwise, pull from bing
*/
$cacheKey = md5( $localQuery );
$raw = wp_cache_get( $cacheKey );
if ( $raw === false ) {
$search->setQuery( $localQuery );
$raw = $search->search();
wp_cache_set( $cacheKey, $raw,'',86400 );
}
$siteResults = json_decode( $raw );
/*
* Try to pull the regular query from cache. Otherwise, pull from bing
*/
$localQuery = trim( $queryTerms );
$cacheKey = md5( $localQuery );
$raw = wp_cache_get( $cacheKey );
if ( $raw === false ) {
$search->setQuery( $localQuery );
$raw = $search->search();
wp_cache_set( $cacheKey, $raw,'',86400 );
}
$results = json_decode( $raw );
/*
* Now merge the resultsets
*/
$finalResults = bing404_merge_results( $results, $siteResults );
/*
* Finally, prepare the output
*/
$output = '
';
foreach ( $finalResults as $value ) {
$output .= sprintf( '
- %s
', $value->Url, $value->Title );
}
$output .= '
';
$bing404_dirname = WP_PLUGIN_URL . '/' . ( basename( dirname( __FILE__ ) ) );
switch ( get_option( 'b4_poweredByBing' ) ) {
case 'Banner':
$output .= '
';
break;
case 'Text':
$output .= '
Powered by Bing
';
break;
case 'Off':
break;
}
return $output;
A few of the code highlights:
- Line 19 – Create the Bing search object.
- Line 27 – If you have specified a local domain, localize the search to only that domain.
- Line 42 – Get the query terms to search for. Note, 2 queries are actually made.
- Line 48 – Execute the query pulling back the most popular items for the blog optionally using your specified query term.
- Line 59 – Execute the query trying to find the page for which the user was actually looking
As I hope you can see, using the Bing Search wrapper makes this code very simple. The bulk of this method is simply parameter checking and setting defaults.
A bit of WordPress magic
Intercepting the 404 page on WordPress took a bit of digging. It turns out however to be simple, once you find the right hook.
/**
* Register the 404 hook.
*
* Only register the 404 hook if the user wants to use our included template.
*/
if ( get_option( 'b4_useIncludedTemplate' ) ) {
add_action( '404_template','bing404_use_included_template_hook' );
}
/**
* include the standard template.
*
* If the user has opted to use the included template then include it for use.
*/
function bing404_use_included_template_hook() {
include dirname( __FILE__ ). '/default-404.php';
exit;
}
The plugin works in one of two ways.
- The plugin includes a 404 page. If you check the option, this will be the one that is used. This should work in 75%-80% of the cases and requires no code changes to get the plugin working.
- If you want to roll your own, include this line in your template’s 404.php.
<?php if(function_exists('bing404_search_bing')) { echo bing404_search_bing(); } ?>
Either way works the same, a call is made to bing404_search_bing()
and the results are displayed.
Conclusion
That is all there is to it. There are several other options for setting region localization, safe search and other options. All in all though, the Bing Search Wrapper allowed me to put this plugin together in a couple of hours. It took care of the details of the search and allowed me to worry about navigating the WordPress API minefield.
Leave a comment
Use the form below to leave a comment:
Responses and Pingbacks
June 4th, 2010 at 12:16 pm
[…] Evans has posted a tutorial on how to get started with the plugin on php|architect. His article discusses the details about how the plugin is […]
June 4th, 2010 at 1:13 pm
[…] Library for PHP project and was created in conjunction with PHP guru Cal Evans, who has posted a tutorial and details about the plugin on php | […]
June 4th, 2010 at 1:19 pm
Great work Cal! Thanks for posting these details as well.
Note: When I installed the plugin I was getting IO errors/file not found on three of the includes, I commented them out and it seems to work fine for me, not sure what functionality I’m missing though.
function bing404_searchBing()
{
/*
include ‘Msft/Exception.php’;
include ‘Msft/Bing/Exception.php’;
include ‘Msft/Bing/Search/Exception.php’;
*/
include ‘Msft/Bing/Search.php’;
Also,
Can you list the other values that are available in the $finalresults collection? I see Title and URL. Could you list any other values that are available? (for example, I’d love to get page description, or post date if those were avail in the results.)
Thanks again!
June 4th, 2010 at 1:41 pm
Caleb,
Strange, the Exception classes got left out of the final package. I am submitting a new package version 1.0.1 that should correct that. Sorry, not sure where it fell down. (Also not sure it installed on my blog from wordpress.org without error. will look into that too.)
I will dig up the other values for you and post them here.
=C=
June 4th, 2010 at 2:13 pm
[…] This plugin should work out-of-the-box with most themes using the included 404 template. You can also define your own to fine tune the look and feel to match your theme. Detailed tutorial on how to use the plugin is available here. […]
June 4th, 2010 at 4:56 pm
Cal – Thanks. I’m looking forward to the updates!
June 4th, 2010 at 5:39 pm
Caleb,
Version 1.0.1 is now in the WordPress.org repository and it’s fixed. Please re-try and tell me if it worked for you.
=C=
June 4th, 2010 at 5:52 pm
Cal –
Looks great. http://developingux.com/dependency-injection-solid (missing page)
I also noticed that the “Use the 404 template ” check box in the settings never stays checked for me, I’m not sure why that is.
Thanks again for putting this out there. I’m looking forward to digging in to the other values that are in the $finalresults collection.
BTW – I used the automatic update plugin and it picked up your update right ways. Very smooth process!
June 4th, 2010 at 9:39 pm
Caleb,
What version of WordPress are you using?
=C=
June 5th, 2010 at 6:35 am
[…] Evans פרסם מדריך לשילוב התוסף לוורדפרס עבור עמוד 404 עם תוצאות מתוך Bing, […]
June 5th, 2010 at 8:55 am
[…] WordPress 404 Plugin built on Bing Wrapper | php|architect (tags: php bing) […]
June 5th, 2010 at 11:28 am
[…] post from the creator of the […]
June 5th, 2010 at 11:33 am
Cal –
I’m using the latest (non-edge…) so I’m not on 3 yet. 😉
I use the automatic update plugin to keep my version up to date as often as I can… btw – I posted about my pimped out 404 here http://developingux.com/2010/06/05/bing-404-plugin-for-wordpress/
Thanks for all the work you’ve done of this!
June 7th, 2010 at 4:12 am
[…] soffre il condizionamento di una palese operazione di marketing: sempre Cal Evans ne ha registrato uno screencast esplicativo che aiuta nell’installazione. Prescindendo dall’onnipresente logo di Bing, […]
June 15th, 2010 at 5:55 pm
[…] week Cal Evans announced the release of the Bing404 Plugin for WordPress, a plugin that takes advantage of the Bing Search Library for PHP released by the Interoperability […]
June 22nd, 2010 at 12:11 pm
[…] wanted to show you this cool 404 page search plugin I found at the PHPArch […]
June 22nd, 2010 at 3:42 pm
Awesome, got it working withing 5 minutes! I used the short version of the plugin, underneath that I placed the ‘select by month’ and ‘select by category’ lists.
July 18th, 2010 at 6:24 pm
[…] wanted to show you this cool 404 page search plugin I found at the PHPArch […]
August 8th, 2010 at 9:31 pm
thank you for the information,
This was helped,
spirit! ! ! ! !
October 17th, 2010 at 4:48 pm
[…] Update: The creator of this plug-in just added a quick start video… go check it out! […]
January 7th, 2011 at 9:19 pm
Thnx phparch team