Last active
January 12, 2018 11:25
-
-
Save kravietz/c04020d9f207cf2a712d to your computer and use it in GitHub Desktop.
DoNotTrack middleware for Django.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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