Monday, December 7, 2009

An Important Lesson From Jacob Kaplan-Moss

Customers expect more from the companies with whom they choose to do business now more than they ever have in the past. Good companies listen to their customers and are constantly in flux in order to accommodate them. They test, adapt, and evolve, almost as if the customers themselves were running the company.

This is much different than the way it was fifty years ago, when the orders were dictated by upper management and trickled their way down to the rank and file employees, who were supposed to carry them out. There are still a lot of companies that try to run themselves in this fashion. While customers demand change, the CEO and the board of directors, in the interest of keeping themselves where they're at (the top) create a bureaucratic layer in the company designed to insulate them from the customers.

This layer is generally called "customer service". Want to know why we're often on hold with people in India? The company is working very hard to ignore you. You might as well yell at the referee on television during a football game. They're counting on it pacifying you without having to actually deal with the source of your frustration.

Of course, I'm not being fair to customer service, because it can be used to both help and hurt a company. Good companies use it to create a feedback loop, where customer requests are taken into consideration by those in charge, and decisions about how to implement those changes are made, then implemented where needed. And those at the top are sincerely grateful that the customers submitted their feedback, because they know that they're better for it.

Lesser companies assign their customer service department the thankless job of damage control and containment. Keep the hoards at bay with this printout of one-liners. If that doesn't work, offer them a free shirt. (This isn't so much "customer service" as it is "management service".)

If you work with Django in any capacity, you're probably aware that it's pretty easy for any developer to get involved in the process of developing with Django itself. You can read the guidelines on the contributing to Django page, and you can keep yourself informed of the latest developments going on by subscribing to the django-developers mailing list. If you're using Django, it's not a bad idea to read that page and then subscribe.

On a couple of occasions, I've gotten myself involved in submitting suggestions. The last time I did this, I thought I had found a security bug, so I fired off an e-mail to the Django security e-mail address. Within a couple of hours, I got a reply back from Jacob Kaplan-Moss. (If you haven't read The Django Book, he's one of the guys who created Django.) I didn't get an e-mail back from his personal assistant, or an automated response telling me that my inquiry would be looked at eventually, or a reply from India. It came from Jacob himself.

It's reassuring to know that the creators of Django are still very active in its development. They're eating they're own dog food. (And why not? Django rocks.) But I'm certain that Jacob and Adrian, in their rise to Django stardom, have been afforded the means to choose their consulting gigs.

The most interesting part is that, after a little back and forth to clarify the issue, it turned out the error was mine. I had forgotten to apply a recent patch the Django installation on my server. In reality, I sent an e-mail to the Django team asking them for help with a problem that didn't exist and, basically, wasted their time. In spite of this, at the end of our discourse, Jacob thanked me, very sincerely, for my time and for taking the trouble to help him resolve the issue.

That is great customer service.

You could argue that, without a product to sell to me, Jacob's kindness wasn't really customer service but instead just common courtesy, happening between two developers with a common goal. I suppose there's a slight distinction between customer service and just being polite to your fellow man, but I believe it's a very fine line. Django is free, but the fact that those at the top are listening to their "customers" is a clear indicator that Django is still very much on its way up. They still want to provide great customer service, and to those of us using Django, that's great news.

If you're just starting a small e-commerce site, you should be taking every part of customer service very seriously. The technology part has gotten very easy to do, but if you just throw up a site with products on it, hook it up with a drop shipping company, and wait for the orders to roll in, it's not going to help you one bit if no one is there to answer the phone when customers call in with their problems. You must read the e-mails and respond thoughtfully to each of them.

Someday, when you're a whole lot bigger as a company, you can send your customer service to India. But I think if there's ever a day that the Django team decides to do this, it will be the same day a lot of us developers start to consider switching to Ruby on Rails.

Sunday, November 22, 2009

Marketing as a Double-Edged Sword

Believe it or not, there's actually a large subset of the population that believes that all marketers are evil lying scum. They tell you to watch out when a marketer opens their mouth, because they're about to try and sell you something that will slowly kill you. We can probably attribute part of this to the cult followers of the late comedian Bill Hicks and his take on marketers.

To be fair, he did have a point. Due to the efforts of more traditional old-school marketing, we had the Flintstones hawking Winston cigarettes on television. What Mr. Hicks failed to point out in his comedy act was that marketing is little more than a tool used in business, and as such, it can be used to do terrible things like convey the idea of how cool it is to smoke cigarettes to children, but it can also be used to do good things.

Most people probably think of marketers as people who spend their time in office buildings brainstorming ways to sell retail products to consumers to help the bottom line. While this is the most well-known aspect of marketing, it's not what marketing really is. Marketing is about ideation and the dispersion of those ideas. And if you do it right, then maybe, just maybe, you achieve the goal you set out to accomplish by influencing a lot of people and getting them to take a desired action. (In Winston's case, it was to get more people to buy cigarettes.)

It's funny that more people don't understand or embrace the deeper concepts of marketing because all of us have something to market. If you don't believe me, go on Match.com and spend some time browsing the profiles of people who are trying to find someone to date. Most of them are terrible; it's painfully obvious that they don't understand what marketing entails because they don't have the slightest clue how they should be marketing themselves.

Personal ads aside, most people do have something that they want to market. They have an idea that they want to spread to others, either about their church, about a politician or a political cause, or about the fact that their college football team is better than every other one. People resist adapting and learning how marketing works because it seems synonymous with advertising, which is by far the most annoying emergent property of the age of technology. The truth is, Obama didn't win the 2008 election because he spent more on television ads than John McCain; it's because he had a remarkably enthusiastic group of people that liked what he stood for. (Because of this, I wouldn't be at all surprised if there was a small handful of people in Illinois that wrote his name in on the ballot for president in 2004.)

Good marketing, to be effective, should be built right into the product you want to sell. If you're running an e-commerce site, I'm not necessarily talking about the quality of your merchandise you're shipping off. In the first chapter of my book, I talk about why you should be building your site from scratch instead of jumping on a platform: because you want to have fine-grained control over the quality of the product. You want to be able to manage the user experience, because you have to sell them on liking the shopping experience before they'll buy anything from you. And if you jump on the platform that your competitors are using, then you don't have any advantage in offering a better shopping experience to the customer on your site than they could get from those competitors.

If you post a profile on Match.com with a picture that isn't really you and claims that you don't live with your parents when you actually do, you might have an easier time getting people to meet up with you, but you'll have a much harder time developing any kind of long-term, meaningful relationship with anyone. Sure, it's better if you don't live with your parents, because then the marketing is built right into the product (you). But effective marketing is also honest; you don't get anywhere by deceiving people.

Wednesday, November 18, 2009

Make the Decision Easier

People love having lots of options from which to choose, but they hate making decisions. Barry Schwartz makes the case in his book "The Paradox of Choice" that a lot of modern unhappiness is the direct result of living an age where we have an abundance of choices. Case in point: one study found that when people were presented with six different types of chocolate versus thirty different types, the people who were shown only six types were more likely to decide upon and buy one of the types of chocolate.

Give people more options, and opportunity costs rise. It compounds the difficulty of choosing between all those options.

So the marketing people who work for companies that make chocolate do focus groups, and people say they want more choice. The more, the better, they will tell you, and they mean it. But consumer behavior tells another story: the more options you give them, the harder it is for them to decide which one they want.

What's the solution here? Make the decision easy for people.

My friend Mark figured this out, and makes a decent side income working at a department store selling perfume and cologne on nights and weekends. When a woman comes in looking for a good perfume, he starts by showing her the spicy one that accosts the nostrils. Then he shows her the one that smells like powder and makes you think of Grandma. Then he moves on and brings out a fragrance that he thinks the woman will actually like and want to buy. Given two not-so-good choices and then a good one, the decision to buy the last one is an easy one to make.

In practice, it's called framing, and it's the reason that merchandise in so many stores is always "on sale". People might not want to buy the complete Futurama series on DVD in a big plastic Bender head for $109.99, but it becomes more appealing if the sign reads: "Was: $139.99. Now: $109.99!"

Sunday, November 8, 2009

Search Results with Only One Result

I have a question about an issue with internal site search on websites. It's related to how the results are rendered to the user if there is only a single item that matches the customer's search. For example, if you search on Amazon.com for something super specific, like "Beginning Django E-Commerce" in the Book category, you'll be taken to search results page that contains a single result. From there, you can click on that single result and be taken to that book's page on Amazon.

However, if you perform that same search on Borders.com, it only returns a single result, but instead of showing that single result to you on a "results" page, it skips that step and just redirects the user to the book's page. It assumes that if there is only one result, that the customer would have clicked on it, and they're trying to save them that step by just forwarding them automatically to that book's page.

I think there are benefits to the "skip the results" page that Borders.com uses, but I always thought that it would be confusing to some people. After they get used to clicking "Search" and getting a results page, they'll enter one search and suddenly they're on a product page. For technical people who are searching the site, it's pretty easy for them to figure out what's going on. But to the average person, isn't it better to leave the user in control of where they are? Isn't it a better approach to keep them oriented, and let them choose whether or not they click through to the single result?

I couldn't find any definitive answer to this question, and I know better than to trust my own opinions. Has anyone ever had any experience in testing this two alternatives as a usability issue? Is there any overwhelming consensus that the Amazon.com way is better than the way Borders.com does it, or vice versa?

Wednesday, November 4, 2009

The Security Process

Security is about more than just the technology involved in the site you're building. Most of the time, security is a process and not a just one stage of the design. When it comes to creating an e-commerce site, there are certain things you should do to make the site less prone to unauthorized compromise. (which is just a fancy way of saying you don't want John Q. Hacker getting his hands on your customers sensitive financial information.) For example, you might restrict network access on your database server so it can only be accessed remotely from the servers running your application, reducing the likelihood that the guys will be able to mess with your database directly.

But this is just the first step. The Great Wall of China was erected to keep the Xiongnu out, but the Chinese did not merely build the wall and then expect that the structure alone would suffice to keep their border secure. They had to keep it manned, making sure there were Chinese guards stationed in watchtowers at periodic points, actively monitoring for potential intruders.

You can put up a firewall, but that's just the first step in defending against network attacks. You have to be much more proactive. Know the kinds of attacks might be brought against your web application, identify the red flags associated with each, and set up your system so you'll be alerted in case your system detects the signs of the attacks. Be ready with a response plan.

Tuesday, October 27, 2009

"Beginning Django E-Commerce" Book Release!

Yesterday, Beginning Django E-Commerce was officially released on Amazon, so it's now in stock and available for purchase. I don't know how long it's going to take my publisher to get the "Look Inside!" functionality working, so I figured that I would post the 500 foot view of the table of contents here for those who are interested an overview of the book's contents:

Chapter 1 - Best Laid Plans
Chapter 2 - Creating a Django Site
Chapter 3 - Models for Sale
Chapter 4 - The Shopping Cart
Chapter 5 - Site Checkout & Order
Chapter 6 - Customer Accounts
Chapter 7 - Product Images
Chapter 8 - Implementing Product Search
Chapter 9 - Intelligent Cross-Selling
Chapter 10 - Adding in Ajax
Chapter 11 - Search Engine Optimization
Chapter 12 - Web Security Overview
Chapter 13 - Improving Performance
Chapter 14 - Django Testing
Chapter 15 - Deployment
Chapter 16 - Django on Google App Engine

It doesn't say it anywhere else, but the book uses Django 1.1. For those curious about what I cover in addition to Django: I use MySQL as the database engine, mod_wsgi to integrate Django with Apache and NginX in deployment, Google Keyczar for symmetric encryption of credit card information, Google Checkout and Authorize.Net as payment gateways, and the jQuery JavaScript library to handle the Ajax functionality. The last chapter is dedicated to showing the basics of how to deploy Django projects onto Google App Engine using the App Engine Patch project.

I'd like to express my gratitude to all of those people who purchased the alpha version of the book, and thank those of you that provided your opinions and feedback.

Sunday, October 25, 2009

The Sweet Relief of A/B Testing

Sometimes, when someone asks you a question, and there's a lot riding on the answer, it's a relief when you can say, "I don't know" and really mean it.

I've worked for a lot of small companies that set up shop online, and management always ends up asking questions like "What should the text be in the header on the homepage?" or "Where should the 'Add to Cart' button be on the product page?" or "How many steps should the checkout product have?" They ask themselves, and ask their cohorts, but don't come up with any definitive answers, so they start asking the technical people who are busy coding up their site what they think.

I'm one of those people coding up the HTML for your site. And I'm telling you flat-out: I don't know.

Part of this is based on the fact that I'm dealing with incomplete information. If you ask the question more specifically, I might be able to give you my opinion. For example, what change are you hoping to affect in the results? In the land of e-commerce, the answer to this question is almost always related to the number of customers that place orders. You want to know if changing some part of your site will increase the total number of conversions.

Even given the intended goal, I have very little relevant experience on which to base my opinion. Marketers tend to ask developers these kinds of questions because they're hopeful that web programmers understand the domain better than they do. Unfortunately, no matter how experienced we are in e-commerce programming, we really don't know. There are lots of reasons for this. The requirements of your site might be different than other sites, even those of your competitors. Most importantly, it's because we are not your customers; we are developers.

Your customers are the highest authority to which you should appeal for answers about how you should design your site, what the copy should be, and what the contents of each page should be. If you ask me, decisions about the wording of value propositions and calls to action are too important to be left up to anyone other than your customers.

So what is the solution? A/B split test. Use a tool like the Google Website Optimizer which allows you to present two different versions of the same page, randomly, to different customers. After enough time has passed and you've gotten enough samples of customers viewing the page you're testing, the Website Optimizer will test both of them, and then give you a report about which version of the page led to the highest conversion rate.

This takes the guesswork out of it. I've been in several meetings where two managers are arguing with one another about some little point about how the site should look, and one of them turns to me, the developer, and says, "What do you like better, my solutions or his?" And then they both turn and look at me, waiting for me to answer, each one hopeful that I'll agree with their opinion so they can rub it in the other's face. Eagerly looking to me for a vote, as if I were some kind of "trump card".

You might be tempted to just agree with the one of the two people who is in a better position to approve your pay increases. Or you might actually be egocentric enough to think you know the correct answer. Don't risk it. Even if you offer an opinion, they might ask you to explain why, and then you're just going to become a fountain spewing forth made-up reasons in an attempt to justify yourself.

As a developer, you should practice saying it a few times, until it becomes automatic: "I don't know. We should split test it." Remember it the next time a couple of managers are engaged in a pissing contest and ask you what you think. You'll feel the relief of never actually having the burden of the decision rest on you. It's a great way to stop arguments before they even start.

Wednesday, October 21, 2009

Excellent AES Overview

In Chapter 12, when I talk about using Google Keyczar in order to handle encryption of credit card information, I mention that the library uses the Advanced Encryption Standard (AES) as the cryptographic protocol. I did not discuss the gory details behind how AES is implemented.

I found the following to explain it in a more concise and entertaining way than I could in the book. I hope you enjoy:

A Stick Figure Guide to the Advanced Encryption Standard (AES)

The Developer Mindset

Last week, as I was wrapping up a user interface item that I had been working on at work, I called my boss over to have a quick look at the web page I had created, to make sure it made sense to a fresh set of eyes. It was a means for me to get some perspective to determine if there were any glaring problems with what I had created. In other words, I wanted to do a brief usability test.

He took one look at the screen and said, "You know, don't worry too much about creating a good user interface. We have a team of user interface engineers working right now to design something for customers, so you don't need to spend your time worrying about this. Focus more on getting it functional, and we'll overhaul it later." (This was the first I had heard of external user interface engineers being involved in any way.)

He then went on to explain that in his experience, he and his business partners could sit there, furrow their brows, and brainstorm all day long about how to make a particular piece of the interface more intuitive. In the end, he realized, it didn't matter. Whatever they came up with confused some customers in a way that they hadn't foreseen. No matter the case, they always ended up having to take the feedback given to them by customers and improve the interface going on this feedback.

Now, he has a good point in this case, and I happen to agree with him entirely. I'm a backend developer and have very little interface experience. In my case, I wasn't trying to create a perfect user interface. I was merely trying to avoid introducing any additional confusion to what was already there.

And while my boss is well within his rights to tell me how to use my time (since he's paying me), there is a slight fallacy in what he was implying. Telling me not to concern myself with the user interface because there's a team of interface engineers that are going to come in and fix it later is like telling a person they don't need to learn to spell because their word processor has a spell checker. Spell checkers don't always catch missing words, or find errors that are contextual.

Creating software that's usable is a process, and I think it actually requires getting customer feedback and then fixing those problems. You're never going to anticipate all of the problems in advance, without asking a customer to try and use the software.

I'm not a expert on either, but whenever I create code for something, I do take a little bit of time to think about how I would break something I had written. I look for Cross-Site Scripting holes or other security vulnerabilities. I step back a page and then come back to the page I'm working on a few hours later to see if the interface makes sense. I code my HTML so that people with screen readers can use it effectively.

From a security, usability, and accessibility standpoint, this is a good mindset to have. It doesn't make my code 100% secure, or usable, or accessible, but I try to avoid adding more problems by keeping aware of the low-hanging fruit. When you're designing something, you don't have to be an expert on these particular fields, but knowing the basics and how to incorporate them will reduce frustration down the road.

It helps if you make this process a habit. In instant messenger chats with friends, I tend to be a stickler for correct spelling, punctuation, and grammar. This isn't because my friends care whether I use my English good or not. It's because later, when I'm typing an e-mail to my boss or a customer at work, I'm already in the habit, and therefore I'm less likely to make a mistake when it might matter.

Tuesday, October 13, 2009

Removing Customer Accounts

I can recall a small handful of times when I decided to price shop around on the Internet for a particular product. I went onto Google Shopping, entered the product name, and started browsing the sites that were selling the product for the lowest prices. I chose the one that appeared the most reputable and didn't send up any red security flags as I started the checkout process.

While I completed my purchases from these individual sites, I had to create a customer account. I had to supply registration information, and, in order to complete my order, I naturally had to provide shipping and billing information as well, which included for some of them my CVV. Each time, the product I had ordered showed up in the mail in the next week or two. (I don't what happened to "Allow six to eight weeks for delivery", but I'm glad those days are gone; I'm from the super impatient MTV generation.)

Of course, I did business with these sites for the single product that I was looking for, and they sent me the product I ordered in the condition promised. They didn't do anything incorrectly. However, once I had completed each of these transactions, I was pretty sure that I wouldn't be ordering anything from them again. It's nothing personal...my purchase was just a means to an end: they had something I wanted for cheap and I bought it from them. The experience of shopping on their site didn't compell me to return to shop more.

The problem here was that, in each of these cases, when I returned to the sites, none of them offered me any closure. If I want to stop being their customer, there was no way for me to remove my information from their system. There was no "Cancel My Account" option that would scrub my shipping and billing information from their customer database. (It was also unclear to me in most cases just how much of my information they had chosen to store; some of them might have kept my CVV despite the PCI guidelines)

The reason they're doing this is simple: they want to make it easy for me to return and purchase more stuff. If there's even a chance that I'll return one day and attempt to make another purchase, they don't want me to be deterred by the inconvenience of having to enter my information again. Why not err on the side of caution and just keep my account there in perpetuity?

Another reason is the potential for vendor lock-in. They're hoping that the inconvenience of having to enter that information on another site might give them an edge over other competing sites that don't already have my information.

This sounds like a bad idea. People are sensitive about their personal information, particularly when it's financial. They're wary about to whom they're going to provide it. Hanging on to customer data in an effort to keep your customers returning to make subsequent purchases seems like sticking your thumb out between the index and middle finger of your closed fist and saying "Got your nose!" It also seems lazy; instead of competing in a creative and intelligent way, you're just holding a customer's data hostage in the hopes that it will provide them a net benefit that will help you.

One other important reason e-commerce companies are so tight-fisted when it comes to customer information: after the dot-com bubble burst, a lot of tech companies found that the only asset they had with any residual value was their customer data. There's value in the data. Of course, that's no reason to refuse to let customers remove their data. To make decisions based on the assumption that your company will eventually fail is a violation of the continuity principle. That is to say, you shouldn't let the "what ifs" cloud the day-to-day operating decisions of your business. You're supposed to be adding value for your customers, not planning your exit strategy.

Here's a progressive idea: let customers delete their accounts. Give them a clear and obvious means of doing it somewhere in the interface of your site. When you're trying to convert them from anonymous customer to registered customer, tell them that you'll provide them the option of removing their data when they decide they're done. And when they choose to remove their data, actually delete it...don't just provide a friendly message letting them think you've deleted it when you're really just copied all of it into an archived table.

Now, I think this is a great idea, and a good feature that more sites should offer. However, before actually trying to do this, you need to give what you're doing some thought. Take the following view function:

def cancel_view(request):
    request.user.delete()

In most cases where there aren't dependency issues lurking in your model relationships, the Django delete the user and all of the data associated with them. That's one nice thing about the ORM: it crawls the model instance hierarchy and deletes everything from the bottom up, instead of coughing up foreign key constraint errors or leaving some records orphaned in other tables.

In some cases, however, you don't want to delete everything. Take the OrderItem model we created in Chapter 5: it contains the quantity and unit price at purchase time for each item sold on the site. This is tied to the Order model, which might contain shipping or tax charges for each order. And finally, this is tied to the User model. Which means if you delete a customer, you delete their order information as well.

You don't want to remove this. This is part of your financial records. You may keep a fastidious paper trail, printing up packing slips and invoices for each order that you ship, and that might be sufficient for bookkeeping purposes. However, around audit time, it will behoove you to have this information in the database.

Exactly what you choose to store, and how to choose to migrate the information, is based on your own business requirements. At the very least, if you're storing credit card information, I would remove that completely at a customer's behest, particularly because it has no value for you once a customer decides they'll never authorize you to bill them for anything again in the future.

If I had to guess: most customers won't end up ever deleting their information. Even the customers that show up once, place one order, and ne'er return probably won't even go to the trouble of deleting their data. It's more about the offer up front, to ease those customers that are uneasy about providing the information in the first place. Think of it as falling under the same umbrella as your store's "Return Policy".

Friday, October 9, 2009

Django Code Snippets

Man, it's great to be a Python developer! I'm in awe of Guido van Rossum, who made the conscious decision when he created Python to force developers to keep their code neatly formed and readable. He did this in the simplest way: format your code nicely or else it won't run.

This is based on indentation used in the code samples. For example, the following code sample will not run:

def say_hello():
    print "hello!"
     print "hola!"

The function attempts to say "Hello" in two different languages. Notice that, inside of say_hello(), the indentation isn't consistent. This causes Python to raise an IndentationError exception.

This constraint may seem fastidious, but it's brilliant in it implications. Mr. van Rossum is telling you to keep your code pretty or it won't run. He based this on the insightful observation that code is read much more often than it is written. Even code that a developer has written becomes alien to the person who wrote it after only a short period of time.

This is innovation in engineering at its finest. The use of curly braces to denote context in computer code has been inherited by many languages, from C to C++ to Java to C#. Python's creator saw a problem with the status quo, and he chose to do something about it. He made his programming language much more usable than several others that came before and after it.

Creating a new programming language is not something most people, even programmers, can do. It's even rarer that people innovate in this fashion. Guido van Rossum did both; this is the reason that he now works for Google.

For this reason, I urge any developer getting started with Python (Django developers, this includes you!) to read the Python Style Guidelines in PEP 8. These guidelines have been put forth by Mr. van Rossum himself. If you're a Python developer and you haven't read PEP 8 yet, go read it now before you write any more code. It's well worth your time.

Of course, a lot of the recommendations made in the document are just that: recommendations. Your code will run just fine even if you don't adhere strictly to every last one of these guidelines. However, in order to keep number of broken windows in Python community code to a minimum (higher quality code = happier developers), you should be following these guidelines whenever you can.

One of the suggestions is to use four spaces for each level of indentation. (The document cautions against using tabs, but if you're going to use them, set the tab width to four character spaces.) Unfortunately, while I was writing Beginning Django E-Commerce, I was using two separate computers to write code and write the book. For this reason, some code samples in the book use four spaces for indentation, while others use five. I didn't catch this error before the book went to press since the Word template uses a very narrow font for code samples in the text. (They come out much wider in print.)

This does NOT mean the book's code is broken. Python allows you to mix different indentation lengths, just not within a single code block. As you're reading, you'll probably notice the difference in indentation between code in earlier chapters and later ones. It's unfortunate, but not a deal breaker. And the source code you can download from the Apress web site uses 4 space tabs for indentation, consistently.

Just something to keep in mind while you're pounding out Django code while working through the book: you are encouraged to use 4-space indents. Do as Guido says...not as I do.