Something I have been thinking a lot about lately is website speed. The load times for one of my largest clients, OverstockDrugstore, were getting worse by the day. It was due to an increased amount of traffic coming to a website that wasn’t properly tuned. After taking a very aggressive approach to decrease load times, conversions (sales) increased by 1-1.5% on days following. It blew my mind (and others at the company) that load times would have a direct impact on conversions.
If you think about it. it makes sense. 75% of their website visitors are new. So, they are visiting and experiencing the website for the first time. Also, many of them are coming from price engines. Most likely when they do a search on an engine, they go down the list clicking on each link. If the page loads slower than the other sites, they may either loose confidence or at least get a little impatient, which would cause them to choose someone else.
So, I thought I would share some of the things I did. Hopefully it will help you increase your overall website speed and in turn increase your conversions (whatever they may be). And if we all work together on implementing these techniques, and maybe even standardizing them, we could make the internet faster, and greener (saving energy). The following only applies to a Linux Server running PHP.
BENCHMARKING
It’s important before you begin, to get an idea of how your website is performing before you try to make it faster. This will give you an idea first of what to focus on and also a benchmark to compare and look back on. First, I would recommend downloading these add-ons for Firefox:
The first thing to do in order to simulate a first-time visitor, who we will mainly focus on, is to disable cacheing. The Web Developer toolbar makes this really easy. On the very left of the toolbar, there is a disable button. Click on it, and select the first option: “Disable Cache”. This will cause every element of a page to be loaded from the server each time you visit the website… exactly what happens when you visit a site for the first time.
The next thing to do is use Yahoo!’s tool, YSlow. It only works if firebug is already installed. But basically, you will see the icon in the bottom right corner of firefox. Load your page, and take note of the amount of seconds it takes to load the page. I would refresh 3-4 times and take an average number to get a good idea of what your load time for a first-time visitor is.
Next, use YSlow’s Performance analyzer to see in what types of areas you can improve. It gives you an overall grade, along with a grade for each area. I am not going to get into each one, since if you click on the name it will open up to a detailed explanation from Yahoo!. They don’t do a great job in explaining HOW to fix the problem though. Also, keep in mind the grade isn’t an end all - be all. Overstockdrugstore is graded a D overall. It’s a bit misleading, since the items may not apply to you at all or be possible for your organization.
MAKE FEWER HTTP REQUESTS is one of the most important things to look at when it comes to speed. Basically, your browser has to send a request for each separate element (image, js/css file, flash etc). The more elements you have, the more requests have to line up and be processed. The number of requests decreases dramatically with Browser-side cacheing, however that doesn’t help first time visitors. So, it’s important to try and cut this number down. A real easy way, is combining all of your CSS into one file, and all of your js code in a single file. For a lot of coders, this can seem a bit dirt but it is a really easy way to start cutting back on the number of GET requests your browser has to make. If you are a seasoned CSS coder, you could also create a CSS sprite. The benefit is having the user only have to download one large image. CSS is then used to show which region of the image is shown.
Expert Note: What I actually do with Overstockdrugstore is use PHP combine all of the js and css files at runtime and cache the result. My script then checks to see if any of the individual files have changed. If not, it uses the cache. If so, it rebuilds the single file. So, I am able to keep files separate for organization as a coding, but combine them into one for the end user. If you haven’t yet, take a look at Minify.
USE A CDN : A CDN or Content Delivery Network, is a server designed especially for delivering content. Amazon has one called CloudFront which is very affordable. The idea behind this is the content you put on your CDN is delivered to the user simulatenously as your page is loading. Your browser can only send two parallel requests per hostname at a time. But it can load content from multiple domains simultaneously. Also, the CDN delivers your content from a server that is closest to the user, increasing speed. If anything, it is a great way to offset your bandwidth.
Expert Note: If a CDN isn’t a reasonable solution, you could always host your images/css/js on a subdomain and deliver the content that way. Although it will always be sent from the location of your host, it could reduce the number of GET requests and organize your static content.
ADD AN EXPIRES HEADER : This has no impact on first-time visitors but can have a huge impact on subsequent page views. Basically, you need to tell your the Browser when the various elements on your page expire. Yahoo! talks about using a future expires header, which basically means saying an element doesn’t expire for 10 years or so. This wasn’t a practical approach for us, since it would cause you to change the filename of the element each time for the browser to download it. With making changes to our javascript/css all the time, this wouldn’t work.
However, putting an expires header of 600 seconds for each element did make since. Looking at our analytics, I realized that a visitor on average would visit the site for around 10 minutes. Because we change images and update products all the time, I figured it would be best to cache things only for around 10 minutes. I figured as well that if someone was comfortable enough to spend 10 minutes on the site, they would unlikely exit due to a sudden page load of a few more seconds (when the cache expired and they had to re-download elements). This number could be different for you, but using some of the logic I laid out you can find a balance.
An easy way to add an expires header to each element is using your htaccess file. Here is what I use for many of my websites:
<FilesMatch “\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|js|css)$”>
Header set Cache-Control “max-age=600, public”
</FilesMatch>
Basically, any element that matches (css/img/js/swf etc) will have an expires header of 600 seconds added to it before it is sent to the browser. Note, this snippet may not do what it is supposed to. Many shared hosts remove the ability to turn this on using htaccess. So, check with your host if it doesn’t seem to do the trick. How do you know if it’s working? Run YSlow Performance again and click on the Components tab. It will list every element and whether there is an expire time associated with it.
GZIP COMPONENTS: This will have an impact on first time visitors. Most browsers have the ability to uncompress files sent to them in a Zipped (compressed) format. This decreases the length of each GET request, since each element is compressed. The browser then uncompresses it and sends it to your screen. Using htaccess it is really easy to apply a rule that will apply to all the elements you want to be sent using GZip:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/x-javascript text/css text/html text/xml text/javascript
</IfModule>
Using GZip on text files will have the greatest impact. Since images and PDF’s for example are already compressed, it’s a waste of CPU power to compress them as well.
PUT CSS AT THE TOP: I am not sure why any of you reading this wouldn’t be in the habit of putting CSS between the <HEAD> tags at the top of your page. But I guess a good reminder.
PUT JAVASCRIPT AT THE BOTTOM: Depending on what you are using javascript for, this may not be possible. However, any javascript that you can put at the bottom that won’t affect page rendering should. If you have a big js file at the top that has to load, that will plug up your HTTP requests, and could slow down the browser from downloading images/logos etc. Basically a page is loaded from top to bottom, so moving things to the bottom that may stop visual things from loading, which intern act as a progress bar, can hinder users from sticking around.
AVOID CSS EXPRESSIONS: Just click on the link within your YSlow to learn more about this one. My guess is it affects very few of you.
MAKE JAVASCRIPT AND CSS EXTERNAL: Putting all of your CSS and Javascript in external files doesn’t only follow web standards, but it allows the individual files to be cached. Inline javascript or CSS is read every time the page is loaded. By having them in separate files, you can have them cache individually. Keep in mind the comment above, that you should combine all of your javascript and css into a single file (if possible) to also reduce your amount of GET requests.
REDUCE DNS LOOKUPS: This one is a bit touchy, since above I was saying how it’s better to spread your requests across different hostnames. Well, if you get too carried away, your browser has to resolve each individual hostname which could I guess slow things down. Although, DNS requests are generally very fast so I wouldn’t worry about this one as much as looking into a CDN server or using subdomains to deliver content. I think the key is just not getting too carried away. Yahoo! recommends only having 4 hostnames at use on your site at a time.
MINIFY JAVASCRIPT: If you have ever looked at the source code of a javascript file and became upset because there was no formatting, and it was basically impossible to read, that is most likely because the host was being smart, and minifying the javascript. This approach basically cleans out a lot of whitespace javascript files can have along with any developer comments that are added. This can decrease the filesize by quite a bit. Yahoo! provides a few ways for you to get this working. I personally use a PHP app called Minify. It can minify your js and css files at runtime and cache the result for future requests.
AVOID REDIRECTS: Read more at Yahoo!
REMOVE DUPLICATE SCRIPTS: Read more at Yahoo!
CONFIGURE ETAGS: My guess is you don’t need to use Etags. They are basically a flexible way to validate entities. If you don’t have a need for them, you might as well not send them to the browser. Doing so will cut down the amount of information attached to your elements. An easy was is to add the line ” FileETag none ” to the htaccess I showed above for expiration headers:
<FilesMatch “\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|js|css)$”>
FileETag none
Header set Cache-Control “max-age=600, public”
</FilesMatch>
This will take of Etags for any of the file types mentioned.
In Yahoo!’s article, they provide a few other things you can be doing to increase website performance. There are a couple things I would like to cover that have made a huge difference.
SERVER-SIDE CACHING: One thing that can have a huge impact on the amount of time it takes for a new user to access your site is how long it takes the page to get generated. Basically, if you have a dynamic website, PHP has to run a lot of database queries in order to get the content of the page. Delivering a static HTML page doesn’t require any database queries, since the file exists it is simply sent to the browser.
I would recommend using a library like Cache Lite or Memcache. The idea here is using these libraries to reduce the amount of database queries you make in order to generate a page. You can set an expire header which will regenerate the page as frequently as you want. If you have a wordpress blog, I would highly recommend looking into Super Cache, a plugin which will allow anyone who knows how to install a wordpress plugin full server-side caching abilities.
IMAGE COMPRESSION: Please take the time to learn the types of images that are best for your project. For example, JPG images are better at compressing pictures with a lot of colors and or gradients. A PNG however would be a much better choice for images with less blending and or color blocks (like a button). Make sure you are optimizing each image on your site, by selecting the appropriate type and compressing it accordingly. It is a very easy practice that a lot of people overlook, but doing it correctly can make a huge difference for first-time load times.
Conclusion:
I personally think that Caching should be a part of web standards. Implementing proper caching isn’t only easy, it decreases the amount of wasted bandwidth and CPU power across the internet. It feel with how flexible and easy to learn certain programming languages are, programmers/coders are becoming lazy in how they write their code. Let’s work together to standardize caching to improve the speed of the internet as a whole as well as free up bandwidth being wasted on sloppy code.
Also, I must say that the things I mentioned are only a piece of the pie. There are a lot of things that can be done to “tune” your apache server or mysql database, and other techniques to decrease the actaul size of your web pages. Please add to this list.
About 6 months ago, me and my parter Mike Annable launched undertook a new project. It is without argument that the auto industry is in dire circumstances. Many argue that causes have to do with leaders not doing enough to provide for a green future. Although that may be true, there is a major problem with car dealerships across the country: they are way behind in optimizing their websites to achieve any exposure.
Knowing this, we undertook to create a software solution with certain goals in mind. For one, we wanted to help out smaller dealerships, who may not have the money or know-how of ranking their sites on major search engines. Secondly, we wanted to create a new standard of web site optimization across the car industry. We found a market that was in need of a solution. A market that has been overlooked.
So, I personally took on task of creating a system that could scale as big as our dream. A system that would ensure dealerships exposure on the web, with a management system that would only require little or no training. About 2 weeks ago, I finished the project, and we launched our first website in a target city in Florida. The site lists all the dealers with Used Cars in Lakeland Florida. The site itself provides a really simple experience for the car buyer. They can easily view the dealers in that area, view inventory and specials, and easily get in contact with the various dealerships. We now also have used cars in orlando florida. used cars in California, and used cars in Utah.
Our hope is that we can start partnering with others to bring these websites to other cities across the nation. We are open for discussion with dealerships and individuals who may be interested in pursuing this opportunity with us.
I am excited for the opportunity to be speaking at SMX West this year, in Santa Clarita, California. I will be speaking the first day (Feb 10th, 2009) and first session on “Technical Issues for SEO Developers”. I have heard great things from past conferences, and I am looking forward to meeting other industry professionals and making new contacts.
If you are thinking about going, make sure to sign up before Feb 9th to save some money. And if you do come, make sure to say hi.
For about 6 months now, I have been working hard to create an SEO-friendly website that will give more exposure to car dealerships’ inventory. I can’t give all of my secrets here, as the automotive industry is a very fierce and competitive market.
I am not doing any tricky or that hasn’t been done before. I am simply following strict guidelines to make the internal link structure clean and symantic, to optimize the site to it’s fullest. Recently we redesigned it, and are hoping to launch the official site for Orlando florida next week. For updates and news, you can check out the official Orlando Florida Used Cars Blog, which will be updated constantly as we approach. We are looking to launch these sites in key areas across the US, and give all dealerships big and small an opportunity to list their inventory. Hopefully something like this can help an industry that’s in a lot of trouble.
Alright, for those of you not jumping on the train it’s time. As I mentioned 2 weeks ago, BLVD Status has been launched for public BETA. We have received a great response, and at this point have over 500 accounts already!
People are finding out why BLVD is so special. And to help convince you as well, take a look at some of the buzz we have been receiving:
I have been keeping very busy with some internal projects. One such project is a new web analytics tool that we launched today, called BLVD Status. We teamed up with Chris Bennett, of 97th Floor about 7 months ago. It’s been a long time in the making, and it’s a big relief that we finished today. I would like to personally thank my lead developer, Charles Berube, who is the best programmer I know. Without him, our vision would never have come this far.
SO WHAT’S DIFFERENT ABOUT IT?
Well, the whole reason we decided to undertake this project was the fact that we felt other analytic tools were too technical, too hard to setup, or too difficult to understand for most users. We wanted to make a tool that accomplished the following goals:
I am happy to say that we accomplished those goals. Here is a bit more information about what we did to accomplish it:
Live Stats
One analytics program we love is Mint. It has to be installed on the users server with a PHP/MySQL setup. Because of this, we were able to see our stats live. Google Analytics and others have a 24 hour delay. We understand it’s necessary to help with server load, but we are trying to stay “live” as long as we can. Our main dashboard for BLVD has 6 boxes, which shows you quickly and effortlessly what is happening with Conversions, Keywords, Referrers, Site Urls, Outgoing Links, and general Traffic. You can drag the boxes to the order of your liking, as well as set a refresh rate to give you fresh look. Needless to say, I keep my browser stats open all day.
Simple User Interface
One thing I loved about this project, was that I was able to design all the user interfaces and logic without having a client breathing down my neck. I tried to come up with a way that would connect all the pieces to give a nice understanding of what’s happening. I feel with too many analytics programs they try to show how cool they are by throwing in google maps, charts, etc… without a real clear understanding of how they should be interpreted. I decided then, to focus more on the individual users coming to the site. I am happy with where it’s at, and already have ideas of where to improve.
Less than 5 minutes to setup
One thing that is so rad about BLVD is you can literally signup for an account, put the tracking script on your website, and see your stats within 5 minutes. And with that, you can track more difficult things like RSS subscriptions, form submissions etc… with ease. Many analytics programs make you have to alter html code in order to track outgoing links and such. Our goal was to keep everything within the dashboard. That way, a user simply has to install the script on their site, configure their conversions, and they are off to the races. This will allow users of all different skill levels to track things once believed as complicated.
Detailed and intuitive reporting
As I mentioned earlier, we had the frustration that many analytics programs provide good data, but simply don’t present it in a way where it can benefit your website. I wanted to create an analytics program, where after looking at the data I could see what is working as far as design, referrals, advertising, keywords etc… Our reporting options at this point aren’t complete… but let’s just say they are going to blow any other analytics reporting out of the water, simply because once again we put the user in the captain’s chair.
Focused on Conversions
Every website needs a purpose. For example, my website is to promote my business in order to get more leads through my contact forms. One purpose of my blog is to get more subscribers to my RSS feed. Well, shouldn’t an analytics program then allow you to track where someone came from before they filled out your contact form or purchased your product? Or which keyword they typed in Google before subscribing to your RSS feed? Well, ours does. This is what we call Micro Conversions, and it’s freakin bad. When someone makes a conversion (you tell the system what a conversion is), you can look back at where they came from, which pages they visited before making the conversion, how long they were on each page, and how long the conversion took. This allows me to quickly see visitors actions before they do what I want them to do. This helps me think of ways to make the site more sticky or see which keywords/referrers are bringing the highest conversion rate.
We took it a step further too, for you social media junkies. You can use our code to place a “Digg This” button on your site, which will act as a conversion. That way you can track which keywords/referrers bring the most Digg clicks etc… It’s pretty cool.
We also allow you to see the current ranking of your keyword, as well as it’s average over a period of time. You can look at each page on your site and see which keywords/referrers led people to that page…. there is so much to learn.
I guess the next step is for you to get an account and try it out for yourself. There are so many other features I could go over, but it’s best you play with it yourself. We are working on some other nice features too, so stay tuned!
The link again: http://www.blvdstatus.com
And of course… let me know what you think!
My site was due for a makeover. I actually created 2 new designs, and would love to know which one you like more.
The live version I definitely like. My idea here was to focus on my recent work, and most importantly give a clean and modern feel. I like the overall tone, and feel it goes with my name and brand.
The first version I actually like a lot too. This one I had been working on for a while. However, I still felt it was missing something, and could feature my work a little better.
I think the main thing with both of these versions, is keeping things simple and clean. That’s what I am all about. Also, don’t think you can steal the second design since I am not currently using it… I most likely will work it into a future client. Or who knows, maybe a do an A/B test using both designs.
For those of you who would like to know, I used Spry to handle the animations. I created my own function that handles the timer to make it move on it’s own, as well as highlight the current number. Also, I used a simple function to pull my latest WP blog posts. The blog and portfolio are currently being redesigned. In the meantime, let’s get some feedback.
I think it’s time I focus a bit on WordPress, a terrific blogging platform. It’s what I use for all of my clients’ sites because of it’s compatibility, flexibility, and nice admin. I have a lot of experience creating custom themes for WordPress. This is actually pretty easy. When I recently designed 5ones.com , one thing we really wanted was to show recent posts from each category. In the industries 5ones covers, media-rich content is very important. So, we wanted to take these excerpts one step further however, and extract the first image of a post, and convert it to a cropped thumbnail to keep things uniform. I am very pleased with the result.
A word on WordPress Themes:
One very important file when creating a WordPress theme, is the “functions.php” file. This works like the plugin section in WordPress. Basically, when your template is loaded, so are these functions. It’s a great way to create specific functions you can use in your template files, without having to create a plugin for each one. And sense the “functions.php” file is only connected to that specific template, you can choose a different template, and those functions will no longer be loaded.
Ok, so how did you do it?
The first step was to show the post title as a link, the author, and then a small except WITHOUT an image. If the author put an image at the top of their post, I didn’t want this to show up. So, in my index.php file, which acts as the home page, I put in this code:
<?php
//get the latest 3 posts for surfing
query_posts('category_name=Surfing&showposts=3');
while (have_posts()) :
the_post();
//execute the output function
show_post($post);
endwhile;
?>
WordPress has a lot of functions built in. So I used their “query_posts” function to get the latest 3 posts in the category “Surfing” (I repeated this later on for Skating and Snow). Then, in the famous WordPress “while loop”, I execute the function “show_post($post)”. The “$post” variable comes again from wordpress, which is actually a post object, containing all the post info (ie content, author, date, permalink, etc…). So, then in my “functions.php” file, I have my “show_post()” function:
//show the post
function show_post($post) {
echo "<div class=\"post\">\n";
echo "<div class=\"img\">\n";
//checks for image
getImage($post->post_content);
echo "</div>\n";
echo "<div class=\"body\">\n";
echo "\t<h3><a href=\"".$post->guid."\">".$post->post_title."</a> - <small>By ".author($post->post_author)."</small></h3>\n";
echo "\t<p>".summary($post->post_content)."<a href=\"".$post->guid."\">Read Full</a></p>";
echo "</div>\n";
echo "<div class=\"date\">".dateFormat($post->post_date)."<br /><br />";
echo "<br /><a href=\"".$post->guid."#respond\">(".$post->comment_count.") Comments</a></div>\n";
echo "</div>\n";
}
For the most part, I didn’t have to do anything new here. I basically used WordPress’s $post object to access specific information I wanted, and put then put it exactly where I wanted it in my XHTML. There are only 4 functions being called that I had to create.
The being called is “getImage()”. This is the function I use to display the small thumbnail next to the post. Here is the function:
//checks to see if there is an image in the post
// if yes, it displays the image in a box
function getImage ($hay) {
$path = explode("<img",$hay);
if(sizeof($path) > 1) {
$src = explode("alt",$path[1]);
$file = explode("src=",$src[0]);
$url = str_replace('"','',$file[1]);
$url = str_replace("'",' ',$url);
$link = explode("/uploads/",$url);
echo "<img src=\"http://5ones.com/dev/wp-content/themes/5ones-v2/gen_thumb.php?x=62&y=39&src=".$link[1]."\" />\n";
}
}
I am not saying this is the easiest, nor best way to do this part. However, it works great for my purposes. Anyways, here is what is going on. I use the variable $hay to hold the actual post content (which I passed in my show_post() function. I then used the explode function to separate any possible image tags in a post. Then, I am able to check the size of the array created, and if it’s large than zero, I know an image exists and continue on with the function. All I am trying to do, is get the path for the image in the post. So, I do a series of explodes and string replaces to isolate the path. Then, I pass the image path I finally get to my image resizing script (maybe I will share later), that crops the image and outputs it. Beauty.
The next function I use is “summary()” which takes the content, strips out html tags and image tags, truncates the length, and then returns the result. It looks like this:
//returns a summary of the content and strips html tags
function summary($copy) {
$new = strip_tags($copy);
ereg_replace("<img[^>]*>", "", $new);
$new = substr($new,0,200);
$new .= "...";
return $new;
}
The last function I use returns the name of the author. Since the post only gives the id of the author, I do a simple DB query to get the authors’ name:
//returns the name of the author based on id
function author($id) {
$sql = "SELECT display_name FROM wp_users
WHERE ID = '$id'";
$q = mysql_query($sql);
$r = mysql_fetch_array($q);
return $r["display_name"];
}
These are the functions I use to create the home page you see on 5ones. Hopefully these functions can be beneficial to someone trying to create the same thing.
Just wanted to put a word out for a new redesign I did for an action action sports news and information site , 5ones, recently redesigned and launched. I must say again, Wordpress is so easy to use. I created a theme and used the mighty functions.php file to create the cool things you see, like parsing a post for images and showing them on the home page, and the way I set up the whole home page for that matter. I am very pleased with the way it turned out. Hopefully this will inspire some of you. If you want to know how I managed to do anything via wordpress you see, don’t be afraid to post.
Today’s post is pretty simple. For those of you who would like to jump ahead, here is your link. Website error messages are always something that seem a bit clunky on most websites. They either show up as crappy looking alert boxes, or mess up the pages design somehow. I would like to show you an easy way to display nice-looking error messages, using the “fade” effect from you guest it, Spry. This is really simple to do, and in my example I show how you can create a function in PHP, as well as use javascript to display your messages.
Fade via Javascript:
Calling a spry effect is very simple. You first need to create a variable which sets up the fade parameters, and then call that variable again and start the fade. It goes a little something like this:
var error_fade = new Spry.Effect.Highlight('errorBox', {duration: '1500', from:'#ffffff', to:'#ff3300', toggle: true});
error_fade.start();
What’s going on here? In english it would read like this. Create the variable “error_fade” and attach a spry effect to it. Make the effect effect the div on my page with the id “errorBox”. Fade the effect for 1500 milliseconds, starting with the color white and fading to a reddish color. The great thing about setting it up in the variable “error_fade” is that I can call it at anytime. I could set up another variable called “success_fade” and give it a different set of parameters. Actually, I end up doing this with php.
Fade via php function:
Obviously the php isn’t going to do the fade. All it will do is call the fade via a function. The great thing about this, is you could put this function in a class and use it to display any type of message, error or not throughout your application. On an app I am currently working on, this function is in my main file of functions used throughout the site. When I want to show a fade, for example on a successful form submission, I will call it. To see an example, submit the form in my example. You can put anything for your email, I am not validating it’s structure. Here is the function that is being used:
function success($message,$time,$from, $to) {
echo '<div class="success" id="suc">'."\n";
echo "<p>$message</p>";
echo '</div>'."\n".'
<script type="text/javascript">
var sts_fade = new Spry.Effect.Highlight("suc", {duration: "'.$time.'", from:"'.$from.'", to:"'.$to.'"});
sts_fade.start();
</script>';
}
Then you can call the function like this, and set all the parameters you want. For the success box on my example:
$message = "<h2>Your message was sent!</h2><p>A representative will contact you as soon as possible!</p>";
success($message,'1500','#f5fa73','#cfebf7');
Using this function is very easy. I can call it at anytime, reusing the code for you recyclers out there, and being able to set the parameters however I would like. One function to handle all of my needs. Well, I hope you enjoy. If you have any problems adding it to your site, let me know. Let’s all make error messages friendlier, and better looking.
Two days in a row. This is the best I have done in a while. I’m not sure what you will be most excited about today, whether it’s going to be for showing you how to use the UPS Rates and Services API, or whether it’s using Spry to do it in real-time, or whether it’s the fact that my stuff makes you smile. Anyways, here is a link to a working sample of my Spry’d UPS Rates and Service API form.
The Problem:
Too often checkout pages are too many steps and too long. Without me getting into it personally, I will give you a tip that will make your online stores more successful: Limit the checkout process to one page. Recently I had a client I built a custom shopping cart for. She didn’t need a robust system like Os Commerce or Zen Cart, so I built one in from scratch. When I came to building the checkout page, I kept asking myself “how can I make this easier for the front-end user”. After fitting everything into one page, and realizing I could use Spry to get shipping rates RIGHT after they put in their zip, I knew I was on my way to land a home run.
The Solution:
I guess there are two parts to this one. The first is how the freak do I use the UPS API of which they supply close to 70 pages of documentation? Well, first off read this article and download his code. I am not going to take credit in creating the function I use. He also takes you through what you need to do on the UPS website, how to configure his script, and how to use his function.
Mark’s script however, simply returns one rate. I wanted to create a way to display several rate options to my customer. You can see what I did on the example page, below the form. So basically, I create an array with all of the shipping options I want to display. Then I run a foreach statement, to read the array one by one and complete Mark’s function. Each one returns a result that I can then display back to the user. However, I added in a radio button for each one, as well as the name of the shipping method next to it with the returned price from the API.
The next step was to integrate it using Spry’s updateContent utility. Like I showed yesterday this is fairly simple. I use the “onblur” handler again for their zip code, and place the zip code as the second input box to give it some time to load. Here is the “checkShipping” function that is called:
var checkShipping = function () {
//get their zip from the ship_zip box
var zip = document.shipping.ship_zip.value;
document.getElementById("Rates").innerHTML="Loading shipping options for Zip: ” + zip + ” …“;
//only check the zip if it’s more than 4 characters
if(zip.length > 4) {
window.Spry.Utils.updateContent(’Rates’, ‘getUps.php?zip=’ + zip);
}
}
It’s pretty simple. Basically I get the value of their zip, and then display some temporary data into my loading div, to alert the user that something is coming. Then I check that their zip is more than 4 characters, and then I use my getUps.php script to retrieve the info. I pass that same zip variable that is being used to show the customer I am retrieving info for that zip, into the php script and then into the function to be used in calculating shipments.
As always, I am sure you are already thinking of ways to extend this further. Better validation maybe? Using sessions to remember their selection and display it if they have to come back and edit the page again? Maybe putting an awesome animated gif of a flying eagle above the form? Hopefully this will help you on your journey, and you won’t be forced to use OS Commerce or Zen Cart just because they have a plugin that does this same thing.
Stay tuned tomorrow as I discuss how Spry can be used to display very nice alert messages. I might even wrap it up into a PHP class.
I have committed many times to be more active in being a more active “blogger”. Some of my posts have been very successful, like “Fighting Spam With CSS” and “Tweak that Gamma“. Also, with being featured on Elance.com recently about wordpress blogs, I have decided to recommit. My new approach, and hopefully this works, is choosing a topic to cover each week. Each day (M-F) I will demonstrate a small example within that topic, that will hopefully be beneficial to you.
This week is Spry.
You can follow the link to learn more about it, but basically it’s another javascript library created by Adobe. Some things I like about it, is 1. It’s completely free (no donations requested from a large company like Adobe); 2. It’s easy to impliment and use; 3. Their examples are really good and cover a wide variety of topics.
Recently, with a large project I have been working on, Spry has been very important in helping me use AJAX to enhance functionality and user-interaction. Recently, I created the registration pages for this same project. I wanted to make it as simple as possible. So for today, I am going to cover how to use Spry’s updateContent utility, to help me out with user login id’s.
The problem:
Like many sites where a login id is required, it can be frustrating once thousands of users are populating the database, to find a unique login id that hasn’t been taken. I am sure you can share my frustration with trying to create a unique account in Xbox live or yahoo chat. On many websites, the user types in their desire username, selects and confirms their password, and then clicks submit. The form then passes the information to a server-side script which checks the database to see if it’s unique, and then either sends back the form with a very disappointing error, or sends a very gratifying page that says “sexyMomma2007″ is available. When the user id is not unique, it can be frustrating. However, when a user has to continually try new ones and resubmit the form, then wait for a response from the server, that only builds on the frustration… until finally the user snaps and chooses a login that makes no sense and forever will be dissapointing.
The solution:
With this in mind, I thought to myself “Is there anything that can be done. Is there any hope”. Then I remembered the new buzzword “Ajax”, and realized, yes… There is a solution. Why don’t you take a look (I hate it when tutorials only put the finished link at the bottom… if you know enough about how it works just by looking at the code, then copy and paste the freaking code and use it in your own site. If you need more love, keep reading).
The instructions are there, but basically put in a username in the “Create login” box, and then click on the password box. You will then see a response of whether it’s ok or not. Also, you will notice if the username is taken, the “register” button becomes disabled, as another reminder they should try another name to continue. You will be happy to know that only 3 usernames are taken on this example: admin (me), modernblue (me), ferris-bueller (me, I wish). So, get some gratification by typing in your favorite user names and obtaining the best response you’ve had in weeks.
Where does spry come in?
First off, I include the spry script (spryData.js) between the <head> tags. Then, I call sprys “updateContent” function using only one line of code. Let’s look at my full function — read the comments:
var checkLogin = function () {
//get the value of their login name
var login = document.user.login.value;
//check the db to see if its available
window.Spry.Utils.updateContent('response', 'checkLogin.php?login=' + login);
}
The “checkLogin” function is the function I call with the “onblur” handler on my input text field. “onblur” is triggered when your cursor first enters the field, and then is clicked somewhere else (focus->blur). So simply, I get their awesome login name, then via spry, I load my “checkLogin.php” script (which you can see below the example) to see if a username is taken. I then pass the variable into my php script, in this case check an array of usernames (I know many of you are rolling your eyes bc I am using an array, rather than a MySQL “SELECT” statement), and then display the response based on it’s availability. I then call the valid login function, which then checks to see whether the response was available, or taken. Let’s take a look at this function:
//check to see if the username is unique
var validLogin = function () {
//get the class of the response span
var answer = document.getElementById('response').className;
if(answer != "success") {
//change the background of the text box to red
document.getElementById('login').className = 'sorryBg';
//disable the register button
document.user.register.disabled=true;
} else {
//change the background of the text box to green
document.getElementById('login').className = 'successBg';
//enable the register button
document.user.register.disabled=false;
}
}
Simply, this login checks the class name of the returned span I sent from my “checkLogin.php” script. If the class is not “success”, I assign the input box the class of “sorryBg”, which makes the background color of the input box red (international error color), and I also disable the register button for people who don’t notice the obvious red box and red error letters. If the class is “success”, then I assign the input box the class of “successBg”, which makes the background green, as well as enable the register button.
Any other ideas?
Of course with this example I am only touching the surface of using spry within forms. I would suggest using a javascript function to make sure the username is the required length, and has the required characters of for your application. Also, don’t forget everything you do user-side, should be re-validated server-side. I am sure some are rolling their eyes, but when you are doing a site for a client whose users are un-trusting (won’t have javascript enabled) you need to accommodate to them. For that same reason you should also accommodate to users who would always have javascript enabled, and especially want to have a quick and easy process. I would recommend looking at this page as well, to learn about Sprys very cool form validation methods.
What’s up for tomorrow?
I am going to share another example of using Spry.Utils.updateContent to show your users shipping rates based on their zip. I am guessing some of you are already starting to think of how this could be handled. I am also going to include a really simple function for connecting to the UPS api, to get immediate quotes.
If any of you need a little more help explanation, let me know via comments. I will try and help the best I can. And please, remember I left out a lot of things for brevity sake, so please keep comments about validation, compliance, security and politics to yourself.
Elance recently asked me to write an article about creating a successful Wordpress blog. Read my Wordpress Tips article.