feedback
Sep 30 2006

Making Design Decisions Based on Visual Mouse-Click data from CrazyEgg.com

by John Dyer

For the last two weeks, I've been running some tests of DTS's website (which was featured on godbit and just won an best of the web award!) with CrazyEgg.com. We tested our two most important pages, the front page, and the Admissions page. The following information could be discovered via standard analytics but is is far more intuitive and easier to "see" with CrazyEgg's visual tools.

DTS Front Page

 Click map Heat map
DTS Front Page Click map DTS Front Page heat map

For those who've never worked on a University website (DTS stats: 2000 students, 200 faculty/staff, 11,000 alumni), the front page must function as: 1) an attractive, informative call-to-action for prospective students, 2) an information portal for current students, alumni, and staff, and 3) a public relations piece for the public and donors. In other words, a University front page needs to convey a lot of information for several very different audiences. Our Lead Designer, Tim Kimberley (of HeLives.com) has done an incredible job laying out all this information. Now, with the CrazyEgg.com data, we've learned a few things that justify our design decisions and will hopefully lead us to make it even better:

1) Be careful with links that don't look like links - In the lower half of the page, the headers "dts family", "feature items", "calendar" are all clickable links that take you to pages with more information in those categories - but, not many people click on them. Perhaps not many users "gets" that those are links since there is no underline. A possible solution is to add a "more" button next to each heading.

2) Unused menu items - From the heatmap, it's pretty easy to see that the top left menu is very popular and that some items are more popular than others. This would be harder to "see" using analytics. The "Become a Student" area is really working and prospective students are using all three sub links. But we also noticed that the "donate" button is not very popular. We may need to rethink how we word that area since it takes up so much valuable real estate.

3) Unexpectedly popular links - The "campusnet" link is a lot "hotter" than we would have guessed. Campusnet is separate website where students login and register for classes. We thought they would just go directly to the website by typing in the URL(campus.dts.edu), but it appears that a lot of them go through this link. In the design phase, I didn't want to include this link, but I'm glad we did (note: we filtered out all web traffic coming from our campus to skew the data toward external visitors, so this link might have been even more popular if we had included students, faculty, and staff using campus computers.)

4) Search - Although we know that many users like to search, it's nice to be able to visually see that the search box is important and heavily used. (note: we also track what the most common search terms are and we display "Popular links" at the top. Ex: fees and bock)

5) Flash? - CrazyEgg.com does not currently have a way to detect flash clicks. We may want to change out the flash rotator to a JavaScript rotator so that we can see more clicks (jCarousel?). (Note: we use unobstrusive JavaScript to ensure users without Flash have a good experience).

Admissions Page (Become a Student)

 Click map Heat map

The Admissions page is probably the most important page on a University website. Once the user has made it past the front page, this is our best chance to layout the information they need and the steps they need to take in order to find out if our school is the best for them. We've done a few things there not found on most sites. In the left column (campus picture and stats) functions to convey a sense of the school and nothing there is clickable. In the right column, we put together some videos about the school and a few interesting links in order to convey a sense of the people at DTS. The center column is focal area where the user can begin to do something. The most important things, "apply" "catalog" and "get information" are prominent icons and the major degree programs are clearly laid out. Lastly, there is a bottom section containing a lot of additional information and links to various admissions related pages. Here's what we learned:

1) Prominent icons work - The center column is heavily used and seems to be functioning perfectly. In our old site, these links were text-only. From the heatmap, we can also see that some users click on the text "apply online" and others click on the graphic.

2) Links don't always need an underline - In the green degree box, users click the "learn more" link under each degree more than they click the title of the degree. Here, users seem to "get it" and both links work.

3) Sometimes icons don't work - The links in the lower right (the two students and one professor) are the least-clicked links on the page. We'd like to keep the faces there, but perhaps we can link to more compelling content to better utilize the space.

4) Lists work if they are clear - The bottom of the page is more utilized than I would have guessed. Users click on all of the links and, because they click on some more than others, we can tell that they are actually reading the links. A glance at the heatmap shows that "Expenses" and "Online Education" are two of the most hit pages. We need to spruce up both of these pages since they are heavily trafficed and also perhaps give them even more prominence (maybe put them in place of #3).

5) Don't rely on anaytics alone! - The "visit campus" link is fairly "hot." Just looking at this data, I probably wouldn't change anything. But, we found out from our Admissions team that if a student visits campus he or she is extremely likely to matriculate. Therefore, it would make a lot of sense to promote this link as well, although we couldn't have known that just from the click data.

Summary

It is much easier to quickly understand which links users are clicking with a visual tool like CrazyEgg.com than with a standard analytics tool where one has to manually analyze the data. It's also much easier to justify tough decisions to non-web developers (administrators, presidents, etc.) using a heatmap than a bar graph. But we also know that analytics (visual or non-visual) do not tell the whole story. Standard analytics, user surveys, and interdepartmental communication are still essential tools for web designers. CrazyEgg's visual tools are a welcome and powerful addition to that lineup.

Links

Sep 1 2006

Quick C# Vista Photo Tag Reader

by John Dyer

I've been reading that Vista adds it's tagging data directly to the file (here and here). I tagged some JPEGs and then opened them up in a text file to see what the XMP data would look like. Then I decided to write some quick and dirty code to read the meta data Windows Vista adds to photos. The code opens the file and reads it line-by-line until it reaches the XMP section. Then it pulls out the Title, Subject, Comments, Rating, and Tags that Vista Photo Gallery adds.

public class VistaMetaExtractor
{
    public static VistaMetaInfo GetMetaInfo(string filename)
    {
        VistaMetaInfo metaInfo = null;
        // Find XMP data in file (it might be faster to read the enter file into memory for files under 10MB)
        string xmpData = FindStringInFile(filename, "<xmp:xmpmeta", "</xmp:xmpmeta>");
        if (xmpData != string.Empty)
        {
            // change namespace definitions (i.e. xmlns:prefix##="http://www.w3.org/2000/xmlns/" )
            xmpData = System.Text.RegularExpressions.Regex.Replace(xmpData, @"xmlns:prefix(?:(\d{1,3}))=""http://www.w3.org/2000/xmlns/""", @"xmlns:prefix$1=""http://randomurl.org""");
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(@"<?xml version=""1.0""?>" + xmpData);
            // add namespaces
            XmlNamespaceManager nsMan = new XmlNamespaceManager(xmlDocument.NameTable);
            nsMan.AddNamespace("xmp", "http://ns.adobe.com/xap/1.0/");
            nsMan.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
            nsMan.AddNamespace("MicrosoftPhoto", "http://ns.microsoft.com/photo/1.0");
            nsMan.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
            nsMan.AddNamespace("tiff", "http://ns.adobe.com/tiff/1.0/");
            nsMan.AddNamespace("exif", "http://ns.adobe.com/exif/1.0/");
            // 2. fill in details from XMP data
            metaInfo = new VistaMetaInfo();
            metaInfo.FileInfo = new FileInfo(filename);
            // TAGS
            XmlNodeList tagNodes = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/dc:subject/rdf:Bag/rdf:li", nsMan);
            metaInfo.Tags = new string[tagNodes.Count];
            for (int i = 0; i < tagNodes.Count; i++)
            {
                metaInfo.Tags[ i ] = tagNodes[ i ].InnerText;
            }
            // TITLE
            XmlNodeList titleNodes = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/dc:title/rdf:Alt/rdf:li", nsMan);
            metaInfo.Title = (titleNodes.Count > 0) ? titleNodes[0].InnerText : "";
            // SUBJECT
            XmlNodeList subjectNodes = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/dc:description/rdf:Alt/rdf:li", nsMan);
            metaInfo.Subject = (subjectNodes.Count > 0) ? subjectNodes[0].InnerText : "";
            // COMMENTS
            XmlNodeList commentNodes = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/exif:UserComment/rdf:Alt/rdf:li", nsMan);
            metaInfo.Comments = (commentNodes.Count > 0) ? commentNodes[0].InnerText : "";
            // RATING
            XmlNodeList vistaRating = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/MicrosoftPhoto:Rating", nsMan);
            metaInfo.VistaRating = (vistaRating.Count > 0) ? Convert.ToInt32(vistaRating[0].InnerText) : 0;
            // STARS
            XmlNodeList ratingNodes = xmlDocument.SelectNodes("//rdf:RDF/rdf:Description/xmp:Rating", nsMan);
            metaInfo.Rating = (ratingNodes.Count > 0) ? Convert.ToInt32(ratingNodes[0].InnerText) : 0;
        }
        return metaInfo;
    }
    private static string FindStringInFile(string filename, string startString, string endString)
    {
        string output = string.Empty;
        bool inString = false;
        bool done = false;
        StreamReader sr = new StreamReader(filename);
        while (sr.Peek() >= 0 && !done)
        {
            string line = sr.ReadLine();
            if (inString)
            {
                // check for final
                int endIndex = line.IndexOf(endString);
                if (endIndex > -1)
                {
                    output += line.Substring(0, endIndex + endString.Length);
                    done = true;
                }
                else
                {
                    // keep appending if not at the end
                    output += line;
                }
            }
            else
            {
                // check for start
                int startIndex = line.IndexOf(startString);
                if (startIndex > -1)
                {
                    output += line.Substring(startIndex);
                    inString = true;
                }
            }
        }
        sr.Close();
        return output;
    }
}
public class VistaMetaInfo
{
    private FileInfo _fileInfo;
    private int _rating;
    private int _vistaRating;
    private string _title;
    private string _comments;
    private string _subject;
    private string[] _tags;
    public FileInfo FileInfo
    {
        get { return _fileInfo; }
        set { _fileInfo = value; }
    }
    
    public int Rating
    {
        get { return _rating; }
        set { _rating = value; }
    }
    public int VistaRating
    {
        get { return _vistaRating; }
        set { _vistaRating = value; }
    }
    public string Title
    {
        get { return _title; }
        set { _title = value; }
    }
    public string Subject
    {
        get { return _subject; }
        set { _subject = value; }
    }
    public string Comments
    {
        get { return _comments; }
        set { _comments = value; }
    }
    public string[] Tags
    {
        get { return _tags; }
        set { _tags = value; }
    }
}

It works pretty well and seems fast enough to make a simple gallery application..