Section 17.1. Lazy Registration


17.1. Lazy Registration

Account, Authentication, Customisation, Customization, Incremental, Login, Password, Personalisation, Personalization, Profiling, Registration, User, Verification

Figure 17-1. Lazy Registration


17.1.1. Goal Story

It's Saturday afternoon, and Stuart is busy planning the evening's activities. He visits a band listings web site, where he clicks on a map to zoom into his local area. Even though he has never visited the site before, a profile, which he can see on the top of the site is already being constructed. At this stage, the profile guesses at his location based on his actions so far. As he browses some of the jazz bands, the profile starts to show an increasing preference for jazz bands, and some of the ads reflect that. Since the jazz thing is a one-time idea, he goes into his profile and tweaks some of those genre preferences but leaves the location alone since the system's guess was correct. Finally, he decides to make a booking, at which point he establishes a password for future access to the same profile including his address, which is posted back to the profile.

17.1.2. Problem

How can the user customize the site while deferring formal registration?

17.1.3. Forces

  • Public web sites thrive on registered users. Registered users receive personalized content, which means that the web site is able to deliver greater value per user. And registered users can also receive more focused advertising material.

  • For nonpublic web sites, such as extranets used by external customers, registration may be a necessity.

  • Most users don't like giving their personal information to a web server. They have concerns about their own privacy and the security of the information. Furthermore, the registration process is often time consuming.

  • Many users spend time familiarizing themselves with a site before registering. In some cases, a user might interact with a site for years before formally establishing an account. There is a lot of valuable information that can be gained from this interaction that will benefit both the web site owner and the user.

17.1.4. Solution

Accumulate bits of information on the user as they interact while deferring formal registration. As soon as the user visits the web site, a user account with auto-generated ID is immediately created for her and set in a cookie that will remain in the browser. It doesn't matter if she never return; unused IDs can be cleared after a few months.

As the user interacts with the application, the account accumulates data. In many cases, the data is explicitly contributed by the user, and it's advisable to expose this kind of information so that the user can actually populate it. In this way, the initial profile may be seen as a structure with lots of holes. Some holes are eventually filled out automatically and others by the user himself. The user is also free to correct any of the filled-in data at any time (Figure 17-2).

Figure 17-2. User Profile


Two particularly notable "holes" are a unique user identifier and a password. It is this combination of attributes that allows the user to access the profile from another machine or a different browser. They will also preserve the profile in the case that cookies are deleted from the user's browser. So, while this pattern is generally about gradual accumulation of profile data, there remains a significant milestone in the user/application relationshipthe moment at which user ID and password are established.

Do the user ID and password have to be provided simultaneously? No. Even that can be incremental as long as you make the email address the unique identifier. In fact, this is pretty common nowadays. Email is usually required anyway, and it's unique, so why not make it the user ID? In the context of Lazy Registration, though, there's an additional benefit, as the email might be accumulated in the natural flow of eventsthe site might add the user to an announcements list, for example. In some cases, the email might even be verified during this process.

Sceptics may wonder why a user would want to actively work with her profile. The answer was formulated in a web usability pattern called "Carrot and a Stick" (http://jerry.cs.uiuc.edu/~plop/plop99/proceedings/Kane/perzel_kane.pdf):

Determine what users consider to be a "valuable" carrot. Offer the end user a portion of that carrot before you request personal information. The content is withheld ("the stick") until the requested information is provided.

Thus, users will only enter information if there is a perceived benefit to them. There is plenty of evidence that this occurswitness the social bookmarking phenomenon, where thousands of users make public their personal links. By exposing their profiles, many of those users are hoping the system will point them in the direction of related resources they have not yet heard of.

Some web sites have used this pattern for years, so what does it have to do with Ajax? Lazy Registration aims for a smooth approach in which the barrier is low for each new user contribution. For instance, you sign up for a web site's mailing list, and your email is automatically added to your profile and shown on the side of the page. With Ajax, there's no need to break the flow. No more "just go over there for a few minutes, then come back here, and if you're lucky, you might be looking at something similar to what you can see now." That's a big win for web sites aiming to drop the barrier of registration, and it's great for users, too.

It's standard practice for web sites to collect data about users. The aim of this pattern is to empower them to contribute to this. Instead of covertly building up a corpus of data on a user, you invite him to add value to his own experience by contributing and maintaining the data himself.[*]

[*] The Attention Trust (http://www.attentiontrust.org/about) is an organization which promotes this idea.

Several technologies are involved in Lazy Registration:


Database

You clearly need a persistent data store in order to retain user profiles.


XMLHttpRequest

Passing profile information back and forth with XMLHttpRequest Calls is the key to the smooth interaction mode you are seeking to achieve with this pattern.


Cookie manipulation and session tracking

A cookie, associated with your domain and identifying a unique session ID, must reside in the user's browser. The session ID can serve as a key on the server side to locate details about the user each time she accesses the web site. In conventional applications, the cookie is pushed from the browser to the server as a header in the response. That's fine for Ajaxian Lazy Registration when the user first accesses the system, though sometimes it may be convenient to use a more Ajax-oriented approach. The first such approach is to manipulate the cookie in JavaScript (http://www.netspade.com/articles/javascript/cookies.xml). The second is to set the cookie using the response from an XMLHttpRequest Call, which all browsers are apparently happy to deal with in the same way as they deal with cookies in regular page reloads. In practice, you're unlikely to be playing with cookies anyway. Most modern environments contain session-tracking frameworks that do the low-level cookie manipulation for you (also see Direct Login). They generally use either URL rewriting or cookie manipulation, and you need the latter to make this pattern work most effectively. Since responses from XMLHttpRequest set cookies in the same way as do entire page reloads, you should be able to change session data while servicing XMLHttpRequest Calls.

17.1.5. Decisions

17.1.5.1. What kind of data will the profile contain?

Usability and functionality concerns will drive decisions on what data is accumulated. By envisioning how users will interact with the web site, you can decide what kind of data must be there to support the interaction. For example:

  • Do you want to provide localized ads? You'll need to know where the user lives.

  • Do you want to use collaborative filtering? You'll need to capture the user's preferences.

In addition, consider that some users, such as employees working on an intranet web site, use certain Ajax Apps all day long. For that reason, the profile might also contain preferences similar to those on conventional desktop applications. Many options will be application-specific, but a few generic examples include:

  • Enabling and disabling visual effects, such as One-Second Spotlight (Chapter 16).

  • Setting Heartbeat-related (see earlier in this chapter) parameters, e.g., setting how long timeout will be and whether the system will prompt the user when it's coming up.

  • Customizing Status Area (Chapter 15) display.

One issue that arises with Lazy Registration is the clearing of data. What if a user visits once and never comes back? You probably don't want to keep that data sitting there forever. Typically, you will probably have a script running daily to delete (or archive) the records of users whose last login was, say, three months ago.

17.1.5.2. How can the profile be accumulated?

You might know what data you need, but are users willing to give it to you? This comes back to the carrot-and-stick argument: you need to provide users a service that will make it worthwhile for them to provide that data. In addition, you need to communicate the benefit, and you must be able to assure them that the data will be safe and secure.

The least imaginative way to gain user data is to pay them for it, or, more deviously, pay others for it. Giving away a T-shirt in exchange for data was fine during the dot-com boom, but hopefully you can do better than that. Give the user a service they really need. For example:

  • If you want the user to provide his email, offer to send email notifications.

  • If you want the user to provide an ID and password, help him understand the benefits: he can log in from anywhere and the data will survive a hard-drive crash.

  • If you want the user to provide his physical address, provide localized search features.

  • If you want the user to rate your product, provide recommendations based on his ratings.

17.1.5.3. How much data should be stored in cookies?

How much you store in cookies depends on your general approach to the Ajax implementation: is the application browser-centric or server-centric? A browser-centric choice would be to pack as much as possible into the browser's local state so as to optimize performance, while running a full-fledged JavaScript application with a little server-side synchronization. A server-centric approach would rely only on data held server-side, with the browser accessing additional data on a need-to-know basis using XMLHttpRequest Calls.

One special concern is the security of cookies. If users access the application from a public PC, there's the risk of unauthorized access. In this case, it's especially advisable not to store sensitive information in the browser and to offer the possibility of cleaning cookies at the end of the session. (For instance, call the option "I'm on a public terminal.")

17.1.6. Real-World Examples

17.1.6.1. Memeflow

Steve Lacey's MemeFlow (http://memeflow.com) is a portal with RSS-backed Portlets. Its use of Lazy Registration is characteristic of several other portals (Figure 17-3). You can immediately build up a collection of your favorite feeds, and when you provide your username and password later on, those feeds will remain.

Figure 17-3. Memeflow


17.1.6.2. Blummy

Alexander Kirk's Blummy (http://blummy.com) is a bookmarklet manager (Figure 17-4). You can start adding bookmarklets to a personal "Blummy" container straightaway (this has a unique URL). When you register, you'll get a URL with your own name, but the old URL remains valid, so you can keep the bookmark you created before registering.

Figure 17-4. Blummy


17.1.6.3. Kayak

Kayak (http://kayak.com) is a travel search engine that retains queries you've made. A query history is available for nonregistered users and becomes part of your profile once registered.

17.1.6.4. Palmsphere

Palmsphere (http://palmsphere.com/store/home) showcases Palm applications for download and purchase. Each item has a Favorite buttonif checked, the item is one of your Favorites. The Favorites list is summarized in your Member Center area, even if you've never registered, and retained in a cookie for the next time you visit.

17.1.6.5. Amazon.com

Amazon (http://amazon.com) has begun incorporating Ajax features only recently, but it blazed the trail for Lazy Registration a long time ago. Visit Amazon (http://amazon.com) as a new user, browse for just a few seconds, and here's what you'll see before even beginning to register or log in:

  • Shopping cart, to which you can add items

  • Recently Viewed Items

  • Page You Madeshowing recent views and bookmarks related to those

  • Ability to update your history by deleting items you viewed

  • Ability to turn off Page You Made

  • Ability to search for a friend's public wish list

17.1.7. Code Example: AjaxPatterns Shop Demo

The Ajax Shop Demo (http://ajaxify.com/shop) illustrates the kind of user interface described by this pattern (Figure 17-5).

Figure 17-5. Ajax Shop Demo


When you run the demo, you'll notice a few things:

  • You can add items to your cart right away.

  • The application guesses your favorite category by watching what you're looking at. If you prefer, you can override the application's guess, and the application will no longer attempt to adjust it.

  • By offering you the ability to send the cart contents to your email address, the application provides you with an incentive to add your email to the profile without yet formally registering.

  • The password and email verification process itself is unintrusivethe main flow of the site is uninterrupted. Even while you're waiting for verification mail, you can continue to play around with the main content. Figure 17-6 shows the application when the user has gone as far as entering an email address and password.

Figure 17-6. Ajax Shop Demo with email address and password entered


To keep things simple, it doesn't actually use a persistent data store; all information is held in the session. That's definitely not advisable for a real system, because you don't want to store passwords and other sensitive data there. Also, it means that the user, in theory, could bypass the email verification by inspecting the cookie. Nevertheless, the application demonstrates Lazy Registration from the user's perspective, and the underlying code provides some illustration of what's required to develop such an application.

Following are some of the features and how they were achieved.

17.1.7.1. Retrieval of categories and items

The application maintains the flow by avoiding any page reloads when categories and items are accessed. No information about categories or items is hardcoded; generic REST services are used to extract the data and are rendered locally in JavaScript.

17.1.7.2. Cart management

Again, the only real relevance of cart management is that page reloads are avoided. The cart contents are tracked in the session, so they should be present when the user resumes using the web site. When the user adds something to the cart, the JavaScript cart is not directly altered. Instead, the new item is posted to the server as XML:

   function onAddItemClicked(item) {     var vars = {       command: 'add',       item: item     }     ajaxCaller.postForXML("cart.phtml", vars, onCartResponse);   } 

And likewise when the cart is cleared:

   function onCartClearClicked( ) {     var vars = {       command: 'clear'     }     ajaxCaller.postForXML("cart.phtml", vars, onCartResponse);   } 

For both operations, the server retrieves the session cart and alters its state:

   $cart = $_SESSION['cart'];   if (isset($_POST["command"]) && $_POST["command"]=="add") {     $item = $_POST["item"];     $cart->add($item);   } else if (isset($_POST["command"]) && $_POST["command"]=="clear") {     $cart->clear( );   } 

Then, the server outputs the final state as an XML response:

   header("Content-type: text/xml");   echo "<cart>";   $contents = $cart->getContents( );   foreach (array_keys($contents) as $itemName) {     echo "<item>";     echo "<name>$itemName</name>";     echo "<amount>".$contents[$itemName]."</amount>";     echo "</item>";   }   echo "</cart>"; 

In the browser, onCartResponse is registered to render the cart based on the resulting XML.

17.1.7.3. Mailing cart contents

The profile block contains, along with several other fields, the user's email. There's also a clickable Mail field on the cart:

   <div>     <div >Email:</div>     <input type="text"  name="email" />   </div>   ...   <span >Mail Contents</span>   ....   $("cartMail").onclick = onCartMailClicked; 

When the user clicks on cartMail, the server checks that the email has been filled in and simply uploads a POST message for the mail to occur. In this case, there's no feedback to the web user, so the callback function is blank:

   vars = {     command: "mailCart",     email: email   }   ajaxCaller.postForPlainText("cart.phtml", vars, function( ) {}); 

The server receives not only the command, but the email address itself, since this might not be in the user's profile yet. Just prior to sending the mail, the server retains the address as part of the user's session:[*]

[*] Again, this is a simplification, because retaining the address would not be necessaryor desirableif the user was already logged in.

   function mailCart( ) {     ...     $email = $_POST["email"];     // Add mail to the profile - it's part of the Lazy Registration.     $_SESSION['email'] = $email;     ...   } 

Then, it's a simple matter of constructing a message from the server-side cart state and sending the email to the specified address using standard server-side libraries.

17.1.7.4. Tracking favorite categories

There's a fixed "favorite category" selector in the HTML. It begins empty and is populated when the categories are loaded:

   <div >     My&nbsp;Best&nbsp;Category: <select ></select>   </div>   function onAllCategoriesResponse(xml, ignoredHeaders, ignoredContext) {     ...     categoryExplores[category] = 0;     favoriteCategoryOption = document.createElement("option");     ...   } 

There's also a mode variable to indicate whether the favorite category selection is automated. It begins in automated mode:

   var isFavoriteCategoryAutomated = true; 

If in automated mode, the script watches each time the user explores an item. Each category is tracked according to how many times the item was explored, and the selector is altered if a new maximum is reached:

   var categoryExplores = new Array( );   ...   function onExploreClicked(category) {     ...     if (isFavoriteCategoryAutomated) {       categoryExplores[category]++;       favoriteCategory = $("favoriteCategory").value;       favoriteCategoryExplores = categoryExplores[favoriteCategory];       if (categoryExplores[category] > favoriteCategoryExplores) {         $("favoriteCategory").value = category;       }     }   } 

If the user decides to overwrite this Guesstimate by manually setting the preference, it will stay manual permanently:

   $("favoriteCategory").onclick = function( ) {     isFavoriteCategoryAutomated = false;   } 

For the sake of simplicity, this field is not actually tracked in the server, though it could easily be incorporated into the user's profile.

17.1.7.5. Verifying password and email

Now for the most important part. The user is finally willing to verify her password and email. These could potentially be broken into two separate verification activities, but since they fit together as a formal registration step, they are combined in the demo.

The trick is to manage the process with a little state transition logic. The registration is broken into a few states with transitions between them. Each state requires you to handle events in a slightly different way. Each transition involves altering the UI a little to reflect what the user can do.

registerState holds the current state:

   /*     "start": When page is loaded     "mustSendMail": When instructions and verify password field shown     "mustVerifySecretNumber": When email sent and user must enter secret       number inside email     "verified": When user is successfully logged in   */   var registerState = "start"; 

The HTML for this demo contains all the necessary fields and buttons. Their visibility is toggled based on the current state. For example, following are the password and password verification fields. The password field is always shown until the user is at the "verified" stage, whereas the "verify password" field is only shown after the user initiates the registration process:

   <div >     <div >Password:</div>     <input type="password"ael  name="password"/>   </div>   <div >     <div >Demo Registration</div>     <div >       <strong>1.</strong> Please ensure email address is correct and       password is <strong>not</strong> confidential, then verify your       password below.     </div>     <div >Verify Password:</div>     <input  type="password" name="verifyPassword" />   </div> 

All three buttons are declared and, again, their visibility will change depending on the current state:

   <input type="button"  value="Login"></button>   <input type="button"  value="Register"></button>   <input type="button"  value="Cancel"></button> 

What's most important here is the Register button, which drives the process through each state. The Cancel button returns the state back to start, which causes the display to return to its initial state too. The purpose of the Login button is purely for demonstration. The Register button is present until the user is verified, and its label changes at each stage of the registration process. Its event handler remains the same throughout; the handler decides what to do based on the current state:

   function onRegisterClicked( ) {     if (registerState=="start") {       registerState = "mustSendMail";     } else if (registerState=="mustSendMail") {       var submissionOK = sendMail( );       if (submissionOK) {         registerState = "mustVerifySecretNumber";       } else {         return;       }     } else if (registerState=="mustVerifySecretNumber") {       verifySecretNumber( );     }     onRegistrationStateChanged( );   } 

And onRegistrationStateChanged( ) exists purely to reveal and hide fields, and to change the button label based on the current state:

   function onRegistrationStateChanged( ) {     if (registerState=="start") {       $("userForm").reset( );       $("login").style.display = "inline";       $("verifyPasswordInfo").style.display = "none";       $("secretNumberInfo").style.display = "none";       $("verifiedInfo").style.display="none";       $("cancel").style.display = "none";       $("register").value="Register";     } else if (registerState=="mustSendMail") {       ...     } else if (registerState=="mustVerifySecretNumber") {       ...     } else if (registerState=="verified") {       ...   } 

17.1.8. Related Patterns

17.1.8.1. Direct Login

Direct Login (see the next pattern) is a companion pattern, since some dynamic behavior can allow for login and registration to appear on the same form.

17.1.8.2. Live Form

It's useful to maintain the profile details in a Live Form (Chapter 14) so that the user can easily add to them and the server can synchronize state and provide opportunities for further enhancement to the profile.

17.1.8.3. Timeout

When data is held in cookies, it's important to expire the cookies if there's a risk that others may gain access to the browser. Timeout (see later) helps the server decide whether the client is still active. If it's not, it may be wise to ensure that any sensitive data is wiped from the cookies held in the browser.

17.1.8.4. Guesstimate

Lazy Registration can sometimes involve inferring information about the user's profile by monitoring his behavior. Thus, it embraces the same nebulous principles as Guesstimate (Chapter 13), where a guess is acknowledged to be imprecise but better than no guess at all.

17.1.9. Metaphor

A good salesperson works the same way. While assumptions might be made based on a prospect's behavior, the salesperson is always listening; her assumptions are always open to challenge. (Malcolm Gladwell depicted this pattern of successful salespeople in Blink [Little, Brown, 2005]).

17.1.10. Want to Know More?

  • OECD privacy guidelines (http://www.oecd.org/document/18/0,2340,en_2649_201185_1815186_1_1_1_1,00.html)

  • Personalization versus Customization (http://www.clickz.com/experts/archives/mkt/precis_mkt/article.php/814811)

17.1.11. Acknowledgments

The idea to handle Lazy Registration in this Ajaxian manner was originally proposed by Chris Were ("Tahpot")(http://tahpot.blogspot.com/2005/06/lazy-registration-with-ajax.html).




Ajax Design Patterns
Ajax Design Patterns
ISBN: 0596101805
EAN: 2147483647
Year: 2007
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net