Along with the discussion around RWD, Adaptive Design, m-dot sites and so on, comes the discussion of identifying “stuff” in the users “thing”. I say “stuff” and “thing” because the terminology we use to discuss this is not very clear. Now, I’ll try to document how I see this.
In general there are three terms, or techniques, we usually implement when we want to identify a property of the user-agent and act based on that:
- User-Agent sniffing
- Feature detection
- Device detection
User-Agent sniffing is the simplest one, where where we just look at the User-Agent in the request, looking for a specific string or pattern to use in a conditional statement. This can be done both client side, in JavaScript, and on the server. Typically looks like this:
var ua = navigator.userAgent; var isiPhone = /iPhone OS 3_1_2/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);
This is clearly a hack and not recommended, neither on the client or the server. Main reason is poor maintainability.
It is still quite common to do this, however. But why? In most cases we do this because we know the User-Agents, or patterns in it, of “things” that can do certain “stuff”. Aka a feature.
Feature detection is the approach where we really don’t care about the User-Agent, but about the “stuff”, or features the “thing” can do. Most common way to do this is by using Modernizr. Feature detection is checking for certain functions or features of the browser using JavaScript for example by checking if a function or object exists
var appCache= function() { return !!window.applicationCache; };
or by playing with the DOM
var inlineSVGworks = function() { var div = document.createElement('div'); div.innerHTML = '<svg/>'; return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; };
The good thing is that this is fairly maintainable since we are not taking the detour via the user-agent to tell what the “thing” can do. Bad thing is that you might experience “false positives”. That is, a test for a feature, lets say application cache returning true, even if the browser doesn’t support that. That happens because the browser vendors can put whatever they want into window.applicationCache and still not actually implement that functionality in the browser. Further, there might be a performance penalty of doing too much in the browser. Maybe not by the feature tests themselves, but how we use them. I have seen many cases where a feature test is run in such a way that it blocks rendering and/or is messing around with the DOM. That hurt performance badly.
Some people confuses User-Agent sniffing with Device Detection. That is not quite fair. First, in modern Device Detection tools, such as WURFL, it is really about features too. Second, Device Detection happens on the server. So in stead of doing actual tests, run-time in the browser, for features, the features are stored in a database. Like any other database, we need a key or ID to access information. This key is (parts of) the User-Agent which is available server side. Good things about this approach is that you can define any property, or “stuff”, you want on a device, browser, OS or whatever, and that you get rid of the “false positives” problem. And not to forget, you know all this on the server so that you can differentiate what you actually send over the air. On the other hand, to get this to work properly the User-Agent of the “thing” need to make sense since that it the key to find the right record in the database. Even if this is mainly for server side use, there are tools that make this type of information available from the browser too.
I am not going to say what’s right or wrong here, but User-Agent sniffing is a hack! 🙂 Device detection and feature detection, on the other hand, are not. Both are about features, there is just a naming issue.