Technical notes, War stories and anecdotes

You’ll hear us at Cloud Four often use the metaphor that mobile Web development is still in the Wild West phase: there’s a lot of hooting and hollering and posturing, but it’s still a sparsely-settled, incompletely-explored and exhilarating place full of legends and buried treasure. Well, perhaps not that glamorous. It’s sort of the unsung, rough-and-tumble mountain man cousin compared to those dashing native apps. But there’s gold in them hills.

When Cloud Four recently helped Hautelook, a high-volume “flash sale” retail site, build their mobile Web strategy, we got a chance to see if some of our bolder theories about the mobile Web—context, content adaptation, technology stack—would hold water in a performance-critical environment.

Supporting large numbers of concurrent connections from widely disparate devices, handling the crush of shopping enthusiasm at 8AM Pacific every day (when new sales events go live), all while interfacing with a remote, third-party API meant we really had to push the envelope. And invent some neat tricks. And find a few things out the hard way.

Adapting the Experience: Server or Client?

It’s an enduring debate: should the savvy mobile Web developer adapt content for mobile devices on the server, or should most of that happen on the device (client) itself? Before everyone gets too riled, let me say this: I believe both approaches have solid merit. There.

For Hautelook, we’re letting the servers do the heavy lifting. In a nutshell, we use the Drupal Web content management system (CMS), along with the WURFL device library and some Cloud Four-brewed software to define and manage content for several categories of devices.

We’re able to put the brawn of the server hardware behind making decisions about incoming requests and are able to route the right devices, very quickly—utilizing memory-based caching and other performance tuning—to the right place, ensuring that only those bytes relevant to the user are delivered. In such a high-traffic environment, it simply won’t do to be pumping out markup, images or CSS that aren’t actively needed for the particular user.

In addition, Hautelook’s mobile Web site supports a rather dizzying array of devices. While the majority of users are on newer smartphones—iOS, Android, BlackBerry 5+ and WebOS are the major platform players here—we do see a consistent flow of folks using all sorts of older devices. For older phones and feature phones, it can be dangerous to rely on the client too much, and especially perilous to assume any sort of meaningful JavaScript or advanced CSS (ahem, media query) support. That puts the server in the best position to make certain kinds of decisions.

Another thing that sometimes precludes client-side adaptation is the need not just to provide adapted content to a given device class, but in fact to provide different content altogether. For example, in Hautelook’s case, product listings are output as HTML unordered lists on modern devices—the semantically obvious way to do it. However, due to some brain-dead-ness in certain devices (I’m looking at you, BlackBerry 4.x browsers, and you, certain weird flavors of IE Mobile), CSS for unordered lists was, well, predominantly it wasn’t behaving in any socially-acceptable way. In this case, we opted to deliver product listings as HTML tables for those devices: inelegant, smacks of 1997, but easier to rein in on ill-behaving phones. We’re able to do that server-side by leveraging Drupal’s theming system and our own content-adaptation framework.

Another situation that calls for not-just-adjusted-but-different content is in the handling of different user contexts: we know that browsing high fashion on a 128-pixel Samsung smartphone is not going to be as compelling as on a big, comfy desktop monitor. Instead we know that those users probably want to find stuff fast and buy it even faster. It’s not just about delivering mobile-shaped content, it’s about delivering mobile-relevant content, fresh and piping hot from the server.

Then there are images. Shoving a 153,600-pixel image at a phone that only has about 16,000 pixels of real estate to work with is like giving 4-by-8-foot sheets of plywood to a kid who wants to build a miniature birdhouse. Even if wood is cheap, it tastelessly wastes a lot of trees, and poor little underpowered Billy can barely lift the thing or cut it with his little toy handsaw. Not to stretch a metaphor too far or anything.

By extending our definition and handling of what a device class is and does, we can deliver the right kind of images and other media to the right kinds of devices.

That doesn’t mean that there is no room for client-side awesomeness! We’re pretty excited about stuff we can do with tools like Modernizr, especially for newer devices. The full solution certainly includes both client- and server-side elements.

Nutshell: How it works

Mobile Web service overview

Akamai sits in front of both sites (desktop and mobile). It’s the first-line mobile detection workhorse. It looks at incoming traffic and determines whether it is a mobile device or not. Mobile devices are sent to the mobile site*.

Sometimes you need an Abrams Tank, sometimes you want the brisk efficiency of a Hyundai (hey, newer Hyundais are pretty decent!). In our case, we’re putting the nginx web server (our high gas-mileage Hyundai) out on the front lines. nginx is dinky and quick, and can handle whole scads of simultaneous connections. Apache has big guns and horsepower on its side, but sprightly little nginx acts as gatekeeper, navigator and hand-holder, only sending for the tanks when it really needs the tanks. nginx handles Keep-Alive connections and load balancing, leaving apache to do what it does best. Even with apache, we’re being as efficient as possible, disabling Keep-Alives and using APC to keep application code in memory.

We can arbitrarily scale by adding more application instances (apache/Drupal) on more servers.

Now we’ve made it to the apache/Drupal piece of the puzzle. We know our requester is a mobile device, but now we want to know what kind. We’ve written a Drupal module that lets us define what characteristics constitute different devices, giving us control over what each device class “means.” This is a (very) similar approach to the available, third-party Drupal module mobile_tools. Our module communicates with the WURFL PHP API, but only when it needs to. Once a device has been identified, we cache what we need to know about it, keyed by User Agent. Any further requests from devices using that User Agent are handled super duper fast, using information cached in memory.

Intelligent caching, while not strictly a mobile-specific tactic, is absolutely core to our strategy. We cache as aggressively as we can, balancing performance against the need to have very fresh data out of the API. API calls are shared across users and multiple page requests, wherever possible.

While we aren’t delivering the same content to each device class, nor are we replicating markup between them. We define baseline content theming, from which each device class inherits, and has the opportunity to override. Again, we cache what we can—yes, even device-specific rendered markup in some cases—to push performance even further.

* Don’t worry! Mobile users can opt to view the desktop site and they won’t be redirected back to the mobile site.

Challenges

Here’s some stuff that was hard (warning, highly Drupal-specific/tech-y):

Drupal has, generally, a phenomenally-flexible hook system. I can, 98% of the time, find a pleasing way to implement something without ugliness. But this breaks down (in Drupal 6) when it comes to tight control of CSS and JS inclusion in pages. Drupal 7 introduces hook_js_alter() and hook_css_alter(), which will fix the exact problem I had to lightly hack around on the theme level for this project.

WURFL is awesome sauce. It contains a veritable treasure trove of device-specific data. One thing that’s challenging still, however, is the conflation of devices and browsers. I hear they’re working on this as we speak! But at present, using the PHP WURFL API, Opera Mini on an iPhone is identified as…an iPhone. With Safari, and WebKit. Eep.

OpenWave browsers (quite popular on older feature phones, but also still used on some recent ones) cause pain. Drupal forms with an action that is the same as the page they are on will create an infinite redirect loop, somehow. The only solution seems to be to tack on an interstitial #redirect page (via hook_form_alter()) for those forms that don’t have one. Also, I was only ever successful in getting them to correctly handle cookies if I used a TLD cookie domain. UGH.

Some BlackBerries don’t take it well if you destroy and write to the same cookie in a single request.

If you want to serve up valid XHTML Mobile Profile 1.2 content, you’ll need to override Drupal’s default theme implementation for ‘table’. It uses THEAD tags, which are a no-no in XHTML MP1.2.

Over the last year, we’ve been talking to people all over the country about what it means to have a comprehensive mobile strategy. That’s one of the many reasons why we were so pleased to work with HauteLook on their mobile web site.

From the very first conversation we had with HauteLook, we were impressed with how they were approaching their mobile strategy and how their infrastructure was built in a way that gave them flexibility to support new devices via robust APIs.

One of the things we talk to customers about is what I refer to as the email problem. It isn’t so much a problem as a user scenario.

Someone sees something that you offer that they are interested in sharing with someone else. Maybe they email a link to their spouse. Or they share it on Facebook or Twitter.

What happens when they follow that link? They go to your web site. What is the experience like if the person is on a mobile device? Is that experience representative of your brand?

This is especially important for companies that have social media campaigns. Links are social media currency.

The challenge is to make sure that when a customer reaches your site that

no matter what device they are using,

no matter where they are in the world

that you provide them with the best possible experience.

HauteLook got this from the very beginning. They wanted to support as many mobile phone users as possible.

To that end, the m.hautelook.com can be used on everything from feature phones with screens as narrow as 128 pixels to images optimized for the iPhone 4’s retina display.

Every morning, HauteLook members receive emails letting them know what the sales are that day. Those links point to the desktop web site. But when those links are viewed on a mobile device, you get a mobile-optimized version of the same page.

The email blast also triggers a morning rush of traffic. The traffic spike is significant enough that performance was key. John and Lyza spent a lot of time working on both the front and backend to make sure the site was fast under the heaviest of loads.

And mobile web is only one part of HauteLook’s mobile strategy. They worked with our friends at Small Society to create an iPhone app for HauteLook members that offers features like push notifications and reminders.

There’s a lot more to this project than can fit in a single post. Everyone at Cloud Four helped in some way to make the site a success. There are lessons from this project that we can’t wait to share.

But for the moment, we just want to thank HauteLook for the opportunity to work with them on such a great project and to thank those people on twitter who have given positive feedback. Nothing made us happier than seeing comments like this one from a Blackberry user who said:

That’s why mobile is amazing. Provide a great mobile experience and your customer will not only use it, but they’ll love you for it!