February 2015

Volume 30 Number 2


Cutting Edge - Lightweight Client-Side Device Detection

By Dino Esposito | February 2015

Dino EspositoThere are two basic options for creating device-friendly Web sites—create a separate mobile site (m-site) or rework a site so it can intelligently adapt content and behavior to the current screen size and orientation. Neither of those two strategies is ideal in all cases. Therefore, the most insightful approach is the classic, “It depends,” approach.

The m-site approach has two major drawbacks. First, all devices are different in terms of screen size and other physical capabilities (from smartphones, tablets and mini-tablets to older cell phones, phablets, wearable devices and so on). In the end, how do you actually define “mobile”?

Years ago, having an m-site made more sense because there was a clear separation between desktop computers and everything else. Today, the space of “everything else” has so many options that a generic unified mobile site is out of the question. The second drawback of an m-site is it requires users to navigate to a distinct URL, typically some m.yourserver.com. This is no longer a desirable solution and only acceptable as a temporary fix.

The other option—a responsive UI—isn’t without its issues, either. The key question is how would you go about making a Web site responsive? A responsive site is commonly associated with the idea that it was built with responsive Web design (RWD). RWD is a development approach that uses the browser implementation of CSS Media Queries to detect screen size and orientation and lets you define breakpoints (essentially a pixel width) to automatically apply a different CSS.

The net effect is attractive. As you resize the browser window and trespass one of those visual breakpoints, the appearance of the site changes to make better use of the available real estate. The content adapts at no extra cost to any full-screen mobile browser used to visit the site. RWD is device-agnostic and scalable to any number and type of devices available now and in the future.

As pointed out in my December 2014 column, “Effective Image Handling in Responsive Web Sites” (msdn.microsoft.com/magazine/dn857356), being device-agnostic is both a strength and weakness of RWD. If your customers are happy with the results you can achieve through RWD (mostly performance and usability), then you’re all set. RWD is your baby and you’re done.

RWD usually works well with sites presenting content without requiring much interaction or wizard-like workflows. The more forms you have, the more you need users to select and type. In that case, the one-size-fits-all approach like RWD is less appropriate. So where are we, then?

The industry demands an effective way to serve appropriate content to any device without remembering a different URL. RWD is a popular approach to achieve this end. However, RWD is unapol­ogetically device-agnostic. Developers don’t love doing device detection. There are bad memories of when making a Web site look the same across multiple browsers required parsing the user agent string and bringing it to countless branches of code.

Device Detection over Feature Detection

While you wait for the time when all browsers eventually expose platform and capabilities through a standard object model, parsing the user agent string is currently the only way to figure out which browser is actually requesting pages from a Web site. Parsing a user agent is a challenge, but there are a few tools that can mitigate the pain to some extent.

One of these tools is the script you get from detectmobilebrowsers.com. This script uses regular expressions to check a list of known mobile keywords and answer the question: “Is it mobile?” In this context, mobile simply means it’s not a desktop browser. Another tool is Modernizr, which has a long list of plug-ins for user agent parsing and detecting touch events to try to detect a tablet.

Modernizr, however, isn’t the right tool to detect anything other than JavaScript-detectable features. And whether the browser is a tablet or a smartphone isn’t something you can detect with JavaScript. You can only ask the browser about its identity through JavaScript, but most browsers (especially mobile browsers) return inaccurate information for a number of reasons, including being incorrectly recognized by legacy code based on user agents.

Modernizr heralds the flag of feature detection versus device detection. It’s an apples-to-oranges comparison. They’re different things serving different purposes. If you need to determine the form factor of the requesting device, feature detection isn’t the way. Some developers detect tablets and smartphones via JavaScript by asking Modernizr to check for touch events. This is increasingly unreliable considering the growing number of touch-enabled desktops and devices you want to treat as desktops.

You need expert help analyzing user agents and returning easily consumable information. Expert help means some framework that’s continuously updated to add new devices as they hit the market. It also implies sophisticated parsing logic that properly handles false positive and uses statistical analysis to work around incorrect information passed by some mobile browsers. Frankly, it’s a lot of work. There are some companies doing it for you, though. These tools are called Device Description Repositories (DDRs).

The WURFL.JS Endpoint

A lightweight form of JavaScript device detection can improve the UX in client-side-intensive Web applications, such as a single-page application (SPA). WURFL (wurfl.sourceforge.net) is a popular DDR that has been around for a few years as a server-side solution. I wrote about using WURFL in an ASP.NET MVC application in my August 2013 column, “Creating Mobile-Optimized Views in ASP.NET MVC 4, Part 2: Using WURFL” (msdn.microsoft.com/magazine/dn342866.aspx).

Server-side WURFL is subject to a license fee whether you use it on-premises or access the DDR in the cloud. The WURFL team recently released a free HTTP endpoint (WURFL.JS) that you can invoke from the client side through JavaScript. To enable JavaScript device detection via the WURFL.JS endpoint, all you need to do is add the following line to HTML (in ASP.NET, you can even place it in the master page or layout file):

<script type="text/javascript" src="https://wurfl.io/wurfl.js"></script>

The referenced resource—wurfl.js—is not clearly a plain JavaScript file you can download and host on-premises or upload in your cloud site. It’s a JavaScript-like HTTP endpoint that injects a JavaScript object right in the Document Object Model (DOM). The net effect is once the browser has made a call to the endpoint, your DOM contains the following:

var WURFL = {
  "complete_device_name":"iPhone 5",
  "is_mobile":false,
  "form_factor":"Smartphone"};

The browser sends its user agent string while making the request. Backed by the server-side WURFL framework, the endpoint analyzes the string and determines key information about the requesting device. Such information is then formatted into three properties in a global object named WURFL (see Figure 1). It’s interesting to notice WURFL.JS can also reliably detect whether your Web page is being viewed from within the WebView component of a native mobile app. This happens when the form_factor property returns App.

Figure 1 Device Information WURFL.JS Injects in the DOM Page

Property Description
complete_device_name Contains a descriptive name for the detected device that typically includes vendor and device name (for example, iPhone 5).
form_factor Contains one of a few predefined strings such as: Desktop, App, Tablet, Smartphone, Feature Phone, Smart-TV, Robot, Other non-Mobile, Other Mobile.
is_mobile Boolean value, indicates whether the device is not a desktop.

WURFL.JS uses a lot of caching to ensure a quick response. In the development phase, you can switch off the cache by adding debug=true to the URL. When the DOM ready event is fired, you can safely use the WURFL object to enable or disable client-side features or request optional data to the server.

WURFL.JS Adds Power to RWD

Suppose you have a page with video and you don’t want it to play on smartphones for performance reasons. With plain RWD, you can’t make adjustments like that. If you hide the video player below a given breakpoint, you won’t be able to play anything when the desktop browser is resized to a tiny window. WURFL.JS used with RWD solves the issue, as shown here:

<script type="text/javascript">
  $(document).ready(function () {
    if (WURFL.form_factor == "Smartphone") {
      $("#video_player").hide();
    }
  });
</script>

First, load the page and style it according to the RWD layout. Next, use WURFL to check the form factor and hide the video player. When a desktop browser is resized to the size of a smartphone, users will still be able to play videos, but not when it’s a real smartphone. An even better formulation of the earlier code is shown here:

<script type="text/javascript">
  $(document).ready(function () {
    if (WURFL.form_factor != "Desktop" &&
        WURFL.form_factor != "Tablet") {
      $("#video_player").hide();
    }
  });
</script>

In this case, the video player is hidden in all cases, except when the device is a desktop or tablet. There’s another more interesting scenario for WURFL.JS. Suppose you have an RWD site in production where all views are generated on the server, within an ASP.NET MVC application, for example.

At some point, you’ll get feedback that smartphone users aren’t having an appropriate experience. Should you consider creating an entirely new m-site for them? If you can use the server-side services of WURFL, then you can easily implement a view switcher within the same site, as demonstrated in my August 2013 column.

This approach would save most of the work you’ve done. Otherwise, there’s not much you can do other than create a separate site and implement some redirect mechanism, as demonstrated in my January 2015 column, “Mobilize an Existing Web Site” (msdn.microsoft.com/magazine/dn890366). To display regular and m-site under the same URL, you still need some good device detection done on the server side.

A pleasant side effect of using WURFL.JS is you can collect device information from the WURFL object and pass it on to Google Analytics. That gives you an immediate measure of how users are visiting your site and which device they use most. If you upgraded to the new analytics.js you need the following:

<script type="text/javascript">
  /* Universal tracking code of Google Analytics:
    see https://goo.gl/HakYmP
  */
  ga('create', 'UA-XXXX-Y', 'auto');
  ga('send', 'pageview', {'dimension1': WURFL.form_factor});
</script>

If you’re using the classic Google Analytics script (ga.js), here’s the slight change you need to implement:

_gaq.push(['_setCustomVar', 1, 'form_factor', WURFL.form_factor, 1]);

Google Analytics has a bunch of built-in features to track mobile and tablet traffic. The mobile traffic incorporates tablet traffic, as well, and can’t immediately separate smartphone from tablet, for example. WURFL.JS adds handy information missing at first in Google Analytics so you can create custom reports just focusing on the numbers instead of data projection. WURFL.JS, though, is just a data provider. It works with Google Analytics, but you can also use it with other analytics tools.

Wrapping Up

In many cases, an RWD site is harder (more expensive) to implement than a plain ASP.NET Web Forms Web site. Don’t listen to the sirens of RWD. RWD is a great solution for desktops and high-end devices, but it might not be appropriate when effectively implementing functions on small devices is crucial for the business. RWD makes a point of being device-agnostic. This means RWD Web sites serve the same content to a 480x360 resized desktop browser window and a full-screen small feature phone.

Hardware and connectivity may be significantly different in the two cases. Performance is objectively a sore point of RWD. At the same time, it might be not be painful in the same way for all sites. Performance issues affect primarily low-level devices. If those devices aren’t common site visitors, you can go with RWD and be happy.

However, the amount of data being served and user expectations may grow in the near future. This would render more devices inadequate and, ideally, requiring an ad hoc view. In this article, I’ve presented a lightweight and nearly unobtrusive client-side solution for detecting the underlying device—WURFL.JS.

WURFL.JS is an endpoint that injects device information in the DOM, specifically the form factor. In other words, it tells you whether the device is a desktop, a tablet, a smartphone, an old phone, an Xbox or perhaps a native app. Based on that, you can arrange small changes in the pages and even feed analytics tools with form factor information.

Knowing how your site performs on a per-form-factor basis is a powerful indicator of its success and the areas you need to improve. If you want more details on how to use WURFL.JS with Google Analytics, check bit.ly/1u0lpGB.


Dino Esposito is the co-author of “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2014) and “Programming ASP.NET MVC 5” (Microsoft Press, 2014). A technical evangelist for the Microsoft .NET Framework and Android platforms at JetBrains and frequent speaker at industry events worldwide, Esposito shares his vision of software at software2cents.wordpress.com and on Twitter at twitter.com/despos.

Thanks to the following technical expert for reviewing this article: Jon Arne Saeteras