Archive for the ‘Uncategorized’ Category

Cloudflare vs. Google Analytics: Why the Numbers Are So Different

It’s certainly well known that Cloudflare’s analytics (or any request-based analytics, for that matter) tend to give larger numbers than those that are javascript based. The de facto explanations make sense: some users navigate away from a page before the it is fully loaded (before the javascript executed); other users keep javascript disabled. There are more.

But these standard answers really can’t explain the discrepancy I tend to see between the real numbers. Take these stats as an example:

Google Analytics

Pageviews: 143,646
Unique Visitors: 36,091

Cloudflare Analytics

Pageviews: 425,785
Unique Visitors: 111,921
Screen Shot 2013-04-28 at 11.18.19 PM Screen Shot 2013-04-28 at 9.49.24 PM

 

If we are to believe these numbers, than either:

  1. Most people browse the web cURL spoofed to look like Chrome, Safari or Firefox
  2. There more at work than the standard explanations

 

In a comment I just made to Hey CloudFlare, What’s Wrong with these Numbers?, I gave one suggestion:

It’s possible that Cloudflare is logging anything it connects to the server, *including* non-2XX code responses. For example, my organization uses the root domain, and 501 redirects any www. subdomain traffic to the corresponding root URL. On CF, this might be marked as 2 separate requests.

On the other hand, I’m not sure this would explain the discrepancy between the 36k monthly *uniques* on GA, verses the 112k on CF. Any thoughts?

But as you see I couldn’t even get through a comment without finding the hole in my argument. So, here’s another suggestion:

 

Prefetching and Prerendering.

There’s a relevant standard, and Chrome, Firefox, Safari, and even IE do it to varying degrees. While I haven’t researched the implementation subtleties of the different browsers, Google Chrome is apparently able to “predict network actions” and might prerender pages based on the links from anywhere, including search results.

And this is what piqued my attention. If I look at queries in the SEO section of Google Analytics, and I select only those with an average position of 10.0 or better, I see 73,599 impressions with only 8,188 clicks. That’s 65,411 opportunities for the browser to prefetch or prerender our site based on first-page Google results alone, which is likely an underestimate. It doesn’t factor in the many results that have extremely high impressions and click through rates, but don’t average on the first page. Here’s the name of the organization itself, for example:

Screen Shot 2013-04-29 at 12.45.26 AM

If Google Chrome is as smart as I think it is, there are many prerender requests to our server attributable to this keyword alone. And with Chrome responsible for nearly 32% of our traffic (and other browsers likely also contributing to the effect), this is a very likely source of this discrepancy.

I’m sure there are even more factors at play, but this is one to look out for… if that’s possible. While Firefox sends some header information when prefetching ( X-moz: prefetch ) Chrome doesn’t.

If you’ve made it this far, let me know if I’ve missed something!

Check out My Wedding Website!

It’s official! The public internet (aka the web that’s not Facebook) knows I’m engaged. My beautiful bride – Miss Emily Shafer – and I have launched our website: mikeandemily.net. We’ve put our story, engagement photos, wedding details, and registry links there for the world to see.

I’ve used Ruby on Rails for the whole thing and built a beautiful RSVP system that’s about as easy to use as it is good looking. By using Active Admin for the system, it’s absolutely cake for Emily and me to manage the guest list. This is one of those things that I really, really wish I had time to blog about in detail. But alas, I will resolve to rant of my awesomeness without evidence.

Oh, and speaking of my awesomeness, check it out on your i-Devices! Ya. Pretty awesome and responsive and surprisingly fast for the crazy, crazy amount of images everywhere. That took a lot of tweaking to get just right, but I think I got it.

So ya – check it out:

Mike and Emily’s Wedding Site

 
 

Rounding inner corners with CSS only

When designing something for the web, sometimes you want to round the inside of a corner. Historically, we've had to use images to make this happen. The problem is, well, images suck. They don't scale well, so you can't change the radius, they waste bandwidth, and any time you want to change their color or style, you're SOL! While CSS has provided the native ability to round outer corners for some time with the `border-radius` property, this whole inner corner business has been tricky... until now. This strategy will let you:
  • Use any color you want including transparent colors!
  • Change the radius on the flu
  • Look good in Retina (highDPI) displays
  • Save a request, bandwidth, and a bunch of hassle!
Check out the jsFiddle: Here's a simple HTML page we're going to make pretty:
Select Code
1
2
3
4
5
6
7
<div class="first">
    <p>This is made with 100% CSS</p>
</div>
<div class="second">
    <p>Go ahead, zoom in, use that Retina display!</p>
</div>
Here's the special CSS-sauce:
Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
html {
    background: url(http://farm8.staticflickr.com/7215/7268755328_ede47bc659.jpg);
    background-size: cover;
    background-repeat: no-repeat;
    height: 100%;
    font-family: Helvetica, Arial, sans-serif;
}

div {
    background-color: rgba(255,255,255,.7);
    color: black;
    position: absolute;
    text-align: center;
}

.first {
    border-radius: 12px 12px 0 0;
    height: 100px;
    left: 100px;
    top: 100px;
    width: 100px;
}

.first::after {
    background: transparent;
    border-radius: 0 0 0 12px;
    bottom: 0;
    box-shadow: -2px 2px 0 2px rgba(255,255,255,.7);
    clip: rect(0px, 12px, 12px, 0px);
    content: "";
    display: block;
    height: 12px;
    left: 100%;
    position: absolute;
    width: 12px;
}

.second {
    border-radius: 0 12px 12px 12px;
    height: 100px;
    left: 100px;
    top: 200px;
    width: 200px;
}

p {
    padding: 12px;
}
​

Updating Your Website to Support Retina Displays

I just got my brand-new Macbook Pro with Retina Display last friday… and it is awesome! It comes after about 9 months of life-support for my old, 2007 MBP, which included bolting the hinges back together and baking the motherboard to re-solder the GPU.

One of the new macbook’s most impressionable features is, of course, its retina display: pixels are truly indistinguishable, even on high-contrast diagonal lines. This wonderful new era of High-DPI screens comes with a cost, though. Because Apple (ingeniously) uses pixel-doubling (and pixel scaling at non-default resolutions) to give familiar screen real estate, most web images look pixelated. Seeing as I am both an in-house and freelance web developer, I decided I needed my sites fixed straight-away! The problem was: I don’t particularly like any of the available solutions (all designed for iOS). The only one I found particularly clever was Retina.js, but even there, I avoid client-side preprocessors like “LESS CSS” and am not a fan of all the extra HTTP requests.

It seems certain that the new, ultra-high-resolution internet is going to be heavily dependant on things like SVG, <canvas>, and robust CSS; at the same time, raster images aren’t going anywhere. To deal with those, we should really get used to hand-coding multiple versions where and when they are necessary. My immediate answer (take it or leave it!) that I used for BioLogos is very simple:

For <img/>’s

In each image tag, I added a data-2x-src attribute with the URL of a double-resolution image. For example:

[html]
// notice the use Apple’s standard "@2x" notation
// make sure you have height and width set!</pre>
<img src="/images/logo.png" alt="Logo" width="325" height="73" data-2x-src="[email protected]" />
<pre>
[/html]

Then, I added some jQuery:

[js]
// replaces ‘src’ with ‘data-2x-src’
$(function(){
if(window.devicePixelRatio > 1.5) $(‘img[data-2x-src]’).each(function(){$(this).attr(‘src’,$(this).attr(‘data-2x-src’));});
});
[/js]

For CSS Backgrounds

There are two strategies here:

  1. Best Option: If you can get an SVG version of your image, just use that!
  2. If you can’t, then add the high-res version behind a media query in CSS:

[css]
#logo {
background-image: url(‘/images/logo.png’);
/* make sure this is the size of the original image */
background-size: 200px 100px; -webkit-background-size: 200px 100px; -moz-background-size: 200px 100px; -o-background-size: 200px 100px;
}

@media all and (-webkit-min-device-pixel-ratio: 1.5) {
#logo {
background-image: url(‘[email protected]’);
}
}
[/css]
And here’s the before/after:

…eventually I’ll get around to retinafying this blog, my most neglected project that ever went live!

Updating Xcode on the App Store… again

So, Xcode is apple’s developer software, and since the App store‘s launch, that’s the only place you can get it. The problem is that the app store makes it a HUGE PAIN IN THE A$$ to update. Because of this, I wrote the following dialogue in Xcode’s review. Oscar nominations can be sent directly to my twitter.

Xcode is awesome. The App store, well, is awesome in its own respect, but completely inapropriate for this kind of software. For that it gets only 4 stars. I think I’m going to hop on the bandwaggon and shout “please just use software update” like a nagging wife:

Hey Apple, can we talk? Please listen to me. No, please, Dear: turn off the TV. So, I know you say I nag – please, Hunny, can you look me in the eyes? I don’t want to be a nag, but I just feel like all our conversations are one-way. You never really listen to me. I know your silence helps create mystery and keeps me coming back… but I really wish you would admit when you’re wrong. Like only offering Xcode on the App store. You know that wasn’t the best idea – please don’t give me that look! It’s not like I’m asking you to surrender something to Google or Microsoft – I’m just suggesting that using software update (which you invented) may be a better aproach. I mean, the developers that are frustrated with the download process are the same ones you want to ship their products on the app store.

– no, wait, Hunny? Please come back… I’m not done…. No, I’m not trying to emasculate you…

The case for buying a Mac

I could probably write a doctoral thesis on why you should ditch your POS windows laptop today and buy a Mac. Of course, writing about something so obvious might be insulting to academia… like studying whether little boys prefer cars or dolls. Oh ya, and I don’t have enought time.

Lucky for all you unenlightened folks, though, I do have time to give you one nudge in the right direction: today I did the quick math to figure out how many hours I will have spent on my Macbook Pro when I replace it this spring. The result? About 10,000 hours. Let me repeat that. Ten. Thousand. Hours…

TEN THOUSAND HOURS!!!

Trust me, your life will be noticeably better with 10,000 fewer hours of frustration.

Please PleASe PLEASE!!!!! Stop using Internet Explorer 6!!

Please PleASe PLEASE!!!!! Stop using Internet Explorer 6!!

Google doesn’t suggest hate

Google’s been quite a tenacious fighter of censorship, taking on the world’s largest government and openly (and maybe ironically?) keeping tabs on big brother with Transparency Report.

In a minor twist, it appears that, despite their anti-censorship commitment, they refuse to suggest hate – I don’t mean that they should be telling you to hate, or that they block “hateful” content (come to think of it, they might do that with safesearch, but I’m not sure). It’s just that they literally don’t give suggestions with the word “hate” in the query. Try it yourself: go to the google home page and type “I hate” and it stops spitting out suggestions. If you have Google Instant turned on, it won’t even show you any results for your query until you hit enter!

Is this good or bad? Well, I’ll tell you how it’s inconvenient: I sometimes use Google’s suggestions to find others’ opinions. Yes, yes, I know that’s what Google Trends is for, but the suggestions are sometimes more useful and funny. For example, try typing “lindsay lohan is a” into google and you’ll get a laugh. Type it into trends? Nada. So, early today, when I wanted to see if Los Angeles was on Google’s list of most commonly hated things, I was out of luck: “I hate ” and nothing.

jQuery and Frames

Do NOT use firebug with this page! (It may crash your browser.)


Hey all! I just noticed that I’ve been getting a lot of traffic from a post I made WAY back in the day at http://simple.procoding.net/2008/03/21/how-to-access-iframe-in-jquery/, and since I’ve changed this site, everybody was hitting 404’s. This a post of what used to be here:

Frame from the same domain as parent.

Not yet loaded…

Frame from a different domain as parent (lifeinnovative).

Not yet loaded…


Browsers follow similar rules with iframes as they do with xml_http_requests: that is, it blocks cross-domain access.

For example, if I am running the above script from the page: http://www.liveintensely.com/parent.html, I can read and write to the frame which’ source is http://www.liveintensely.com/iframe.html. HOWEVER, if the frame’s source is on a different domain, like http://lifeinnovative.com, javascript is denied both read and write access to the frame.

Check out the above example, and (simplified) source code below:

[html] <html> <head> <title>jQuery and Frames</title> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> jQuery( function() { $(‘#frame1’).load( function(){ $(this.contentDocument).find(‘body’).html(‘This frame was modified with jQuery! Yay!!!’) }); $(‘#frame2’).load( function(){ $(this.contentDocument).find(‘body’).html(‘This frame was modified with jQuery! Yay!!!’) }); }); </script> </head> <body> <h2>jQuery and Frames</h2> <h4>Frame from the <i>same</i> domain as parent.</h4> <iframe id="frame1" src="iframe.html"></iframe> <h4>Frame from a <i>different</i> domain as parent.</h4> <iframe id="frame2" src="http://lifeinnovative.com/frame_for_liveintensely_demo.html"></iframe> </body> </html> [/html]
Return top