Saturday, February 16, 2013

Checking for Technical Requirements in a Sign-up Process

As mentioned in my last post on feature detection vs. user agent sniffing, we do use feature detection for some of our Coursera features, and I wanted to talk here about one particularly interesting usage.

A month ago, we launched a new product called "Signature Track." We created it because we wanted to give students a way to verify that they really are who they say they are, and that they are the ones that are actually doing the assessments. That will give their certificates and accomplishments more meaning.

To verify their identity, we ask them to give us a typing pattern (on a hard keyboard, where biometrics algorithms works best) and to take a photo of themselves (from their webcam, so that they can't just upload a photo). They have to do that both when they register for Signature Track and after each assessment they do.

That means that there are a few technical requirements for them to be in Signature Track: they need a hard keyboard, they need a webcam, and they need the Flash plugin (it is possible to access the webcam via HTML5 getUserMedia, but it is a bit buggy, so we're starting with Flash only access). Since the Signature Track signup process is multi-step, we wanted to warn users ahead of time about all the requirements, so that they didn't go through one step and then be frustrated to discover they couldn't complete the next step. Here's how we checked for support (or tried to) for each of our requirements:

Hard Keyboard

As far as I know, there's no actual way to query if the user is on a device with a hard keyboard. You can query whether the device supports touch events, and that's what we started off with doing by checking for the existence of document.ontouchstart, but then we found out that several browsers may start exposing Touch APIs on non-touch devices, so that seemed not very future-safe. Paul Kinlan had a good idea that we good monitor the sequence of events while a user is typing - if the keypress came before a touch event, they are likely using a physical keyboard. However, we can only do that check once the user has actually started the process, and we wanted to give users a heads up before they even dove in.

So, for now, we are no longer using feature detection - we are instead doing a check on the user agent to see if a user is on a known mobile device:

 function isMobileDevice() {
    var ua = navigator.userAgent || navigator.vendor || window.opera;
    return (/iPhone|iPod|iPad|Android|BlackBerry|Opera Mini|IEMobile/).test(ua);

If they are on a mobile device, they'll be brought to a page letting them know what we've detected, and we track in our analytics how many users get to that page:

We will likely add in the physical keyboard check based on events in the actual typing phase and warn users when they appear to be on a soft keyboard. Or, we improve the algorithms so that users can match their patterns even when typing from soft keyboards.

Flash Plugin

I typically go to Modernizr for my straightforward feature detection needs, but unfortunately, they do not include a check for Flash. I looked through their issue threads on it and did some Googling, and after trying a few options, I decided that the SWFObject library was the most straightforward option.

After including that library, our check is simply:


If they don't pass that check, they'll be brought to a page letting them know what we've detected, and we track in our analytics how many users get to that page:


As with the physical keyboard, the browser does not give any indication whether a user has a webcam. We would have loved if it did while we were brainstorming this product, because we wanted to figure out how many users would even have a webcam available, but alas! The only way to know if a user has a webcam is to use Flash or getUserMedia to ask for permission to use their webcam. If they don't have one, you'll get an error in response.

So, unfortunately, we can't warn users ahead of time about lack of a webcam, but we do try to message that via a modal at the very beginning, along with other reminders:

If you have a product with technical requirements, what do you do to check for them in the sign-up process? I'd love to hear more in the comments.

Why isn't our warning banner based on feature detection?

In my last post, I showed how we display a banner above Coursera to users on explicitly unsupported browsers, to warn them that the site is known not to work well on them.

After my post, Kyle Simpson, a well-known web developer and creator of the talk "Browser Versions are Dead", put together a post about why he thinks browser version detection should be avoided, and feature detection should be used instead.

He has some great points in it. Generally, the web developer community is trying to move towards using feature detection instead of user agent sniffing to warn users and degrade website functionality. We try to do that at Coursera where it makes sense for specific features (we deliver video via Flash if you don't have native HTML5, e.g.), but we determined that it's not practical to do that for our cross-site warning, for a few reasons:

  • We would have to test for *a lot* of features, and those tests would take time on page load. We could cache the results of those tests in a cookie or localStorage, and so there would only be a one-time cost. But if the browser upgraded and suddenly did start supporting a feature, we would need to know to re-run the tests - and as far as I know, the only way to know about a browser upgrade is via user agent sniffing and some knowledge of how versions work.
  • We couldn't just tests for features, like "does canvas work", we would also have to test for performance. We've seen some older browsers simply can't handle the amount of JavaScript that we use or simultaneous XMLHttpRequests that we send off, and they will hang. How does one test for a hanging browser yet still recover? I imagine it's possible, but I don't know if it's easy.
  • I have personally been bitten by feature detection in the past and now approach it cautiously. There are some features that developers have put a lot of approach into figuring out rigorous feature testing for, like all of the tests in Modernizer.js, but there are other features that are newer and whose detection quirks are less known. For example, when I tried to use FormData for sending a form, I checked for the existence of it on window. Unfortunately, it existed in Safari, but Safari wasn't actually setting the data, and since the FormData API had no accessors, there was no way that I could feature detect it. I resorted to user agent sniffing instead, blacklisting that Safari version for that feature. That is just one example, and there have been others.
  • We have limited resources. Yes, we could try to solve the problem of doing performant, comprehensive feature detection tests, of caching them and figuring out when to update our cache, doing performance tests, and determining the cross-browser feature detection technique for every single feature we use. Or, we could focus our time on our actual product, and decide that it's okay to say "Alright, we know we don't work in these older browsers, so let's just tell users what we know."

Something that I've come to appreciate in my last 8 months as engineer is that we can't always do what's perfect and ideal. Sometimes, we have to do what is practical and be cognizant that there is a better way, and when the time has come, try to move to the better way.

Wednesday, February 13, 2013

Warning Users on Older Browsers

As web developers with finite time and resources, we have to make a conscious decision of which browsers we will support. Every supported browser means additional bugs to fix when things don't work, and additional browsers to do both manual and automated testing in. And as you all know, some browsers are much harder to support than others (*cough* IE6 *cough*).

At Coursera, we have decided to support IE9+, Firefox 12+, Chrome (any version), and Safari 5+, and we document that decision on our help site.

Letting users know

But, our website still works in other browsers, so we do not want to block a user from using it completely, if that is their only option. We do want them to be aware that they are on an unsupported browser, though, so that they are prepared for some features to not quite work. Since 99.99% of users do not consult the help site before they use a website, we need to find a way of messaging this to them when they're on the site. Pop up a modal? Make them sign an agreement that they know they're on an older browser? Float a banner somewhere? Turn everything bright red?

Our approach: the top banner

We opted for the top banner approach, which has become a fairly common paradigm on websites for warning-style messages. We have a little JavaScript browser banner library that we can include on any of our sites. It starts by checking the user agent to see if the user is on an un-supported browser. I debated between checking if they're on a whitelisted browser versus checking if they're on a blacklisted browser, and I went for the latter approach. I figure that we can always add more to that blacklist, if we see many people on a particular old browser.

If the user is on an unsupported browser, then it animates a banner sliding down with the message "You are using an unsupported browser, so some features may not work. Please upgrade to a modern browser." We link to our help site so that users can read which browsers we support and hopefully decide to download one of them.

You can see the full code for our banner in this gist, a demo of it in this jsfiddle, and a screenshot below:

Is it enough?

We've had users ignore the banner in the past (as evidenced by oblivious forum posts) and have been iterating on it to increase its obviousness (increasing the font size, adding the push-down animation), but we will probably still have users that ignore it and get upset when something doesn't work.

In particular, we have some parts of our class sites that work much better than others in older browsers (like lecture watching vs. peer graded assignments), and we have debated whether we should have a harsher warning in some places versus others. But, we decided that our users are likely to eventually experience both features, so it is the responsible thing to warn them everywhere.

If anything, we may make the warning even more obtrusive in the feature, like a modal which forces the user to acknowledge its existence before continuing, to make sure that users do not get started on a class in a browser and think that they will be successful, only to discover later that there are some aspects of the class that they just cannot complete at all.

So, that's where we're at right now. I'd love to hear about other approaches to browser messaging. Let me know in the comments!

Thursday, February 7, 2013

My Lasik Journey (Part 1)

me being a dork in glasses I started wearing glasses when I was 8 years old. I'm pretty sure my attraction to big shiny CRT monitors and my tendency to stare directly at the sun contributed to that fact. I hated glasses, because I already felt like a dork, and when I wore them, I felt even dorkier. (See photo for evidence →)

So in late middle school, when it is of the utmost importance for a young girl to feel as least dorky as possible, I started wearing contacts. I hated actually putting in contacts - I'd come out of the bathroom with tears streaming down my face every time - but once they were in, I could keep them in for months and months, never taking them out, and my eyes would never dry up. I could even wear just one contact at a time, and I could see just fine - as I would oft demonstrate by doing a one-eyed cartwheel down the balance beam.

Fast forward 15 years, and things change. Now, my eyes notice the contacts, and I find myself noticeably affected by how dry they are. I even go to bed early just to give my eyes a rest. And I still hate glasses. As much as people tell me, "but glasses are cool!", I immediately feel like a dorky 10-year-old again when I put them on, and my confidence starts to wane.

Last week, my glasses broke, my contacts ran out, and I decided that it was time to do something I've been thinking about for a long time: Lasik surgery. I don't want my eyes (or lack thereof) to be something that I think about every day for the rest of my life, now is as good as time as any to start the rest of my life. Plus, I have health insurance again, thanks to Coursera. ☺

So, here's what I've learnt in my Lasik journey so far, and I hope that it helps you with your own decisions.

What is Lasik?

intralasik diagram

As it turns out, there are multiple types of Lasik-esque surgeries. Here's my layman's description of them, but note, I'm not a doctor!

  • Lasik: In this surgery, the doctor cuts a corneal flap using a microkeratome knife, and then uses a laser to shape the cornea to fix your vision. Most doctors do not offer this anymore (at least the ones I talked to).
  • IntraLasik: This one is all laser, all the time. The doctor creates the flap using a laser, and then does the shaping with a laser. It is considered safer and more precise than Lasik, and is the preferred technique.
  • PRK: In this surgery, there is no flap creation at all. Instead, the doctor reshapes the cornea by modifying the top layer of the eye. The healing process is longer and more painful for PRK, so it is only recommended if your eye's surface is already misshaped.

Will insurance cover it?

This was a big question I had, because I knew Lasik was an expensive procedure ($5K-$10K seems to be the range). What will my insurance actually cover? Apparently, in the VSP network that we're in for our insurance, we always get 20% off the procedure, regardless of which one we go with. And that's it. Oh, well, it's "elective" surgery, so I'll be thankful that anything is covered. (I could argue that I could potentially die one day while wearing glasses and biking in the rain at night, but alas).

What doctor should I go to?

After money, the big concern around Lasik is safety and success. It involves putting a freaking laser in your eye, after all. So, you have to figure out: who is the best equipped person to put a laser in your eye? I did my research the usual way- emailed my colleagues, tweeted out to followers, perused Yelp reviews. In the end, I got multiple referrals for Dr. Ella Faktorovich of Pacific Vision Institute, and after having a great chat with them on the phone where they answered all my questions, I was convinced.

Am I eligible?

Not everyone is a good candidate for Lasik surgery. Or atleast, that's what Dr. Faktorovich believes, so her office puts you through a series of checks first to make sure. It's the usual stick your head in a contraption while they shine lights on you thing, and they use the results to determine if you are a candidate, and for which surgery (IntraLasik or PRK). As it turns out, my eyes are "boring" (to quote their chief engineer, who put up with my never ending array of technical questions), which means that I get to go for IntraLasik, the surgery with the fastest recovery. Woot!

How much will it cost?

The cost varies per doctor, but for Pacific Vision Institute, the final cost for me will be $6900, which includes the 20% VSP discount, the $300 discount for coming from a referral, and a $300 discount for me coming from an awesome university (I think the doctor threw that in because her daughter goes to USC and I was sporting my Trojans shirt today!).

What's next?

My pre-op visit is next Tuesday, where they'll dilate my eyes and I'll try to avoid staring at the sun, and then my actual surgery will be on Valentine's Day. (Not to jinx myself but...) Best date ever?