Instantly share code, notes, and snippets.

Embed
What would you like to do?
DoNotTrack middleware for Django.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from django.views.generic import TemplateView
__author__ = 'Paweł Krawczyk'
DNT_HEADER = 'HTTP_DNT'
class DoNotTrackMiddleware(object):
"""
When this middleware is installed Django views can access a new
``request.dnt`` parameter to check client's preference on user tracking as
expressed by their browser configuration settings.
The parameter can take True, False or None values based on the presence of
the ``Do Not Track`` HTTP header in client's request, which in turn depends
on browser's configuration. The header indicates client's general
preference to opt-out from behavioral profiling and third-party tracking.
The parameter does **not** change behaviour of Django in any way as its
sole purpose is to pass the user's preference to application. It's then up
to the owner to implement a particular policy based on this information.
Compliant website should adapt its behaviour depending on one of user's
preferences:
- Explicit opt-out (``request.dnt`` is ``True``): Disable third party
tracking for this request and delete all previously stored tracking data.
- Explicit opt-in (``request.dnt`` is ``False``): Website may track user.
- Header not present (``request.dnt`` is ``None``): Website may track user,
but should not draw any definite conclusions on user's preferences as the
user has not expressed it.
For example, if ``request.dnt`` is `` True`` the website might respond by
disabling template parts responsible for personalized statistics, targeted
advertisements or switching to DNT aware ones.
Examples:
- `Do Not Track (DNT) tutorial for Django <http://ipsec.pl/node/1101>`_
- `Do Not Track - Web Application Templates
<http://donottrack.us/application>`_
- `Opt-out of tailoring Twitter <https://dev.twitter.com/docs/tweet-
button#optout>`_
References:
- `Web Tracking Protection <http://www.w3.org/Submission/web-tracking-protection/>`_
- `Do Not Track: A Universal Third-Party Web Tracking Opt Out
<http://tools.ietf.org/html/draft-mayer-do-not-track-00>`_
- `Tracking Preference Expression (DNT) <https://www.w3.org/TR/tracking-dnt/>`_
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
"""
Read DNT header from browser request and create request attribute for use in templates
and echo the DNT header in response per section 8.4 of draft-mayer-do-not-track-00
"""
if DNT_HEADER in request.META:
if request.META[DNT_HEADER] == '1':
# '1' means 'do not track me'
request.dnt = True
else:
# '0' means consent to tracking
request.dnt = False
else:
# no DNT headers means no tracking preference
# this is the default behaviour
request.dnt = None
response = self.get_response(request)
# echo the DNT header to acknowledge we understand it
if DNT_HEADER in request.META:
response['DNT'] = request.META[DNT_HEADER]
# if client sent DNT: 1 we respond with 'Not tracking' status
# otherwise we respond with 'Tracking' status
if request.dnt:
response['Tk'] = 'N'
else:
response['Tk'] = 'T'
return response
class TrackingStatusView(TemplateView):
"""
View to return TSR (Tracking Status Resource) JSON file. Requires a `tracking.json` template
in the `templates` directory that needs to be customized for your website. An example:
{
"tracking": "{{tracking_status}}",
"compliance": [
"http://www.w3.org/TR/tracking-compliance/",
"https://www.eff.org/.well-known/dnt-policy.txt"
],
"controllerDescription": {
"name": "WebCookies.org",
"uri": "https://webcookies.org"
},
"controller": "https://webcookies.org/",
"same-party": [
"webcookies.info",
"webcookies.org",
"webcookies-20c4.kxcdn.com"
],
"policy": "https://webcookies.org/doc/privacy-policy"
}
Add the view in your `urls.py` file:
urlpatterns = [
...
url(r'^\.well-known/dnt/', never_cache(TrackingStatusView.as_view()), name='tracking_status'),
...
]
References:
- `How sites can comply with Do Not Track <https://trackingprotection.github.io/Implementation/DNTGuide/#tracking-status-resource>`_
"""
template_name = 'tracking.json'
content_type = 'application/tracking-status+json'
def get_context_data(self, **kwargs):
if self.request.dnt:
return {'tracking_status': 'N'}
else:
return {'tracking_status': 'T'}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment