Archive for the ‘WordPress’ Category

Ad Logger ‘click logging’ plugin for WordPress

Tuesday, October 4th, 2011

Ad Logger for WordPress is a new plugin for logging clicks on iframe adverts and other social network buttons. At the moment it can log Google AdSense / Amazon Associates adverts, and Facebook, Twitter and Google +1 social media buttons. It also has a ‘catch-all’ mode which will log any other iframe clicks.

Clicks stats in one place – You can get statistics for all these services individually but Ad Logger allows you to see all the clicks in one place. It will however give you different number; Ad Logger counts raw clicks, whereas your ad/social media provider will count valid clicks.

Raw click logs – With Ad Logger you can see the raw logs which will give you information that your ad/social media provider probably won’t allow you to see such as IP address, page referrer, and browser agent.

Reports – Ad Logger has an AJAX UI to allow you to move through the results easily. As well as seeing the log you can view reports showing the which browser, referrer, page, IP most of your clicks come from. And you can filter the results to show all the logs for a specific IP, page, iframe type, etc by clicking on the type icon, or the ⇓ arrows.

Click bombing protection – As it has access to the raw click logs Ad Logger can help you to combat intentional or accidental AdSense ‘click bombing’ by disabling adverts if too many clicks are registered. It can disable ads that you may have inserted using the Ad Injection plugin, or by dynamically hiding the div that you have put the adverts into.

Ad Logger’s main UI

Here is the main UI, from top to bottom you can see the yellow message bar which I use to highlight the latest updates, then the navigation buttons. To the right of the navigation buttons are the report links.
Next is the main log table – you can see it combines clicks from AdSense, Amazon Associates, Facebook, Twitter and Google +1. You can click on the type icon or the ⇓ arrows to filter your results.
Under the table you can set how many rows are shown at once.
Next are the boxes to select which iframes are logged.
Then the optional click blocking preferences.
Finally you can configure what information is shown in the log table, and what information gets stored to the database.

ad logger main ui

Example Ad Logger report

This is the type report and shows how many clicks occurred on each type of iframe. Here you can see that there were 27 clicks on Facebook like buttons, and 5 on Google +1.

ad logger type report

Filtered report

By clicking on any of the ‘type’ icons you can filter your results to just that type. Here I clicked on the Facebook icon and so am just seeing Facebook button clicks.

ad logger filtered

How does it work?

Ad Logger works by using JavaScript to monitor whether a click has ‘probably’ occurred. I say probably because this method isn’t 100% accurate. It is pretty good though. It notes when the mouse pointer has entered the iframe, and then listens for a ‘blur’ even which corresponds quite well to someone clicking on the ad/social button.

Ad Logger does not modify your original ad code, so hopefully won’t break your ad provider’s TOS. I can’t however guarantee this, so you have to make a judgement call as to whether you think it is safe for you to use.

Results are stored in a new table in your WordPress database. This table can be cleared of data at any time, and it will be automatically deleted if you uninstall the plugin. The plugin limits the size of the table to 100,000 rows (this will be configurable in a later release).

If you have configured click blocking then Ad Logger will use a cookie to count how many clicks have occurred. If the limit is reached then Ad Logger can then set another cookie which will prevent Ad Injection’s ads from being added to new pages, and/or it can remove the div containing the ads from the current page.

How much does it cost?

Nothing! £0, $0! You are however welcome to make a donation via the plugin UI if you find it useful. I have spent several hundred hours of my own time producing this plugin, which I have now released under a GPLv2 licence.

How do I install Ad Logger?

Ad Logger is available for free from the WordPress plugin repository.

The easiest way to install it by searching for ‘Ad Logger’ from the ‘Add New’ link in the ‘Plugins’ section of the WordPress UI.

Future planned features

Future planned features include being able to block adverts by IP address (which will work either standalone with Ad Logger, or in conjunction with Ad Injection), more awareness of other iframe types, and possibly the ability to log non-iframe events. E.g. other advertising/affiliate link clicks.

Include a different advert in each WordPress post depending on category

Sunday, September 11th, 2011

I’ve had many requestes from people who want to include different adverts on each post according to the post category. One example would be a football website that has a different post category for each team. They might want different ads to show depending on the team. E.g. ads for Liverpool F.C. might not appeal to followers of Manchester United!

With Ad Injection there is no way to achive this directly in the UI, but by adding some simple PHP code to one of the ad slots you can do this.

1. In your plugins directory create a sub-directory called ‘ad-injection-ads’. e.g. /wordpress/wp-content/plugins/ad-injection-ads/

2. Create a text files in this folder for each of the categories that you want an ad for. The text files should be named [category nicename].txt The ‘nicename’ of the category is the category name with spaces and dots converted to ‘-‘ and apostrophes removed. e.g.

Liverpool = liverpool.txt
Manchester United = manchester-united.txt
A.F.C Aldermaston = a-f-c-aldermaston.txt
Bishop’s Stortford = bishops-stortford.txt

ad injection ad code box

3. Then put the code below (from the starting <?php to the closing ?>) into one of the ad box – shown above. The code will load the text file ad matching the category name when the post is displayed.

<?php
$plugin_dir = dirname(__FILE__);
$ad_dir = dirname($plugin_dir).'/ad-injection-ads/';
if (file_exists($ad_dir)){
    global $post;
    $categories = get_the_category($post->ID);
    foreach ($categories as $cat){
        // nicename: spaces and dots are converted to '-' and apostrophes are removed
        $full_ad_path = $ad_dir.$cat->category_nicename.'.txt';
        if (file_exists($full_ad_path)){
            $ad = file_get_contents($full_ad_path);
            if ($ad === false) echo "<!--ADINJ CATCODE: could not read ad from file: $full_ad_path-->n";
            echo $ad;
            break; // only show first category ad that matches
        } else {
            echo "<!--ADINJ CATCODE: could not find ad at: $full_ad_path-->n";
        }
    }
} else {
    echo "<!--ADINJ CATCODE: could not find ad directory: $ad_dir-->n";
}
?>

Some extra information:

  • This code will load one text file ad per post. If for example you had a post with the categories ‘Liverpool’ and ‘Manchester United’ it would load which ever ad it found first.
  • If will ignore categories that have no text file in the directory. If you have a post with the categories ‘Liverpool’ and ‘Latest News’ then it will always load the liverpool.txt as long as you don’t create a ‘latest-news.txt’.
  • This code will only work in ‘direct’ ad insertion mode. It won’t work in ‘mfunc’ mode.

Expansion ideas:

  • Show a default advert if no text file exists.
  • Create multiple text files for each category and then randomly select one (shown below).
  • Use different code for top, random or bottom ads. e.g. you could have liverpool_top.txt and liverpool_random.txt

Randomly picking one advert from a pool of ads

Here is a more complex example which allows each category to have a pool of text ads to choose from. It will randomly pick a file that contains the category nicename as a substring. If the category nicename is ‘liverpool’ the code will pick out any files in the directory containing ‘liverpool’, e.g. ‘liverpool.txt’, ‘liverpool1.txt’, ‘liverpool2.txt’. If you put this code into the ‘random’ advert and want a different advert to appear in each slot you should tick the ‘Re-select an ad for each position on post’ box in the ad placement settings of Ad Injection.

<?php
$adinj_filter_category_ads_filter;
if (!function_exists('adinj_filter_category_ads')){
function adinj_filter_category_ads($file) {
    global $adinj_filter_category_ads_filter;
    return strpos($file, $adinj_filter_category_ads_filter) !== false;
}}
$plugin_dir = dirname(__FILE__);
$ad_dir = dirname($plugin_dir).'/ad-injection-ads/';
if (file_exists($ad_dir)){
    $files = scandir($ad_dir);
    global $post;
    $categories = get_the_category($post->ID);
    foreach ($categories as $cat){
        // nicename: spaces and dots are converted to '-' and apostrophes removed
        global $adinj_filter_category_ads_filter;
        $adinj_filter_category_ads_filter = $cat->category_nicename;
        $filtered_files = array_filter($files, 'adinj_filter_category_ads');
        $random_file = array_rand($filtered_files);
        $full_ad_path = $ad_dir.$filtered_files[$random_file];
        if (file_exists($full_ad_path)){
            $ad = file_get_contents($full_ad_path);
            if ($ad === false){
                echo "<!--ADINJ CATCODE: could not read ad at: $full_ad_path-->n";
            }
            echo $ad;
            break; // only show first category ad that matches
        } else {
            echo "<!--ADINJ CATCODE: could not find ad at: $full_ad_path-->n";
        }
    }
} else {
    echo "<!--ADINJ CATCODE: could not find ad directory: $ad_dir-->n";
}
?>

Randomly picking many adverts from a pool of ads

This will pick a selection of adverts from an ad pool and display them all without duplicates. The use case for this could be if you want to display a selection of adverts down your sidebar. You might have a pool of 20 adverts, and this code can pick any number of those and show them in random positions, without duplicating any adverts. Name your adverts ‘widgetadpool1.txt’, ‘widgetadpool2.txt’, etc. Then modify the ‘$i < condition' in the for loop to select how many of the adverts you want to show.

<?php
if (!function_exists('adinj_adhtml_filter_ads')){
function adinj_adhtml_filter_ads($file) {
    return strpos($file, 'widgetadpool') !== false;
}}
$plugin_dir = dirname(__FILE__);
$ad_dir = dirname($plugin_dir).'/ad-injection-ads/';
if (file_exists($ad_dir)){
    $files = scandir($ad_dir);
    $filtered_files = array_filter($files, 'adinj_adhtml_filter_ads');
    for ($i=0; $i<10; ++$i){ // max num ads shown
        $random_file = array_rand($filtered_files);
        $full_ad_path = $ad_dir.$filtered_files[$random_file];
        if (file_exists($full_ad_path)){
            $ad = file_get_contents($full_ad_path);
            if ($ad === false){
                echo "<!--ADINJ RAND: could not read ad at: $full_ad_path-->n";
            }
            echo $ad.'<br />';
        } else {
            echo "<!--ADINJ RAND: could not find ad at: $full_ad_path-->n";
        }
        unset($filtered_files[$random_file]);
        if (empty($filtered_files)) break;
    }
} else {
    echo "<!--ADINJ RAND: could not find ad directory: $ad_dir-->n";
}
?>


Ad Injection 1.2.0.0 preview – WordPress ad management plugin

Tuesday, September 6th, 2011

Ad Injection (the plugin for injecting adverts into your WordPress blog) version 1.2.0.0 should be out in a week or two (mid-September 2011). Here is a preview of some of the new features – the screen shots are from the unreleased version so the UI may change slightly before release.

New ad positioning options

Ad Injection already has many options for selecting exactly how the top, random and bottom ads are positioned. But some people need more control, so 1.2.0.0 will have a load of new features.

ad injection placement settings

  1. With 1.2.0.0 it will be possible to have the top ad start at a position other than at the very top. You will be able to choose a paragraph for it to start, or a character position. If you choose a character position the ad will appear at the next paragraph after your chosen character. The character count is based on the raw number of characters in the content (which includes HTML tags).
  2. Ad Injection has had the option to select which paragraph the random ads start at for a long time. Recently I added options to start the ads ‘at or after’ a paragraph/character position as well. The new 1.2.0.0 will have options to start the ads from the middle of the post – particularly useful if you like a top, middle and a bottom advert. There are several different methods by which the middle position can be calculated.
  3. A brand new feature is to set a position to stop the random adverts. You can stop the adverts by paragraph/character count, in the middle of the post, or two thirds of the way down the post.
  4. These options were previously hidden away on the Ad Rotation tab. They all affect the ad placement settings so it made more sense to move them here.
  5. The bottom ad no longer has to be right at the bottom of the post. If you want it at the last-but-one paragraph, you’ll be able to do that.
  6. Another setting relevant to this section that was previously hidden away where you probably wouldn’t spot it.
  7. Instead of disappearing when you exclude all the home or archive ads, these sections will now fade away. This (I hope) makes it obvious that the options do exist, but that they are disabled.

Blogs with thousands of tags

I had been having intermittent reports that parts of the UI were not drawing on some blogs. I found out that this was caused on blogs that had large numbers of tags, but very little memory. The old Ad Injection would load all the tags at once (which on some blogs could be thousands).

A recent update to Ad Injection includes an update to load the tags in batches of 100, and the new 1.2.0.0 version will move the filters section futher down the screen, so if you do run out of memory you will (hopefully) still be able to use the most useful parts of the UI.

ad injection filters

Minor UI tweaks

You can see in this screenshot the tick boxes which will become transparent instead of invisible in Ad Injection 1.2.0.0. And on the right I’ve added the ‘days older than’ settings information to the summary. These are important settings so I think it makes sense to have the information easily visible.

ad injection global settings

New features :) / New bugs :(

This update will include major changes to the part of the code that does the insertion of advert into your post content. As such it may contain new bugs – but don’t worry I usually get bugs fixed pretty soon after they are reported. If you want to beta test the 1.2.0.0 version contact me via the feedback form in Ad Injection, or via this website.

If you have any comments on the soon to be released Ad Injection 1.2.0.0 please do get in touch.

You can download Ad Injection from the WordPress site, or from your blog by searching for ‘Ad Injection’.

Notes on upgrading to WordPress 3.0 on 1and1

Tuesday, June 22nd, 2010

Normally I’d wait until at least the x.01 release of a new WordPress before upgrading. But this time I wanted to try the new WordPress soon after the final 3.0 version was out. I still waited a few days before installing it to let other people discover and fix any initial problems.

Problems and fixes

My wait paid off as a number of people who were using the same hosting company as me (1and1) found that the upgrade was failing with a ‘Fatal error: Allowed memory size of xxxxxxxx bytes exhausted’.

The fix for this problem is very simple – increase the allowed memory size, either by adding a php.ini , updating the wp-config.php, or for those who could wait a few days for an easier fix, by installing the Memory Bump plugin.

I installed Memory Bump, and went through all my usual WordPress backup steps, before attempting the install.

I pressed the Upgrade button, WordPress did something for about a minute and then I got this error message:

Downloading update from http://wordpress.org/wordpress-3.0.zip.
Download failed.: Operation timed out after 60 seconds with 1023460
bytes received
Installation Failed

Not to panic though, this error is just saying that WordPress didn’t manage to download the new install package before its 60 second timeout. I pressed the button again, and this time it worked!

Downloading update from http://wordpress.org/wordpress-3.0.zip.
Unpacking the update.
Verifying the unpacked files…
Installing the latest version…
Upgrading database…
WordPress upgraded successfully

New themes

The reason I wanted to upgrade as soon as possible was so that I could give reviewmylife a new theme. The old Kubrick theme was getting a bit old.

old reviewmylife blog

After a bit of searching and experimenting I found the News Magazine Theme 640 which I have now switched to.

new reviewmylife blog

One word of advice if you are switching themes – if you swap to a new one, and then back to the previous you might find that all your widgets have been set to inactive. You’ll have to re-add them again.

A second piece of advice is to keep any caching plugin you might have disabled whilst you play about with new themes and theme settings. This will make sure that you always see the latest generated pages, and not older cached ones. Don’t forget to turn the caching back on afterwards!

A later error

Whilst modifying one of my plugins I got this error on trying to activate it.

The plugin generated 3 characters of unexpected output during
activation. If you notice “headers already sent” messages,
problems with syndication feeds or other issues, try deactivating
or removing this plugin.

There are many possible causes, but in my case the problem was down to having opened the .php in Notepad and accidently saving it as UTF-8 instead of ANSI. I re-saved it as ANSI and it worked again.

Renaming table prefix on WordPress 2.9

Wednesday, May 19th, 2010

I wanted to rename the table prefix for this blog before upgrading to WordPress 3.0. I knew about the WordPress Table Prefix Rename Plugin which claimed to work for WordPress 2.x, but I couldn’t find anyone saying they had tried it specifically on WordPress 2.9.

wordpress table rename plugin

The only thing to do was to try it myself. As stated in the documentation this plugin doesn’t actually rename the tables, it copies the tables, and gives the copies your chosen prefix. It also modifies a few entries in the new tables which refer to the tables by name. Then it modifies the prefix entry in wp-config.php.

Before using it I looked through the PHP source code to make sure I was happy with what it was going to do. And of course I made full backups of my tables just in case it all went wrong.

I disabled the WP Super Cache plugin, and deleted the cache, to make sure that after the rename I could see the actual generated blog pages, rather than pages that had previously been cached by WP Super Cache.

I also opened the phpMyAdmin control panel that my web host (1and1) uses for managing the MySQL databases.

After installing and activating the plugin I went to its setting page, typed in my chosen table prefix, and pressed ‘Generate New Tables’. After 2-3 seconds it was done. I made a copy of the SQL statements that had been used (they get displayed on screen) for reference just in case I needed them later.

Then I pressed ‘Change $table_prefix’ button. This only took a second.

To check that everything had worked I logged out of WordPress and back in. I checked a few pages on the blog as well. And I checked wp-config.php using my FTP program to make sure it had been modified. It had all worked!

Using phpMyAdmin I checked that the new tables were the same size as the old ones (taking into account any overhead in the original tables).

I’d recommend you keep the old tables until you are sure that the new ones are working fine. Wait a few weeks – or even longer before deleting them if you have space. They don’t do any harm, and act as an extra backup of your data.

Table renaming tips

  • Read the plugin source so you know what it is going to do.
  • Backup your database tables, and verify that the backup is good.
  • Set aside enough time to restore your blog from backups in case it all goes wrong.
  • Keep your original tables if you have the space. More backups are good.


Writing WordPress posts offline in Word with the help of VBA macros

Monday, February 15th, 2010

If you want to write your WordPress posts offline (i.e. in a separate editor to the WordPress editor), then you may find you have to spend a fair bit of time reformatting the blog post to add any required WordPress formatting before you can publish.

There are lots of reasons for wanting to write your WordPress blog posts offline. You may not have access to the internet at the time you are writing. You may find the WordPress editor to be a pain, or maybe you have another editor that you’d much rather write with.

I like writing using Word 2007 so I created some VBA macros which allow me to add bits of formatting to the post (titles, links, photos) faster than I could do manually.

wordpress word 2007 macros

These macros help you format posts which are meant to be pasted into the WordPress non-WYSIWYG post editor. I don’t know what would happen if you pasted posts formatted with these macros into the WordPress WYSIWYG editor.

Description of WordPress macros

Here’s a description of the macros from the source code at the end of this post. I’m only describing the main macros, not the other supporting functions in the code that these macros need.

BoldForWordPress – Adds ‘Strong’ tags around the highlighted text and also makes the text bold in Microsoft Word to make the titles easier to see when you are editing your blog posts.

BoldForWordPress

Will be turned into:

<strong>BoldForWordPress</strong>

PhotoLinkSite1 / PhotoLinkSite2

Changes the image name into an image link with just a few bits for you to fill in to complete the HTML. It will try to auto generate an ALT tag from the image name by turning any hyphens ‘-‘ into spaces. Highlight an image name such as ‘myimage.jpg’ and click the image button.

wordpress-blog.jpg

Will be changed into:

<img src="http://www.????.co.uk/data/2010/xxxx/wordpress-blog.jpg"
 width="" height="" alt="wordpress blog" />

If you have multiple sites then you can use the template code in PhotoLinkSite1 / PhotoLinkSite2 to allow you to create links which already contain each of your sites URLs. If you only have one site then just delete PhotoLinkSite2.

Listify

Listify will convert a number of lines of text into a HTML list.

Item 1
Item 2
Item 3

Will become:

<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li></li>
</ul>

The code will give you an extra list element at the end in case you want to add more items to your list. If you don’t want it just delete it.

Link

Highlight some text or a URL and this will create your <A HREF… link. If you highlight text beginning with ‘http’ then it will put the text into the link section, otherwise it will put it into the description section.

This is some text

Will become:

<a href="">This is some text</a>

And:

http://www.advancedhtml.co.uk/

Will become:

<a href="http://www.advancedhtml.co.uk/"></a>

SpacingTable

This will insert a piece of fixed HTML which can be used to add extra spacing to images or Amazon iframes. See my post Adding spacing round an iframe in WordPress for more information. If you select the iframe HTML the spacing table will be put around it. If you have nothing selected then the spacing table will just be inserted straight where the cursor is. This is what will be inserted:

<table border="0" cellspacing="10" align="right">
 <tr><td></td></tr></table>

AdSense

This macro is useful if you use the Adsense Injection plugin. Press it once and it will insert a tag to disable AdSense in the current post. Press it again and you will get the tag to start the AdSense from a certain point in your post. Here are the two tags it will insert.

<!--noadsense-->
<!--adsensestart-->

Splitter

This inserts a line of hashes and asterisks into the text. This isn’t useful for the WordPress blog post, but I use it to split up sections in the Word document when I’m writing multiple posts. This is what this macro outputs:

*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#

How to create and configure the toolbar buttons

Here are some brief instructions for how to setup these macros. You’ll need the source code below.

First click on the ‘View’ tab and then the ‘Macros’ button on the right hand side of the ribbon.

word 2007 macros button

If you haven’t added any macros before you’ll need to create a dummy one so you can access the Visual Basic macro editor. Type in ‘Dummy’ as the macro name and press ‘Create’. You’ll be taken straight to the editor.

create dummy word 97 macro

Paste all the macro VBA source code below into the editor. Save the macros by going to the File menu and pressing ‘Save Normal’.

Now you need to create some buttons and link them to the macros. Click on the little down arrow (pictured below) to get the Customize Quick Access Toolbar menu. Press ‘More Commands’.

customize quick access toolbar

In the ‘Choose commands from’ pull down list select ‘Macros’.

choose commands from menu

Now click on each of the macros and then press ‘Add’.

adding macros to the quick access toolbar

To give each macro a unique icon, click on each on in turn, press ‘Modify’, and then choose your icon.

add icons to macros

You should now have your macro buttons setup and it will look something like this.

wordpress word 2007 macros

Visual Basic (VBA) WordPress macro source code

Here is the VBA macro code – it’s not pretty but it works. It has been tested on Word 2007. You should be able to get it working on other versions of Word as well, but it might require minor modifications if it doesn’t work as expected.

You might want to customise the URLs in PhotoLinkSite1 / PhotoLinkSite2 to fit your own blog.

Sub BoldForWordpress()
    'Wordpress bold title
    Dim TitleStr
    TitleStr = Selection.Text
    Dim HasNewLine As Boolean
    If Right(TitleStr, 1) = Chr(13) Then
        HasNewLine = True
    End If
    TitleStr = TrimNewLine(TitleStr)
    With Selection
    .Delete
    .Font.Bold = wdToggle
    .TypeText ("<strong>")
    .TypeText (TitleStr)
    .TypeText ("</strong>")
    .Font.Bold = wdToggle
    End With
    If HasNewLine Then
        Selection.TypeText (Chr(13))
        Selection.MoveLeft
        Selection.Font.Bold = wdToggle
    End If
End Sub
Function TrimNewLine(Str) As String
    'Remove newline from string
    If Right(Str, 1) = Chr(13) Then
    TrimNewLine = Left(Str, Len(Str) - 1)
    Else
    TrimNewLine = Str
    End If
End Function
Function TrimPlus(TheString) As String
    'Trim space and newline
    TheString = Trim(TheString)
    TrimPlus = TrimNewLine(TheString)
End Function
Sub Replace(FromStr, ToStr)
'Replace text in the current selection
    With Selection.Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = FromStr
    .Replacement.Text = ToStr
    .Forward = False
    .Wrap = wdFindStop
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    .Execute Replace:=wdReplaceAll
    End With
End Sub
Sub PhotoLinkSite1()
Call PhotoLink("http://www.????.co.uk/2010/xxxx/")
End Sub
Sub PhotoLinkSite2()
Call PhotoLink("http://www.????.co.uk/2010/xxxx/")
End Sub
Sub PhotoLink(LinkBase As String)
    'Turn the image name into a link
    Dim PicString, AltString
    PicString = Selection.Text
    ' Remember newline
    Dim HasNewLine As Boolean
    If Right(PicString, 1) = Chr(13) Then
        HasNewLine = True
    End If
    PicString = TrimPlus(PicString)
    'Create alt text
    Call Replace("-", " ")
    Call Replace(".jpg", vbNullString)
    Call Replace(".png", vbNullString)
    Call Replace(".gif", vbNullString)
    AltString = Selection.Text
    AltString = TrimPlus(AltString)
    'Write HTML
    With Selection
    .Delete
    .TypeText ("<img src=""")
    .TypeText (LinkBase + PicString)
    .TypeText (""" width="""" height="""" ")
    .TypeText ("alt=""" + AltString + """ />")
    End With
    ' Re-add new line
    If HasNewLine Then
        Selection.TypeText (Chr(13))
    End If
End Sub
Sub Listify()
    'Add list tags to a plain text list
    Dim ListString
    Call Replace(Chr(13), "</li>" + Chr(13) + "    <li>")
    ListString = Selection.Text
    Selection.Delete
    Selection.TypeText ("<ul>" + Chr(13) + "    <li>")
    Selection.TypeText (ListString)
    Selection.TypeText ("</li>" + Chr(13) + "</ul>")
End Sub
Sub SpacingTable()
    'Add a table which puts space around Amazon
    'product links
    Dim TableString
    TableString = Selection.Text
    TableString = TrimPlus(TableString)
    With Selection
    .Delete
    .TypeText ("<table border=""0"" cellspacing=""10""")
    .TypeText (" align=""right""><tr><td>")
    .TypeText (TableString)
    .TypeText ("</td></tr></table>")
    End With
End Sub
Sub Link()
    'You can either select some plain text or a
    'URL to be turned into a link
    Dim LinkString
    LinkString = Selection.Text
    Dim HasNewLine As Boolean
    If Right(LinkString, 1) = Chr(13) Then
        HasNewLine = True
    End If
    LinkString = TrimPlus(LinkString)
    Selection.Delete
    If Left(LinkString, 4) = "http" Then
        Selection.TypeText ("<a href=""")
        Selection.TypeText (LinkString)
        Selection.TypeText ("""></a>")
    Else
        Selection.TypeText ("<a href="""">")
        Selection.TypeText (LinkString)
        Selection.TypeText ("</a>")
    End If
    'Fix up the new line
    If HasNewLine Then
        Selection.TypeText (Chr(13))
    Else
        Selection.TypeText (" ")
    End If
    Selection.MoveLeft
    'Put the cursor in the correct place so you
    'can complete the link
    Selection.MoveLeft Unit:=wdCharacter, Count:=4
    If Not Left(LinkString, 4) = "http" Then
        MoveCount = 2 + Len(LinkString)
        Selection.MoveLeft Count:=MoveCount
    End If
End Sub
Sub Splitter()
'Easily visible line for dividing posts
Sp = "*#*#*#*#*#*#*#*#*#*#"
Selection.TypeText (Sp + Sp + Sp + "*#*#" + Chr(13))
End Sub
Sub Adsense()
'For use with Adsense Injection plugin
NoAdsense = "<!--noadsense-->"
If Selection.Text = NoAdsense Then
    Selection.TypeText ("<!--adsensestart-->")
Else
    Selection.TypeText (NoAdsense)
    With Selection
    .MoveLeft Unit:=wdCharacter, Count:=16, Extend:=wdExtend
    End With
End If
End Sub


Tips for upgrading to WordPress 2.9 on 1and1

Thursday, December 24th, 2009

A few days ago I upgraded the my blog from WordPress 2.8.5 to 2.9. Here are some tips on what I did in case you run into any of the same issues that I did. That blog is hosted by 1and1 and some of the information may be specific to them.

This isn’t meant as a full upgrade guide – just a collection of tips that may help you.

First make sure you backup your data! There are some general wordpress backup tips on a post I did about a previous upgrade.

1. Export the SQL database

In the MySQL admin panel I selected these extra options: ‘Add DROP TABLE’ and ‘Complete inserts’, and then chose to save the file as a .gz (gzip) archive. If you need a free application to read .gz archives then I recommend 7-Zip.

Oneandone MySQL icon

2. Export the XML data

Export the XML post data from the WordPress admin panel (Tools->Export).

3. Zip and downloaded the blog files

Zip up the actual files on the server. On 1and1 the easiest way to do this is to logon to your admin panel, go to the Webspace Explorer, right-click on the directory and select ‘zip’.

You can then right-click on the zip file and choose download to copy it down to your computer.

4. Verify the data

I verified that the exported SQL data, XLM and .zip files were valid. The easiest way to verify the SQL and XLM data is to look at it in a text viewer such as NoteTab Light and make sure that the data at the end of the file is valid. Sometime a download can silently fail and you can end up with truncated data. If you try to restore the data from a truncated file then the restore will fail.

Verify the .gz file by making sure it will open in 7-Zip.

Click on the upgrade button

I finally was ready to click on the upgrade button. I clicked on it and a second or two later I got the message:

‘The update cannot be installed because WordPress 2.9 requires MySQL version 4.1.2 or higher. You are running version 4.0.27’

How I got around it

The partial answer is contained in the post here. However I’ll add a few bits of information on what I did differently.

I created a new MySQL 5.0 database from the MySQL admin panel. On the old 1and1 business hosting package I think you can create two MySQL databases (or up to 10 on the newer business hosting package) so you don’t need to delete the existing one first. Don’t delete it – you may need it if everything goes wrong with the upgrade!

I didn’t import the data by using the XML backup. I imported the data into the new MySQL 5.0 database from the gzipped SQL archive that I’d created in step 1 above.

You can import the SQL data from the MySQL admin panel by going to the tab to execute SQL commands, and then selecting the .gz file. Importing the SQL file through a .gz file gets around the 2MB size limit in the MySQL admin panel.

Importing from the .gz file rather than the .XML will import all your database data, and plugin settings, whereas if you do it from the .XML file you may have to manually re-enter various settings into your blog.

In your wp-config.php you will have to ensure that the DB_NAME, DB_USER, DB_PASSWORD and DB_HOST have been updated with the settings of your new MySQL 5.0 database.

Upload the wp-config.php file and if everything has gone right your blog should still be working and look exactly the same as before. Your blog will be using the old version of WordPress but will be accessing the data from the new MySQL 5.0 database.

You should now be able to click on the upgrade button and the blog should upgrade in less than 5 seconds.

This worked fine for me on 1and1. If you have loads of plugins or a heavily customised theme you may find more problems. If this is the case you can try deactivating plugins, or switch to the default theme.

If you really can’t get things to work you should be able to roll back to your pre-2.9 WordPress blog by restoring the files that you zipped in step 3 above. You MySQL 4.0 database should still be there (as long as you didn’t delete it).

Upgrading WordPress can often be a pain but at least having upgraded the SQL database from 4.0 to 5.0 should avoid more problems in the future. And now with WordPress 2.9 you can look forward to batch updating your plugins rather than doing them one at a time!

Upgrade WordPress to 2.8.1 on 1and1

Tuesday, July 14th, 2009

In the bad old days upgrading anything WordPress related (plugins, themes, or WordPress itself) would at best involve manually downloading a zip, extracting it locally and then using FTP to upload the changes to your web server. At worst it could require manually editing files, and making database changes.

In February last year I wrote about how cool it was that the All in One SEO Plugin had a one-click upgrade facility. Updating plugins had always been a big pain, especially when you have a blog with many plugins (this one has about 10) so it was great when WordPress introduced one-click plugin upgrade support. Although plugins could now be upgraded with a single click, upgrading WordPress itself was still a manual task.

In WordPress 2.7 they introduced one click upgrade support of WordPress itself. When 2.8.0 was released a message at the top of my blog console prompted me to do a one-click upgrade. I decided to wait. Upgrading to a x.x.0 release can be risky. These are major updates and often have many bugs. Waiting until the x.x.1 release can be safer unless there is an urgent reason to upgrade (such as a critical security update).

Another reason for delaying a WordPress upgrade is that it can take a while for the plugins that you use to be updated to be compatible with the new version. Sometime no changes are needed, but when WordPress update their database structure, plugins are particularly vulnerable to breaking.

Even though you can now upgrade from 2.7.x to 2.8.x with one click, upgrading is never that simple. With each upgrade there is a chance that you will completely trash your blog.

Firstly make sure you have plenty of time. If it goes well it shouldn’t take too long. What you don’t want to do is for it to go badly wrong and end up with your blog trashed, just before you have to leave for an urgent appointment.

You MUST do your backups before upgrading. Before backing up I make sure all the plugins are up-to-date and I delete any comment spam so this isn’t backed-up.

I always do three different backups.

  1. File backup – I FTP all the blog files down to my computer.
  2. XML export – Export all the blog information as an XML file using the Tools->Export option.
  3. MySQL database backup – A full MySQL database backup using the backup instructions from the official WordPress website. On 1and1 you select the MySQL admin panel using the highlighted button shown below.

Oneandone MySQL icon

After backing up I verify that the backups look correct. I generally diff the XML and database dump to my previous backup using the Beyond Compare tool. The main thing to check is that the backups haven’t been truncated due to a failed download. If the files are much smaller than previous backups then you may have a problem.

I’d read that in order for the upgrade to work on 1and1 you need to ensure that your website is processing .php files using PHP5 rather than PHP4. To ensure this you must have the below line in your .htaccess file in the root of your blog.

AddType x-mapp-php5 .php

After all this there was just one thing left – to press the ‘Upgrade’ button.

I pressed it and held my breath. Some messages appeared on the screen and about 10-15 seconds later it said the upgrade had succeeded. At first I thought something must have gone wrong, as it was so quick. I logged back into the blog and saw that it had worked!

The only problem that I found was due to me having made some changes to the default theme. These changes had been overwritten. Luckily due to the file backup that I had made by FTP I was able to restore them in a few minutes. The lesson to learn here is not to change the default theme. You should copy it to a new directory and only change the copied version. If you want to keep any updates to the default theme in sync with your modified theme you may have to manually merge them in, but at least you won’t lose your theme updates.

Congratulations to the implementers of this feature in WordPress. It is much appreciated by me :)

Speeding up a WordPress blog with caching

Monday, August 4th, 2008

I decided to investigate some methods of speeding up page load times on my this blog.

An obvious way to do this seemed to be to add some caching to the site to reduce the load on the MySQL server.

Searching for WordPress caching information gives a lot of references to adding a define('WP_CACHE', true); line to your wp-config.php file. However this information is now out of date. The WordPress file-based object cache was removed in version 2.5.

I decided on the WP Cache 2.0 plugin which stores the generated pages in /wp-content/cache/ and then serves them to your readers. It does this completetly transparently.

Two questions that I did have about WP Cache before I installed it were:

  1. Does it work with Google AdSense?
  2. Will Google Analytics still work?

The answer to both of these questions is yes!

I’ve been using the plugin on my other blog for about a week now with no problems. The speed difference is noticeable but small. You may notice a bigger difference if you have a more popular blog than mine.

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.

related_posts_404()
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.

blog/wp-content/themes/default/404.php
<?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(); ?>
	</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>