File: woopra.py

package info (click to toggle)
python-django-analytical 3.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 720 kB
  • sloc: python: 4,693; makefile: 7
file content (132 lines) | stat: -rw-r--r-- 4,736 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
Woopra template tags and filters.
"""

import json
import re
from contextlib import suppress

from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError

from analytical.utils import (
    AnalyticalException,
    disable_html,
    get_identity,
    get_required_setting,
    get_user_from_context,
    get_user_is_authenticated,
    is_internal_ip,
)

DOMAIN_RE = re.compile(r'^\S+$')
TRACKING_CODE = """
     <script>
      var woo_settings = %(settings)s;
      var woo_visitor = %(visitor)s;
      !function(){var a,b,c,d=window,e=document,f=arguments,g="script",h=["config","track","trackForm","trackClick","identify","visit","push","call"],i=function(){var a,b=this,c=function(a){b[a]=function(){return b._e.push([a].concat(Array.prototype.slice.call(arguments,0))),b}};for(b._e=[],a=0;a<h.length;a++)c(h[a])};for(d.__woo=d.__woo||{},a=0;a<f.length;a++)d.__woo[f[a]]=d[f[a]]=d[f[a]]||new i;b=e.createElement(g),b.async=1,b.src="//static.woopra.com/js/w.js",c=e.getElementsByTagName(g)[0],c.parentNode.insertBefore(b,c)}("woopra");
      woopra.config(woo_settings);
      woopra.identify(woo_visitor);
      woopra.track();
    </script>
"""  # noqa

register = Library()


@register.tag
def woopra(parser, token):
    """
    Woopra tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your Woopra domain in the ``WOOPRA_DOMAIN`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return WoopraNode()


class WoopraNode(Node):
    def __init__(self):
        self.domain = get_required_setting(
            'WOOPRA_DOMAIN', DOMAIN_RE, 'must be a domain name'
        )

    def render(self, context):
        settings = self._get_settings(context)
        visitor = self._get_visitor(context)

        html = TRACKING_CODE % {
            'settings': json.dumps(settings, sort_keys=True),
            'visitor': json.dumps(visitor, sort_keys=True),
        }
        if is_internal_ip(context, 'WOOPRA'):
            html = disable_html(html, 'Woopra')
        return html

    def _get_settings(self, context):
        variables = {'domain': self.domain}
        woopra_int_settings = {
            'idle_timeout': 'WOOPRA_IDLE_TIMEOUT',
        }
        woopra_str_settings = {
            'cookie_name': 'WOOPRA_COOKIE_NAME',
            'cookie_domain': 'WOOPRA_COOKIE_DOMAIN',
            'cookie_path': 'WOOPRA_COOKIE_PATH',
            'cookie_expire': 'WOOPRA_COOKIE_EXPIRE',
        }
        woopra_bool_settings = {
            'click_tracking': 'WOOPRA_CLICK_TRACKING',
            'download_tracking': 'WOOPRA_DOWNLOAD_TRACKING',
            'outgoing_tracking': 'WOOPRA_OUTGOING_TRACKING',
            'outgoing_ignore_subdomain': 'WOOPRA_OUTGOING_IGNORE_SUBDOMAIN',
            'ignore_query_url': 'WOOPRA_IGNORE_QUERY_URL',
            'hide_campaign': 'WOOPRA_HIDE_CAMPAIGN',
        }

        for key, name in woopra_int_settings.items():
            with suppress(AttributeError):
                variables[key] = getattr(settings, name)
                if type(variables[key]) is not int:
                    raise AnalyticalException(f'{name} must be an int value')

        for key, name in woopra_str_settings.items():
            with suppress(AttributeError):
                variables[key] = getattr(settings, name)
                if type(variables[key]) is not str:
                    raise AnalyticalException(f'{name} must be a string value')

        for key, name in woopra_bool_settings.items():
            with suppress(AttributeError):
                variables[key] = getattr(settings, name)
                if type(variables[key]) is not bool:
                    raise AnalyticalException(f'{name} must be a boolean value')

        return variables

    def _get_visitor(self, context):
        params = {}
        for dict_ in context:
            for var, val in dict_.items():
                if var.startswith('woopra_'):
                    params[var[7:]] = val
        if 'name' not in params and 'email' not in params:
            user = get_user_from_context(context)
            if user is not None and get_user_is_authenticated(user):
                params['name'] = get_identity(context, 'woopra', self._identify, user)
                if user.email:
                    params['email'] = user.email
        return params

    def _identify(self, user):
        name = user.get_full_name()
        if not name:
            name = user.username
        return name


def contribute_to_analytical(add_node):
    WoopraNode()  # ensure properly configured
    add_node('head_bottom', WoopraNode)