What I learned about Friction, Attention and App Adoption

buyer_signupPossibly the most significant lesson I learned whilst developing and launching ChangesThatStick.com (CTS), my mobile- and web-based goal/habit/exercise tracking app, concerned the ever-decreasing attention span of users and how it affects app adoption.

In an increasingly-connected world, in which we carry our on-line lives in our pockets, our patience and attention span when exploring new offerings (apps, websites, etc) have decreased significantly. The number offerings vying for our attention has sky-rocketed and, as many of them are now “free”, our perceived value of them — and hence willingness to invest in exploring them — has declined.

We seem to have become jaded by the sheer number of possibilities, the learning curves, the dependencies, whether our friends are using them, whether our data will be locked in, whether the offering will be genuinely useful in our real lives (remember those?). Not only does everything now need to be “free”, whatever that means, but it needs to assimilate itself into our on-line world seamlessly, providing instant perceived value… or else we walk away.

The gap between a user who thinks your offering sounds great (and perhaps even raves about it to friends), and a user who is signed-up, using it and liking it… has become rather a chasm.

During the Beta phase of CTS I learned the hard way how one particular factor, of the few that we are in control of, affects app adoption in this attention-deprived world: friction.

Friction – Anything that slows or hinders, even minutely, the user’s path from first hearing about your offering, understanding it, choosing to use it, signing up, actually using it and finally seeing the benefits… is friction. At every point on that path, friction comes into play and a portion of your potential user base walks away silently. This may be because their attention threshold has been exceeded, because they get distracted by another aspect of their on-line life (an alarm, a notification, an email), or simply because they park your offering and intend to return… but never do. Even the simple passage of time is friction: Waiting for your registration email or staring at an hourglass because your app is slow.

Zero to Signed-Up – The moment a new potential user becomes aware of your offering, you have a fleeting window of their time and attention in which to convince them that it is sufficiently interesting to warrant their usage. Beyond a simple, attractive and clear landing page, they need to be able to sign-up with zero obstacles. That means no pre-registration, no “We’ll email you a link”, or lengthy registration forms to fill out. Recently, Social Sign-up has become the easiest way to register new users; they simply sign-up using their existing Facebook or Twitter credentials. One click, and they are a user. Great, now what?

Instant Value – Beyond sign-up, an offering needs to provide some instant value, or at least the perception of instant value. This means no initial blank home page, no arduous up-front configuration, and no “wizards” full of options to capture more about the user before they can do anything. The offering must use what little it already knows about the user to provide a little instant value. If they used social sign-up, perhaps it could show them which friends are already using the offering, or make suggestions based upon the activities of those friends.

Lack of instant perceived value creates friction. In the case of CTS, the initial blank app with the need for heavy up-front configuration and choices put many users off using it.

Offer Alternatives, but Anticipate Defaults – Users come to an application with their own mental model of how it fits into their world. For CTS, this meant their existing model of their efforts to lose weight, exercise more, adopt/control certain habits, or just a desire to find out about any of those. The differences in those models dictates the need to offer options, alternatives and different ways to use the app. But crucially, the app also needs to anticipate which of those options most closely fits this user’s mental model, and default to it. Options are great for later, but users today expect a degree of automatic customisation, anticipation and intelligence in the apps they use.

For CTS, in hindsight, offering sign-up paths tailored to different kinds of users may have helped here: runners, weight watchers, habit changers, etc. For each of these populations of potential users, the application could begin with default choices that more closely reflects the likely usage. Subsequently, the user can then choose other alternatives, once they see the app is useful.

Integration – It is no-longer enough to make an application available on a range of devices: desktops, tablets, phones. Users also want integration, either with other apps or third parties. In the case of CTS, each potential use of the app came with a list of potential future integrations: RunKeeper or “Map My Run” for running, Withings wi-fi scale for weight capture, etc. Whilst users appreciated that these integrations would appear eventually, lack of any deemed to be a deal breaker for them led to them going elsewhere. Why wait, if it is already available elsewhere? Lack of an integration right now created friction.

Integration can be as simple as allowing data to be imported from another app (one-off migration or incremental import), taking a feed from a third party (such as body weight data, run data), as ubiquitous as Facebook’s support for “Share” and “Like” links on third-party sites, Twitter’s “Tweet” links, or as complex as allowing visualisation of recent running activity on a Google Map.

For CTS, I believe some of these integrations needed to be there from launch. Promised integrations create friction.

Free, at least initially – Users will experiment with an app for “free”, learn to love it, and then perhaps be open to discussing a monthly subscription cost. But any mention of cost up-front tends to create friction and kill their adoption.

A subset of users will pay for a known app. No-one will even talk about paying in future for an unknown offering. Thoughts of money create friction and, whilst claiming an app is “free” then charging for it later is dishonest, postponing talk of payment plans or subscription fees minimises friction whilst users discover whether they actually like (and therefore value) the app. Once they value the app, providing more detail about the cost is acceptable.

I still feel a paying audience exists for CTS, but discussing a monthly subscription fee before resolving the other adoption issues above, kind of kills the appeal.

Getting all of the above lined up for optimal user adoption is a complex task. To a degree, A/B Testing can help when choosing between a few options. But there is a limit to what you can try out on potential users and the number of meaningful experiments you can run. There are simply too many dimensions, and I feel you have to “get it right” to a certain degree up-front before anyone sees it. After all, no-one takes a second look at your app. It needs to appeal first time.

Reducing friction combines elements of good app design (mental models, UX), but also psychology, marketing and a degree of creativity. CTS taught me a great deal, and my next offering will incorporate what I learned.

One UI across Many Devices (My Approach)

This was a tough post to write, and I’m in danger of stirring up much debate… Amongst those who have a favourite UI technology (it must be Flash, simply has to use JQuery, or GWT). Or amongst the ones who insist on native apps on mobile devices, rather than web apps or native wrappers. In-fact amongst anyone who has ever made a technology choice relating to a UI and is passionate about that choice. I realised a while back that this is complex and emotive territory. People have invested heavily and passions tend to run high.

But I’m concerned here, primarily, with describing what worked for my sabbatical year project, ChangesThatStick.com (CTS), and also with the choices that made this an educational experience for me. So bear with me, if I’m crossing a line, re-inventing a wheel, ignoring this framework or that technology, not using the “latest and greatest”, etc, as there was method in my madness at the time, I promise.

002

Why the challenge? – Firstly, why is it even challenging to make an app or web-site site available on many different devices anyway? Some would say that the availability of a browser on most devices makes delivering a universal web app very simple. To a degree that’s true, but only if it takes into account the following:

  • Available space : The available screen space differs wildly between devices. Some features might need to drop away automatically on the mobile version, with additional options appearing only on devices capable of showing them. Or the additional desktop options may become hidden behind a menu on a mobile device, such that they are available but don’t hog space by default.
  • Content sizing and zooming : In my opinion, mobile versions of web apps should display content pre-zoomed to 100%. There’s nothing worse than going to a web-site on your iPhone, only to be required to zoom in to see the “Login” button. Having to squint isn’t good. Similarly, buttons that look great on desktops may not look so great on an iPhone retina display, or they may be too small to select easily with your finger.
  • Dynamic Interaction : Many web apps are clunky in comparison to native apps, omit features such as drag-and-drop, and involve too many page refreshes when content changes. Thankfully, a combination of AJAX and features available in HTML5 are addressing this (see later).
  • Bandwidth usage : A highly-connected, bandwidth-hogging web app on a desktop in an office or home environment is fine. But it simply wouldn’t work on a 3G connected mobile device. And even if it did, the user would stop using it once they saw their next bill.

Why bother? – Given these difficulties, why even bother with one interface? Why not just provide a different UI on each device?… Web for desktop/tablets, and native for each mobile platform. This is fine if you have the development resources to build them and keep them in-sync. As a one-person development team, this simply wasn’t an option for me with CTS.

Why write a framework? – There are existing frameworks and technologies for web applications, some very much suited to dynamic apps. But part of this was an educational exercise and, as a primarily server-side developer, I wanted to delve into client-side technology whilst exploring a framework that would let me build my app in a productive way. I believe that whenever you use a framework, you should dive into the technology it hides from you, just a little. The additional understanding gained can often help you to solve future problems you encounter. No framework entirely hides the complexity of the underlying technology. Sometimes, writing a new framework leaves you with a better solution; something new and unexpected and better suited to the task at hand.

Dynamic Views, without the hassle – I wanted a UI framework that simplified the task of taking a server-side model (activities, goals and targets in the case of CTS), building a view of that model (perhaps embellished with additional UI state), representing that as server-side UI components, rendering it as HTML and pushing it to the browser. Depending on the app, there can be many layers in that pipeline between server-side model and browser-side HTML.

But, for a given view, that pipeline shouldn’t be one-off. Whenever the server-side model or UI state changes, the view, the UI components and the resulting HTML DOM in the browser should also change. I think this should be possible without refreshing the entire page, and without any additional app development effort. There should be no need to re-render entirely; the framework should determine what changed and pass only that delta to the browser.

Some server-side changes might result in a simple CSS tweak, or appearance of a new row on the page, or re-ordering of existing elements… whatever the view would have originally rendered to represent the new server-side state. For a long time, I have wanted a UI framework that hid the complexity of handling all this from the developer, and updated the client-side view seamlessly  Certain frameworks help here, but I still believe they over-complicate it. So my goal was to implement this myself, if only to learn how hard it is.

Actions – I wanted it to be possible to mark the views with available actions which, when invoked by the user, call back to the server and allow the relevant UI controller or model entity to handle them. Beyond including them in view mark-up / templates, developers shouldn’t need to think too hard about how to get notification of those actions back to the server. And if the actions map to existing HTML events (clicks, mouse movements, etc), it should be even easier to embed them in HTML content.

This is perhaps a slightly server-side view of app UI development, and very much a thin client model, but I believe it formalises the process of rendering the client-side view, annotating it with actions, and keeping that view in-sync with the server.

Implementation – What I actually ended up building therefore was a UI framework based upon server-side Views, each composed of a hierarchy of one or more Fragments.  Each Fragments has a Builder capable of generating content, either directly as HTML or as XML with an XSL stylesheet to provide the HTML. There are many other potential ways of generating content, but I settled on XML / XSL here. It works. As they say, “your mileage may vary” 😉

Crucially, builders are in charge of when they update their content and push it to the View. The framework determines how the resulting HTML content has changed, and pushes only those changes to the browser as a series of deltas, which the browser applies to the HTML DOM. This allows changes in server-side state to drive what the user sees, with very little additional developer effort.

Fragments can embed other fragments, and this is achieved by including fragment tags in content. The framework resolves those tags and ensures the correct overall content appears in the browser. The builders for any fragments that are removed from the view are informed of their removal.

This orchestration of a fragment hierarchy encourages implementation of fragment builders representing standard UI components, or containers, and their re-use throughout the application. Fragments may represent entire pages, single cells in table or anything in between.

Client-Side – In the browser, an XmlHttpRequest (XHR) object is used to keep everything in-sync with the server. The server holds on to the client connection until further changes are pushed, however, the connection has a maximum time to live and reconnection occurs after a configured period (required for certain deployment configurations, such as Amazon’s Elastic Load Balancer). Changes reach the client as an XML document of commands describing which portions of the DOM to modify / replace / delete. This server response may be JSON in future, but I chose XML for the first implementation.

Actions, embedded in content via fragment tags that the framework translates into HTML event handlers, are triggered in the client and passed to the server via another XHR object. They are given a sequence number and, when the server is slow to respond, a modal throbber automatically appears. In this way, if the connection is slow, the user knows their invocation of an action is being handled. This helps greatly when using CTS on a mobile.

Connection problems are also handled generically, and a modal status message appears when the connection is lost, offering re-connection when it returns. If the server-side view has since been destroyed, perhaps due to server restart or simply expiry, the client is re-connected to a new view.

HTML5 Canvas – An important part of CTS is the compelling visualisation of progress towards a user’s goals. For this, I wanted to build some custom charts with pleasing axes, shading, and annotations. So I built support for the new HTML5 Canvas functionality into the UI framework, allowing server-side fragment builders to render a Canvas and draw content on it, via a series of commands translated client-side into the required JavaScript.

pull-ups

Browser Compatibility – Obviously, all of this requires a browser with up-to-date HTML5 support, and it also relies on a fair amount of framework JavaScript. There was the danger that particular browser variations would cause it to fail. So I wrote a JavaScript browser compatibility test, to be executed up-front. If that test fails, all the user sees is a “browser compatibility” page, listing supported browsers.

That said, all JavaScript errors are captured and routed to the server anyway. This allowed me to capture info on device-specific failures as they happened, and attempt to turn around fixes for them, perhaps even before users were aware. Particularly on the new Windows 8 Phone, it meant I was able to debug an issue whilst only requiring the user simply to hit refresh a few times, after each update.

Performance – I tested the bandwidth usage of all of this and, combined with sensible caching and compression of JavaScript, CSS and image resources (to be covered in a future post on deployment issues), I found that CTS used a pleasingly small amount of bandwidth when connecting and using for day-to-day logging of activities and goals.

pics

So, this was rather a high-level tour of my approach to one UI across several devices, for CTS, and my strange decision to write my own framework. I learned a great deal, and feel that my appreciation of other UI frameworks is now heightened. I still consider this framework to be a strong candidate for CTS, but I also feel better equipped to choose a more suitable alternative on other projects.

I haven’t even begun to describe how CTS handles differences in screen size, clarity of icons on devices, auto-zooming on iPhones, etc. But I’ll probably save them for another post.