A Technique for Tracking Page Print Using CSS Background Images

Printing a web page is still one of the most popular ways that customers interact with a classifieds search engine. At AutoConX, we try to track that metric for our sellers, so they can see how frequently people print off their listings for safe keeping. Our legacy platform presents users a print-dedicated page to track such details. But what is a modern, responsive technique for tracking that kind of interaction? I wanted something that could target printing by any means possible: triggering a JavaScript print event, using browser keyboard shortcuts or menu items and even using the cloud printing capabilities on mobile devices. CSS’s print media seemed like the way to go.

First, how to handle the actual tracking. A common technique involves creating a “tracking pixel.” When an image tag is dropped into the page, it appears to load a small, transparent gif. What actually happens is that special code executes behind the scenes and just returns data in the form of a small, transparent pixel. I crafted a 1px by 1px transparent gif as the tracking pixel and created a handler event that would call a stored procedure that would track the print in the database. Then the handler would return the data from the transparent pixel to the browser to be rendered as any other image. The CFML code roughly looked like this:

Next, I needed to use that URL as the `src` for an image. I dropped an image tag into a section of code already setup to show only for print media. The section displays a QR code and canonical URL so people with the paper version can get back to the web version. It looked like this:

I opened Chrome Dev Tools, chose the Network panel and reloaded the page. A call to my tracking pixel was made even though the image was hidden from the screen. This is an age old situation that has made it necessary to create new tags like picture and attributes like srcset for displaying different images for different browser scenarios. It was worth a shot, but now I knew this wouldn’t be as easy as I’d hoped.

Let’s try the stylesheet instead. I created the selector `.detail--trackprint` and used my tracking pixel as a background image. It looked like this:

I reloaded the page and… oh, right. CSS URLs are relative to the CSS file. Another rookie mistake. What I needed is something that is relative to the executing page so that the CFML framework gets the appropriate listing information needed for tracking. I tried briefly to use data attributes to build my background image URL, but the `attr()` function is still only good for content. Inline styling would be my best bet. I modified my original view:

I reloaded the page and watched the Network. No call. I emulated print media and reloaded the page. CALL! Success! I deployed the code to our dev server and put some other team members on QA. They weren’t seeing tracking counts as high as they should be. I dug into it with my own testing and found that the browsers (I saw this behavior in several of them) were caching the print preview after the first print. It makes sense and saves the browser some work and data transfer. However, I need to get as close to accurate as possible. I added a cachebuster to the background image:

This proved to be the solution we needed. But it doesn’t track every print! I know. This technique is equivalent to what we have in our legacy system, so in that sense it is a responsive implementation of the same accuracy our sellers already have. I could add some long polling JavaScript to increment the cachebuster while the page is loaded. This would give us
stats on the same page without reloading, but that seems overkill for a secondary metric. That number still wouldn’t be entirely accurate, because users can print more than one copy at a time. In the end, this was just enough development to meet the needs of the sellers.

Author: Miles Rausch

I've made a smart playlist of all the songs with 0 plays. I listen to them because I feel bad for them not because I like the music. I'm THAT guy.

Leave a Reply