Posts Tagged ‘PHP’

AdSense Injection WordPress plugin tweaks

Thursday, July 24th, 2008

Update 7th December 2010: Use the new Ad Injection plugin for WordPress instead as it will do what these tweaks do, and more.

On this blog I use the Adsense Injection plugin to automatically add Google’s targeted AdSense adverts to my posts. The plugin is excellent and has helped to make more money for this site but there are a few tweaks that I have done.

First, I’ve made a modification so that if a individual post page is shorter than a certain number of characters then the number of adverts is limited to one.

Second, I’ve made a change so instead of looking for ‘<p’ tags to use as AdSense insertion points it looks for the full paragraph tag – ‘<p>’. The reason I did this is because I often include code in my posts in <pre> tags and the AdSense plugin code was inserting adverts in my source code snippets which looked wrong. After making this change the adverts only appear in the text of my posts.

Both sets of changes are shown in the code below. You can simply replace the ai_the_content() function in version 2.0 of the plugin with this version.

function ai_the_content($content){
  global $doing_rss;
  if(is_feed() || $doing_rss)
    return $content;
  if(strpos($content, "<!--noadsense-->") !== false) return $content;
  if(is_home() && get_option('ai_home') == "checked=on") return $content;
  if(is_page() && get_option('ai_page') == "checked=on") return $content;
  if(is_single() && get_option('ai_post') == "checked=on") return $content;
  if(is_category() && get_option('ai_cat') == "checked=on") return $content;
  if(is_archive() && get_option('ai_archive') == "checked=on") return $content;
  global $ai_adsused, $user_level;
  if(get_option('ai_betatest') == "yes" && $user_level < 8)
    return $content;
  if(get_option('ai_notme') == "yes" && $user_level > 8)
    return $content;
  # RML: backup content
  $original_content = $content;
  $numads = get_option('ai_nads');
    $numads = get_option('ai_nadspp');
  $content_hold = "";
  if(strpos($content, "<!--adsensestart-->") !== false){
    $content_hold = substr($content, 0, strpos($content, "<!--adsensestart-->"));
    $content = substr_replace($content, "", 0, strpos($content, "<!--adsensestart-->"));
  while($ai_adsused < $numads)
    $poses = array();
    $lastpos = -1;
    # RML: change <p to <p> to stop ads before <pre>
    $repchar = "<p>";
    if(strpos($content, "<p>") === false)
      $repchar = "<br";
    while(strpos($content, $repchar, $lastpos+1) !== false){
      $lastpos = strpos($content, $repchar, $lastpos+1);
      $poses[] = $lastpos;
    //cut the doc in half so the ads don't go past the end of the article.  It could still happen, but what the hell
    $half = sizeof($poses);
    $adsperpost = $ai_adsused+1;
      $half = sizeof($poses)/2;
    while(sizeof($poses) > $half)
    $pickme = $poses[rand(0, sizeof($poses)-1)];
    $replacewith = ai_pickalign(get_option('ai_lra'));
    $replacewith .= ai_genadcode()."</div>";
    # RML: remove hardcoded length
    $content = substr_replace($content, $replacewith.$repchar, $pickme, strlen($repchar));
    # RML: if content is short then limit to one advert
    if(strlen($original_content) < 2500) return $content_hold.$content;
  return $content_hold.$content;

Adding ‘Related Posts’ to WordPress articles and 404 error pages

Tuesday, July 22nd, 2008

Many blogs have a list of related articles after each of their posts. I wanted something similar for my WordPress blog but found it wasn’t as easy to do as I thought it would be.

At the same time I was interested in capturing any access attempts to non-existent pages (causing a 404 error), and showing a list of suggested links. This is something that is useful to do to turn people who get 404 errors into readers of your blog.

I first looked at the WASABI related post plugin. It did what I wanted with the related entries but it requires you to add a tag to each post where you want the related entries to appear. There is also a version of the plugin which can generate sensible links for any 404 errors. It does this by turning the incorrect URL into a list of terms which are then used to find related posts.

The next plugin that I read about was called ‘Aizattos Related Posts’. This plugin was originally based on WASABI but has evolved since. It inserts related links without needed to add any special tags to the posts. A lot of good feedback was given about this plugin but it seems that the author has removed it from the original download site. Fortunately someone has re-posted this plugin to this site.

I therefore have what I need in two separate plugins. I installed the Aizattos Related Posts plugins and then created a modified version of the WASABI 404 handling code. The 404 handler is in one function ‘related_posts_404’. Below is the modified version of the WASABI code which will work with the Aizattos Related Posts plugin. As well as showing the related links it also shows an extract from the post page. Just put this function in the Aizattos Related Posts plugin PHP file.

function related_posts_404($limit=5, $len=50,
	$before_title = '', $after_title = '',
	$before_post = '', $after_post = '',
	$show_pass_post = false, $show_excerpt = true) {
    global $wpdb, $post;
    $before_title   = '<span class="aizatto_related_posts_title" >';
    $after_title    = '</span>';
    $before_excerpt = '<div class="aizatto_related_posts_excerpt">';
    $after_excerpt  = '</div><p></p>';
    $before_related = '<li>';
    $after_related  = '</li>';
    $search_term = $_SERVER['REQUEST_URI'];
    $search = array ('@[/]+@', '@(..*)@', '@[-]+@', '@[_]+@', '@[s]+@', '@archives@','@(?.*)@','/d/');
    $replace = array (' ', '', ' ', ' ', ' ', '', '','');
    $search_term = preg_replace($search, $replace, $search_term);
    $search_term = trim($search_term);
    $terms = $search_term;
    $time_difference = get_settings('gmt_offset');
    $now = gmdate("Y-m-d H:i:s",(time()+($time_difference*3600)));
    // Primary SQL query
    $sql = "SELECT ID, post_title, post_content,"
         . "MATCH (post_name, post_content) "
         . "AGAINST ('$terms') AS score "
         . "FROM $wpdb->posts WHERE "
         . "MATCH (post_name, post_content) "
         . "AGAINST ('$terms') "
		 . "AND post_date <= '$now' "
         . "AND (post_status IN ( 'publish',  'static' ) && ID != '$post->ID') ";
    if ($show_pass_post=='false') { $sql .= "AND post_password ='' "; }
    $sql .= "ORDER BY score DESC LIMIT $limit";
    $results = $wpdb->get_results($sql);
    $output = '';
    if ($results) {
        foreach ($results as $result) {
            $title = stripslashes(apply_filters('the_title', $result->post_title));
            $permalink = get_permalink($result->ID);
            $output .= $before_title
                .'<a href="'. $permalink .'" rel="bookmark" title="Permanent Link: '
		. $title . '">'
		. $title . '</a>'
		. $after_title;
            if ($show_excerpt=='true') {
                $post_content = strip_tags($result->post_content);
                $post_content = stripslashes($post_content);
                $words=split(" ",$post_content);
                $post_strip = join(" ", array_slice($words,0,$len));
                $output .= $before_excerpt . $post_strip . $after_excerpt;
        echo $output;
    } else {
        echo $before_title.'Fuzzy ...'.$after_title;

Although no code modifications are needed for the related links in your normal posts, you will have to make a modification to your theme’s 404 page if you want related links for any ‘Not Found’ errors. In blue below is the modification I made to my 404.php for the default theme.

<?php get_header(); ?>
	<div id="content" class="narrowcolumn">
		<h2 class="center">Error 404 - Not Found</h2>
		<p>We're sorry but the page you are looking
		for isn't at this location. Were you perhaps
		looking for one of these articles?</p>
		<?php related_posts_404(); ?>
<?php get_sidebar(); ?>
<?php get_footer(); ?>

Using a common form mail script for multiple websites

Thursday, June 12th, 2008

I run a number of different websites. Most of them have a contact page which is powered by a form mail script. Until recently each of these websites used an almost identical copy of the same form mail script – I use PHPFormMail but you could adapt this solution for other form mail scripts. Each contact us page has very similar HTML in it. I wanted a way of sharing a common form script and wanted to avoid the duplicated HTML without losing the individual styling of each contact us page.

For this to work for you you’ll need:

  1. All your websites to be on a single host. The code on this page is what I used on my 1and1 hosting account, but the solution should be similar for other web hosts.
  2. To be allowed to use .htaccess files.
  3. Have enough technical knowledge to understand what I’m saying and to customise this for your own site. I’ll give you enough information to implement this, but only if you have enough understanding of knowledge of HTML, PHP and .htaccess files.

On my web server I use one directory for each domain. I map my domain names to directories like this:    ->   /advancedhtml-web/    ->   /reviewmylife-web/ ->   /interrail-web/

You’ll note that it is not possible to access the root of my web hosting account ‘/’ from the web.

I’ve added a common directory to store the form mail script and the form HTML. This directory is not accessible from any web address. I’ll explain the contents of the later on.


The formmail.php is my usual PHPFormMail script.

I then set up a global variable in a .htaccess file in the root of my web server. This .htaccess file is not accessible to any of my website visitors but it is processed.

The contents of the .htaccess look like the below snippet. You’ll need to replace the /kunden… part with the path of your own common directory.

SetEnv COMMON_PATH /kunden/homepages/25/dxxxxxxx/htdocs/common

If you don’t know what your web server path looks like create a file called ‘test.php’ with the following contents – <?PHP phpinfo(); ?> and then load file from your browser. You can use this test.php to verify that your new environmental variable is present. Below is my
<form method="post" action="commonformmail.php">
<table width="80%" cellpadding="0" cellspacing="0">
  <td><font face="arial">Name</font></td>
  <td><p><input type="text" name="name"></p></td>
  <td><font face="arial">Email</font></td>
  <td><p><input type="text" name="email"></p></td>
  <td><font face="arial">Subject</font></td>
  <td><p><input type="text" name="subject"></p></td>
  <td><font face="arial">Message</font></td>
  <td><p><textarea name="message" rows="15" cols="45"></textarea></p></td>
  <td><p><input type="submit" name="Submit" value="Send"></p></td>
<input type="hidden" name="redirect" value="thanks.htm"></p>
<input type="hidden" name="recipient" value="commonmail">
print "<input type="hidden" name="referer" value="" . $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] . "">n";
<input type="hidden" name="env_report"

Look at the PHPFormMail documentation for information about the redirect, recipient and env_report fields. You’ll note that I have added a referer field so that I’ll know which of my websites this form was posted from. The value of the recipient field has to be present in the PHPFormMail $recipient_array. If your contact page is a .html rather than a .php you’ll have to make sure that you can use PHP in HTML files.

In your contact us/email HTML file you can include the form like this:

include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/');

The final part of the solution is to add a commonformmail.php to each of your individual website directories. It will look like this and just includes the shared form mail script.

include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/formmail.php');

From now on you can change the behaviour and look of all your website forms from one place.

Hidden field spam trap for PHPFormMail

Friday, May 30th, 2008

If you have a form mail script on your website you may find that you reguarly recieve automated spam to your email account. Even worse it is possible that spammers may use your form mail script to send spam to other people.

One well known method of significantly reducing (or even stopping) spam without having any impact on your website visitor is to add a hidden field to your form. Real human visitors will not see this field and leave it blank. Automated spam scripts will fill it in. You can therefore easily tag or reject any emails that have this hidden field filled in. This method of stopping spam has been talked about on many other blogs – for example on modernblue, and horizonweb.

I’m not going to explain the technique in depth – you can read about it on the above links. I’m just going to show you how to apply this form of spam protection if you are using the PHPFormMail script.

You will need to add an entry to your style sheet to hide the spam trapping field. I use two fields with similar names – one to display a field as normal and one to hide a field. I suggest you use different names to me to make it less likely that spam scripts will work around this trap.

div#formstyle1 { display: inline; }
div#formstyle2 { display: none; visibility: hidden; }

In blue you can see where I have added the spam trap field next to the usual message field.

<td><font face="arial">Message</font></td>
<div id="formstyle1">
  <textarea name="message" rows="10" cols="40"></textarea>
<div id="formstyle2">
  <p>Please leave the following field blank: </p><input type="text" name="spamtrap">

There are two things I can do in the PHPFormMail script if spam is detected (i.e. if the spamtrap field is not empty). I can either tag the email with a [spam?] tag, or I can reject it.

I have commented out the ’email rejection’ lines so the below modification will tag the email. If you want to enable the ’email rejection’ then you can simply uncomment the relevant two lines.

function send_mail()
	global $form, $invis_array, $valid_env, $fieldname_lookup, $errors;
	$email_replace_array = "r|n|to:|cc:|bcc:";
	### Anti-spam: start - reject email ###
	#if (($form['spamtrap']) != '')
	#	return true;
	### Anti-spam: end                  ###
	if (!isset($form['subject']))
			$form['subject'] = 'WWW Form Submission';
	if (isset($form['subject_prefix']))
			$form['subject'] = $form['subject_prefix'] . $form['subject'];
	if (!isset($form['email']))
			$form['email'] = '';
	### Anti-spam: start - tag email ###
	if (($form['spamtrap']) !='' )
			$form['subject'] = '[SPAM?]: ' . $form['subject'];
	### Anti-spam: end               ###
	switch ($form['mail_newline']) {
		case 2:		$mail_newline = "r";
		case 3:		$mail_newline = "rn";

Since applying these changes to my various sites, the script has caught all the formmail spam that I was previously getting.

If you do decide to adopt these changes then make sure you test them carefully – first try testing with the spam trap field visible, before making it invisible. I’d also suggest that you adjust the field and style sheet names to make it harder for spammers to bypass.

Improved KML embedding of Google Maps into web pages

Sunday, December 23rd, 2007

I’ve been further improving the code that I described in my previous in my previous post – ‘Adding KML Google Maps overlays to WordPress posts‘.

I’ve made these changes:

  1. Option to specify a latitude / longitude / zoom for the map. This allows you to have one map and then show lots of different views of it
  2. The code is now implemented as a function rather than as included PHP. This means that the full map can be included in one line of PHP and the code only has to be included once in each page.

As before you can include a whole map which will be automatically centred and zoomed for you. The require_once is only needed once on each page, but no harm will come to you if it is included more than once. Only one argument is needed – the full URL to the KML file. A width / height can be included if you want.


In the require_once you can either include an absolute path or a relative path.

View Larger Map
The new options allow you to specify the latitude, longitude and zoom values. When you specify these values you also have to specify the width / height of the map. The argument list is:

  1. Full URL of KML – note this is the full URL not a relative one
  2. Width of map – in pixels
  3. Height of map – in pixels
  4. Latitude
  5. Longitude
  6. Zoom
	450, 400, "51.515339", "-0.054374", 15);

View Larger Map
To get the latitude / longitude / zoom values view your KML file in Google Maps. Click on ‘Link to this page’ as described in the previous post. Alter the zoom and position of the map so it shows that you want. Then copy the latitude / longitude / zoom values from the HTML box. The latitude / longitude are the values in the ‘ll’ parameter (latitude is first). The zoom is the ‘z’ parameter.

So if we are looking at the following page in Google Maps.

Getting latitude, longitude, and zoom values from Google Maps

The latitude is 51.49966, the longitude is -0.053108 and the zoom is 16.

Here are the three files you’ll need.


You can see a demonstration of these scripts at Here I have one KML file for my whole walking route, but I include multiple zoomed-in views of the map so I can describe the route in small sections.

For these scripts to work they’ll need to be interpreted as PHP4 rather than PHP5. If your web host is interpreting PHP files as PHP5 by default (which more and more of them are) simply put these PHP files in a separate directory and add a .htaccess with the following contents to that same directory.

# Treat files in this directory as PHP4
AddType x-mapp-php4 .php

Adding KML Google Maps overlays to WordPress posts

Thursday, December 20th, 2007

Embedding basic KML Maps into your blog post

There is an easy way to include Google Maps KML overlays in your WordPress blog if you are willing to have all the size and style information hardcoded into each post. All you have to do is to go to type the KML location into the search box and then click on ‘Link to this page’.

Embedding KML into your WordPress blog using Google Maps

You can then add the HTML into your blog post by copy / pasting it from the second text box.

HTML for embedding Google Maps in a WordPress blog post

Google make it easy to change simple settings such as the map size by following the ‘Customise…’ link. Below is what the actual embedded map would look like. Handily the map is automatically zoomed into whatever data is in your KML file – In this example we’re looking at a walking track across London.

View Larger Map

This is great for if you want to add the odd maps to your blog, or if you don’t believe you’ll need to alter the style later on. The problem comes if you want to separate all the style information out of the embedded map iframe.

The problem with the Google Maps HTML generator

Imagine if you had a site with dozens or even hundreds of embedded KML files. One day in the future you decide that you want to change the style and look of all the maps. Maybe you want to change the size, add some extra links under each map, or add new features from the Google Maps API to each map. Below is what the actual HTML code embedding this KML file looks like. As you can see it is pretty ugly and it wouldn’t be fun to edit dozens / hundreds of these to change the way they look.

<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src=";hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;;ie=UTF8&amp;ll=51.497414,-0.054315&amp;spn=0.044967,0.044325&amp;om=0&amp;output=embed&amp;s=AARTsJozG9M05ndgSB8zlZU1Qavi7qH_cw"></iframe><br /><small><a href=";hl=en&amp;geocode=&amp;time=&amp;date=&amp;ttype=&amp;;ie=UTF8&amp;ll=51.497414,-0.054315&amp;spn=0.044967,0.044325&amp;om=0&amp;source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small>

Under normal circumstances it would be easy to separate out this code into a different file and pass in the KML file URL as a parameter. The problem is that Google have added a security parameter to the argument list (s=AARTsJozG9M05ndgSB8zlZU1Qavi7qH_cw in this case) which locks in the KML URL. You can edit the style parameters (width / height etc) but you can’t change the URL. If you do you get an error saying “Forbidden Your client does not have permission to get URL…”. Google have done this so they can keep a track of how much load individual sites are putting on their server. Unfortunately it means that if you want to use a new KML you have to use the Google Maps site to generate the HTML.

A solution and another problem for WordPress bloggers

There is a way around this, and that is to use the Google Maps API. This will allow you to programatically include as many KMLs as you want without using Google’s HTML generator. To use the API you have to sign up for a Google Maps API Key. There is one final problem – each key can only be used from one individual web directory. This can be a big problem if you are a WordPress user. Bill from the techrageo blog has already written about this so I won’t repeat what he has said. You can read his blog and look at his solution for yourself.

There are however some problems with his solution.

  1. You would need to create a new HTML file for each Google Map you are embedding.
  2. The width and height of the iframe have to be embedded in each map in each blog post or HTML page that you use it on.
  3. The JavaScript in his solution doesn’t quite do what I want.

Here is my solution which is inspired by his but solves these three issues. Please note that as with Bill’s solution this will require some programming knowledge. You will need to make modifications to my scripts to get them to work on your site.

To embed a KML file with my solution all you have to do is include a small section of PHP in your blog post. To allow me to embed PHP in my blog posts I’ve installed the Exec-PHP plugin. This is what the PHP looks like.


You must set the $mapxml variable which points to your KML file – it has to be the full URL, not a relative one. You then load the mapiframe.php file with the ‘require’ command. Optionally you can set a $width and a $height variable for the width/height in pixels, but this will re-introduce problem number 2. If you don’t set these values then default sizes (which you can change) will be used.

Embedding the KML with this PHP means that your blog posts now don’t contain any formatting infomation for the maps. All the formatting can be controlled from the following common scripts.

This is what your mapiframe.php looks like, it contains the common iframe information. You will probably need to fix the link to the loadmap.php file for your own web server.

Include a KML on WordPress Blog
See for details.
if (!isset($mapxml))
	print "ERROR: Missing mapxml";
if (!isset($width))
	$width = "450";
if (!isset($height))
	$height = "450";
$mapxml = urlencode($mapxml);
print <<<ENDHTML
<iframe width="$width" height="$height" scrolling="no"
frameborder="0" marginheight="0" marginwidth="0"
If you see this, your browser doesn't support iframes.
Please upgrade to a more recent browser.</iframe><br /><small>
<a href=";hl=en&amp;q=$mapxml&amp;ie=UTF8&amp;om=1&amp;source=embed"
style="color:#0000FF;text-align:left">View Larger Map</a></small>

Here is the code for loadmap.php. You’ll need to replace the Google Maps API key with your own one.

Include a KML on WordPress Blog
See for details.
Remember to replace the Google API key with your
own one or this script won't work!
if (!isset($mapxml))
	print "ERROR: Missing mapxml";
if (!isset($width))
	$width = "450";
if (!isset($height))
	$height = "450";
print <<<ENDHTML
  <title>Google Map Loader - $mapxml</title>
  <script src="" type="text/javascript"></script>
  <script src="googlemaploader.js"></script>
<body onload="initialize()" onunload="GUnload()">
<div id="map" style="width:$width; height:$height"></div>
<span id="mapxml" name="$mapxml"></span>
<script type="text/javascript">
 function initialize() {
  if (GBrowserIsCompatible()){

This is the googlemaploader.js file which loads the KML using the Google Maps API. It correctly sets the viewport in the map view and adds a few controls to the map.

// Script to load and position a KML/XML Google Map
// See for details.
var kml;
function LoadGoogleMap(){
  // Find mapinfo span and get name attribute
  var mapxml = document.getElementById('mapxml').getAttribute('name');
  kml = new GGeoXml(mapxml, PositionMapCallback);
function PositionMapCallback(){
  var map = new GMap2(document.getElementById("map"));
  map.addControl(new GSmallMapControl());
  map.addControl(new GMapTypeControl());

This is the final result. Yes it looks very similar to the one generated by the Google Maps HTML generator. But if I ever need to change all my embedded maps it will be really easy for me.

View Larger Map
Here are some download links for the three files you need.


You’ll need to change the Google API key in loadmap.php. You’ll also need to fix the inter-file references so all the scripts reference each other correctly. All three scripts should be placed in the directory that you created the Google API key for.

Update: Make sure you check out my Improved KML embedding of Google Maps into web pages post for some updates to these scripts.