Flop-timized: Marketo LPs and the case of the 300KB favicon

Quick: How big are your Marketo LPs?

I know you don't have the size in KB at your fingertips. But you're probably thinking, “Smallish… tiny bit of CSS, forms JS, optimized images. Definitely smaller than our corporate home page, I can tell you that much.”

What if I told you that your Marketo LPs may be forcing users to download your home page's full HTML, twice — in addition to downloading the LP and its own assets?

(And I do mean “your home page.” Not something the size of your home page, but your actual home page.)

The correct response, of course, is “I'd believe you. Now tell me how to fix it, after tooting your own horn for a few paragraphs.”

Why bytes matter

You probably already get this, but download size matters for several interrelated reasons:

  1. User experience (time-to-visible). We all know a page that's slow to render is a bad move. In the MarTech world, unoptimized hero images are repeat offenders, as are unnecessary script libraries and dynamically fetched HTML (a half-second to populate a DIV is fine for a single-page web app, but maybe not for an LP).
  2. User experience (interactive). Different from initial render time, but just as bad, is slow user interaction with the page due to sluggish background tasks (Ajax calls for form data enrichment, for example).
  3. Search engines care. Google ranks slow sites lower than their competition, other signals being equal. We don't know the threshold that kicks a site into the “slow” category, nor do we know exactly what's measured (the main page HTML? some dependent assets? all assets?). But removing totally unnecessary downloads can never hurt.
  4. Bandwidth isn't free. Maybe it's effectively free for you on the server side. But every mobile carrier that I know of still charges, ultimately, per byte of data. So someone can be on LTE PlusPlusUltra and not notice they just downloaded 2MB of HTML, CSS, JS, and PNGs. But if their monthly quota is 6GB they can only do that 3000 times a month. That's 100 pageviews a day. (I really start to notice stuff like this when my creaky DSL goes down and I try to do my job via hotspot.)
  5. Connections aren't fast. Don't think about your FIOS or your office's metro Ethernet. Think about when your phone switches to 3G but you keep surfing instead of putting it away.
  6. Connections aren't always-on. This is closely linked to (4) and (5) as it's a mobile-only issue, but slightly different. The larger your assets, the more likely that users will start to download them, then enter a tunnel and have the download aborted. This problem can be worse with secondary assets than with the main page, since you can end up with a visible-but-broken page (as opposed to a page that clearly needs to be refreshed since it never rendered).

True, you can have a “big” page in terms of either asset size or number of assets which still is fast enough, at least on desktop. But it's almost impossible to have a page that has both slow-to-load assets and a lot of them that performs acceptably.

The main concerns for today, anyway, are (4), (5), and (6) above — and maybe (3) if we knew how it really worked. For reasons explained below, (1) and (2) aren't really in the picture, which is good.

Watching the bytes go by

Apologies for using shots of real, identifiable sites, but this kind of thing is impossible to simulate without breaking a working instance (it's an instance-wide problem) and I also wanted to show a real-world size distribution.

(Seriously, man, sorry for the first one… I've just known about it for so long that it's my prime example. If I were going to Summit, I'd deserve an unfriendly punch in the arm.)

Ages ago (this post has been in draft for 6 months) I was measuring someone's Munchkin performance and noticed something weird. Opening Dev Tools on one of their Marketo LPs, I saw multiple requests for their corporate homepage:

ss

My first thought was they were embedding an IFRAME of their homepage for some reason (maybe a form hosted there?) which would account for requests for additional text/html assets within the main HTML page.

But it wasn't that. I zoomed in and look what I found:

ss

Those are actually requests for the site's favicon, which are redirected to their homepage, then redirected again to the default language path (/en), where they download the entire HTML for the English homepage!

Huh? Well, Marketo includes these tags in LPs by default:

ss

That's two different <link> tags both pointing to the relative path /favicon.ico, that is, the full path is https://pages.example.com/favicon.ico from the standpoint of the Marketo LP.

But that file doesn't exist by default in a Marketo instance, so Marketo redirects to the fallback page, in this case https://www.example.com. From there it's redirected to the default language.

Realize this is all happening in the context of downloading an image, but that's the way browsers work, as we also learned (and exploited) in my strange idea of pages as tracking pixels. Once the browser starts getting an asset, with few exceptions it will download the entire asset before determining that the format is invalid: obviously it's not going to try to make an ICO out of the HTML but it doesn't know that it's a bad icon if it hasn't retrieved it. (It would be possible to check the initial “magic numbers” that begin all image file formats and abort early, but Chrome, at least, doesn't do this.)

Let's look at a few more real-world sites.

Here there's an extra 20KB to download::

ss

Here an extra 250KB, which is really huge:

ss

And I saved the best for last:

ss

If you search around the net, very few Marketo users have fixed this.

Why did you say “300KB” in the title —

— when the screenshot only shows 2 * 33KB = 66KB?

I had to make a judgment call based on two (debatably) equally true numbers.

In this case, the file is compressed on the wire using gzip to get it down to 33KB:

ss

But after decompression (which needs to happen before it's used) it's a 161,554KB file:

ss

So is this a “a 33K file” or “a 160K file”?

In terms of network I/O, it's a 33K download. But remember we're specifically concerned with mobile devices. In terms of memory and browser cache requirements, these are really 160K files, plus the (tiny in the grand scheme, but not negligible on an older phone) CPU time to decompress.

So I'm choosing to call them “160K files.” Maybe erring on the side of alarmism, but as true as not.

It's not the worst thing

Admittedly, favicon fetching is a deep-background task. So this isn't directly impacting the initial render time or interactive experience: that's why I said (1) and (2) up above aren't really part of this.

But you're undeniably wasting bandwidth. Definitely theirs, but yours as well, even if it's unmetered. If you get 250,000 LP hits, that's 500,000 homepage hits. (Your webmaster would see them in their server logs, but they're not going to show up in JS-based analytics as favicons don't load analytics.js!)

And simultaneous connections matter, too. Browsers only keep open a set number of connections — think downloads in motion — to a given server. Most people don't understand that this is perhaps the real problem with loading many unneeded assets on the same page: not that they individually take long to download, but that they create, if you will, wait steps. The usual max is 6 connections. So if you're loading 6 (necessary) assets from www.example.com, this favicon prob may mean 2 of those assets have to wait in line behind the favicons. Not good!

So, in sum…

Fix it anyway!

ss

(Adjust http:/https: as necessary for your sites.)