@madpilot makes

Browser version switching – quick fix?

I have just finished reading the two A List Apart articles (by Aaron Gustafsen and Eric Meyer) on the concept of using browser meta tags to specifically target browsers. Go and read the articles to get the full story, but the basic premise it to devise a meta tag that stipulates which browser version the site is targeted at, eg:

<meta http-equiv="X-UA-Compatible" content="IE=8" />

It’s an interesting concept to say the least, and I’m quite torn – the standards-nazi in me wants to yell from the roof tops how stupid an idea it is. The time-poor developer in me is jumping for joy, because I could target a specific set of browsers and KNOW that is would forever more work in said browsers.

The biggest problem I see is that browser vendors will need to ship multiple layout engines with each release – the number of which grows at a rate of n. So after a couple of releases, imagine how big the binary installs (and source code) would be? Just as an example, Firefox 2.0.x is currently up to point release 12 – that is 12 difference rendering engines since mid-last year.

Couldn’t the browser developers use a decision tree approach to minimise the codebase? No, not really, as this would potentially add bugs into previous versions – that is programming 101. This would break the previous renderer, defeating the purpose of this idea.

I really see this as THE show stopper. Why are the browser makers going to add to their work load? They are stuggling to build to the standards specification as it is. Programming is hard, this just makes it harder.

Having said that, if the browser makes can work a way around this issue, it does fix the problem, which is one that I’ve been piping up about for ages (I thought I’d written a blog post about it, but apparently not). When IE 7 came out, the goal posts moved – sure IE 6 was broken, but at least we had had 5 years of understanding HOW it was broken. Now all of a sudden, this new browser comes out and things change (exactly the issue causing this kafuffle). Firefox releases a new browser every couple of months – sure they are point releases, but there are still rendering bug fixes in there – so the goal posts are just moving they are being flung at a rate of knots.

I’m not saying that the browser developers should go dormant as Microsoft did, but maybe, just maybe being able to lock down a target to work against would make our lives a little more pleasant? I know the open source world has issues with the concept of “stable” code, but this effectively gives us web developers a “stable” baseline to work with – yes there will be bugs, but at least, if we work around the bugs, the hacks won’t break in future versions.

To those that argue this would encourage lazy programmers, maybe, but there are still a lot of people out there that are using tables and spacer gifs to mark up their websites – there will always be slackers, but there will also be those who strive for more. Why should those that are pushing the envelope be punished by a browser upgrade?

Will there still be a problem after February 12?

According to this article, a forced IE 7.0 rollout will occurring about three weeks. So the only people using IE 6.0 will be places that forcibly deny the update (it’s opt-out, not opt-in as it was before). One could argue that such a mechanism, as meta tag switch would have meant that the long suffering IT staff charged with blocking Windows update would have been able to strike that task off their list, as IE 7.0 would drop back to IE 6.0 mode for these users. Therefore, the question should be would this technique ALLEVIATE the problem?

Things the need to happen to make it work:

  1. We need to still be able to use standard mode. If we don’t specify a meta tag, it should default to the latest and greatest rendering engine
  2. The browser vendors need to work out a good way of serving up multiple version of their engines that don’t conflict with each other – maybe some sort of download on demand thing?
  3. If a browser finds a site targeted at a newer version it doesn’t know about, it should try to render it anyway – it is up to the web developers to make sure it degrades nicely (they have to at the moment).
  4. The browser vendors still need to care about standards – they still have to play nice, because this fix doesn’t improved CROSS-BROWSER compatibility.

As long as we, as web developers and they, as browser developers still strive for the holy grail, and they can work out how to have multiple rendering engines coincide with out out having to maintain a separate 500Gb harddrive just to contain them, it might not be as bad an idea as everyone initially thinks it is…

Be a good netizen: Use the correct HTTP response code

Remember the good ol’ days back before dymanic websites where pages had .html extensions and when you tried to access a page that didn’t exist you got an ugly, yet reassuring 404 Not found page? The significance of this page is actually pretty important – not only does it tell the user that the page is not found but it returns a special HTTP status that tells web spiders the same thing. As web developers, sometimes we forget that humans aren’t the only ones accessing our pages, and as a result don’t use the correct HTTP response codes to denote what is going on.

What the hell is a HTTP response code?

When your web browser makes a request to a web server, the web server will return a status code as well as the web page, which tells your browser what has happened. This response is usually made up of two parts: a number (which is for any spiders or bots that might be accessing the web site) and a string (which is for humans) and back when everything was static the web server took care of everything.

Unfortunately for web developers, in this environment of database driven web sites, we often don’t have the luxury of letting the server take care of everything, so this article aims to show you that it isn’t that difficult to do HTTP responses correctly. As I will show later, this can adversely affect your ranking in your favourite search engine.

Let’s try it out

Firstly, lets see what happens when you actually make a request – you can see what is going on using another old school application: Telnet.

Open up command line or Terminal.app or terminal depending on you flavour and type the following:

telnet madpilot.com.au 80

You will get a prompt and type the following (Windows users might not see anything as the telnet client won’t echo what you type):

HEAD / HTTP/1.1

Host: madpilot.com.au

…and hit enter twice – you should see something like:

HTTP/1.1 200 OK

Server: Mongrel 1.0.1

Status: 200 OK

Cache-Control: no-cache

Content-Type: text/html; charset=utf-8

Content-Length: 4123

The first line of the response is the important bit – it tells the web browser that the response conforms to HTTP version 1.1 and more importantly the response code is 200 and the response type is OK! The 200 type is the most common response you will come across, it means that the page was found and served up correctly. Generally your web server WILL take care of this one for you. Let’s look at how you can change that status code.

I’ll use PHP as an example, because it is still the most common dynamic language – but you can do this in any language, leave a comment if you would like an example of how to do it in another dialect. It is all very simple – BEFORE you output any HTML, call the header() function as such:

header("HTTP/1.1 404 Page Not Found");

As you have probably guessed, this will tell the browser that the page it requested was not found. Why would you want to do that? Obviously if the script is being run, it has been found? Well, yes – that is true, however, when the HTTP specification was written, CMSs and dynamic product catalogues weren’t even thought about – so we need to think a little bit differently.

Let’s look at an example: Your customer has requested to see the details for product #10 by browsing to

http://www.yourcomany.com/products/view/10

Product #10 exists, so we serve up the details, but what if the customer decides to see what product #20 is? If product 20 doesn’t exist, then what should we do? One option is to print out “Product not found” which is fine for the user, but what happens if your favourite search engine tries to hit product #20? If you maintain the default action the search engine will receive a 200 OK status which makes it think that the product exists and it will index it! This just pollutes the search engines’ index and hurts your ranking, which is bad. So what we can do is serve up the 404 header from above and this let’s both the user AND the search engine know that what they have requested doesn’t exist.

So what other response codes can we use? There is a complete list here, but I’ll run through a couple of the common ones:

301 Moved Permanently: This response code means the resource that has been requested USED to live here but has now moved somewhere else and will never return. Returning this status code is extremely important if you are changing the structure of your website, as you can tell the browser where it needs to go to get the resource. More importantly, it also tells your search engine to update it’s index with the new URL. You need to supply the new URL as part of the request, so it looks something like this:

header("HTTP:1/1 301 http://www.yoursite.com/new-url");

302 Found: The 302 is actually generally used incorrectly. The most common use is to redirect a user to another page TEMPORARILY which is actually what the 303 code is for. unfortunately, not all browsers support 303 and actually expect a 302 in this case. So who are we to argue? If you are a PHP developer, you have probably used

header("Location http://www.yoursite.com/somewhere");

before – this is exactly what this does.

403 Forbidden: If you wanted to really play HTTP right, you would return this code every time someone tried to access a private URL when they weren’t logged in. It means the server knows what you are trying to do, but isn’t going to let you do it.

404 Page not found: This has been covered – basically if the resource the agent wants doesn’t exist, you serve this up.

410 Gone: This page you are looking for used to exist, but it doesn’t anymore. In fact there isn’t even a new URL, so if you are a search engine, just forget about it. Whether search engines listen to this, I’m not sure, but it can’t hurt.

500 Server Error: Something went wrong with the server. I would throw this up if there is an error that is stopping the page from loading, such as a missing database or a broken web service or similar.

Don’t forget that you can also server up content to the browser (in fact, if you don’t humans will just get a blank page), so it is recommended that you serve up a nice friendly message to your visitors explaining what happened.

So there you go – now there is no excuse for serving up errors to your users and forgetting about our automated friends. So when you are writing your next kick-arse web app, spare a thought for the visitors that aren’t so good at parsing human talk.

How to lose friends and infuriate people.

Warning: The following post is an usability rant aimed squarely at the incompetent software developers contracted to Citibank. Please enjoy the ride.

When I went to the UK about 4 years ago, I opened a Citibank UK bank account so that I could get paid whilst I was working. The actual account is really great – much better than any account you can get over here in Australia. There are no fees at all – none, nada, zip. At they time they also provided some great overdraft facilities. As I still occasionally do work for UK clients, and as it costs me nothing, it remains opened.

Significant point #1: I can’t go to a branch, and I need to call international to talk to a customer support officer – I rely on internet banking heavily.

Unfortunately, the online banking experience does not reflect the quality of the account. There are so many usability issues, the developers should be brought before some sort of tribunal.

Javascript Keyboard: This is a favourite amoungst banks as they believe it provides security from key logging software. BOLLOCKS! Javascript is a very dynamic language, it would be extremely simple to write a Javascript function that could be injected onto a page which would reveal the password. All a Javascript keyboard does is increase the chance of me getting my password wrong and slows me down. in fact, if someone was shoulder surfing, they would be able able to read my “keypresses” much easier than if I typed them on a normal keyboard. JavaScript keyboards are stupid.

JavaScript Keyboards are stupid.

Secret Question and Answers: Next, Citibank requires you to answer one of five pre-defined question/answer pairs. In a previous session, I was required to spend twenty minutes picking and answering questions. Why twenty minutes? Because you need to enter your username, password twice (both times using the previously labeled stupid Javascript keyboard), then finally pick five out of twenty questions, type in answers, then type in answers AGAIN to confirm them. After you enter an answer, they are automatically starred out, so you can’t see them.

Challenge Questions are not secure. A small amount of digging will allow you to get most of these details about someone. Heck, if you can get hold of someones bank statement, you can work out at least a couple of answers. All they do is make it frustrating for legitimate users. I couldn’t remember if I used capitals (To this day, I’m still not sure if they are case sensitive) or whether I used abbreviations. And what happens if my favourite colour changes? I’m screwed. Challenge questions are stupid!

Challenge questions are stupid

Guess what, I couldn’t remember the specific format of the challenge question I was asked, so I was locked out, which meant I needed to go through the above procedure again. This time, I took too long, so the session timed out.

I click the login link once more, enter my username and password (again, stupid Javascript keyboard) but it confirms that my username is locked. I need to click the “unlock username” link. I click said link, and it tells me I NEED TO ENTER A USERNAME AND PASSWORD. Two problems here:

  1. Generally people do not expect text links to be associated with text boxes. if you want the data in a text box to relate to an action, make that action a button.
  2. There is no indication that I need to fill in this information until AFTER I have tried.

Finally, I have navigated to the “unlock username” page. Only to be presented with another stupid form. This time, I need to fill in my username, card number, e-Pin (welcome back stupid Javascript keyboard) and account number. Now, I don’t know about you, but as far as I’m concerned, my credit card number is probably more valuable to a thief than my e-Pin, yet the former is in full view of everyone and isn’t protected by stupid virtual keyboards.

The unlock you account screen is stupid!

Now, after attempting this frustrating process a number of times, I am completely locked out from my online account and I will need to call the UK to get it sorted out. Go team Citibank.

So what can they do about this to make the process simpler? I think BankWest has got it right:

  1. They issue a Personal Access Number (PAN) – The number is short, so it is easy to remember, but it is not easily derivable from the account number of any user details.
  2. they politely remind users that they haven’t changed they password in a while. Which is much nicer then forcing me to do it. If I’m stupid enough to not change my password regularly, even when warned, well that is my tough luck.

Other things worth trying:

  1. Limit the amount of money that can be transferred in a day, especially for person-to-person transfers – having access to online banking accounts is not much use unless you can transfer the money out.
  2. Give users the choice of blocking person-to-person transfers and BPay – I only ever check my balance through this system so I have no need for transfer facilities.

The bottom line is these “security” measures aren’t that much more secure that a standard username/password conbination yet they are infinately more annoying and frustrating.

So banks: PLEASE STOP USING THEM.