Page Speed: Our Super Fast SaaS Marketing Website

Whoa! That was fast! About 0.2 seconds. No database. No plugins. Minimal scripts. Weighs in at a whopping 118 kb's. This is how we built it.

Every SaaS company has two main websites:

  1. The web app.
  2. The marketing website.

The goal of the marketing website is to get people to use the web app. Most of the time they're separate. Separate code bases. Separate domains.

Because they're separate, many SaaS companies use WordPress or another CMS to build their marketing site. Easy to use. Fast turnaround. Quick training.

Makes sense.

I wanted to use WordPress too… until Mike—our technical co-founder—told me there's a better way.

You see, WordPress has a dirty secret. Besides being constantly targeted by hackers, it's suuu-per slow and always will be.

The world's fastest WordPress site will never out-perform what we've built.

Here's proof…


Maxing out page speeds with these tests.

Out of all the sites that give page speed advice, this one loads the fastest.

Pingdom

Bundlify Pingdom

According to Pingdom, our homepage loads in 134 milliseconds, faster than 100% of all tested websites.

PageSpeed Insights

Bundlify PageSpeed Insights

Google's PageSpeed Insights gives us a score of 96/100 for desktop and 91/100 for mobile. They'd give us a higher score if we removed Google Analytics 😀.

GTmetrix

Bundlify GTmetrix

GTmetrix grades us at 97% for both their PageSpeed and YSlow tests.

If we wanted to, we could get A+'s and 100%'s for each of these tests, but some of their scoring is based on impractical or outdated recommendations. Use them as a guide, not gospel.


Why website speed matters.

Speeding up your website is the only guaranteed way to improve each part of your online marketing:

  1. User Experience - People like, trust, and spend more money on websites that load faster. Amazon found that every 100 millisecond delay in load time resulted in 1% loss of sales.
  2. Search and Social Rankings - Search engines, and now Facebook, give higher rankings to fast loading websites. Both Google and Facebook revealed that website speed is one of their algorithm metrics for search rankings.
  3. Ad Conversions - Ad clickers can't convert if they exit before they see your site. Econsultancy found that 40% of consumers leave a website if it takes more than three seconds to load.

Plus, mobile users literally pay per MB to load your website.

Shouldn't you be treating them to a fast-loading, low-cost experience?

Yes, you should. Here's how…


What determines website speed and how to make it load faster.

Page speed is determined by three factors:

  1. HTTP requests - The fewer the requests, the faster it loads. 20-30 requests is good. Under 10 is great. Our homepage has 9.
  2. Page weight - The smaller the page content (i.e. images, JavaScript, fonts, etc.), the faster it loads. 1-2MB is good. Under 1MB is great. Our homepage is 0.1MB.
  3. Hosting - The better the hosting, the faster it loads. Upgrade to a dedicated server, add a CDN, and enable caching. We're hosted on Amazon S3 and CloudFront.

According to Pingdom, the average load time is 3-5 seconds. Google's Site Performance for Webmasters video suggests:

"2 seconds is the threshold for ecommerce website acceptability. At Google, we aim for under a half second."

Here are the steps we took to get this site to load in under 0.2 seconds…


Scrap the database and build a static website.

Pure HTML, CSS, and minimal scripts.

I mentioned earlier that WordPress will never outperform us. It's because WordPress is database-driven. Every post, page, comment, etc. is pulled from the database before displaying on the page.

Even a simple, one-page WordPress website might make 50+ database requests. That takes time.

What's the best way to build a static website?

Go with one of these static website generators. Like a CMS, but they output static pages.

We built ours with Middleman because it's Ruby-based, which is the language we're using to build the app.

What's the result?

Let's take a look.

As part of our pre-build process, I built this same site on WordPress. Here's the comparison:

WordPress vs Middleman comparison graphic

Middleman loads 14x faster with 1/3 as many requests as the same site built with WordPress.


Optimize the Time To First Byte.

How many times have you gone to a website and seen nothing but a blank screen while it loads?

That. Should. Never. Happen.

Think about how a website loads. Get the background, text, and images up as fast as possible.

Here's how:

  1. Write clean code. - Every div, span, and line of CSS makes your site load a little slower. Deliver the design you want with the minimum amount of HTML and CSS.
  2. Optimize the frames per second. - Use the latest HTML5 and CSS3 standards. For instance, we found that CSS flex scrolls cleaner than a traditional grid.
  3. Eliminate render blocking JS. - Make sure every element above the fold—where the bottom of the screen hits the page—renders before a single line of JS is triggered.

Part of making a fast loading website is making it feel even faster than it is. Get the first pixel up quickly!


Host on a dedicated or on-demand server.

If you host on GoDaddy, HostGator, BlueHost, etc., you're probably on a shared hosting server.

Which means your website is one of hundreds, maybe thousands of websites on that server. If any one of those sites get a spike in traffic, your website speed will suffer and it might even go down.

What's the alternative?

One option is a dedicated server, which runs between $70-120+ per month.

Since we don't have a database, we host on-demand with Amazon S3, which costs $1-2 per month.

Plus, S3 with CloudFront gives us instant and unlimited scalability.


Deliver assets through a Content Delivery Network.

A CDN will host your assets on servers around the world so every visitor, regardless of location, can experience a fast loading website.

Someone in the UK will receive the files from the European server. Someone in the US will receive the files from the US server.

It automatically pulls the files from the physically closest server, which boosts your page speed.

We host our assets and marketing website on Amazon CloudFront.


Compress and optimize every image.

If you create a PNG or JPG file in Photoshop, it saves unnecessary meta data to the file. This extra info makes the image 4-5x heavier than it needs to be.

When you upload that image to your website, it carries that data and slows down your page speed.

Instead, make a habit of compressing images with a tool like TinyPNG before you add them to your website. It can save 60-90%.

TinyPNG saved file size

As an example, the featured image on this post was 478kb prior to compression and dropped to 173kb after.

No loss in image quality and it loads much faster.


Minimize the file size of your typography.

The fastest typography option is a system font; Fonts that are pre-loaded on most devices.

We're using Avenir, which is a system font on iOS, and Helvetica as a fall-back, which is a system font on all devices.

If you prefer rendering a premium font from a tool like Typekit, make sure you load only the minimum characters, weights, and styles.

Typekit's characters, weights, and styles

In this example, we're loading the default languages and only 4/16 weights and styles, saving 396kb. Which is a lot considering our entire homepage is 118kb.


Remove all unnecessary JavaScript.

After images, JavaScript is usually the heaviest part of a page.

We cut out as much of the JavaScript that we could while still maintaining the base functionalities as a marketing site.

Here's what we kept:

  1. Google Analytics - For tracking traffic.
  2. Drip marketing - For email subscriptions.
  3. Bootstrap modals - Minimum JS for modal functionality.
  4. Disqus comments - For blog post comments.

That's it.

No ads. No third-party fonts. No flashy jQuery plugins.


Minify the JavaScript, HTML, and stylesheets.

When you upload a JS, HTML, or CSS file to your server, it'll have hundreds of extra line breaks and spaces which makes these files bigger.

To manually minify these files before you upload them to the server, use:

  1. JavaScript - Try UglifyJS to minify your JS.
  2. HTML - Try HTML Minifier to minify your pages.
  3. CSS - Try CSSO to compress your stylesheets.

Middleman has minifying tools baked in. It automatically compresses files, removes duplicate lines, and chucks the code into an uglifier each time we deploy.

Most CMS's have minifying plugins.


Reduce and defer JavaScript.

After removing unnecessary JS and minifying what's left, it's time to reduce and defer it. Which means delivering the JS only after the rest of the page has loaded.

This is how we reduced or deferred our JS files:

  1. Bootstrap - We reduced it by removing all of the non-modal JS, which is the only functionality we're using.
  2. Drip - Drip has one tiny script that we added to the bottom of the page.
  3. Disqus - We deferred the injection of the JS. We don't load it until you start scrolling on the page.

The only JS we didn't reduce or defer is Analytics because we don't want to mess with Google's code (for now).


Enable gzip compression.

Gzip is a file format and method of compressing files so your server can deliver them faster.

It's standard practice. Most hosting companies and servers have gzip compression by default.

To see if you have gzip compression, use this tool.

If it's not enabled, contact your host or follow these instructions.

For us, CloudFront has this baked in.


Cache your pages and assets when appropriate.

When you visit a website with caching, you'll notice that the second time you visit is much faster than the first.

This is because your browser is caching files locally so they don't need to be re-loaded on each visit.

There are two types of caching.

1. Browser Caching

Set expiry dates in the HTTP header for static resources. This instructs the browser to load previously downloaded files rather than re-loading the same ones next time you visit.

Google recommends a minimum cache time of one week and preferably up to one year for assets that change infrequently.

To set expiry dates, follow these instructions.

2. Resource Caching

Additionally, you can individually cache your pages, database (if you have one), objects, files, etc.

This gives you more control for breaking the cache when you update old files.

We use Middleman's cache busters to add hashes—random strings of letters—to the ends of file names. When we update them, the hashes and strings update to make sure you see the updated versions.

Caching on Bundlify

For instance, when we re-load the homepage with cached assets, the page weight drops to less than 1kb!

We have browser caching configured through S3 and file caching through Middleman.


Create static social sharing buttons.

custom social sharing buttons

These are our custom-coded social sharing buttons that display at the bottom of each post.

The JS that creates social media buttons is typically one of the heaviest parts of a marketing webpage.

If we were to load the official Facebook, Twitter, Google+, Pinterest, and LinkedIn sharing buttons, we'd add 30 HTTP requests to this page:

  1. Facebook - 10 requests
  2. Twitter - 4 requests
  3. Google+ - 6 requests
  4. Pinterest - 7 requests
  5. LinkedIn - 3 requests

Instead, we re-created them as static HTML buttons that pass parameters through a URL string.

Here's the HTML

As long as you have your social media meta tags set up correctly, these links will work. Replace the URL's and sample data.

Facebook

<a href="https://www.facebook.com/sharer/sharer.php?u=http://yourdomain.com" target="_blank">Facebook</a>

Twitter

<a href="https://twitter.com/home?status=Your page title http://yourdomain.com @yourhandle" target="_blank">Twitter</a>

Google+

<a href="https://plus.google.com/share?url=http://yourdomain.com" target="_blank">Google+</a>

Pinterest

<a href="https://pinterest.com/pin/create/button/?url=http://yourdomain.com&amp;media=http://yourdomain.com/pageimage.png&amp;description=Your page title" target="_blank">Pinterest</a>

LinkedIn

<a href="https://www.linkedin.com/shareArticle?mini=true&amp;url=http://yourdomain.com/yourimage.png&amp;title=Your page title&amp;summary=Your page summary&amp;source=http://yourdomain.com" target="_blank">LinkedIn</a>


Pull sharing data on build.

Part of the reason that social media buttons are heavy is because they deliver up-to-the-second shared counts.

We could've skipped the shared counts, but they play an important role in helping you decide if something's worth reading and sharing.

Rather than displaying up-to-the-second stats—which would cost us speed—we pull the data and re-calculate these numbers every time we deploy, which is about every eight hours.

This saves 30 HTTP requests on every blog post which is 3x more than our entire homepage.


Employ HTML prefetching and prerendering.

If you know which page your visitor is headed to next—i.e. they're looking at a list of blog posts—you can use HTML prefetching and prerendering to start loading the resources before they click:

  1. Prefetching - Tells the browser to download the next page's assets and store them in the cache.
  2. Prerendering - Tells the browser to preemptively load the entire next page. Only supported by Google Chrome.

Across the website we've implemented prefetching of potential next pages.

This gives us about a 100ms headstart. Which is all we need when our load time is 134ms 😀.


Deliver through HTTP/2.

HTTP/2 is a major revision of the HTTP network protocol and is aimed at making the web faster.

Without getting technical, HTTP has a number of limitations that slow down websites. HTTP/2 makes it more efficient.

Check with your hosting company to see if your server is already configured to enable HTTP/2.

The only catch… you must have an SSL certificate.

We're delivering all of our assets through HTTP/2 on CloudFront.


Broken links cause 404 errors which generate extra HTTP requests, even if the page you're delivering isn't a 404.

Use W3C's Link Checker or Dead Link Checker to find and fix your broken links.

Every time we deploy we run automated tests to check for code quality, including broken links and missing source URL's. None here.


Eliminate redirects.

When you click an ad, you'll notice that the URL changes three or four times before it settles on its destination. These are redirects and they slow down your website.

Redirects create additional HTTP requests and increase load time. So you want to keep them to a minimum.

We do this nicely by having none.


Build for speed from scratch.

We used Middleman as the framework for building this site. Otherwise, we built it from scratch. Layouts. Pages. Partials. Asset folders. Nested CSS. Etc.

Not a single unnecessary div or line of CSS. Nothing left unscrutinized.

Every line of code has it's purpose.


How everything adds up.

9 requests, 0.2 MB, and 0.13 seconds for our homepage.

Bundlify Pingdom

18 requests, 1.0 MB, and 0.15 seconds for this post.

load time screenshot


What we could do to make it faster and why we don't.

Even with everything we did above, there's still more we could've done to speed up this website.

But we decided against it because these bonus tips either defeat the purpose of a marketing site or make it harder to maintain.


Inline CSS.

Rather than having one, master stylesheet, we could've added the CSS as inline styles on every page. This would make it faster.

However, it'd be a nightmare to maintain when we make design changes. Rather than updating one line, we'd have to update hundreds (eventually thousands).

Technically faster, practically unwise.


Non-retina images.

Every image you'll find here is 2x the size of it's container. For an image to not be blurry on retina screens, it needs to be twice as tall and twice as wide.

As you can imagine, this bumps the file size by 4x which is why it's important to compress them before uploading them to the server.

More and more screens are becoming retina-ready. We decided to accommodate the future at a small cost towards page speed today.


Remove all images.

Even further, we could've removed all images.

Would be faster, but images play an important role in communicating our message.

Would this post be as valuable without images? I don't think so.


Convert icons and PNG's to SVG's.

One thing we plan to do but haven't done yet is convert the vector-based logo and social icons into SVG's.

SVG's almost always load faster and scale infinitely, but they need to be handcrafted to receive the space saving benefits.


Remove all scripts.

We also could've removed Google Analytics, Drip, Bootstrap, and Disqus but these scripts play critical roles.

Without these four tools, we'd have no idea if our marketing site is effective. No traffic data. No subscriptions. No comments.

Removing these would make it load faster, but would also remove the purpose of the marketing site.


These are the tools we use to check our page speed.

  1. Pingdom - Test page speed from multiple locations around the world.
  2. PageSpeed Insights - Google's official speed test and recommendations.
  3. GTmetrix - Scores your website and gives performance optimization tips.
  4. WebPageTest - Test more advanced, multi-step transactions, content blocking, and more.
  5. Think with Google - Google's mobile page speed test.

All five will give you the same tips you found here, but prioritized so you know what you should focus on first.


What this means for you.

If you already have a database-driven website—which you probably do—you can still cash in on 17 of the 18 tips.

If you're building a new website—for yourself or a client—consider using a static website generator like Middleman.

When Mike first told me about it, I was skeptical. New learning curve. Slower build time (so I thought). Unfamiliar territory.

Turns out, I love it.

More flexibility. More secure. No plugins or version updates. And it allows me to work instantly, rather than bogging down Mike with marketing-related distractions so he focus on building the web app.

Plus, it's one of the fastest websites you'll ever see.

Performance is a priority in everything we've built, the marketing website should be the same.