CSS-Only Solution For UI Tracking
- By Krasimir Tsonev
- October 16th, 2014
- 22 Comments
The web is flourishing up. We are building applications that work wholly in a browser. They are responsive; they have tons of facilities and work underneath many devices. We suffer providing high-quality formula that is good structured and tested.
But what matters in a finish is a impact for clients. Are they removing some-more products sole or are there some-more visitors for their debate sites? The final formula customarily uncover if a plan is successful. And we rest on statistics as a measuring tool. We all use instruments like Google Analytics1. It is a absolute proceed to collect data. In this article, we will see a CSS-only proceed for tracking UI interactions regulating Google Analytics.
2The Problem
We grown an focus that had to work on several devices. We were not means to exam on many of them and motionless that we had to make all simple. So elementary that there wasn’t a possibility to furnish cart code. The pattern was clean, minimalistic, and there wasn’t any formidable business logic.
It was a website displaying information about one of a client’s products. One of a tasks was to lane user visits and interactions. For many cases, we used Google Analytics. All we had to do was to place formula like a instance next during a bottom of a pages:
(function(i,s,o,g,r,a,m)i['GoogleAnalyticsObject']=r;i[r]=i[r])(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '......', '......');
ga('send', 'pageview');
This dash was adequate for tracking page views, traffic, sessions, etc. Moreover, we placed JavaScript where a user interacts with a page. For example, clicking on a link, stuffing an contention field, or checking choice boxes.
ga('send', 'event', 'ui-interaction', 'click', 'link clicked', 1);
The guys from Google rubbed these events nicely, and we were means to see them in a account. However, during some indicate a customer reported that there were inclination that have bad or no JavaScript support. They represented roughly 2% of all a inclination that visited a site. We started acid for a fortitude that did not engage JavaScript. We were prepared to acknowledge that we could not collect statistics underneath these circumstances.
It was not that bad, though a customer common another issue. Our small focus was going to be partial of a private network. The computers there had JavaScript incited off for confidence reasons. Also, this private network was critical for a client. So, he insisted that we still get stats in those cases. We had to yield a scold solution, though a problem was that we had customarily CSS and HTML accessible as tools.
3The Solution
While acid for a solution, we was monitoring a Network add-on in Chrome’s developer collection when we beheld a following:
In a beginning, we suspicion that there was zero unusual. Google Analytics’s formula done few HTTP requests for a tracking processes. However, a fourth mainstay shows a Content-type
header of a response. It is an image. Not JSON or HTML, though an image. Then we started reading a support and landed on this Tracking Code Overview6. The many engaging partial was:
When all this information is collected, it is sent to a Analytics servers in a form of a prolonged list of parameters trustworthy to a single-pixel GIF picture request.
So, Google indeed done a HTTP ask though not a pardonable Ajax call. It simply appends all a parameters to an image’s URL. After that it performs a ask for a GIF file. There is even a name for such requests: beacon7. we wondered since GA uses this approach. Then we satisfied that there are some benefits:
- It is simple. We initialize a new
Image
intent and ask a value to asrc
attribute:new Image().src = '/stats.gif?' + parameters
- It works everywhere. There is no need to supplement workarounds for opposite browsers as we do for Ajax requests.
- Tiny response. As Stoyan Stefanov said8, a 1×1px GIF picture could be customarily 42 bytes.
I done few clicks and sent events to Google Analytics. Knowing a ask parameters, we was means to erect my possess picture URLs. The customarily thing to do in a finish was to bucket an picture on a page. And yes, this was probable with pristine CSS.
background-image: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
Setting a background-image
CSS skill army a browser to bucket an image. Finally, we successfully used this technique to lane user actions.
9Tracking User Actions
There are several ways to change styles formed on user input. The initial thing we suspicion about was a :active
pseudo class. This category matches when an component is activated by a user. It is a time between a impulse a user presses a rodent symbol and releases it. In a case, this was ideal for tracking clicks:
input[type="button"]:active
background-image: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
Another useful pseudo category is :focus
. We available how many times users started typing in a hit form. It was engaging to find out that in about 10% of cases users did not indeed contention a form.
input[name="message"]:focus
background-image: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
On one page, we had a step-by-step questionnaire. At a end, a user was asked to establish with some terms and conditions. Some of a visitors did not finish that final step. In a initial chronicle of a site, we were not means to establish what these users had comparison in a petition since a formula would have been sent after completion. However, since all a stairs were customarily radio buttons, we used a :checked
pseudo category and successfully tracked a selections:
input[value="female"]:checked
background-image: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
One of a many critical statistics we had to broach was about a farrago of shade resolutions. Thanks to media queries this was possible:
@media all and (max-width: 640px)
physique
background-image: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
In fact, there are utterly a few judicious operators10 that we can use. We can lane screens with a specific aspect ratio; inclination in landscape orientation; or those with a fortitude of 300dpi.
11Drawbacks
The problem with this kind of CSS UI tracking is that we get customarily a initial occurrence of a event. For example, take a :active
pseudo category example. The ask for a credentials picture is dismissed customarily once. If we need to constraint any click then, we have to change a URL, that is not probable though JavaScript.
We used a background-image
skill to make a HTTP requests. However, infrequently we competence need to set a genuine picture as a credentials since of a application’s design. In such cases we could use a content
property. It is customarily used for adding content or icons though a skill also accepts an image. For example:
input[value="female"]:checked
content: url('http://www.google-analytics.com/collect?v=1_v=j23a=...');
Because we are requesting an image, we should make certain that a browser is not caching a file. The statistics server should routine a ask any time. We could grasp this by providing a scold headers. Check out a picture below. It shows a response headers sent by Google:
Sending a following headers guarantees that a browser will not cache a image:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
In some cases, we might confirm to write a possess statistics server. This is an critical note that we contingency cruise during development. Here is a elementary Node.js-based implementation. We used that for contrast purposes:
var fs = require('fs'),
http = require('http'),
url = require('url'),
img = fs.readFileSync(__dirname + '/stat.png'),
stats = ;
var collectStats = function(type)
console.log('collectStats type=' + type);
if(!stats[type]) stats[type] = 0;
stats[type]++;
http.createServer(function(req, res)
var ask = url.parse(req.url, true);
var movement = request.pathname;
if (action == '/stat.png')
collectStats(request.query.type);
res.writeHead(200, 'Content-Type': 'image/gif', 'Cache-Control': 'no-cache' );
res.end(img, 'binary');
else
res.writeHead(200, 'Content-Type': 'text/html' );
res.end('Stats server:pre' + JSON.stringify(stats) + '/pren');
).listen(8000, '127.0.0.1');
console.log('Server is using during http://127.0.0.1:8000');
If we save a formula to a record called server.js and govern node server.js
we will get a server listening on pier 8000. There are dual probable URLs for querying:
* http://127.0.0.1:8000/ - shows a collected statistics
* http://127.0.0.1:8000/stat.png?type=something - collecting statistics.
By requesting a PNG in a second URL, we are incrementing values. The following square of formula shows a HTML and CSS that we have to place in a browser:
input type="button" value="click me"/
input[type="button"]:active
background-image: url('http://127.0.0.1:8000/stat.png?type=form-submitted');
Finally, as a final obstacle we have to discuss that some antivirus program or browser settings might mislay 1×1px beacons. So we have to be clever when selecting this technique and make certain that we yield workarounds.
14Summary
CSS is customarily deliberate a denunciation for requesting styles to webpages. However, in this essay we saw that it is some-more than that. It is also a accessible apparatus for collecting statistics.
(ds, il, og)
Footnotes
- 1 http://www.google.com/analytics/
- 2 #the-problem
- 3 #the-solution
- 4 http://www.smashingmagazine.com/wp-content/uploads/2014/10/1-google-analytics-large-preview-opt.png
- 5 http://www.smashingmagazine.com/wp-content/uploads/2014/10/1-google-analytics-large-preview-opt.png
- 6 https://developers.google.com/analytics/resources/concepts/gaConceptsTrackingOverview
- 7 http://www.phpied.com/beacon-performance/
- 8 http://www.phpied.com/beacon-performance/
- 9 #the-tracking
- 10 https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
- 11 #drawbacks
- 12 http://www.smashingmagazine.com/wp-content/uploads/2014/10/2-google-analytics-large-preview-opt.png
- 13 http://www.smashingmagazine.com/wp-content/uploads/2014/10/2-google-analytics-large-preview-opt.png
- 14 #summary
↑ Back to topShare on Twitter
CSS-Only Solution For UI Tracking
Nenhum comentário:
Postar um comentário