Tracking When Users Print Pages

Originally posted on my blog on March 26, 2013.

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.

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 {
  { content: url(*/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.


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 articles on print styles:

Stuff I’ve Written

What’s New in QuantumCMS 5?

Over the past few years, my role at Algonquin Studios has expanded to include the front-end development of QuantumCMS, our in-house content management system. In that time, QuantumCMS has changed a lot. We’ve crushed bugs, added new features, and enhanced the user interface

The release of QuantumCMS 5 is slated for May 1, 2013 and I’m really excited about this version. Not only have we redesigned the interface, but we’ve also added new features, vastly improved some existing features, and upgraded the code under the hood.

Here’s a look at some of things that you can expect in QuantumCMS 5:

New Interface

We’ve given the interface a clean and fresh look that’s easy on the eyes, but the layout is largely the same as previous versions, so you won’t have to hunt around for anything.



Edit Page


Site Tree

We’ve built a new site tree control from the ground up. In addition to new icons and styles, the tree now includes drag-and-drop page moving and sorting in all supported browsers. We also added a feature to indicate when a page has drafts. In such cases, a small pencil is displayed over the page type icon.


File Manager

This release will introduce a brand new file manager. The file manager is no longer available as a tab in the left pane, but now opens in a new window so you have more room to work. The new file manager supports drag-and-drop for moving files and includes basic image editing features like resize, crop, and rotate. In modern browsers, you can even drag files from your computer into the window to quickly upload them to the server. And yes, I said files! With the new file manager, you can upload multiple files simultaneously.



We’ve added a set of new screens that can be used to help define business rules and manage content that is specific to an area of the site. A section is simply a page and all underlying pages. In QuantumCMS, you can define any page as the root of a section and apply custom content like Linked Pages and Properties that will appear on all pages within that section of the site.

Although there are many potential uses, we believe that this will be particularly helpful for sites with multilingual content, mini-sites, or both. Making use of this feature requires some template updates, because the functionality must be coded to match the site’s business rules.


Linked Page Images

We noticed that a lot of web sites associate images with their links so we’ve attempted to make that easier by adding a Link Image file picker to the Linked Pages screen. Much like Sections, the Linked Pages feature is implemented uniquely for each web site so template updates are necessary to make use of this feature.


Open Pages in New Window

You may have noticed that there is now a check box on each page that is labeled, “Open in a new window.” By checking that box, all links to that page in the navigation, search results, and site map will open in a new window automatically.

Site Speed

I’ve saved perhaps the best for last. In QuantumCMS 5, we’ve made a bunch of code updates to streamline the page rendering process. That ultimately means that sites on this version will load faster. Additionally, we believe our new Sections feature will further this for those clients that make use of it. We’ve made major strides to accomplish this and we believe that it will pay dividends for our clients as well.

I hope that you enjoyed getting a sneak peak at our upcoming release. Please feel free to share your feedback!

Chrome: Blink and You Missed the News

This post originally appeared on my blog on April 4, 2013.

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.


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).

Jeff’s Guide to Managing Customer Expectations

Any reputable company will tell you that customers are your lifeblood–without them, your business can’t exist.  It’s crucial to keep them happy, and a large part of that is managing their expectations. When I first started working in this field I underestimated just how important expectation management can be to customer satisfaction but I quickly learned from my managers to always keep this idea in the back of my mind.

Imagine your experiences at various restaurants: if you’re stopping for a quick bite to eat at a fast food restaurant, you’re (typically) expecting low quality food, but you’re expecting it to arrive quickly and not put a sizable dent in your wallet. If you’re booking reservations at a Michelin star restaurant, the exact opposite would be true.  However, in both situations, it’s possible to be completely satisfied with the product and service you receive simply because of the different expectations that you started with.

Although it’s a different situation, the same concept can be applied to providing software support-a large part of how happy customers are with your company is due to the expectations that are initially set and then either met or not met on a regular basis. While it’s important to always strive to provide the highest level of support possible, it’s also extremely important to set realistic expectations. Here are a few of the things I like to keep in mind in order to better manage our customers’ expectations:

  • Consistency is key.  Providing fantastic service one day and poor service the next will frustrate your customers, since they’ve come to expect a certain standard. Making yourself available to assist a customer after normal support hours will set the expectation that someone will always be available to do provide immediate assistance, regardless of the time of day. Make sure that’s a commitment you can follow through on, every time.
  • Always mind how you word things.  Sugar coating may make things sounds better to your customers, but if it leads to the impression that you’ve promised something and failed to deliver, you’ll just end up looking bad. You should always be kind, helpful, and accommodating but don’t feel pressured to say or promise anything that you can’t back up. A temporarily frustrated customer now is better than an enraged customer in the future.
  • Make it clear what you can and can’t assist with. While always trying to help your customers as much as you can sounds like a great idea, providing partial assistance with things you’re not familiar with isn’t.  Unless you’re prepared to take full responsibility for any consequences or you’re equipped to continue assisting with that issue going forward (see the first bullet!), it’s best to have them contact the appropriate support team for help.
  • Make sure your customers are kept in the loop. This is a rather broad statement, but it’s an important thing to remember-nobody likes being left in the dark, especially when a product or service they’re paying money for is involved. Even a quick note, letting them know you’re still working on their issue, will reassure your customer that they haven’t been forgotten and are still a priority for you. Expectations for great customer service are higher than ever and, thanks to technology and social media advancements, there are a ton of quick, easy methods and tools to keep your customers “in the know.”

I highly recommend sharing these tips with new employees at any company, as they can help expedite the growth from rookie to seasoned veteran in the customer service world.  Every company has different support procedures, but these concepts should be universal whether you’re in fast food or software development.  What are some ways you’ve failed to meet customer expectations?  What are ways you try to meet them on a daily basis?

Making a Good “First” Impression

There’s nothing like the old cliché, “You never get a second chance to make a first impression.” In the software development business, this quote definitely holds true. Earning a client’s trust will hopefully happen the first time you meet with them to discuss their problem and work to identify a business solution, but once you gain that trust and come to an agreement to help them achieve their business solution, it doesn’t stop there. There are other points during a project that provide an opportunity to make a good impression, to ensure a successful project, and a great client relationship in the future:

Project Kickoff Meeting

At the start of the project we usually conduct a project kick-off meeting. Sometimes this meeting is with your initial contact, on whom you’ve already made a good first impression (or you wouldn’t have the job), but often this meeting will introduce you to the client contact who you’ll work with throughout the course of the project. It’s important to convey, during this meeting, that you understand the company’s needs and that you’re willing to listen to their ideas, suggestions, and pain points. Here are a few examples of what I do in these meetings to help ensure I’m making a good impression:

  1. Come organized and be prepared. Make sure the client knows that you understand their problem.
  2. Ask questions and don’t assume you know any answers. You’ve got questions for a reason; assuming the answers will ultimately leave you lacking vital information you’ll need later on.
  3. Listen to what the client wants and, if what they explain doesn’t make sense, see if you exlpore new ways of “explaining it” with them. I often have clients draw what they want on a whiteboard. While the drawing might not be an accurate representation of what will be needed in the long haul, having the client take control and talk things out while sketching is a good way to get them to focus on the goals of the project and gives you a great opportunity to gather requirements.
  4. Be sure someone from your team is taking diligent notes that you can refer to after the meeting and throughout the course of the project, making sure nothing gets missed.
  5. After the meeting, send the client an email, summarizing all the details and plans that were discussed.

First Client Demo

One of my favorite things about the software development process is seeing the client’s reaction when you first show off the solution you’ll be providing. Depending on the size of the project, and how many meetings it took to fully gather the requirements, the amount of time between kick-off to the first demo could be months-a lot of hard work goes into the requirements and construction, so you don’t want this first demo to go poorly. Having a bad demo might strip their confidence in you and what you’ve been striving to achieve with them. Here are some suggestions that have helped me ensure a great initial demo:

  1. Manage the client’s expectations about what they’ll see in the demo prior to arriving for your meeting. If you don’t know what to expect, they might be disappointed when that “cool feature” they’re all waiting for isn’t quite done.
  2. Try not to demo something that isn’t believed to be fully developed. Works-in-progress will probably throw errors and not perform to expectation, so save them for next time, when they are done!
  3. Try to populate the demonstration to utilize data that the client will understand. This may seem subtle to the developers, but having the client understand exactly what they are looking at will generate more productive questions and weed out unnecessary ones. If the client is fixated on “Why do all the fields say ‘Testing A’?” they won’t be focusing on whether you’ve accomplished the task at hand.
  4. For each screen or process you review, be sure to ask if it makes sense and take note of the reaction of the customers. It is usually pretty easy to tell from their expressions whether or not they “get” what you just showed them. Don’t underestimate this step-if you go through an entire demo without offering an opportunity for questions you’ve probably lost them.

As you can see, there are at least three different times where you need to make a good “first impression” throughout a project. This idea has been hammered home to me recently in my personal life, as well, as I’ve interacted with two separate businesses where my first impression of them was less than impressive. I thought to myself “Why would I spend my money on a product when I don’t have confidence that my best interests aren’t being considered?” Make sure you’re considering your clients’ best interests when working on projects for them and make sure the impression you’re providing leaves them confident you’re doing just that-putting them first!

Conservative Values of Software Development

I have been associated with software development for over 35 years. I wrote my first software using assembly language. Every thing that executed in our software in those days was written by us. We did not have libraries to link to or objects to include or API’s to call. I am not trying to imply that software development is easier now than it was before. The challenges faced by today’s developer are different than what we faced. Software written in those days accomplished less with more lines of codes than today’s software. The technologies, methods and many other aspects of software development may have changed but the basic rules that we followed those days still hold value.
Let me introduce you to those basic rules that I always followed. I call them the conservative values of software development.

Keep it simple:

One of my professors of assembly language programming gave us a challenge as our first assignment. We had to write a simple program to determine if a given number was prime using a pseudo language which contained only one executable statement and one declarative statement. It took us hundreds of lines of code to accomplish that simple task. The lecture that followed that assignment taught me a life long lesson: Simple programs are easy to debug, easy to follow, and usually more efficient to execute. Writing a complex line of code that can accomplish several tasks may make you feel good about your coding skills but pray that no one else has to debug or change that code some day, because they won’t agree that you’re a good coder. Accomplishing the same set of tasks in few simple lines of code will be better in the long run. Simple code is more readily reusable. I’m not preaching that you shouldn’t use all the tools at your disposal, just that you should remember to keep it simple.

Don’t lose focus on your target users:

This rule is more applicable to today’s developers because we use so many different apps in our day to day lives that using software becomes a second nature to us and we start developing our software to behave the way we want our software to behave, which can lead to many assumptions and prejudices of user requirements on our part. You’ll only work once to build the software but the user will use it many, many times to help them take care of some important business. Your number one goal should be to make sure that they can accomplish the tasks important to them in most efficient and simple steps. They might be wowed by fancy features the first few times they interact with your software but, in the long run, its efficiency and ease of use will be the only things that will matter.

Making your software mistake proof:

Making assumptions about a user’s requirements is as bad as assuming that all users of your software know what they are doing. Yes, they do know their business and probably know what they want to accomplish but you can’t expect them to always enter the right values in the right fields and chose the right action. But you shouldn’t attribute their mistakes to lack of knowledge, repetition can often create “slip-ups” and if little mistakes create a lot of “fix it” work, then failure isn’t just theirs but your software’s, as well. You know the business rules and you know what mistakes can corrupt the data or corrupt the process–put in the extra effort to edit for those mistakes. Your users may not realize it, or even appreciate it, but you’ll create a more efficient process for them and that should always be your goal.

Software Developers are like people who build roads. Basically, we’re providing a means to get from Point A to Point B in the most direct way, saving our users time and hassles.   Remember not to build a scenic road, full of curves and bumps, if you’re building it for drivers who use it to get to work every day!