diff --git a/README.rst b/README.rst
index 68004b1..4056e17 100644
--- a/README.rst
+++ b/README.rst
@@ -68,6 +68,7 @@ Currently Supported Services
* `Optimizely`_ A/B testing
* `Performable`_ web analytics and landing pages
* `Piwik`_ open source web analytics
+* `Rating@Mail.ru`_ web analytics
* `SnapEngage`_ live chat
* `Spring Metrics`_ conversion tracking
* `UserVoice`_ user feedback and helpdesk
@@ -90,6 +91,7 @@ Currently Supported Services
.. _`Optimizely`: http://www.optimizely.com/
.. _`Performable`: http://www.performable.com/
.. _`Piwik`: http://www.piwik.org/
+.. _`Rating@Mail.ru`: http://top.mail.ru/
.. _`SnapEngage`: http://www.snapengage.com/
.. _`Spring Metrics`: http://www.springmetrics.com/
.. _`UserVoice`: http://www.uservoice.com/
diff --git a/analytical/templatetags/analytical.py b/analytical/templatetags/analytical.py
index 3ab7c52..ad4fba7 100644
--- a/analytical/templatetags/analytical.py
+++ b/analytical/templatetags/analytical.py
@@ -32,6 +32,7 @@ TAG_MODULES = [
'analytical.optimizely',
'analytical.performable',
'analytical.piwik',
+ 'analytical.rating_mailru',
'analytical.snapengage',
'analytical.spring_metrics',
'analytical.uservoice',
diff --git a/analytical/templatetags/rating_mailru.py b/analytical/templatetags/rating_mailru.py
new file mode 100644
index 0000000..d495824
--- /dev/null
+++ b/analytical/templatetags/rating_mailru.py
@@ -0,0 +1,71 @@
+"""
+Rating@Mail.ru 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{7}$')
+COUNTER_CODE = """
+
+
+"""
+
+
+register = Library()
+
+
+@register.tag
+def rating_mailru(parser, token):
+ """
+ Rating@Mail.ru counter template tag.
+
+ Renders Javascript code to track page visits. You must supply
+ your website counter ID (as a string) in the
+ ``RATING_MAILRU_COUNTER_ID`` setting.
+ """
+ bits = token.split_contents()
+ if len(bits) > 1:
+ raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
+ return RatingMailruNode()
+
+
+class RatingMailruNode(Node):
+ def __init__(self):
+ self.counter_id = get_required_setting(
+ 'RATING_MAILRU_COUNTER_ID', COUNTER_ID_RE,
+ "must be (a string containing) a number'")
+
+ def render(self, context):
+ html = COUNTER_CODE % {
+ 'counter_id': self.counter_id,
+ }
+ if is_internal_ip(context, 'RATING_MAILRU_METRICA'):
+ html = disable_html(html, 'Rating@Mail.ru')
+ return html
+
+
+def contribute_to_analytical(add_node):
+ RatingMailruNode() # ensure properly configured
+ add_node('head_bottom', RatingMailruNode)
diff --git a/analytical/tests/test_tag_rating_mailru.py b/analytical/tests/test_tag_rating_mailru.py
new file mode 100644
index 0000000..2e91a60
--- /dev/null
+++ b/analytical/tests/test_tag_rating_mailru.py
@@ -0,0 +1,47 @@
+"""
+Tests for the Rating@Mail.ru 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.rating_mailru import RatingMailruNode
+from analytical.tests.utils import TagTestCase
+from analytical.utils import AnalyticalException
+
+
+@override_settings(RATING_MAILRU_COUNTER_ID='1234567')
+class RatingMailruTagTestCase(TagTestCase):
+ """
+ Tests for the ``rating_mailru`` template tag.
+ """
+
+ def test_tag(self):
+ r = self.render_tag('rating_mailru', 'rating_mailru')
+ self.assertTrue("counter?id=1234567;js=na" in r, r)
+
+ def test_node(self):
+ r = RatingMailruNode().render(Context({}))
+ self.assertTrue("counter?id=1234567;js=na" in r, r)
+
+ @override_settings(RATING_MAILRU_COUNTER_ID=None)
+ def test_no_site_id(self):
+ self.assertRaises(AnalyticalException, RatingMailruNode)
+
+ @override_settings(RATING_MAILRU_COUNTER_ID='1234abc')
+ def test_wrong_site_id(self):
+ self.assertRaises(AnalyticalException, RatingMailruNode)
+
+ @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 = RatingMailruNode().render(context)
+ self.assertTrue(r.startswith(
+ ''), r)
diff --git a/docs/install.rst b/docs/install.rst
index 77517c4..192617f 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -172,6 +172,10 @@ settings required to enable each service are listed here:
PIWIK_DOMAIN_PATH = 'your.piwik.server/optional/path'
PIWIK_SITE_ID = '123'
+* :doc:`Rating@Mail.ru `::
+
+ RATING_MAILRU_COUNTER_ID = '1234567'
+
* :doc:`Woopra `::
WOOPRA_DOMAIN = 'abcde.com'
diff --git a/docs/services/rating_mailru.rst b/docs/services/rating_mailru.rst
new file mode 100644
index 0000000..c278622
--- /dev/null
+++ b/docs/services/rating_mailru.rst
@@ -0,0 +1,73 @@
+===================================
+Rating@Mail.ru -- traffic analysis
+===================================
+
+`Rating@Mail.ru`_ is an analytics tool like as google analytics.
+
+.. _`Rating@Mail.ru`: http://top.mail.ru/
+
+
+.. rating-mailru-installation:
+
+Installation
+============
+
+To start using the Rating@Mail.ru 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 Rating@Mail.ru 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:`rating-mailru-configuration`.
+
+The Rating@Mail.ru counter code is inserted into templates using a template
+tag. Load the :mod:`rating_mailru` template tag library and insert the
+:ttag:`rating_mailru` 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 rating_mailru %}
+
+
+ ...
+ {% rating_mailru %}
+
+ ...
+
+
+.. _rating-mailru-configuration:
+
+Configuration
+=============
+
+Before you can use the Rating@Mail.ru integration, you must first set
+your website counter ID.
+
+
+.. _rating-mailru-counter-id:
+
+Setting the counter ID
+----------------------
+
+Every website you track with Rating@Mail.ru gets its own counter ID,
+and the :ttag:`rating_mailru` 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:`RATING_MAILRU_COUNTER_ID` in the
+project :file:`settings.py` file::
+
+ RATING_MAILRU_COUNTER_ID = '1234567'
+
+If you do not set a counter ID, the counter code will not be rendered.
+
+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:`RATING_MAILRU_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.