3 Techniques to Make a Good Footer Great
Alok wrote this on May 13, 2013 in Product Design. It has 2 comments.
We recently wrote about what your footer says about your business. You could say footers have been on our minds a lot. We've even asked ourselves, "What makes a good footer, great?" Here's what we've come up with: a good footer must provide valuable information that allows people to navigate the site, engage and re-engage visitors with quality content, and give them a means to seek help.
It's easy to design footers as an afterthought. Designers assume that visitors just blow past it anyway — and why shouldn't they? People spend 20% of their attention below the fold. Yet those that scan to the bottom will eventually hit the footer and it'd be a disservice not to use it to your advantage.
What Your Footer Says About Your Business
Responsive CSS Framework Comparison
5 Key Responsive Web Design Elements
SEO 101 Resources: Beginner’s Guides and Tutorials
Configuring the PlaygroundVanity will work out of the box on a default configuration. Assuming you’re using Redis on localhost, post 6379, there’s nothing special to do.
Database connection information is loaded from config/vanity.yml, based on the current environment (RACK_ENV or RAILS_ENV). Example:
development: adapter: redis connection: redis://localhost:6379/0 production: adapter: mongodb database: analyticsIf there’s no configuration file and the application does not create a connection explicitly, Vanity will default to the Redis instance running on localhost at port 6379.
The available database adapters are:
- redis — This adapter is used by default. Available options are connection and password. host, port, database (defaults to 0) options are available, but deprecated.
- mongodb — Available options are host, port, database (defaults to “vanity”), username and password.
- active_record — Uses existing ActiveRecord configuration, by you can over-ride by supplying different options. To pick different underlying adapter, set active_record_adapter.
You want Vanity to collect information (metrics, experiments, etc) in production, but there’s no point collecting data in other environments. You can turn data collection on and off by setting Vanity.playground.collecting. Under Rails, collection is turned off in all environments expect production.
You may want to turn data collection on for integration tests, depending on what you’re testing. Also, you may need to turn it on if your development server runs more than one process, e.g. if you’re using Passenger for development and want to use the Vanity console to pick a particular alternative in an A/B test.
Available configuration options are:
name Is all about … Default load_path Directory containing experiment files experiments logger This should be obvious default/Rails collecting False if you won’t want data collected true When running under Rails, Vanity defaults to using the Rails logger, locates the load_path relative to Rails root, uses the config/vanity.yml configuration file (if present) and turns collection on only in production mode.
If you run a different setup, use the playground object to configure Vanity. For example:
Vanity.playground.load_path = "exp" Vanity.playground.establish_connection "redis://db.example.com"
3 Techniques to Make a Good Footer Great
Alok wrote this on May 13, 2013 in Product Design. It has 2 comments.
We recently wrote about what your footer says about your business. You could say footers have been on our minds a lot. We've even asked ourselves, "What makes a good footer, great?" Here's what we've come up with: a good footer must provide valuable information that allows people to navigate the site, engage and re-engage visitors with quality content, and give them a means to seek help.
It's easy to design footers as an afterthought. Designers assume that visitors just blow past it anyway — and why shouldn't they? People spend 20% of their attention below the fold. Yet those that scan to the bottom will eventually hit the footer and it'd be a disservice not to use it to your advantage.
Did you ever want to resize a video on the fly, scaling it as you would an image? Using intrinsic ratios for video, you can. This technique allows browsers to determine video dimensions based on the width of their containing block.
Illustration:With intrinsic dimensions, a new width triggers a new height calculation, allowing videos to resize and giving them the ability to scale the same way images do. See example one.
The concept
The idea is to create a box with the proper ratio (4:3, 16:9, etc.), then make the video inside that box stretch to fit the dimensions of the box. It’s that simple.
The trick
The padding property is the magic that styles a box with an intrinsic ratio. This is because we’ll set padding in a percentage, based on the width of the containing block.
The CSS rules below illustrate how to style the parent and child to create a “magic wrapper”—a container that proportionally resizes itself depending on the width of its parent. See example two.
.wrapper-with-intrinsic-ratio { position: relative; padding-bottom: 20%; height: 0; } .element-to-stretch { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: teal; }Let’s review the declarations in each rule, starting with .wrapper-with-intrinsic-ratio.
position: relative By declaring position: relative all child elements will position themselves in relation to this container. padding-bottom: 20% This declaration gives the box a specific format. Using 20% for padding makes the height of the box equal to 20% of its width. We specifically chose to use padding-bottom rather than padding-top. This is because IE5 removes the “space” created via padding-top from the flow. In other words, using padding-top: 20% would create the layout we want, but the box would act like an absolutely positioned element, overlapping the next elements in the flow. height: 0 Specifying a height of 0 gives this element “layout” so that IE5 and IE6 will dimension the inner box properly. To learn more, visit “On having layout.”Note: because IE5 and IE6 treat width as a minimum width, you should not use width: 100% as a layout trigger. This causes the box to expand to fill its container rather than respect the width we set for that container.Now, let’s consider each declaration within our .element-to-stretch rule.
position: absolute This frees the element from the height boundary of its parent. This way, it can be positioned over the “padding area.” top: 0 We set top: 0 to position the box near the top of its parent. left: 0 This declaration positions the box near the left side of its parent. width: 100% Declaring width: 100% makes the box stretch to fill the width of its container. height: 100% This declaration makes the box stretch to fill the height of its container. background: teal We apply a color to reveal the layout of the box.The real deal
Example three uses a YouTube video (with YouTube markup), so we need to make room for the chrome. Note that the height of the chrome is static: it is 25 pixels tall, regardless of the dimensions of the video. We also change the padding value to display the video in a widescreen format (16:9).
#containingBlock { width: 50%; } .videoWrapper { position: relative; padding-bottom: 56.25%; padding-top: 25px; height: 0; } object, embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }Let’s take a closer look at our new selectors and declarations, starting with the #containingBlock selector.
width: 50% This is just a wrapper to demonstrate resizing the video based on the viewport width. In the previous example, the containing block was the body element.Now, let’s examine a couple of the declarations under the .videoWrapper selector.
padding-bottom: 56.25% To create a 16:9 ratio, we must divide 9 by 16 (0.5625 or 56.25%). padding-top: 25px To avoid issues with the broken box model (IE5 or IE6 in quirks mode), we use padding-top rather than height to create room for the chrome.Finally, we use the object, embed selector because, while some browsers rely on object (e.g., Safari), others need embed (e.g., Firefox).
Note: I’m using YouTube’s markup for now, but at the end of this article I’ll be using valid markup and dropping embed.
The fix(es) for Internet Explorer
To make this work in Internet Explorer, just add an extra wrapper. (I never said it would be pretty.) See example four.
#containingBlock { width: 50%; } .videoWrapper { position: relative; padding-top: 25px; padding-bottom: 56.25%; height: 0; } * html .videoWrapper { margin-bottom: 45px; margin-bot\tom: 0; } .videoWrapper div, .videoWrapper embed, .videoWrapper object { position:absolute; width: 100%; height: 100%; left: 0; top: 0; }Let’s take a closer look at our new selectors and declarations, starting with our .videoWrapper selector.
height: 0 As seen in example two, IE5 and IE6 need “layout.”Now, let’s look at our * html .videoWrapper selector. Called the “star html hack,” this selector makes sense only for IE6 and under, as only these versions parse the following declarations:
margin-bottom: 45pxAs seen in example two, top padding creates some issue in IE5. Here, we use an arbitrary value (that should work with various chromes) to compensate for the “space” we lose by using padding-top. This is to prevent the video from overlapping subsequent elements.margin-bottom: 0The CSS escape notation (backslash character) within the property name acts as a filter to set a different value for IE6. IE6 “sees” this declaration, while IE5 ignores it. If you prefer using conditional comments rather than the filters above, feel free to move these declarations to IE specific style sheets or style elements in the head of the document.Finally, the .videoWrapper div selector is the extra wrapper we need to make things work in Internet Explorer versions 5, 6, and 7.
Note: we use .videoWrapper div, .videoWrapper embed, and .videoWrapper object {} rather than .videoWrapper * {} to prevent styling alternative content.
The clean up
To make this solution more versatile, we remove padding-top declarations from the previous rules and associate them with classes. This way, we can easily style videos with different ratios and/or chromes. See example five.
#containingBlock { width: 50%; } .videoWrapper { position: relative; height: 0; } * html .videoWrapper { margin-bottom: 45px; margin-bot\tom: 0; } .videoWrapper div, .videoWrapper embed, .videoWrapper object { position: absolute; width: 100%; height: 100%; left: 0; top: 0; } .wideScreen { padding-bottom: 56.25%; } .fourBYthree { padding-bottom: 75%; } .chrome_25 { padding-top: 25px; } .chrome_35 { padding-top: 35px; }Let’s take a look at our new classes, starting with .wideScreen.
.wideScreen We use this class to style div.videoWrapper with a 16:9 ratio. .fourBYthree We use this class to style div.videoWrapper with a 4:3 ratio. .chrome_25 This class makes room for chrome that is 25 pixels tall. .chrome_35 This class makes room for chrome that is 35 pixels tall.The validation issue
When it comes to video, supporting web standards is not easy. First, most vendors do not encode ampersands. Most often, they rely on the twice-cooked method (using the non-standard embed element).
To make our markup standards-compliant, we first replace all ampersands in URLs with “&” Then, we implement a single-object method. Unlike the nested-objects method, this technique feeds user agents a single object, as the sample code shows below. See example six. (Line wraps marked » —Ed.)
<div id="containingBlock"> <div class="videoWrapper"> <div> <!--[if IE]> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" »width="480" height="295"> <param name="movie" value="http://www.youtube.com/v/mDRYnaajUcY » &hl=en&fs=1&showinfo=0" /> <![endif]--> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="http://www. » youtube.com/v/mDRYnaajUcY&hl=en&fs=1&showinfo=0" width="480" » height="295"> <!--<![endif]--> <param name="quality" value="high" /> <param name="wmode" value="opaque" /> <p><a href="http://www.adobe.com/go/getflashplayer"><img alt= » "Get Adobe Flash player" src="http://www.adobe.com/images/shared/ » download_buttons/get_flash_player.gif"/></a></p> </object> </div> </div> ... </div>This single-object technique facilitates generating code as the “forking” is done in a single place <object> rather than in two places <object> and </object>.
The bonus
Because we have an absolutely positioned element within the box, we can hide content “behind” the video. Note: this content is outside the object. It is not “alternative content” per se. See example seven.
<div id="containingBlock"> <div class="videoWrapper"> <div> <!--[if IE]> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" » width="480" height="295"> <param name="movie" value="http://www.youtube.com/v/ » mDRYnaajUcY&hl=en&fs=1&showinfo=0" /> <![endif]--> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="http://www. » youtube.com/v/mDRYnaajUcY&hl=en&fs=1&showinfo=0" width= » "480" height="295"> <!--<![endif]--> <param name="quality" value="high" /> <param name="wmode" value="opaque" /> <p><a href="http://www.adobe.com/go/getflashplayer"> <img » alt="Get Adobe Flash player" src="http://www.adobe.com/images/shared/ » download_buttons/get_flash_player.gif"></a></p> </object> </div> <p>The following is the description of the video embeded in this document.</p> <p>This short clip is about YouTube widescreen formatting. It shows the two main formats (16:9, 4:3) and also explains the best way to create a Flash movie according to the new widescreen format.</p> </div> ... </div>The SWFObject script approach
To automate this method, we can use the SWFObject script to add the .videoWrapper class we need for styling and also to plug in the wrapper we need for IE. See example eight. (Note: in this last example, the width of the containing block is set in ems.)
To add the code we need, we replace the following line in SFWObject v1.5 (around line 117):
n.innerHTML = this.getSWFHTML();With the ones below:
n.className += " videoWrapper"; if(typeof document.documentElement.style.zoom != "undefined"){ var wrapper4ie = document.createElement("div"); n.appendChild(wrapper4ie); wrapper4ie.innerHTML = this.getSWFHTML(); }else{ n.innerHTML = this.getSWFHTML(); };And that’s all there is to it. With just a little CSS and your new know-how, you too can resize and scale videos on the fly. See what you can do with the intrinsic ratio technique and share your results in the discussion.
It’s not unusual to have a flashback to the Netscape Navigator 4 and Internet Explorer 5 days when working on an HTML email. The quality of rendering engines is totally inconsistent, most modern development techniques are unavailable, and even images – an essential element of many emails – are turned off by default in many clients. This can feel like 1998, but the web development community has learned a lot since then. Strategies like progressive enhancement and modern tools like Litmus can help us build HTML emails suited for today’s Babylon of inconsistent desktop clients, various web clients, tablets, smartphones, and high resolution displays.
Last month we decided to start sending educational emails to new Beanstalk customers to familiarize them with our features. The plan was to send a total of three emails with a set interval between them. After designing these emails I decided to explain my process and go through the tools and techniques I used.
Working on layout
We decided that each educational email will be written by a member of our team. Chris, founder of Beanstalk, wrote about deployments, Ilya, one of our lead developers, introduced users to advanced tools, and Russ, our systems engineer, explained our approach to security.
I started with a simple design but wasn’t really happy with it:
Emails written by our team members were personal, but the design didn’t reflect this. It looked as if the email was coming from a company, not the person who actually wrote it. So we decided to put the authors in the front seat while still referencing Beanstalk, and metadata is the perfect place to do this:
Now that its clear that the email is from Beanstalk I simplified the look, added the author’s photo and removed the logo:
This looks and feels much more like a personal letter written on the product’s stationery paper rather than a corporate brochure – exactly what I tried to achieve.
Bringing responsiveness to emails
To figure out which email clients are the most popular between our users I checked Campaign Monitor statistics from our latest newsletter. The results are impressive, but not too surprising for a geeky product like Beanstalk – 30% used Apple Mail, 23% iPhone, 19% Gmail, 6% Sparrow, 5% iPad, 3% Android and the remaining 14% is all other combined. This means that a third of our recipients use devices with smaller screens and our email may not be readable to them.
In normal view our text column width is set to 600 pixels, which limits the number of characters per line to about 85-90 – a top boundary for good readability. I started with adding the @media query for screens narrower than 780 pixels to allow for some whitespace and the green border around the text:
@media only screen and (max-width: 780px) { div[class="bs-email"] { padding-right: 20px !important; padding-left: 20px !important; } div[class="bs-email"] .bs-wrap { width: 100% !important; } div[class="bs-email"] .bs-content img { max-width: 100% !important; height: auto !important; } ... }Here I decreased whitespace around the text, let the text column and images take all of the available space and moved the sender photo inside the column:
Next is a version for small screens, like the ones on smartphones. I added another @media query for max-width: 380px after the first one, where I decreased whitespace even more, removed the green border around the email and set a smaller line height to fit more content on the screen:
Using @media queries in emails with old table-based layout still feels unreal to me, but they‘re well supported in new devices and old clients just ignore them. The only exception I can think of is Yahoo! Mail, which ignores the @media declaration itself but applies all included styles to your normal view. To fix this I use attribute selectors like div[class="className"] or h1[id="unique"], which it ignores too. Speaking of hacks, I can’t recommend HTML Email Boilerplate enough as a starting point in email coding – it’s a great collection of workarounds and fixes to rendering problems in major clients.
High resolution displays
What do people checking emails on iPhones, iPads and Androids have in common? Most of them look at high resolution displays, like Apple‘s Retina. Adding hi-res graphics to email is tricky as many of these people may be on a slow and expensive 3G connection, and nobody will wait a minute for the email to load.
My first take was to replace img elements with divs and use original images as backgrounds, while providing a hi-res version through the @media query only when it is actually needed. This is a hack from any standpoint – divs have no semantic value, they don’t provide alt text when images are disabled, and some old clients just won’t display background images. Even worse is that Gmail and other clients without @media support will show original image on hi-res devices, like MacBook Pro with Retina screen.
This is when I decided to go with the simplest available solution – just create all images twice as big and downsize them with width and height attributes of the img element. This solution works everywhere from Gmail to iPhone, but the downside is increased file size. I used ImageOptim and ImageAlpha rigorously to trim all extra bytes from our graphics and screenshots, and in some cases went with overcompressed JPEG instead of PNG. The total size of an email with 3-5 big images is about 100-150 KB, which is a lot but still not terrible, especially considering we don’t use any graphics in the design (except of logo in the bottom) and images appear only after a few paragraphs of text.
Testing emails
Any testing starts with sending an HTML email, and it’s not as easy as it may sound. First, you need to host all images and assets somewhere so they can be linked from HTML. Second, you need to turn your HTML file into an email and send it. One option is to create a free account on Campaign Monitor or MailChimp and send email previews to your own email address – this works well, but the process can be a bit slow. My new choice and a recent discovery is the Direct Mail app for Mac – it’s free for up to 50 emails per month, beautifully designed and works really well.
Litmus is another favorite of mine. I checked it before but wasn’t sold on the idea of testing and debugging emails based on screenshots, so I always maintained my own library of email clients and accounts. Things changed when they released Interactive Testing which allows you to test, troubleshoot and preview emails in real-time. Not every client in their library has this tool yet, but even the limited selection saved me an enormous amount of time.
Gathering data
I’m risking sounding like a Litmus promoter, but another feature we used for the first time in our transactional emails and totally loved is Litmus Analytics. We generated unique tracking codes for every type of email we send, so now we have a solid set of data on our recipients and their reaction to each of the emails we send. The way they collect this data is some sort of magic, but seeing engagement reports, email clients statistics and even the number of forwards is really empowering. With real data at our hands we can see which emails our users like the most and change our communication accordingly.
Hopefully you found something new in this walk through of my design and development process for emails. Know a better way to do something or have a tool recommendation? Let me know in comments!
Faster Websites: Crash Course on Web PerformanceBy Ilya Grigorik on January 15, 2013
Delivering a fast and optimized user experience in the browser requires careful thinking across many layers of the stack - TCP and up. In a rather ambitious undertaking, when I got the chance to run a three hour (marathon) workshop at Devoxx 2012, I tried to do exactly that: a crash course on web performance. Even with that much time, much was left unsaid, but I'm happy with how it went - it turned out to be one of the most popular workshops.
The best part is, the video is now available online for free! The Devoxx team did an amazing job of post-processing the recording, with inline slides, full agenda navigation, and more. Check it out below. Hope you like it, and let me know if you have any feedback, comments or questions.
Life of a web request: TCP, HTTP, SPDY, Mobile and Navigation Timing
Part one covers much of the underlying networking infrastructure, which you may not think about day-to-day, but which often dictates the delivery and consequent performance of your application:
- What is the impact of slow sites?
- What is "fast" and how are we doing today?
- Life of an HTTP request, TCP-up
- Faster networks will save us, right? (Mostly) Wrong!
- Bandwidth doesn't matter (much)
- HTTP 1.0/1.1 and TCP performance
- SPDY in 10 slides, or less
- Performance of Mobile networks
- Under the hood of Chrome's network stack
- Navigation Timing & Real user measurement (RUM)
Life of a webpage: DOM, CSSOM, rendering, acceleration
Part two picks up from slide 79 and is focused on the architecture and the execution model of the browser:
- Tokenizing, parsing, and construction of the DOM
- Building the Render Tree (DOM and CSSOM)
- Measuring visual & rendering performance
- Hardware acceleration 101
- Putting it all into practice on a synthetic example
- Critical Path analysis for guardian.co.uk
- Performance rules, tips and tricks to apply on your site
Ilya Grigorik is a web performance engineer and developer advocate on the Make The Web Fast team at Google, where he spends his days and nights on making the web fast and driving adoption of performance best practices.
Follow @igrigorik
Responsive CSS Framework Comparison
Object-oriented CSS is awesome. But littering your markup with non-semantic classes is not awesome. Those classes sprinkled all over your HTML are going to change, and that’s not gonna be fun. But if you combine OOCSS and Sass you get the best of both worlds: modular CSS without bloated, hard-to-maintain HTML.
OOCSS leads to hard-to-maintain HTML.
First off, quick disclaimer, a bunch of you probably freaked out the second you read “non-semantic”. Here’s the thing, I don’t actually care about them being non-semantic. I care about what that means for upkeep. Non-semantic classes aren’t needed to describe a component, which means they will change.
The only way to make modules in plain CSS is to define non-semantic classes. (For now.) Then you apply those classes to all of your HTML elements. That’s the OOCSS way of approaching modules. But it comes with big problems:
I don’t want to have to trawl through HTML every time I flip-flop on styling decisions. I work at a startup—things change all the time.
I don’t even have access to some of the DOM elements I would need to add classes to! If you’re using Javascript components to render elements on your page, then you can’t add classes to elements inside the component. (Unless you do some janky, unspeakable things.)
Besides the unmaintainable HTML, everything else about OOCSS is spot on. Abstracting repetition into modules is the only way to keep CSS maintainable on large projects. So how do we get the benefits without the drawbacks?
OOSass to the rescue!
Combining OOCSS and Sass gives you super powers. The @extend directive in Sass lets you inherit styles from another selector without duplicating everything like a @mixin. Which is sweet, but even @extend calls can cause code bloat if you nest them or use them with nested selectors.
Luckily Sass 3.2 added a feature called placeholders. Placeholders are selectors that output nothing unless they are extended. Here’s what a placeholder looks like:
%separator border-top: 1px solid black hr @extend %separator .separator @extend %separatorThat would generate the following CSS:
hr, .separator { border-top: 1px solid black }Placeholders don’t have the code bloat problems that mixins or regular @extend calls have. That makes placeholders perfect for creating non-semantic CSS modules. I call these modules “patterns”. They are little bits of style that you can mix and match throughout your stylesheets.
I’ll show you a real use case.
Take the golden child of OOCSS as an example: the .media module. You probably want to apply the .media module to a bunch of your components: .status, .profile, etc.
Thing is, you don’t want to have to repeat .media all over your HTML. Especially because you’re already going to be repeating .status and .profile. That’s where using placeholders makes things awesomely DRY. Here’s our %media pattern:
%media overflow: hidden &:first-child float: left &:last-child overflow: hiddenNow instead of having to repeat .media on all of your elements, you just extend the %media pattern anywhere you want to use it:
.status @extend %media // Status-specific styles here... .profile @extend %media // Profile-specific styles here...This means that in your HTML you only need to add the semantic classes: .status and .profile—the ones you don’t mind typing because without them all you have is an <article> element.
You also get flexibility. If you decide to change the way statuses look so that the .media module no longer applies, just remove that @extend call and your done! No combing through your HTML to remove .media classes.
Sharp eyes might have noticed that I used a slightly modified version of the .media module. That goes back to not having access to the DOM when using Javascript components…
OOSass makes styling Javascript components easy.
The biggest problem I have with OOCSS is it assumes you have complete control over the DOM and can add classes to it. That’s not always true! When you’re rendering Javascript components (or using someone else’s), you can only touch the top-most element of the component.
If you attach a DropdownView to your .user-dropdown element, you could add a .media class to .user-dropdown. But there’s no way to add classes to the dropdown’s .button or any of its .menu-item’s because you have no control over the DOM inside that component.
With Sass placeholders, that’s not a problem:
.dropdown // Normal styles for every dropdown... .user-dropdown // Extra styles for user-specific dropdowns... .menu-item @extend %mediaYou’d have to do uncouth things to get that to work with pure CSS classes: reaching into components and destroying their encapsulation, or using some sort of horrific string-based className API. But with Sass patterns you can easily augment DOM elements that you have no direct control of.
Okay, okay, get to the examples!
I love reading through other people’s CSS patterns, so I figured I’d share some of my own. Here are some of the patterns I use all over Segment.io:
Lip
This is an Apple-style separator, creating a lip above the content underneath it. (Notice I also have %reversed-lip for handling a lip in the opposite direction.)
%lip clear: both display: block height: 5px background: url('/public/images/patterns/lip/lip.png') no-repeat background-size: 100% 100% %reversed-lip @extend %lip background-image: url('/public/images/patterns/lip/reversed-lip.png')Valley
This just adds two lips to the top and bottom of an element to make it feel like it is recessed into the area around it.
%valley position: relative overflow: hidden &::before, &::after content: '' position: absolute left: 0 right: 0 &::before @extend %lip top: 0 &::after @extend %reversed-lip bottom: 0Plane
A very simple, rounded-corner box. These are the backbone for all of the colored planes on Segment.io
%plane box-shadow: 0 2px 5px rgba($black, .1) border-radius: $border-radius-medium %white-plane @extend %plane background-color: $white %off-white-plane @extend %plane background-color: $off-white ...Seam
You know those borders people make by putting a black line and a white line together and making them translucent? I call that a seam.
%seam clear: both display: block height: 0px border-top: 1px solid rgba($black, .12) border-bottom: 1px solid rgba($white, .15)Well
Similar to a valley, this is just a depression in the page, for things like <code> samples. (It’s actually really similar to the code samples on this blog.)
%well box-shadow: inset 0 1px 5px rgba($black, .14) border-radius: $border-radius-medium %off-white-well @extend %well background-color: $off-white %light-gray-well @extend %well background-color: $light-gray ...Now it’s your turn.
Hopefully that gives you a good idea what patterns can be and how to use them in your CSS components. They’re everywhere.
They should only do one thing, and they should do it well. Harry Roberts mentions that you should keep their names vague and non-semantic. That forces you to make them abstract so that you can use them all over the place. And you can always build patterns on top of each other, like I’ve done in the valley example.
If you have similar patterns of your own, I’d love to see ‘em!
Responsive Design TestingThis tool is for everyone who needs a quick and easy way to test their website design in multiple screen widths.
Permalink style testing
You can test any website, and provide the link to anyone you like by adding their URL to the end of the testing page address. For example: http://mattkersley.com/responsive?google.com
Installing on your own server
- Copy index.html and responsive.js onto your machine
- Update the deafultURL at the top of responsive.js to your own website
- Upload the files into a subdirectory on your server
- Navigate to the new subdirectory via a browser
Once you've uploaded, you can navigate your website from within the iframes, and the others will update. This won't work for external sites however due to browser security restrictions.
Interactive content
- audio
<audio src="audio.mp3" controls preload="none" autoplay loop> </audio>- video
<video width=360 height=240 controls poster="image.jpg"> <source src="movie.mp4" type="video/mp4"> <source src="movie.ogg" type="video/ogg"> </video>Use either the src attribute or source elements.
Metadata contentstyle
The type attribute is optional.
The optional scoped attribute indicates that the styles are intended just for the subtree rooted at the style element's parent element, as opposed to the whole document.
script
The type attribute is optional.
Character encoding
<meta charset="utf-8">
SEO 101 Resources: Beginner’s Guides and Tutorials
The Rails flash is typically used for short messages:
app/controllers/sessions_controller.rb1 redirect_to root_url, notice: "You have been logged out."But it can be used for more than that, any time that you redirect and want to pass along some state without making it part of the URL.
These are some things I’ve used it for.
Identifiers for more complex messages
Maybe you want to show a more complex message after signing up, containing things like links and bullet points.
Rather than send all that in the flash, you can send some identifier that your views know how to handle.
This could be the name of a partial:
app/controllers/users_controller.rb1 2 3 4 5 6 7 class UsersController < ApplicationController def create @user = actually_create_user flash[:partial] = "welcome" redirect_to some_path end end app/views/layouts/application.html.haml1 2 - if flash[:partial] = render partial: "shared/flashes/#{flash[:partial]}" app/views/shared/flashes/_welcome.html.haml1 2 3 4 %p Welcome! %ul %li= link_to("Do this!", this_path) %li= link_to("Do that!", that_path)Or just a flag:
app/controllers/users_controller.rb1 2 flash[:signed_up] = true redirect_to root_path app/views/welcomes/show.html.haml1 2 - if flash[:signed_up] %p Welcome!Pass on the referer
Say you have some filter redirecting incoming requests. Maybe you’re detecting the locale and adding it to the URL, or verifying credentials.
You can use the flash to make sure the redirected-to controller gets the original referer.
app/controllers/application_controller.rb1 2 3 4 5 6 7 8 9 10 11 12 class ApplicationController < ActionController::Base before_filter :make_locale_explicit private def make_locale_explicit if params[:locale].blank? && request.get? flash[:referer] = request.referer redirect_to params.merge(locale: I18n.locale) end end endNow, any controller that cares about the referer could get it with:
1 flash[:referer] || request.refererGoogle Analytics events
Say you want to track a Google Analytics event event with JavaScript when a user has signed up. You could do something like this.
Send event data from the controller:
app/controllers/users_controller.rb1 2 3 4 5 6 7 class UsersController < ApplicationController def create @user = actually_create_user flash[:events] = [ ["_trackEvent", "users", "signup"] ] redirect_to some_path end endThen turn it into JavaScript in your view:
app/helpers/layout_helper.rb1 2 3 4 5 def analytics_events Array(flash[:events]).map do |event| "_gaq.push(#{raw event.to_json});" end.join("\n") end app/views/layouts/application.html.haml1 2 :javascript = analytics_eventsThe flash vs. params
You may have considered that any of the above could have be done with query parameters instead. Including common flash messages:
app/controllers/sessions_controller.rb1 redirect_to root_url(notice: "You have been logged out.") app/views/layouts/application.html.haml1 2 - if params[:notice] %p= params[:notice]Using the flash means that the passed data doesn’t show in the URL, so it won’t happen twice if the link is shared, bookmarked or reloaded. Also the URL will be a little cleaner.
Additionally, the user can’t manipulate the flash, as it’s stored in the session. This adds some protection. If the flash partial example above used params, a user could pass in ../../admin/some_partial to see things they shouldn’t.
Fin
I’d love to hear about what unconventional uses you’ve put the flash to!
Flotr2 is a library for drawing HTML5 charts and graphs. It is a branch of flotr which removes the Prototype dependency and includes many improvements. Features: mobile support framework independent extensible plugin framework custom chart types FF, Chrome, IE6+, Android, iOS lines bars candles pies bubbles To use Flotr2, include the flotr2.min.js script in your page and create a visible <div> with positive width and height. A graph is drawn with the Flotr.draw(container, data, options) method. API: Flotr.draw(container, data, options) container a visible DOM element with positive width and height. data an Array of series. options a configuration object containing flotr configuration options, defining axes, grids, legends, etc. Data Each series is either an array of points [[x0, y0], [x1, y1] ...] or an object with series options and a data member. Internet Explorer Flotr2 is fully supported in IE 9+ and explorer canvas or flashcanvas may be conditionally included to support older versions, as seen in the example above. The following are the default configuration options for Flotr. Additional options are added for individual graph types and plugins. In general, those can be found at the top of each plugin or graph file. Flotr2 Defaults This project uses smoosh to build and jasmine with js-imagediff to test. Tests may be executed by jasmine-headless-webkit with cd spec; jasmine-headless-webkit -j jasmine.yml -c or by a browser by navigating to spec/SpecRunner.html. Directories js/ main source files js/plugins/ flotr plugins js/types/ chart types spec/ Jasmine tests examples/ stable and development example pages make/ build configuration files lib/ included libraries build/ temporary directory used during build Extending Flotr may be extended by adding new graph types and plugins. Graph types define how a particular chart is rendered. Examples include line, bar, pie. Existing graph types are found in js/types/. Plugins extend the core of flotr with new functionality. They can add interactions, new decorations, etc. Examples include titles, labels and selection. Plugins are found in js/plugins/. Flotr2 is on Google groups Issues Please submit issues and pull requests on github at http://github.com/HumbleSoftware/Flotr2/issues. Source The source is available on github at http://github.com/HumbleSoftware/Flotr2.
Increasing Application Performance with HTTP Cache Headers Last Updated: 11 July 2012 http headers performance Table of ContentsThe modern day developer has a wide variety of techniques and technologies available to improve application performance and end-user experience. One of the most frequently overlooked technologies is that of the HTTP cache.
HTTP caching is a universally adopted specification across all modern web browsers, making its implementation in web applications simple. Appropriate use of these standards can benefit your application greatly, improving response times and reducing server load. However, incorrect caching can cause users to see out-of-date content and hard to debug issues. This article discusses the specifics of HTTP caching and in what scenarios to employ an HTTP cache header based strategy.
Overview
HTTP caching occurs when the browser stores local copies of web resources for faster retrieval the next time the resource is required. As your application serves resources it can attach cache headers to the response specifying the desired cache behavior.
When an item is fully cached, the browser may choose to not contact the server at all and simply use its own cached copy:
For instance, once CSS stylesheets from your application are downloaded by the browser there’s no need to download them again during the user’s session. This holds true for many asset types like javascript files, images and even infrequently changing dynamic content. In these instances it is beneficial for the users browser to cache this file locally, and use that copy whenever the resource is requested again. An application using HTTP cache headers is able to control this caching behavior and alleviate server-side load.
It is intuitive to think about the end-user’s browser as the primary consumer of HTTP cache headers. However, these HTTP cache headers are available to, and are acted upon by, every intermediate proxy and cache between the source server and the end user.
There are two primary cache headers, Cache-Control and Expires.
Cache-Control
Without the cache-control header set, no other caching headers will yield any results.
The Cache-Control header is the most important header to set as it effectively ‘switches on’ caching in the browser. With this header in place, and set with a value that enables caching, the browser will cache the file for as long as specified. Without this header the browser will re-request the file on each subsequent request.
public resources can be cached not only by the end-user’s browser but also by any intermediate proxies that may be serving many other users as well.
Cache-Control:publicprivate resources are bypassed by intermediate proxies and can only be cached by the end-client.
Cache-Control:privateThe value of the Cache-Control header is a composite one, indicating whether the resource is public or private while also indicating the maximum amount of time it can be cached before considered stale. The max-age value sets a timespan for how long to cache the resource (in seconds).
Cache-Control:public, max-age=31536000While the Cache-Control header turns on client-side caching and sets the max-age of a resource the Expires header is used to specify a specific point in time the resource is no longer valid.
Expires
When accompanying the Cache-Control header, Expires simply sets a date from which the cached resource should no longer be considered valid. From this date forward the browser will request a fresh copy of the resource. Until then, the browsers local cached copy will be used:
Note: If both Expires and max-age are set max-age will take precedence.
Cache-Control:public Expires: Mon, 25 Jun 2012 21:31:12 GMTWhile Cache-Control and Expires tells the browser when to next retrieve the resource from the network a few additional headers specify how to retrieve the resource from the network. These types of requests are known as conditional requests.
Conditional requests
Conditional requests are those where the browser can ask the server if it has an updated copy of the resource. The browser will send some information about the cached resource it holds and the server will determine whether updated content should be returned or the browser’s copy is the most recent. In the case of the latter an HTTP status of 304 (not modified) is returned.
Though conditional requests do invoke a call across the network, unmodified resources result in an empty response body – saving the cost of transferring the resource back to the end client. The backend service is also often able to very quickly determine a resource’s last modified date without accessing the resource which itself saves non-trivial processing time.
Time-based
A time-based conditional request ensures that only if the requested resource has changed since the browser’s copy was cached will the contents be transferred. If the cached copy is the most up-to-date then the server returns the 304 response code.
To enable conditional requests the application specifies the last modified time of a resource via the Last-Modified response header.
Cache-Control:public, max-age=31536000 Last-Modified: Mon, 03 Jan 2011 17:45:57 GMTThe next time the browser requests this resource it will only ask for the contents of the resource if they’re unchanged since this date using the If-Modified-Since request header
If-Modified-Since: Mon, 03 Jan 2011 17:45:57 GMTIf the resource hasn’t changed since Mon, 03 Jan 2011 17:45:57 GMT the server will return with an empty body with the 304 response code.
Content-based
The ETag (or Entity Tag) works in a similar way to the Last-Modified header except its value is a digest of the resources contents (for instance, an MD5 hash). This allows the server to identify if the cached contents of the resource are different to the most recent version.
This tag is useful when for when the last modified date is difficult to determine.
Cache-Control:public, max-age=31536000 ETag: "15f0fff99ed5aae4edffdd6496d7131f"On subsequent browser requests the If-None-Match request header is sent with the ETag value of the last requested version of the resource.
If-None-Match: "15f0fff99ed5aae4edffdd6496d7131f"As with the If-Modified-Since header, if the current version has the same ETag value, indicating its value is the same as the browser’s cached copy, then an HTTP status of 304 is returned.
Visibility
Most modern browsers include robust request/response visualization and introspection tools. The Web Inspector found in both Chrome and Safari shows the response and request headers in the ‘Network’ tab.
An initial request to http://http-caching-demo.herokuapp.com/ shows the default set of headers returned by the application (with no cache directives).
By adding the cached query parameter, http://http-caching-demo.herokuapp.com/?cache=true, the application turns on caching with both Cache-Control and Expires headers (both of which are set to 30 seconds in the future).
Adding an etag parameter to the request, http://http-caching-demo.herokuapp.com/?etag=true, causes the sample app to specify the ETag digest of the JSON contents.
On deeper inspection the ETag-based conditional request executes as expected. With the initial request the browser can be seen downloading the file from the server:
However, on subsequent requests you are able to see the server responding to the browsers ETag check with a HTTP status of 304 (not modified) which causes the browser to use its own cached copy:
Use-cases
Static assets
Under normal usage, the starting point for any developer should be to add as an aggressive caching strategy to the files in the application that will not change. Normally this will include static files that are served by the application such as images, CSS file and Javascript files. As these files are typically re-requested on each page, a large performance improvement can be had with little effort.
In these instances, you should set the Cache-Control header, with a max-age value of a year in the future from the time of the request. It is recommended that Expires should be set to a similar value.
1 year is 31536000 seconds
Cache-Control:public; max-age=31536000 Expires: Mon, 25 Jun 2013 21:31:12 GMTIt is not generally a good idea to go any further than this as greater time periods are not supported by the RFC and may be ignored.
Dynamic content
Dynamic content is much more nuanced. For each and every resource, the developer must assess how heavily it can be cached and what the implications might be of serving stale content to the user. Two examples would be the contents of a blog RSS feed (which will not change more than once every few hours), to the JSON packets which drive a user’s Twitter timeline (updating once every few seconds). In these cases it would be reasonable to cache the resources for as long as you believe possible without causing issues for the end user.
Private content
Private content (ie. that which can be considered sensitive and subject to security measures) requires even more assessment. Not only do you as the developer need to determine the cacheability of a particular resource, but you also need to consider the impact of having intermediary caches (such as web proxies) caching the files which may be outside of the users control. If in doubt, it is a safe option to not cache these items at all.
Should end-client caching still be desirable you can ask for resources to only be cached privately (i.e only within the end-user’s browser cache):
Cache-Control:private, max-age=31536000Cache prevention
Highly secure or variable resources often require no caching. For instance, anything involving a shopping cart checkout process. Unfortunately, merely omitting cache headers will not work as many modern web browsers cache items based on their own internal algorithms. In such cases it is necessary to tell the browser to explicitly to not cache items.
In addition to public and private the Cache-Control header can specify no-cache and no-store which informs the browser to not cache the resources under any circumstances.
Both values are required as IE uses no-cache, and Firefox uses no-store.
Cache-Control:no-cache, no-storeImplementation
Once the concepts behind HTTP caching are understood the next step is to implement them in your application. Most modern web frameworks make this a trivial task.
If this article is incorrect or outdated, or omits critical information, please let us know. For all other issues, please see our support channels. Your feedback has been sent to the Dev Center team. Thank you.
Need reasons to love Bootstrap? Look no further.
Built for and by nerds
Like you, we love building awesome products on the web. We love it so much, we decided to help people just like us do it easier, better, and faster. Bootstrap is built for you.
For all skill levels
Bootstrap is designed to help people of all skill levels—designer or developer, huge nerd or early beginner. Use it as a complete kit or use to start something more complex.
Cross-everything
Originally built with only modern browsers in mind, Bootstrap has evolved to include support for all major browsers (even IE7!) and, with Bootstrap 2, tablets and smartphones, too.
12-column grid
Grid systems aren't everything, but having a durable and flexible one at the core of your work can make development much simpler. Use our built-in grid classes or roll your own.
Responsive design
With Bootstrap 2, we've gone fully responsive. Our components are scaled according to a range of resolutions and devices to provide a consistent experience, no matter what.
Styleguide docs
Unlike other front-end toolkits, Bootstrap was designed first and foremost as a styleguide to document not only our features, but best practices and living, coded examples.
Growing library
Despite being only 10kb (gzipped), Bootstrap is one of the most complete front-end toolkits out there with dozens of fully functional components ready to be put to use.
Custom jQuery plugins
What good is an awesome design component without easy-to-use, proper, and extensible interactions? With Bootstrap, you get custom-built jQuery plugins to bring your projects to life.
Built on LESS
Where vanilla CSS falters, LESS excels. Variables, nesting, operations, and mixins in LESS makes coding CSS faster and more efficient with minimal overhead.
A full version of Twitter's Bootstrap with themes, enhancements, and other goodies.
You are Downloading a Release Candidate
I'd like to get as many developers as possible to play with Kickstrap and help me find the loose ends.
While some devs have deployed KS without any problems, I do not recommend using this for production until v. 1.0
Known Issues | Tweet me for any questions
The Facebook Social Plugins (Like Button, Send Button, Comments Box) make integrating your website with Facebook, via the Open Graph, fairly easy.
But how best to track users’ social actions on your website and your website links on Facebook?
This article explains how these two powerful Social Analytics tools differ, the pros and cons of each, and how you can use them together to get useful insights into your analytics…
Now that Google has rolled out Google Analytics for tracking social interactions, many users would like some clarity on how best to use Google Analytics with Facebook Domain Insights, Facebook’s own tool for measuring social actions on its Social Plugins on your website.
Google Analytics Social Interactions Tracking and Facebook Domain Insights
Although both Facebook Domain Insights and Google Analytics Social Tracking offer statistics for Facebook Social plugins on your website — how many times users clicked the Like or Send buttons or used the Comments box — each has its strong points.
Facebook Domain Insights provides lots of user data on actions on Facebook — how many times links to your website are showing up in the News Feed, Page Walls and Profile Walls, how many times users posted links to your website on Facebook and how many times those links were clicked. And, importantly, Domain Insights provides user-demographic data.
Facebook:
Facebook Insights for Domains offers a consolidated view of key metrics for any website, even those that have not implemented Facebook Platform. For example, if a user links to your site in their Facebook status message, that data is included in the analytics for your domain. You can access sharing metrics and demographic information per domain and per URL so you can optimize your content for sharing and better tailor your content to your audience.Google Analytics announced its enhanced analytics for social tracking on June 29, 2011. These new metrics provide more detail on actual actions on your website than does Facebook Domain Insights, distinguishing between clicks on the Like button that Like or Unlike your page, as well as more options for date ranges.
Google:
With Social Plug-in Analytics, recorded interactions range from a Facebook “Like” to a Twitter “Tweet.” While event tracking can track general content interactions as well, Social Analytics provides a consistent framework for recording social interactions. This in turn provides Google Analytics report users with a consistent set of reports to compare social network interactions across multiple networks.Comparing Google Analytics Social Tracking with Facebook Domain Insights
Both analytics tools offer detailed tracking on your website social actions, but they differ primarily in the details they provide and, importantly, in the way the analytics are presented. The only metrics they have in common are how many times the Facebook Like and Send buttons and Comments box on your website were interacted with.
Beyond that, each analytics tool offers unique ways to slice and dice your visitor stats.
Facebook Domain Insights: THE Analytics Tool for On-Facebook Data
When it comes to providing visitor data for actions taken on Facebook, Domain Insights is definitely the tool.
Facebook Domain Insights User Demographic Statistics
One big benefit Facebook Domain Insights offers is user demographics — the age, gender, language and country of those posting, sharing and clicking on your links:
Facebook Domain Insights distinguishes between two types of links to your website posted to News Feeds or Walls:
- Social Plugins: Links generated by Facebook Social Plugins on your website — the Like and Send buttons and the Comments box;
- Organic Shares: Links that people included in their status messages or Wall posts;
Facebook Distribution and Engagement
For the Social Plugins and organic shares, Facebook Domain Insights displays:
- the number of times people viewed stories (impressions) generated by Like button clicks on your website;
- the number of clicks sent to your website from stories in News Feed, Page Walls and Profile Walls;
- the number of views of inbox messages (impressions) generated by the Send button;
- the number of clicks sent to your website from Send button messages;
- the number of times people included a link (organic share) in a status message or Wall post;
- the number of times people viewed stories (impressions) generated from organic shares;
- the number of organic clicks sent to your site from stories in News Feed, Page Walls or Profile Walls.
Website Engagement: Tracking Actions on the Facebook Social Plugins
Facebook Domain Insights also provides the following data about actions taken with the Social Plugins (Like, Send, Comments)on your website:
- the number of times a Like button, Send button or Comments box was displayed on your site or specific page (impressions);
- the number of times a Like button, Send button was clicked on your site or specific page;
- the number of times people clicked a Like button on your site AND added a comment;
- the Like button CTR (Click-Through Rate) — Impressions divided by clicks.
Google Analytics Social Tracking: Better Website Social-Engagement Data
Facebook provides a lot of very useful data on actions on Facebook, as would be expected. And, of course, Google doesn’t have access to this data, so Domain Insights is the tool for measuring on-Facebook distribution and engagement.
However, Google Analytics is definitely THE analytics tool for tracking actions on your website, offering bounce rates, time on site, % of new visits — the standard Google Analytics fare — as well as graphs and charts. Plenty of ways to slice and splice the data!
And you’re not just limited to Facebook Social Plugins. Google Analytics Social Interactions tracking also supports the LinkedIn Share button, the Twitter Tweet button, and the Google +1 button.
NOTE: Read my Social Media Examiner post on implementing Google Analytics Social Tracking on your website.
AND you can track Facebook “Unlikes” as well as Likes. As mentioned below, it appears Facebook Domain Insights aggregates both Likes and Unlikes into one number, perhaps due to the fact that they represent clicks on the same button.
Google Analytics Social Interactions Tracking provides:
Comparing Useability, User Interfaces & Data
Discrepancies in Website Like Button Clicks
I noticed that there was a discrepancy with the number of Like-button clicks between Facebook Domain Insights and Google Analytics for a given week.
Domain Insights indicated there had been 41 clicks to the Like button, where Google Analytics indicated 28 Like clicks and 11 Unlike clicks. Totalling 39 clicks on the Like button. I suspect that Domain Insights may be counting both Likes and Unlikes as the same click on the Like button.
The stats for the number of Send button clicks was approximately the same. Domain Insights indicated 8 “total number of recipients” in messages sent with the Send button, and Google Analytics indicated 6. The difference is likely due to the ability to have multiple recipients for a Send-button message.
Viewing Stats for Your Individual Website Pages
Facebook Domain Insights offers an easy way to get the tracking data for an individual Web page, via a “Select Page” link:
You just paste in the full URL in the popup dialog and — voila! — You have the stats for that page, available for today or the week (But NOT for the month, which is available for all but the “Select Page” view).
Google Analytics, although it does provide much greater flexibility in selecting data ranges, does not allow you to input a specific website URL for which you’d like the tracking data.
THE TAKEAWAY: Use Both Google Analytics Social Track AND Facebook Domain Insights
Each of these two analytics tools has its strengths, and using them in tandem to gauge the effectiveness of your website’s social buttons is definitely the way to go.
Let me know in the comments your experiences using these two tools.
Technorati Tags: Facebook, Facebook Domain Insights, Facebook Insights, Google, Google Analytics, Social Tracking, Visitor Tracking Tools
Converting visitors into valuable users is arguably the most fundamental element of managing a website. We’re going to take a closer look at conversion, discuss what it is, cover some common pitfalls, and tackle improving your site’s conversion rates.
I’ll never forget what my high school economics teacher told the whole class during our first lesson:
The single most important motive for any entrepreneurial activity is profit.
Simple, yes. Cynical, perhaps. But to forget this mantra is to fail in business.
Equally, in web design, it’s easy to forget a website’s raison d’être and become distracted by the finer points of design and development. Whether a site aims to promote a business profile, sell products, or gain a subscribed following, it has specific goals and therefore specific conversions to achieve.
What is Conversion?
Conversion is a marketing term which describes the completion of a desired action by an individual (web site visitor, in our case). These actions can take many forms; subscription to a newsletter, completed sale, application for more information, to name but a few.
Relevant Terminology
Let’s cover a few more of the basics to avoid confusion later..
Conversion Rate: The quantity of successful conversions relative to the amount of casual visits. conversion rate = number of goal achievements / visits.
Impressions: The amount of times an advert is delivered (appears on a web page).
Click Through Rate (CTR): A way of measuring the success of an online ad campaign. click through rate = clicks on an ad / ad impressions. For example, a banner ad delivered 100 times (100 impressions) which receives one click has a CTR of 1%.
Conversion Funnel: A method used in analytics for determining a route taken through a given site. The funnel may begin with an ad or search system, continues through navigation and finally a completed conversion.
Goal: A desired result determined by those who manage a website. Google analytics provides tools for laying out funnels and goals, and measuring their effectiveness.
Conversion Rate Optimization (CRO): Analysis of conversion, failed conversion, and solving any problems encountered.
Whose Responsibility is it?
Optimizing a site’s conversion rate is down to everyone.
Everyone involved in the development of a website plays their own part. In a typical project the client may be responsible for the content and copy, functionality and efficiency may be down to the developer, whereas the visual flow and structure sits with the designer. Conversion should be forefront in each individual’s mind, and success relies on a combination of efforts.
So how do we measure conversion rates in order to optimize them?
Goals and Funnels
Google analytics allows us to track, not only if users reach our goals, but how they get there. We can define goals in the form of urls (even urls which don’t generate a pageview, such as on-page actions) and track how many conversions are realized. As we’ve discussed, these goals can assume the form of a definite url; a purchase confirmation page, a newsletter subscription, even a download file. But your desired goal may just as likely be defined as a specific amount of time spent on the site, or a minimum number of pageviews. These are all valid goals and they’re all trackable.
The following image shows the setting up of a (definite url) goal in Google analytics. Pretty straightforward; you enter a name by which you can recognize the goal data, then the type of goal it is, its url (in this case) and – if the conversion can be valued monetarily – you can whack a value in at the end.
Here we’ve determined our goal as being “thankyou.html”, a page which is reached once someone has completed the contact form on our site. Once data has been gathered, a metric, just like the graphs you’re used to in Google analytics, will be generated. We’ll be able to see the fluctuating success (or failure) of this goal.
So we can see how our goals are performing, but it’s more valuable to be able to see where along the process strengths and weaknesses may lie. That’s where funnels come in. A funnel represents a specific route which you expect users to take to reach your chosen goal. By determining possible paths through your site, you can clearly see how many users follow them, complete them, or at which points they abandon hope and go elsewhere. Let’s edit our existing goal setup and add a potential funnel:
We’d already specified our goal as being “thankyou.html”, and here we’ve specified one way of getting there through the homepage, a portfolio page, and then the contact page. This is an ideal path which we’d like to encourage our users to take, and now (thanks to funnels and goals) we can see just how realistic that is.
Take a look at this (albeit fabricated) visualization report for the funnel we just specified:
The figures may be fake (genuine conversion rates tend to be a fraction of this!) but you can clearly see users gradually dropping off the radar as they approach the goal. Visualizations such as this highlight the weak links in the chain, enabling you to target the problem areas of your site.
At this point, you’ve been made more aware of possible pitfalls in your site structure. For the sake of argument let’s say you know there’s a problem with your contact page – plenty of users are reaching it, but a high proportion are failing to complete the form. How do we go about nailing down exactly where the problem lies?
How do I Improve my Conversion Rate?
Conversion Optimization is about analysis on a case-by-case basis. Examine the success of your goals, scrutinize where problems may lie, and experiment with solutions until you’re confident of the results.
In spite of what you may read elsewhere (largely by companies which offer quick fix solutions), there are no magic remedies for poorly performing sites because there are simply too many variables at play. What works well for one site, may be disastrous for another. Analyze your issues and apply common sense.
Consider the idea that your users have arrived at your site, fully committed to fulfilling your goals. Every poorly designed bit of navigation, every vague instruction, every illogical layout is another hurdle between your user and succesful conversion. Hurdles can take many forms and they may not always be obvious, but identifying them is (clearly) important.
Sometimes, we get caught up trying to sell people, when all they really want is for us to make it easier for them to buy. KISSmetrics
“Good design” combats all possible problems, so I’m not going to list every last detail of what makes up a succesful solution. There are, however, some common sense areas which (as a designer) are definitely worth experimenting with…
Calls to Action
The term Call to Action describes a web page element which solicits action by the user. Often found in the form of a “click me!” button, a link which entices visitors to take the next step, calls to action can be the make or break of your conversion rate.
Typically, size, contrast, and positioning play an important role. Your call to action must grab the users’ attention and convince them to dive in. Check out this experiment by Josh Porter highlighting the benefits of a simple color change to his site’s “Get Started Now!” button.
As always, we cannot generalize these results to all situations. The most we can say is that they hold for the conditions in which they occurred: in this page design, on this site, with the audience that viewed it. Josh Porter
What should you take away from this? No, not that you need to change your buttons to red. Simply that the aesthetics of a call to action button can affect the outcome of a user’s behavior. Check out Paul Boag’s article 10 techniques for an effective ‘call to action’ for some sage advice.
Forms
Forms are a classic culprit for scaring users away. How many times have you gone to purchase something, only to give up when presented with a mammoth info-greedy form?
Take CAPTCHA inputs for example. Perceiveably neccessary to prevent spam filling your inbox, but they’re proven to be large walls to climb over for many users. A report by Casey Henry back in 2009 pointed out the direct effect CAPTCHAs have on conversion.
Examine the following images; both illustrate conversion across 50 websites, the action in question being successful submission of a form. The first shows activity with CAPTCHA turned on, the second with the CAPTCHA turned off. (Green areas represent failed conversions).
The results of this experiment would suggest that preventing SPAM isn’t worth also preventing conversions.
Positioning
This ties back in with our look at calls to action; consider where you place your elements for interaction. The fold (the area of a website visible without having to scroll) is technically awkward to define these days, thanks to different devices displaying various resolutions and proportions. However, it’s safe to say that a user should be made aware of their following action as soon as possible.
Analyzing heat maps makes it clear where users focus most of their attention on any given web page. This report from a couple of years ago highlights areas of attention on scrollable pages. Looking at the image below, we can see that most attention is given to the top of a web page, falling as the page is scrolled down. A secondary peak of interest occurs when the footer is reached.
These thoughts would suggest that it’s wise to place calls to action prominently at the top of a web page, and again at the bottom.
OK. So we’ve covered what conversion is. We know how to measure the conversion rate of our site, and we’ve looked at some possbile areas of improvement. How do we now work out what works and what doesn’t?
A/B Testing
Having established that there’s a problem, it’s time to (once again) lean on Google and see if we can figure out how to fix it. We turn now to Google’s Website Optimizer tools.
Setting up an experiment (known as an A/B Test, or a Split Test) here will allow us to compare conversions across several versions of the same page. For example, we have our existing contact page, this will act as our control. We then duplicate the page, making some deliberate alterations which we believe may improve (or worsen) the chances of our users completing a conversion. We may decide that the contact form has too many fields, that we’ve applied unfairly restrictive form validation, that the form is poorly positioned on the page. There are many variants which could alter the outcome, so make a few versions of the page and set them up in an experiment.
Once you’ve added your pages, plus a destination page to track conversions (the “thankyou.html”), you’ll be prompted to add a wee snippet of javascript to each page, after which you can upload them to your web server. When a user reaches your original page, they’ll be served one of the alternatives and carry on as normal. Data is collected about the varying success of each page (obviously, the more data collected, the more accurate you can expect results to be)
A tested combination typically needs about 200 conversions to get statistically significant results. Web Optimizer Help
Matrices are made available for your analytical pleasure:
What you’re aiming for is a High-confidence winner, a page which, after enough data has been collected, is perceived as being the most successful candidate amongst your page variants. You can then confidently implement the winning configuration in your site and hopefully experience a higher rate of conversion. Better still, you may recognize exactly what it is which makes your “High-confidence winner” so outstanding and be able to apply that magic to the rest of your site!
For more information on A/B testing, check out Lara Swanson’s recent article A Primer on A/B Testing on A List Apart.
Conclusion
If you weren’t previously aware of the concept of conversion, I hope I’ve given you a good understanding of it. If you’ve had experience of goal/funnel analysis, and A/B testing I’d love to hear your thoughts! When all’s said and done, conversion is pretty important. I’m going to leave you with one final thought:
Forget about pulling in more traffic until your site successfully converts the visitors it already gets.
- Stumble!
- I like it!
- Not for me
- Not for me More
- Share to Facebook
- Share
- Comment
- Sponsored
- Click "Stumble!" to discover a new page.
I have to admit: I’m a recovering regexaphobe. When I was new to analytics, I remember someone sending me a snippet of regular expressions (AKA regex) to solve a goal setup conniption I was having. It looked like a foreign language to me. I was fascinated by it but repelled at the same time.
Sadly, my intimidation of regex prevented me from doing more powerful analysis. I tried everything to avoid it and would copy and paste code from articles I saved in my Delicious when I had to create a custom filter. But eventually I hit a wall I couldn’t scale unless I conquered this beast, and I set out on a quest to learn it. But I resolved to only learn enough regex to help me as an analyst. No propeller for me, thankeww.
As unsexy as regex is, I’m writing this post because if you don’t know the basics, you too will be limited in your ability to create segments, goals, and filters in Google Analytics — or whatever Web-based analytics platform you’re using. So I’m going to hit on the main ones you’ll need, without the use of geek speak. I will even subject myself to public scorn by my awesome programmer friends by sharing the goofy mnemonic devices I used early on to remember a few of them I just couldn’t seem to get down.
For ease of scanning, I’m also breaking my regex characters up into leagues to signify which ones I use most, occasionally and seldom to never.
Major League
Pipe (|)
The pipe character (|) is the regex equivalent to or. So let’s say you want to find out how many conversions you received from Google, Bing, or Yahoo, you could set up a segment that looks like this:
Tip: Remember to change the Condition field to Matches regular expression if you use regex to create a segment.
Another example of when I use the | character is when I’m creating a goal, and a step in the goal funnel or conversion can include more than one page:
Dot (.)
The . is a wildcard character. It means match any one character. It can be a number, letter, or special character (even a white space). By itself, it’s not that amazing, but with the help of the next playa, the asterisk (*), it’s all kindsa bad to the bone.
Asterisk (*)
This is the MVP of all regex characters, in my opinion. It says to match 0 or more of the characters before it. So, in other words, it looks at the character before it (most often the . character) and says there may or may not be that character and an unlimited number of matches afterwards.
To be honest, the Advanced Segments area was made so that you could easily go without ever using regex to create segments. It may take you longer — like if you use the Or operator to include all of the different sites that you want to include in your social media segment — but you can get away with it. Between and/or operators and the ability to choose options like Contains or Starts with from the Condition field, you can oftentimes avoid using .*, so I’ll use a more advanced example of how I use these wonder twins.
We have several clients who use subdomains. By default, Google Analytics only shows the URI (the part of the URL after the domain). The problem with that is it clumps all of the site’s pages into one repository, and you can’t easily see which pages are from which subdomains. So I created the following filter that combines the Hostname (domain) and the Request URI (URI) and replaces the standard URI with the full URL. Here, the .* means the Hostname and URI can use any characters.
Backslash (\)
This character escapes out the following character. In plain English that simply means that it says treat the following character as a regular ol’ character and NOT a regex character. So if I write out index\.aspx\?query=funky\+boots (shout out to Michelle Robbins) I’m saying treat the . , ?, and + signs as characters and don’t interpret them as regex. (You’ll learn about the ? and + characters soon.)
Minor League
Caret (^)
This simply means your selection has to begin with whatever you put after it. I use this both in segments and goals. Let’s say I want to look at just the landing pages in one directory of my website. I would use something like this:
I’m only putting this character in the minor leagues because you could choose Starts with from the Condition drop-down menu when creating a segment. But Google doesn’t offer you that option elsewhere.
Dollar Sign ($)
This regex character means that your string ends at that point. For example, health insurance$ matches cheap health insurance but not health insurance rates. Or you could attach a $ to the end of a URL to prevent that URL with any query strings from being included in your match. Or at the end of a directory to analyze only traffic to your category page and not its subpages.
Now here’s a little mnemonic device I, a non-propeller head, came up with when I first started learning regex, but you have to promise not to laugh.
Promise?
Okay, I thought of how you lead someone with a carrot (I know it’s a different spelling — work with me) by putting it out in front and how at the end of the day it’s all about the money. So the ^ goes in front in a regex expression and the $ at the end. Go ahead and laugh (promise breaker), but I guarantee you’ll remember next time.
Question Mark (?)
Technically, this character means 0 or 1 of the character before, but I like to think of it as the previous character being optional. Maybe it’s there, maybe it’s not — who knows, really? Hence the ?. See how easy this is when you’re not learning from a text book printed on recycled paper with a monospaced font?
Okay, so let’s say you want to see keywords that include dining room, but some of your searchers passed notes all through third grade and never learned that doubling up the consonants before –ing makes the vowel short. So how do you include these misspellings? You could use the ? this way:
It would return keywords that match dining room and dinning room.
Parentheses ( )
Parentheses are used to form groups — just like you learned in algebra. I really don’t use these often in creating garden-variety segments or goals. I use these more when I’m creating rewrite filters. Why would I do that? Because I’m in desperate need of a hobby. But besides that, I use them for sites that, for whatever reason, can’t (or won’t) rewrite their nasty dynamic URLs. It’s very difficult to interpret landing page reports that consist of dynamic URLs. So I give them prettier, more intuitive names. (Hmm … Sounds like another post for another day.)
For one client’s site, I wanted to create a bucket for all the URLs that were generated when someone searched for a property on their site. Believe it or not, this was the regex I had to write to create a net big enough to scoop up all of those pages:
(^/index\.html\?pclass.*)|(/index.html\?action=search.*)|(/index\.php\?cur_page=.*)|(/index\.html\?searchtext.*)|(realty/index\.html\?pclass.*)
We’ll get to what all of these regex characters mean, but each group in parentheses was a different version of the resulting search listings pages, depending on where you initiated your search. Ugly, huh? I mean, the regex I wrote was beautiful; it was the code that necessitated this regex that should be sent to bed without dinner.
Another example would be Sep(tember)? would match Sep or September. Or if you wanna get all crazy with it, (S|s)ep(tember)? would match sep, Sep, September, and september. But now I’m just showing off. Sorry.
City League
Square Brackets ([ ])
This means match any one of the characters between the brackets. So, c[aou]p would match cap, cop, and cup. But you can only pick one; that’s the key to the brackets. You can throw in a dash to indicate a range of characters to choose from. For example, [0-5] would mean you could pick any one digit between 0 and 5. I have used these when filtering out IP addresses for larger companies that have a span of IPs. So the IP might look something like this:
This would cover a range of IPs where the last octet spans from 130 to 138.
Plus Sign (+)
To be honest, I never use this character. Actually, I think I used it once just to get the t-shirt. But it means one or more of the previous character. So it’s a lot like the asterisk, except it requires that at least one character matches. It’s a diva.
Curly Braces ({ })
Again, I rarely use these in Google Analytics — usually only with really tricky URL rewrites. But curly braces indicate how many times you may want a character repeated. For simplicity’s sake, I’ll explain how to use it with an example that you probably wouldn’t use in your analytics but would make more sense. (Life is all about compromises.) Let’s say you want to indicate a number that is a US-based five-digit zip code. You would write it as [0-9]{5} because there are five digits in a US zip code.
You could also express a range with curly braces by using the convention {minimum, maximum}. For example, let’s say you have a list of product IDs that start with three lower case letters followed by a hyphen and then three-to-five digits. You could indicate them this way:
[a-z]{3}-[0-9]{3,5}
Testing Your Regex
The best part of Google Analytics is every report comes with a filter at the bottom. And that filter is sensitive to regex. I tried several different regex testers before discovering this is the best regex testing ground when creating regex specific to Google Analytics.
How would you leverage it? Just go to the report that contains the items you’re writing the regex for: the Keyword report if you’re trying to concatenate keywords, Traffic Sources if you’re trying to identify specific sources, etc.
So if I’m writing regex to capture a group of pages to concatenate in a segment to analyze, I’ll go to the Top Content report and paste my regex into the filter. If all of my pages are present and accounted for, I’m golden. It’s a real time saver.
If you want to learn more about using regex, I cut my teeth on LunaMetric’s Regular Expressions for Google Analytics guide (PDF). And Robbin Steif personally answered questions I had about the quiz at the end. That was impressive.
So your turn: How do you use regex with your analytics? Any tips you’ve learned in the trenches? Let us know here or connect with us on Facebook or Twitter. Also, anything you want to learn more about with Google Analytics? Let me know below or on Twitter, my cyber home away from home.
UPDATE: See eight practical examples of regex in Google Analytics.
Google Analytics 5 took the best features of their analytics program and made it even easier to use with new organization and visualization features. Here are nine awesome things you can do with Google Analytics 5 that will help you get the most out of your analytics information and use it to improve your website’s content, conversions, and user experience.
1. See your most important analytics data first.
If there is one (or more) pieces of data you want to see at a glance every time you login to your analytics, be sure to set it up in the Dashboards area.
You can create multiple dashboards, each of which can contain multiple widgets. To create a new dashboard, simply go under Dashboards in the menu bar of your analytics and then select New Dashboard. Then add your widgets. You can choose from widgets that show you one particular metric, a pie chart comparing metrics, a timeline of one to two metrics, or a table showing a dimension with two specific metrics. Each type of widget can also be filtered.
The best part of the dashboards is you can change the date range and see all of your widgets update with that date range’s data. This is great if you want to see an overview of your stats for traffic, goal completions, and other metrics of your choosing all in one place.
2. Find out which online campaigns bring the most traffic and conversions.
Have you been curious which of your online marketing campaigns (anything from local search to social media marketing) are the most successful in terms of bringing traffic and conversions to your website? Then it’s time to look at your advanced segments.
To create an advanced segment, click on the Advanced Segments dropdown and then the New Custom Segment. If you wanted to track traffic from local search directories, then call your custom segment Local Search Profiles and start entering the sites you have profiles on such as maps.google.com/maps/ for Google Places and yelp.com for your Yelp listing.
Once you have entered all of the domains you want to track, you can preview the segment to ensure it is pulling the right data and then save the segment. To view it, click on the Advanced Segments, check the custom segment you want to view and click apply. Now you can see all of your traffic and goal conversion data that arrives from those sources which will give you a good idea of what is working the best for your website. With the right custom segments, you can find out the ROI of your social media campaign as well as your other online marketing strategies.
3. Determine where your best visitors are located.
Have you considered using advertising via Google, Facebook, StumbleUpon, or other services? If not, it might be a daunting task to determine who you should target during your ad setups. Many of them will ask if you want to focus on a specific country or target your ad worldwide.
Thanks to Google Analytics, you don’t have fret any longer. Simply look under your Visitors menu to see the Location demographics of your visitors.
Here, you can see your worldwide stats, including the average time on site and bounce rate of visitors from particular countries. You can also drill down to particular countries and see these stats as well as your goal conversion rates in particular regions.
Now you will know the specific locations whose visitors bring you the most conversions. Targeting visitors in these locations with your ads will result in even more goal completions for your site.
4. Learn what people are searching for on your site.
Most people know how to find the keywords that bring visitors to their sites from search engines. But how would you like to go beyond that to find out what visitors are searching once they are on your site?
If your website has a search box, go ahead and perform a search to see the URL of the search results. As an example, my blog’s search results URL is http://kikolani.com/?s=blogging. Once you have this for your site, click on the settings wheel icon in the top right corner of your Analytics menu bar and find your Profile Settings. Under Site Search Settings, select the option to Do track Site Search and enter s as the query parameter (or the one that fits your site’s URL structure).
To see the results of this setup, go to the Content menu and the Site Search area. Under Usage, you can see what terms are being searched for, if visitors refined their search, continued browsing your site, or exited which will let you know if they are finding what they want. Under Pages, you can see which pages people are upon when they decide to use the search feature. When you click on each page, you can see what terms they searched for.
Site Search can help you determine if people are finding what they are looking for on your site. It can also give you ideas of which pages of your content need more specific information as well as the new content you can create on your site to further engage your visitors.
5. Visualize what people click on the most.
Curious where people are making the most clicks on your site? In-Page Analytics under the Content menu will pull up your website in the Analytics browser with information on the percentage of clicks that have happened on each internal link on your site.
You can hover over each link to see additional details and click through to more pages on your site to see more details. This can help you visually see what areas of your site are the most popular, and help you identify where people are clicking on your site. So if you have a particular link you want visitors to see, you should be sure to place it in the areas of your website that receive the most clicks.
6. Uncover your top content.
Want to know which pages keep your visitors on your website the longest, or have the lowest bounce rate? You can see this quickly by going under the Content menu and selecting Pages under Site Content.
This section can help you identify which pieces of content keep visitors on your site the longest and lead to them wanting to continue onto more pages on your site. This can help you produce more content that people will like in the future.
7. Identify your worst performing pages.
A few items down in the content menu from your top pages are your top exit pages. This will tell you how many people are arriving and exiting on a particular page.
This is somewhat common for blogs as people are coming to find a particular piece of information and then leave (hopefully) satisfied. But for other websites, it may signify that people are not finding what they are looking for on that page and then leaving. This may mean that you need to evaluate your site’s content to ensure that visitors are finding what they want and getting a call to action so they get where you want them to be before they leave, such as subscribing to a mailing list or purchasing a product.
You may want to consider using KISSinsights on these top exit pages to find out why people are leaving these pages.
8. Determine where people abandon the shopping cart.
Does your website have a multiple step checkout process? If so, you should setup a goal for your website using a Goal Funnel. To do so, click on the settings wheel icon and click on Goals. Create a new goal with the Goal Type of URL Destination. After you enter the basic goal details, including the final URL of the checkout process (usually a thank you for your order page), then check the Use funnel box to enter each of the URLs that correspond to the steps a visitor must take when purchasing an item.
By using this setup, you will then be able to view reports showing you when people abandon their shopping cart during their purchasing process.
If you note a particularly high amount of people who exit on the payment page, you’ll know that you need to do some work in order to make that page more shopping friendly. Or if people exit before confirming their order, you’ll know that there is something missing that is making people not want to click that final button. Fixing these issues can lead to more sales in the long run!
9. Discover if you need a mobile site.
Have you been wondering if you need a mobile version of your website? Find out by looking under the Visitors menu. There you will find a Mobile option where you can see all the way down to a specific device and the percentage of your total visits that are from a mobile device.
The key on this screen is looking at the average time on site and the bounce rate. If your average time on site is lower and the bounce rate is higher than your overall numbers, then you’ll know that you’re losing that much of your mobile traffic.
What Awesome Things Do You Learn from Google Analytics?
Now it’s your turn – what awesome things have you learned about your website from Google Analytics? Please share your tips and tricks in the comments!
About the Author: Kristi Hines is a freelance writer, blogger, and social media enthusiast. Her blog Kikolani focuses on blog marketing, including social networking strategies and blogging tips.
One font, 150+ icons
In a single collection, Font Awesome is a pictographic language of web-related actions.
Free for commercial use
The Font Awesome webfont and CSS libraries are completely free for commercial use.
Screen reader compatible
Font Awesome won't trip up screen readers, unlike most icon fonts.
Infinite scalability
Scalable vector graphics means icons look awesome at any size.
CSS control
Easily style icon color, size, shadow, and anything that's possible with CSS.Broad compatibility
Wide @font-face support means Font Awesome works in modern browsers .