Recently I released a WordPress plug-in for Google Analytics that adds a tracking code and dozens of various pieces of meta data to Blogs. Since the release of version 4, I’ve updated it 6 times, to the point where it’s now at version 4.0.6.

In this article I would like to share my experiences in maintaining this and other WordPress plug-ins and other common practices that I’ve distilled from this work.

The updates that I released had a couple of reasons, ranging from bug fixes to new features and also fixes in documentation.

Maintaining a WordPress plugin

Website and Account Configuration

Almost as soon as I released the plug-in, people who updated it told me that it worked wonderfully, and others were said that it didn’t work for them. I later figured that I hadn’t tested the plug-in with a Google Analytics account that only had one website registered. Fixing this bug was easy, but determining this problem took a while.

Being able to log into a few hosts gave me access to back end and FTP of these people was invaluable as it helped me to test my fix. This enabled me to release 4.0.1 within an hour of the 4.0 release.

Another mistake I made was forcing everyone to reconfigure the plug-in. I assumed it wouldn’t be too much work for people, and to make sure the settings were clean, but it turned out that a lot of people didn’t want to reconfigure.

With 4.0.2, I came up with a way to inherit some of the settings and clean up the mess I made, and in 4.0.4 I made a change that I will add to all of my plug-ins:

Good practice #1: Don’t assume anything about people’s websites and external accounts.

Versioning Option Arrays

As a seasoned WordPress developer, I store all of the options for my plug-in in one option in the database, which is basically a big array. Why I hadn’t ever added a version number to these options is a mystery to me. Doing so makes it possible to do some very cool things: I can now add new features and set a default for these new features as soon as a user upgrades; I can show the user different messages based on the version they had before they upgraded; and more.

Good practice #2: Add a version number to your option arrays.

I’m still not using the WordPress option API stuff (check out this post by Ozh to learn all about it), which I probably should, but for now I find it easier to handle the saving and validation of options myself.

Don’t Release Too Soon

If you’ve got a bug that’s bugging your plug-in’s users, you’ll probably want to release a bug fix as soon as possible. This caused an issue with my 4.0.3 release, because I didn’t properly test some of the code I introduced, causing me to have to release 4.0.4 just two hours later to fix a stupid mistake I’d made with Booleans. Nothing is as painful as 500 people downloading a version of your plug-in that doesn’t actually work.

Good practice #3: Test, test, test before you release, even when you’re in a hurry.

Know Which Version People Are On

Over the past two weeks, I’ve been helping several people who said they were on the latest version of my plug-in but in fact were not. To remedy this, I’ve started outputting the version number in the comment that the plug-in outputs before the tracking code. Problem is, if people run a plug-in such as W3 Total Cache (which everyone should use by the way) or anything else that minifies their output, which comment will get lost.

There’s a solution for that, too: I’d already wrapped the script in <CDATA> tags, to help with Strict XHTML validation. Minifying will not occur within those CDATA tags, so I moved my “branding” comment to the CDATA section, and I can now always see, first, that my plug-in is active and, secondly, which version of the plug-in they’re using.

Good practice #4: Make sure you can see which version of your plug-in the people are running.

URLs in WordPress

One of the things that can generate pretty awful bugs is a Blog’s URL. Whether it’s due to people running their entire Blog on https or “simply” running their Blog in a sub-directory, it can cause headaches. It did for me in version 4.0.2 when I added URL sanitization: all relative URLs in posts and text widgets starting with a / were made absolute, in order to properly track these URLs. Tiny issue: I forgot about blogs in sub-directories, so a tiny portion of people would end up with links that used to go to /home but that now went to I know, that was stupid; but that’s why I’m telling you: so you don’t make the same mistake.

Good practice #5: Make sure all URLs you use will work in all circumstances, whether WordPress is in a sub-directory, on a sub domain or just in the root.

Writing to the Root Directory

Somewhat related to the last issue, although I encountered this while developing my WordPress SEO plug-in, not the Google Analytics plug-in: if you write a file — say, an XML site map file — to the root of a website, and the website is actually a WordPress multi-site installation, things can go horribly wrong.

Check out the following scenario:

User 1 writes and publishes a post on

An updated XML site map for is generated, and is updated.

User 2 writes and publishes a post on

An updated XML site map for is generated and is overwritten

See what just happened? The XML site map now contains only the posts from blog-2… This is exactly why the wp-content directory was created. There’s hardly ever a need to put a file in the root of an installation, and by not doing so, you make it far easier to run your plug-in in a multi-site/WordPress MU environment.

Good practice #6: If you’re generating files, generate them in the wp-content directory of your Blog. Do not write files to the root directory unless you absolutely, positively have to. And if you do have to do it, make sure it doesn’t go wrong when your plug-in is active on multiple Blogs in the same multi-site instance.

Rethink Your Filters

On the day that I released 4.0, I got quite a few feature requests, ranging from very simple to somewhat more complex. One that came in quite rapidly and caught my eye happened to be quite simple: the users wanted the same outbound link that in my plug-in tracks the content of an article to track in text widgets. Because I don’t use text widgets that much, it never occurred to me to do this. It was a valuable lesson, though: