-
-
Notifications
You must be signed in to change notification settings - Fork 167
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #84 from sikmir/yandex-metrica
Support Yandex.Metrica
- Loading branch information
Showing
6 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
""" | ||
Yandex.Metrica template tags and filters. | ||
""" | ||
|
||
from __future__ import absolute_import | ||
|
||
import json | ||
import re | ||
|
||
from django.conf import settings | ||
from django.template import Library, Node, TemplateSyntaxError | ||
|
||
from analytical.utils import is_internal_ip, disable_html, \ | ||
get_required_setting | ||
|
||
|
||
COUNTER_ID_RE = re.compile(r'^\d{8}$') | ||
COUNTER_CODE = """ | ||
<script type="text/javascript"> | ||
(function (d, w, c) { | ||
(w[c] = w[c] || []).push(function() { | ||
try { | ||
w.yaCounter%(counter_id)s = new Ya.Metrika(%(options)s); | ||
} catch(e) { } | ||
}); | ||
var n = d.getElementsByTagName("script")[0], | ||
s = d.createElement("script"), | ||
f = function () { n.parentNode.insertBefore(s, n); }; | ||
s.type = "text/javascript"; | ||
s.async = true; | ||
s.src = "https://mc.yandex.ru/metrika/watch.js"; | ||
if (w.opera == "[object Opera]") { | ||
d.addEventListener("DOMContentLoaded", f, false); | ||
} else { f(); } | ||
})(document, window, "yandex_metrika_callbacks"); | ||
</script> | ||
<noscript><div><img src="https://mc.yandex.ru/watch/%(counter_id)s" style="position:absolute; left:-9999px;" alt="" /></div></noscript> | ||
""" | ||
|
||
|
||
register = Library() | ||
|
||
|
||
@register.tag | ||
def yandex_metrica(parser, token): | ||
""" | ||
Yandex.Metrica counter template tag. | ||
Renders Javascript code to track page visits. You must supply | ||
your website counter ID (as a string) in the | ||
``YANDEX_METRICA_COUNTER_ID`` setting. | ||
""" | ||
bits = token.split_contents() | ||
if len(bits) > 1: | ||
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0]) | ||
return YandexMetricaNode() | ||
|
||
|
||
class YandexMetricaNode(Node): | ||
def __init__(self): | ||
self.counter_id = get_required_setting( | ||
'YANDEX_METRICA_COUNTER_ID', COUNTER_ID_RE, | ||
"must be (a string containing) a number'") | ||
|
||
def render(self, context): | ||
options = { | ||
'id': int(self.counter_id), | ||
'clickmap': True, | ||
'trackLinks': True, | ||
'accurateTrackBounce': True | ||
} | ||
if getattr(settings, 'YANDEX_METRICA_WEBVISOR', False): | ||
options['webvisor'] = True | ||
if getattr(settings, 'YANDEX_METRICA_TRACKHASH', False): | ||
options['trackHash'] = True | ||
if getattr(settings, 'YANDEX_METRICA_NOINDEX', False): | ||
options['ut'] = 'noindex' | ||
if getattr(settings, 'YANDEX_METRICA_ECOMMERCE', False): | ||
options['ecommerce'] = 'dataLayer' | ||
html = COUNTER_CODE % { | ||
'counter_id': self.counter_id, | ||
'options': json.dumps(options), | ||
} | ||
if is_internal_ip(context, 'YANDEX_METRICA'): | ||
html = disable_html(html, 'Yandex.Metrica') | ||
return html | ||
|
||
|
||
def contribute_to_analytical(add_node): | ||
YandexMetricaNode() # ensure properly configured | ||
add_node('head_bottom', YandexMetricaNode) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
""" | ||
Tests for the Yandex.Metrica template tags and filters. | ||
""" | ||
|
||
import re | ||
|
||
from django.contrib.auth.models import User, AnonymousUser | ||
from django.http import HttpRequest | ||
from django.template import Context | ||
from django.test.utils import override_settings | ||
|
||
from analytical.templatetags.yandex_metrica import YandexMetricaNode | ||
from analytical.tests.utils import TagTestCase | ||
from analytical.utils import AnalyticalException | ||
|
||
|
||
@override_settings(YANDEX_METRICA_COUNTER_ID='12345678') | ||
class YandexMetricaTagTestCase(TagTestCase): | ||
""" | ||
Tests for the ``yandex_metrica`` template tag. | ||
""" | ||
|
||
def test_tag(self): | ||
r = self.render_tag('yandex_metrica', 'yandex_metrica') | ||
self.assertTrue("w.yaCounter12345678 = new Ya.Metrika" in r, r) | ||
|
||
def test_node(self): | ||
r = YandexMetricaNode().render(Context({})) | ||
self.assertTrue("w.yaCounter12345678 = new Ya.Metrika" in r, r) | ||
|
||
@override_settings(YANDEX_METRICA_COUNTER_ID=None) | ||
def test_no_site_id(self): | ||
self.assertRaises(AnalyticalException, YandexMetricaNode) | ||
|
||
@override_settings(YANDEX_METRICA_COUNTER_ID='1234abcd') | ||
def test_wrong_site_id(self): | ||
self.assertRaises(AnalyticalException, YandexMetricaNode) | ||
|
||
@override_settings(ANALYTICAL_INTERNAL_IPS=['1.1.1.1']) | ||
def test_render_internal_ip(self): | ||
req = HttpRequest() | ||
req.META['REMOTE_ADDR'] = '1.1.1.1' | ||
context = Context({'request': req}) | ||
r = YandexMetricaNode().render(context) | ||
self.assertTrue(r.startswith( | ||
'<!-- Yandex.Metrica disabled on internal IP address'), r) | ||
self.assertTrue(r.endswith('-->'), r) |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
================================== | ||
Yandex.Metrica -- traffic analysis | ||
================================== | ||
|
||
`Yandex.Metrica`_ is an analytics tool like as google analytics. | ||
|
||
.. _`Yandex.Metrica`: http://metrica.yandex.com/ | ||
|
||
|
||
.. yandex-metrica-installation: | ||
Installation | ||
============ | ||
|
||
To start using the Yandex.Metrica integration, you must have installed the | ||
django-analytical package and have added the ``analytical`` application | ||
to :const:`INSTALLED_APPS` in your project :file:`settings.py` file. | ||
See :doc:`../install` for details. | ||
|
||
Next you need to add the Yandex.Metrica template tag to your templates. This | ||
step is only needed if you are not using the generic | ||
:ttag:`analytical.*` tags. If you are, skip to | ||
:ref:`yandex-metrica-configuration`. | ||
|
||
The Yandex.Metrica counter code is inserted into templates using a template | ||
tag. Load the :mod:`yandex_metrica` template tag library and insert the | ||
:ttag:`yandex_metrica` tag. Because every page that you want to track must | ||
have the tag, it is useful to add it to your base template. Insert | ||
the tag at the bottom of the HTML head:: | ||
|
||
{% load yandex_metrica %} | ||
<html> | ||
<head> | ||
... | ||
{% yandex_metrica %} | ||
</head> | ||
... | ||
|
||
|
||
.. _yandex-metrica-configuration: | ||
|
||
Configuration | ||
============= | ||
|
||
Before you can use the Yandex.Metrica integration, you must first set | ||
your website counter ID. | ||
|
||
|
||
.. _yandex-metrica-counter-id: | ||
|
||
Setting the counter ID | ||
---------------------- | ||
|
||
Every website you track with Yandex.Metrica gets its own counter ID, | ||
and the :ttag:`yandex_metrica` tag will include it in the rendered | ||
Javascript code. You can find the web counter ID on the overview page | ||
of your account. Set :const:`YANDEX_METRICA_COUNTER_ID` in the | ||
project :file:`settings.py` file:: | ||
|
||
YANDEX_METRICA_COUNTER_ID = '12345678' | ||
|
||
If you do not set a counter ID, the counter code will not be rendered. | ||
|
||
You can set additional options to tune your counter: | ||
|
||
============================ ============= ============================================= | ||
Constant Default Value Description | ||
============================ ============= ============================================= | ||
``YANDEX_METRICA_WEBVISOR`` False Webvisor, scroll map, form analysis. | ||
``YANDEX_METRICA_TRACKHASH`` False Hash tracking in the browser address bar. | ||
``YANDEX_METRICA_NOINDEX`` False Stop automatic page indexing. | ||
``YANDEX_METRICA_ECOMMERCE`` False Dispatch ecommerce data to Metrica. | ||
============================ ============= ============================================= | ||
|
||
Internal IP addresses | ||
--------------------- | ||
|
||
Usually you do not want to track clicks from your development or | ||
internal IP addresses. By default, if the tags detect that the client | ||
comes from any address in the :const:`YANDEX_METRICA_INTERNAL_IPS` setting, | ||
the tracking code is commented out. It takes the value of | ||
:const:`ANALYTICAL_INTERNAL_IPS` by default (which in turn is | ||
:const:`INTERNAL_IPS` by default). See :ref:`identifying-visitors` for | ||
important information about detecting the visitor IP address. |