Tuesday, April 30, 2013

WWW Project Turns 20

WWW Logo. Twenty years ago, on April 30 1993, CERN announced the World Wide Web project. While the web existed before then, this was the first time that HTML's specification was opened up to the general public, allowing anyone to learn how to mark up documents.

Eight days and twenty years ago, Mosaic 1.0 was released (you might recall I wrote up a little tribute). In the span of about a week, the first generally-available web browser and the first publicly-available HTML specification were both announced, all culminating in this very blog you are reading now (amiright?).

In honor of this, CERN has re-posted its web pages explaining the project.

CERN has created a companion site about the restoration of this first web site, where you can contribute and stay on top of ongoing progress to restore more of those early days of the CERN web environment. There is also an interview with Robert Cailliau as he reflects on the past 20 years. The BBC provides some coverage on its site, including some clips from its 20-year-old coverage. .net Magazine has an interview with Mark Boulton who has helped CERN with getting this site up.

I thought that it might be interesting to see those CERN pages using the web browser released at about the same time. Sadly, due to Mosaic 1.0 not supporting host headers, and due to the CERN site being overloaded today, I was forced to spider the pages and surf from local copies. Other than the address bar, however, these screen captures still load the same HTML.

NOTE: I plan to also show screen captures in a modern browser and a mobile browser, along with links to these pages so you can see them for yourself, but with the CERN site timing out, I'll have to add them later. There is a mirror available, however.

Screen Captures in Mosaic 1.0

You may click/tap/select each image to see a full-size version (800 × 700).

The World Wide Web project.
Technical Details.
HyperText Mark-up Language
Tags used in HTML
Hypertext Markup Language
Future plans for HTML

Screen Captures in Firefox 20

You may click/tap/select each image to see a full-size version (800 × 700).

The World Wide Web project.
Technical Details.
HyperText Mark-up Language
Tags used in HTML
Hypertext Markup Language
Future plans for HTML

Screen Captures in Chrome on a Nexus 7 tablet

You may click/tap/select each image to see a full-size version (800 × 1280).

The World Wide Web project.
Technical Details.
HyperText Mark-up Language
Tags used in HTML
Hypertext Markup Language
Future plans for HTML

Monday, April 22, 2013

NCSA Mosaic Turns 20

Mosaic logo. 20 years ago today (yesterday), NCSA Mosaic 1.0 was released (read Marc Andreesson's announcement on www-talk). Mosaic was the browser that opened the web to the masses, making the web more interesting for people like me.

As a college student who used Usenet, FTP sites, struggled with WAIS, Archie and Veronica, and had fallen in love with the ease of Gopher, the web was still just out of arm's reach for me. With Mosaic came the ability to see pictures directly in the page content — a whole new world for someone used to accessing the internet via only dumb terminals up to that point.

I had forgotten all about it until I saw this tweet from @mattur:

With this post, I'm not bringing anything new to the Mosaic story (at least no more than you get from this three-year-old Wired article on Mosaic), but instead I am taking time to remember that while it may seem like an eternity in web years, it still feels like yesterday that I was downloading Mosaic and trying the web seemingly for the first time.

You can also re-live at least part of this experience.

Download a Copy of Mosaic 1.0

Back when I became an ecommerce developer, less than 4 years after the release of Mosaic, I started an archive of browsers so that I could test the applications I was building in more than just the client's favorite browser. As time wore on and my collection grew, I created the evolt.org browser archive so that everyone could have access to any browser.

If you want to run NCSA Mosaic 1.0 and relive the early days of the web (even though few pages will render at all), just grab a copy of Mosaic 1.0 from the archive and fire it up. It turns out you don't need Windows 3.1 to run the Windows version, it will run just fine (mostly) under Windows XP, or in my case a Windows XP virtual machine.

Mosaic Screen Shots

NCSA is kind enough to offer a screen shot of Mosaic 1.0 for Windows so that you can see how awesome it was:

Screen shot of Mosaic 1.0 from the NCSA web site.

Sadly, that page on the NCSA site doesn't exist anymore. Visiting it in Mosaic 1.0 today gives you a funny-looking page. The browser uses the Mosaic icon for missing images and the full text of the Google Analytics tracking code is displayed (so they'll never know I was here):

Screen shot of Mosaic 1.0 today while surfing the NCSA site.

Even spending a few minutes in Mosaic, unable to surf most sites, will give you some insight into the early days of the web. There was no text styling. If you as a site owner wanted to enforce fonts or colored text, you couldn't. However, as a user of Mosaic, it was very easy to specify the font styles for different block-level elements within a font menu.

Eagle-eyed readers might notice a "Header 7" option:

Note the ability to change font settings for block-level elements.

Related

If you find this kind of stuff interesting, the W3C has a Web History Community Group where you can help out with the challenge of archiving an incredibly fluid medium, and preserving a little bit of history in the process.

Yep, somebody made a page that tracks Mosaic logo sightings.

As John Allsopp points out, nobody responded to the original email announcing Mosaic 1.0, perhaps setting the tone for browser discussions for years to come:

Update: April 30, 2013

Just over a week later (from the launch of Mosaic and from the this post), CERN has re-posted its 20-year-old WWW Project site which helped provide everyone with an understanding of HTML so they could make their own sites. I have a write up, with screen captures in Mosaic 1.0, on my blog.

Thursday, April 4, 2013

Chrome: Blink and You Missed the News

The new Blink logo. It's old news by this Thursday morning, but in case you had not heard, Google is forking WebKit to make its own rendering engine, Blink. Opera will be using the Blink fork of WebKit as its rendering engine.

A combination of people who are far smarter, far more well connected, and in timezones that allow them to write about this sooner, along with all the Twitter chatter, has already hashed out the major details. As such, I will link to them below. I would be a terrible blogger if I didn't offer my opinion, however.

I will format this the way I did when I provided my in-depth analysis of Opera's move to WebKit (away from Presto) less than two months ago.

So what does this really mean?

For Developers

Any developer who is complaining that this means there is another browser/engine against which they will need to test has been doing it wrong.

Web developers should always test against different browsers, regardless of their engine. In particular, WebKit has so many nuanced implementations that not independently testing against each browser that uses WebKit belies either a lack of understanding of how WebKit is implemented or laziness.

If you aren't sure what is different between each WebKit implementation (Chrome, Safari, Android browser, Opera, etc.), I encourage you to read my post "WebKit Will and Won't Be the New IE," where I provide a high-level overview of these variances.

For Users

At this point it doesn't mean a whole lot.

Google will argue this is better for users. Apple will argue that Google took its ball and left. Opera won't be arguing. None of that impacts users because we have mostly done a good job of promoting standards-based development. I again refer you to "WebKit Will and Won't Be the New IE" for how poor testing can impact users, but that's not a function of the engines.

Because Apple only allows WebKit on iOS devices, and even then it restricts those browsers to a different JavaScript engine and thus a lesser experience, Chrome and Opera for iOS may still stay on WebKit. Over time as its harder to incorporate features from Blink back into the WebKit core, there may be feature divergence which may affect users.

That's just speculation on my part.

For Standards

For a specification to become a W3C recommendation, there must be two 100% complete and fully interoperable implementations, which basically means two browsers need to support it. When Opera announced the shuttering of Presto, that left Trident (Internet Explorer), Gecko (Mozilla), and WebKit (Safari and Chrome) as the remaining engines (of measurable size). Essentially, two out of the three of them had to agree to implement a feature.

With Blink, provided the W3C recognizes it as a stand-alone engine, there is now one more engine back in the mix, essentially returning the count to where it was in February before Presto's wind-down (to be fair to Presto, it's expected to exist in the wild until 2020, but with no new feature development).

I am hoping that this is a good thing for standards.

Blink won't be using vendor prefixes (even though it will have inherited some), so I consider that a step in the right direction. While I think this matters to developers, I think it matters even more to standards.

Technical Aside

From Peter-Paul Koch:

Chrome 28 will be the first stable release to use Blink; earlier versions will use WebKit. Opera and Yandex will start using Blink whenever they start using Chromium 28.

Related

First some bits from The Twitters:

And now to the related links:

There's this one from 2010 by Haavard Moen that I thought worth highlighting: "Dear Google: Please fork WebKit."

Update, 5:35pm

A video Q&A from Google Developers about Blink (time markers available on the Chromium blog).

Tuesday, March 26, 2013

Tracking When Users Print Pages

A few months ago I had the pleasure of writing a piece for .net Magazine about print styles (Make your website printable with CSS). It was posted to .net's web site last month and received an overwhelming one comment. That comment, however, summed up something I hear all the time:

Would be interesting to see some statistics on how many people actually print websites.

For years I have argued that the best user statistics are those for the site you are building. In the absence of global numbers for how many users print web pages, in this post I'm going to show you how you can measure how many (and which) pages get printed from your site by using Google Analytics. I am also hoping those who know everything about Analytics can answer some of my questions.

The Concept

While looking around for existing solutions to track printed pages, I found this article: Use Google Analytics to Track When People Print your Web Pages (written exactly one year before I got my own code working). While there doesn't appear to be anything wrong with this approach (I did not try it), how it both produces the tracking code (JavaScript) and presents the data in Analytics (different than how I report on custom events), doesn't match my preferred approach.

I want to be able to call the Google Analytics tracking image (__utm.gif) only when the page is going to be printed, skipping unnecessary HTTP calls and the resulting image download (brief though it is). I rely on the CSS @media print declaration to call the image. I also don't want to write that image call to the page with yet more client-side script when I can assemble it all right on the server.

Since my post Calling QR in Print CSS Only When Needed already outlines the general flow (presuming I only want to support Internet Explorer 8 and greater), I can lean on the CSS syntax there.

To reiterate this technique will not work in versions of Internet Explorer 7 and earlier.

Constructing the Query String

I had a heck of a time finding information on how the Analytics query string needs to be constructed, and when I did find information it didn't always explain the values in much detail.

Google's developer site has information on all the query string parameters for the GIF request, but no information on what is required or what all the possible values might be. I did find a list of what may be the required parameters while searching among a thread on tracking emails with Analytics. Through a good deal of experimentation I came up with the following minimum list for my purpose:

Variable Description
utmac Account String. Appears on all requests. This is your UA-#######-# ID.
utmwv Tracking code version. While my standard GA requests use 5.4.0, I opted to use 4.3 for reasons I no longer recall.
utmn Unique ID generated for each GIF request to prevent caching of the GIF image. I just concatenate the current year, month, day, hour, minute and second.
utmhn Host Name of your site, which is a URL-encoded string.
utmr Referral, complete URL. In this case I just insert a dash so it is not blank.
utmp Page request of the current page.
utmt Indicates the type of request, which is one of: event, transaction, item, or a custom variable. If you leave it blank, it defaults to page. Because I am tracking events, I use event.
utme Extensible parameter. This is where you write your event. I use 5(Print*{page address}). See below for why.
utmcc Cookie values. This request parameter sends all the cookies requested from the page. It can get pretty long. It must be URL encoded. It must include __utma and __utmz values.

Because the whole point of this is exercise is to track the event in Google Analytics, it was important to understand how to construct the event for the query string. I struggled a bit.

I still haven't figured out what the number 5 maps to, but it works. I also found that I need an asterisk as a separator, though I found no documentation explaining it. In the end, the only way a print event tracked as I wanted was when I constructed it as: 5(Print*/Accessibility). In this example, /Accessibility is the address of the page I am tracking.

The other tricky bit is pulling the cookie value and stuffing it into the string. Conveniently I can get to this within our content management system (QuantumCMS, which you should use) on the server side. Many others (if not most or all) have a similar ability. At the very least you have to include the __utma and __utmz values, passed as encoded parameters for utmcc. Without these, my tracking would not fire.

The Completed Query String

For ease of reading, I will break the string to a new line at each &. This represents what is generated when I visit the careers page on the Algonquin Studios site using Opera.

http://www.google-analytics.com/__utm.gif
?utmac=UA-1464893-3
&utmwv=4.3
&utmn=2013326124551
&utmhn=algonquinstudios.com
&utmr=-
&utmp=/Engage/Careers
&utmt=event
&utme=5%28Print*/Engage/Careers%29
&utmcc=__utma%3D267504222.1477743002.1364314722.1364314722.1364314722.1%3B%2B__utmb%3D267504222.17.7.1364314901604%3B%2B__utmz%3D267504222.1364314722.1.1.utmcsr%3D%28direct%29|utmccn%3D%28direct%29|utmcmd%3D%28none%29

Constructing the CSS

Now that you have the query string and the Google Analytics tracking image, you just need to call the image when the page is printed. All you need to do is embed a style block at the top of your page with the print media query, and call the image within it:

@media print {
 header::after
  { content: url(http://www.google-analytics.com/__utm.gif?utmac=UA-1464893-3&utmwv=4.3&utmn=2013326124551&utmhn=algonquinstudios.com&utmr=-&utmp=/Engage/Careers&utmt=event&utme=5%28Print*/Engage/Careers%29&utmcc=__utma%3D267504222.1477743002.1364314722.1364314722.1364314722.1%3B%2B__utmb%3D267504222.17.7.1364314901604%3B%2B__utmz%3D267504222.1364314722.1.1.utmcsr%3D%28direct%29|utmccn%3D%28direct%29|utmcmd%3D%28none%29); }

If you read my post on embedding QR codes, then this code will be familiar — I use header::before in that example. As such, I use header::after here so you can use them both keyed off the same element (header) without conflict.

If you look closely, you may have noticed that my event parameter looks like 5%28Print*/Engage/Careers%29 instead of 5(Print*/Accessibility). I URL encoded the parentheses on the entire string to make certain that they do not conflict with the parentheses in the CSS. If you don't do that, the browser will get confused and fail to load the image.

Once you have the CSS in place, I recommend going into HTTP Fox or the Chrome Developer Tools to make sure the image is called when you fire a print preview (save paper!), and then to make sure it has the parameters you expect — particularly the utme value:

Screen shot of Chrome Dev Tools.
Screen shot of Chrome Dev Tools showing the query string parameters for the tracking GIF.

Checking Your Google Analytics Report

Assuming you've verified all is working well, you just need to run a report for events in Google Analytics. Bear in mind that Analytics isn't up-to-the-minute, so you may need to give it some time to capture all the data.

Log into your Analytics account and make sure you set the report date to the time period where you rolled out these changes. Choose "Content" from the "Standard Reports" on the left side. From there, expand "Events" and then select "Top Events." You should see "Print" as one of the items in the "Event Category" column (you may need to show more rows).

Screen capture from Google Analytics
After you click "Top Events," you will see all of the events you are tracking (if any other).

Click on the word "Print" in that grid and you will see all the pages that were tracked (ostensibly because you or a user printed the page).

Screen capture from Google Analytics
The report is handy if you know the page addresses, but Analytics doesn't think of them as such. As a result, clicking the addresses will not take you to the page.

From here you can run a secondary dimension to cross-reference this with more information. In my example, I tested different pages in different browsers so I could quickly verify the cross-browser support. You can run screen resolution, landing page, or any other dimension that you think might be handy to compare.

Screen capture from Google Analytics
An example comparing the printed pages with the browser as a secondary dimension of the report.

Conclusion

I am just adding this to my own site, so I don't have any numbers to offer as part of this post. However, if you implement this please feel free to let me (and everyone) know how many users you have who print and for what site. I don't expect the numbers to be high, but I do expect to see it happen here and there.

If you have any additions, corrections or suggestions, please let me know. I am still unclear how all the Google Analytics query string parameters come together and exactly what they all mean, so there may be some optimizations I can work into it.

Related

Related articles on print styles:

Stuff I've Written

Update: October 16, 2014

Over at Smashing Magazine, Krasimir Tsonev appears to have independently developed the same method in his post, CSS-Only Solution For UI Tracking. I left a comment pointing folks here and to my Web Standards Sherpa article covering same.

Sunday, March 24, 2013

Women in Technology

Portrait of Augusta Ada King, Countess of Lovelace
Augusta Ada King, Countess of Lovelace (1815—1852), considered by many to be the first computer programmer (of any gender). Portrait by Alfred Edward Chalon.

Lately you've probably heard plenty about education in the US and the renewed push for STEM (science, technology, engineering, math). As STEM education gets attention, it has reminded us all that there is a shortage of women in STEM-related fields as well as STEM-related courses and programs.

As someone in the technology industry, I can see this difference when I go to conferences, when I speak at classes, when I review job applications, and when I talk to women in my life who are interested in technology.

That's why it was heartening to hear about a local young woman spinning up a chapter of Girl Develop It here in Buffalo (also on Twitter at @gdiBuffalo).

I hope this group pans out. I think it can benefit both men and women.

Challenges in Tech

I hate to blunt this positive by bringing in negatives, but it's because of these negatives that I see such value in this new local group.

There are so many pithy, rambling, crazy, angry things on a daily basis about gender in technology that I'd rather not add to the noise. I will, however, link to examples of why I feel there is a need for resources for women in our industry. There are far far more examples out there.

Back on a positive note, there are other resources on the web for women, such as Ladies in Tech, Girls Who Code, and Black Girls Code.

Tuesday, March 12, 2013

WebKit Will and Won't Be the New IE

Web developers have been looking to call everything the new Internet Explorer for a while now. With Opera's recent move to WebKit as its rendering engine (replacing Presto), even more developers are suggesting that WebKit is becoming the new IE.

I think they are right, but for the wrong reasons.

How WebKit Won't Be the New IE

Unlike Trident (Internet Explorer's rendering engine), WebKit can be wielded in many different ways by many different browsers. It's less a singular rendering engine and more a collection of pieces and parts that can be assembled in different ways. The tweet above demonstrates that there can be different WebKit implementations.

You may argue that the example above is just a case of the first implementation of an update that will make it into all browsers that use WebKit. That may very well be true (we don't know yet), but there are many more examples of differences as Paul Irish painstakingly details in his post WebKit for Developers. I encourage you to read it because it's an almost hilarious dive into the rabbit hole of WebKit. The most salient and clear point is the bullet list of what is not shared in WebKit ports:

  • Anything on the GPU
    • 3D Transforms
    • WebGL
    • Video decoding
  • 2D drawing to the screen
    • Antialiasing approaches
    • SVG & CSS gradient rendering
  • Text rendering & hyphenation
  • Network stack (SPDY, prerendering, WebSocket transport)
  • A JavaScript engine
    • JavaScriptCore is in the WebKit repo. There are bindings in WebKit for both it and V8
  • Rendering of form controls
  • video & audio element behavior (and codec support)
  • Image decoding
  • Navigating back/forward
    • The navigation parts of pushState()
  • SSL features like Strict Transport Security and Public Key Pins

That amounts to quite a lot of potential variance between WebKit-powered browsers, which is how WebKit is not the new IE.

How WebKit Will Be the New IE

Far too many developers are always looking for ways to justify testing less. It could be laziness, it could be lack of access to enough device configurations, it could be … well, frankly, I think it's the first one. My IE10 tweet above was based on watching people thrilled as much at taking a shot at Internet Explorer as they were at feeling they could test on one fewer browser.

Developers may use the common engine in one browser as justification for not testing on all the WebKit browsers, or they just may not know about the potential for dramatic differences between implementations. What happens when everyone builds for one awesome browser engine (or one perceived common engine)? We end up with a browser monoculture, devoid of testing for other variations.

As a web developer since the dawn of the web, I've seen it happen before. I remember surfing on Netscape only to find a site didn't take into account my screen colors or resolution, or on Internet Explorer only to find a site didn't take into account my laptop pixels-per-inch default. I was using the popular rendering engine of the day, but the assumption that all users on that engine would all have the same experience was wrong then, and it will be even more wrong now.

WebKit will become the new IE if web developers continue these false assumptions and fail to test other WebKit implementations. Developers will build for one implementation, test for it and maybe a couple variations, and call it a day.

Conclusion

My fear is that all the gains we've made in the last few years toward a more inter-operable standards-based web (leaving behind the Internet Explorer monoculture) will fall away as we unwittingly move toward a WebKit-tweaked yet non-multi-WebKit-inter-operable web.

In short, we'll test for one WebKit, not realize (or care) about all the other variations, and end up breaking the web all over again.

WebKit won't be the new IE, but WebKit will be the new IE.

Friday, March 8, 2013

Calling QR in Print CSS Only When Needed

For those of us who put together print styles for our sites, we've probably tossed around the idea of embedding QR codes so that users can quickly get back to a page they have printed. In the hardcopy version of my article for .net Magazine, "Make your website printable with CSS," I show how you can embed QR codes in your page (it's not included in the online version).

In my example I use the Google Charts API to generate the QR code on the fly. The problem in my example is that the QR code image gets called whether or not you print the page. Not only is this an additional HTTP request, it's also an additional download that immediately gets hidden. This puts a bandwidth burden on users who aren't printing, but it's also the only way to support your users on Internet Explorer 8 and below (who may be the ones trapped at the office who want to bring the document home).

If you truly have no IE8 or below users, then the less bandwidth-hoggy approach is rather simple, if a bit inelegant.

Since each call to the Google Charts API to get the QR code must include the full address of the page, I cannot leave this to my linked CSS file (which is static, not run through any server-side processing), nor would I want to push every URL for every page of my site into that file. Initially I wanted to use a data- attribute to hold the URL and then, using the generated content feature of CSS, have it take that value and feed it into the content: CSS declaration to have it generate the image from there. Except that's not how CSS works. You cannot use CSS to generate an image from a CSS variable.

The easiest solution is to a put a style block at the top of your page (something I hate doing) and feed the current page's URL into the Google Chart API query string to dynamically draw the image. The rest of the styles that affect placement, spacing, etc. should all be in your print stylesheet already. The example:

@media print {
  header::before
    { content: url(http://chart.apis.google.com/chart?chs=120x120&cht=qr&chl=http%3A%2F%2Falgonquinstudios.com/Engage/Careers); }
}

That's it. Now when (and only when) you call the print styles, the image will load. As proof, here is a screen shot using HTTPFox showing the page before the print styles were called and after, where you can clearly see the QR code is called only when the print styles are fired.

Screen shots of the list of HTTP requests before and after the print styles were fired. You can click / tap to see the full-size image.
Screen shot of the print preview with the generated QR code in place.

Note: This technique will not work in any version of Internet Explorer that doesn't support CSS generated content, which includes IE 8 and below. Internet Explorer 9 and above happily include the QR code generated with this method.

Update: March 26, 2013

I build on this technique to show you how you can use Google Analytics to track which and when pages of your site are printed: Tracking When Users Print Pages.