If you have been paying attention to Tech News and the U.S. Government you may have heard about the ‘Do Not Track’ initiative that may become law. In a nutshell, the Do Not Track (DNT) initiative is a law that would require web sites to not track a user on sites they don’t visit.
Ok, take the time to read that very carefully; ‘sites they don’t visit’. You can still track the user on your site if they directly come to your site, but you cannot share tracking information with other sites. A good summary of this can be found at www.donottrack.us. Specifically, the site sums it up as: Do Not Track is a technology and policy proposal that enables users to opt out of tracking by websites they do not visit, including analytics services, advertising networks, and social platforms. So, if your website uses Google Analytics or shares info with Facebook, you need to know about this and you need to make some changes in your code.How it works
DNT is a browser based option that allows the user to say ‘Don’t track me’ and is supported in most newer browser. For instance, in FireFox 14.0.1 it can be found under Options -> Privacy -> Tracking
.
What then happens is that the browser, with every request, will send an additional HTTP Header to tell the web site to not track the user. The HTTP Header is named DNT
(Wikipedia List_of_HTTP_header_fields) and has two possible values: 0
or 1
.
DNT
is set to 1
then the user should not be tracked. Any other value should permit tracking (though the spec says the only other value is 0
). From there it is up to the web site to pay attention to the header or to ignore it
Code to the rescue!
If you decide that you are going to support DNT, good for you! Most of us don’t like to be tracked so we should lead by example! Also, it’s very easy to support!
Since most of the tracking code (such as Google Analytics) is in the presentation layer (.html/.jsp/.gsp/etc) it makes sense to place the DNT check/code there as well. Nothing is easier in this case than a custom tag to accomplish this. The tag (which means that if you have your tracking code in HTML you will have to change it to a .jsp/.gsp or some other dynamic page) simply needs to check if DNT == 1 and if it does, don’t render what is in the body of the tag. Let’s first take a look at the final result:<track:trackable> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'xxxxxxx']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </track:trackable>
Time to break it down:
<track:trackable>
This is our custom tag. Anything that exists within it will be rendered only if it is OK to track the user (DNT != 1)
var _gaq = _gaq || []; _gaq.push(['_setAccount', 'xxxxxxx']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();
This is the code to have in the page if tracking is allowed (in this case it’s Google Analytics)
</track:trackable>
This end our tag
Now let’s look at the code for the tag. Again, this is GRAILS taglib code but I’ll go over it step-by-step so you can translate it to whatever you want.
class TrackTagLib { static namespace = "track" /** * if the user is trackable the contents between the tag are rendered */ def trackable = { attrs, body -> if (request.getHeader("DNT") != "1") { out << body() } } }
Wow that’s simple isn’t it? Break it down:
class TrackTagLib {
Define the class
static namespace = "track"
This names the tag prefix for us (the track
in <track:trackable>
)
def trackable = { attrs, body ->
Defines the trackable
method and gets passed in two variables:
- attrs – any attributes passed to the tag
- body – the code that exists between the start and end of the tag
if (request.getHeader("DNT") != "1") {
If the HTTP Header DNT
does not equal 1 (i.e. we are allowed to track)
Note that in some languages you made need a null check for if the DNT header even exists before you check its value (not needed in Groovy/GRAILS)
out << body()
Since we are allowed to track, render the body of what is between the <track:trackable>
tag.
Not to difficult and very easy to use. Putting the code in a taglib allows you to use it on any of your pages so that you can quickly and easily support DNT.
Google Analytics
I thought I should take a minute (just sit right there and let me tell you how I became the Prince of a town called Bel Air) to comment on Google Analytics and its Terms of Service (TOS).
Most developers do not read TOS agreements and you really should (see South Park Season 15:Humancentipad). One section in particular needs attention (currently section 7):
You will not (and will not allow any third party to) use the Service to track, collect or upload any data that personally identifies an individual (such as a name, email address or billing information), or other data which can be reasonably linked to such information by Google. You will have and abide by an appropriate Privacy Policy and will comply with all applicable laws and regulations relating to the collection of information from Visitors. You must post a Privacy Policy and that Privacy Policy must provide notice of Your use of cookies that are used to collect traffic data, and You must not circumvent any privacy features (e.g., an opt-out) that are part of the Service.
So, you may have a few action items:
- Make sure you have a Privacy Policy page on your site
- Make sure the Privacy Policy page informs that use that you are using Google Analytics for tracking
- Make sure you are not setting custom parameters in Google Analytics that allow you to determine who the user is. This is the main reason Google Analytics does not display IP addresses of users that were tracked. User information must be anonymous
Legally tracking user page flow
So what happens if you get a directive that your site should be able to track the flow of a user through the site? What can you do?
Well, your actually OK. DNT allows you to still track a user, you just can’t give the info to sites the user hasn’t visited (or, to be more safe, anything other than your site). You can still record the user name and the page they visited so you can get a user page flow, but you can’t use something like Google Analytics to do this.
Or can you?
What you could do is record anonymous user page flow. Google Analytics supports the ability to pass in your own custom variables. One of those variables could be a Universal Unique ID (UUID) that could be used with Google Analytics filters to get an idea of user page flow.
PLEASE NOTE: The UUID cannot be related back to the actual user of the system. You can’t use their user name, db primary key, or ANYTHING that would allow you to tie the user to that UUID. That would violate the TOS.
So What do you do? Easy, you put the UUID in the users session and every time your Google Analytics code is called you pass the UUID. If you really think about this you will realize that technically you could at this point relate the user to the UUID if you were to dig into the sessions (via MBeans or some custom code) and you would be right. We would be violating the TOS at this point. At this point it is more of a “just don’t do it”.Since this is a little sketchy because it could be abused I will not be posting code on how to do this. You are on your own, please follow the TOS.
Conclusion
As you can see, it is very easy to introduce support for DNT. You can still track users on your site, but you cannot share it with other sites.
Take the time to be considerate to the users and implement DNT.