This commit is contained in:
Rodrigo 2020-05-20 15:31:25 +02:00 committed by GitHub
commit 257388bb4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 100 additions and 40 deletions

View file

@ -5,14 +5,13 @@ Analytical template tags and filters.
from __future__ import absolute_import
import logging
from importlib import import_module
from django import template
from django.template import Node, TemplateSyntaxError
from importlib import import_module
from analytical.utils import AnalyticalException
TAG_LOCATIONS = ['head_top', 'head_bottom', 'body_top', 'body_bottom']
TAG_POSITIONS = ['first', None, 'last']
TAG_MODULES = [
@ -83,7 +82,7 @@ def _load_template_nodes():
try:
module.contribute_to_analytical(add_node_cls)
except AnalyticalException as e:
logger.debug("not loading tags from '%s': %s", path, e)
logger.trace("django-analytical settings not (or not properly) configured for '%s': %s", path, e)
for location in TAG_LOCATIONS:
template_nodes[location] = sum((template_nodes[location][p]
for p in TAG_POSITIONS), [])

View file

@ -13,7 +13,6 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, get_required_setting
USER_ID_RE = re.compile(r'^\d+$')
INIT_CODE = """<script type="text/javascript">var _sf_startpt=(new Date()).getTime()</script>"""
SETUP_CODE = """
@ -57,6 +56,8 @@ def chartbeat_top(parser, token):
class ChartbeatTopNode(Node):
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
if is_internal_ip(context):
return disable_html(INIT_CODE, "Chartbeat")
return INIT_CODE
@ -83,6 +84,8 @@ class ChartbeatBottomNode(Node):
"must be (a string containing) a number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
config = {'uid': self.user_id}
domain = _get_domain(context)
if domain is not None:

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
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
CLICKMAP_TRACKER_ID_RE = re.compile(r'^\w+$')
TRACKING_CODE = """
<script type="text/javascript">
@ -50,6 +50,8 @@ class ClickmapNode(Node):
"must be an alphanumeric string")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = TRACKING_CODE % {'tracker_id': self.tracker_id}
if is_internal_ip(context, 'CLICKMAP'):
html = disable_html(html, 'Clickmap')

View file

@ -7,11 +7,11 @@ 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 get_identity, is_internal_ip, disable_html, \
get_required_setting
get_required_setting
SITE_ID_RE = re.compile(r'^\d+$')
TRACKING_CODE = """
@ -56,6 +56,8 @@ class ClickyNode(Node):
"must be a (string containing) a number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
custom = {}
for dict_ in context:
for var, val in dict_.items():

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
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
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SETUP_CODE = '<script type="text/javascript" src="{placeholder_url}">' \
'</script>'.\
@ -45,6 +45,8 @@ class CrazyEggNode(Node):
)
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = SETUP_CODE % {
'account_nr_1': self.account_nr[:4],
'account_nr_2': self.account_nr[4:],

View file

@ -5,11 +5,11 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, is_internal_ip, disable_html
FACEBOOK_PIXEL_HEAD_CODE = """\
<script>
!function(f,b,e,v,n,t,s)
@ -70,6 +70,8 @@ class _FacebookPixelNode(Node):
)
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = self.code_template % {'FACEBOOK_PIXEL_ID': self.pixel_id}
if is_internal_ip(context, 'FACEBOOK_PIXEL'):
return disable_html(html, 'Facebook Pixel')

View file

@ -6,6 +6,7 @@ from __future__ import absolute_import
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
@ -52,6 +53,8 @@ class GaugesNode(Node):
"must be a string looking like 'XXXXXXX'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = TRACKING_CODE % {'site_id': self.site_id}
if is_internal_ip(context, 'GAUGES'):
html = disable_html(html, 'Gauges')

View file

@ -86,6 +86,8 @@ class GoogleAnalyticsNode(Node):
"must be a string looking like 'UA-XXXXXX-Y'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
commands = self._get_domain_commands(context)
commands.extend(self._get_custom_var_commands(context))
commands.extend(self._get_other_commands(context))

View file

@ -6,6 +6,7 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import (
@ -51,6 +52,8 @@ class GoogleAnalyticsGTagNode(Node):
"must be a string looking like 'UA-XXXXXX-Y'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = SETUP_CODE.format(
property_id=self.property_id,
)

View file

@ -6,6 +6,7 @@ from __future__ import absolute_import
import decimal
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
@ -62,6 +63,8 @@ class GoogleAnalyticsJsNode(Node):
"must be a string looking like 'UA-XXXXXX-Y'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
import json
create_fields = self._get_domain_fields(context)
create_fields.update(self._get_other_create_fields(context))

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, \
is_internal_ip, disable_html, get_required_setting
is_internal_ip, disable_html, get_required_setting
TOKEN_RE = re.compile(r'^\S+-\S+-\S+$')
TRACKING_CODE = """
@ -55,6 +55,8 @@ class GoSquaredNode(Node):
"must be a string looking like XXX-XXXXXX-X")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
configs = [TOKEN_CODE % self.site_token]
identity = get_identity(context, 'gosquared', self._identify)
if identity:

View file

@ -5,11 +5,11 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, is_internal_ip, disable_html
HOTJAR_TRACKING_CODE = """\
<script>
(function(h,o,t,j,a,r){
@ -52,6 +52,8 @@ class HotjarNode(Node):
)
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = HOTJAR_TRACKING_CODE % {'HOTJAR_SITE_ID': self.site_id}
if is_internal_ip(context, 'HOTJAR'):
return disable_html(html, 'Hotjar')

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
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
PORTAL_ID_RE = re.compile(r'^\d+$')
TRACKING_CODE = """
<!-- Start of Async HubSpot Analytics Code -->
@ -48,6 +48,8 @@ class HubSpotNode(Node):
"must be a (string containing a) number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = TRACKING_CODE % {'portal_id': self.portal_id}
if is_internal_ip(context, 'HUBSPOT'):
html = disable_html(html, 'HubSpot')

View file

@ -7,16 +7,16 @@ from __future__ import absolute_import
import hashlib
import hmac
import json
import sys
import re
import sys
import time
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import disable_html, get_required_setting, \
is_internal_ip, get_user_from_context, get_identity, \
get_user_is_authenticated
is_internal_ip, get_user_from_context, get_identity, \
get_user_is_authenticated
APP_ID_RE = re.compile(r'[\da-z]+$')
TRACKING_CODE = """
@ -126,6 +126,8 @@ class IntercomNode(Node):
return params
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
params = self._get_custom_attrs(context)
params["app_id"] = self.app_id
html = TRACKING_CODE % {

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, get_required_setting
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SITE_CODE_RE = re.compile(r'^[\w]+$')
SETUP_CODE = """
@ -51,6 +51,8 @@ class KissInsightsNode(Node):
"must be a string containing three characters")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
commands = []
identity = get_identity(context, 'kiss_insights')
if identity is not None:

View file

@ -7,11 +7,11 @@ 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_identity, \
get_required_setting
get_required_setting
API_KEY_RE = re.compile(r'^[0-9a-f]{40}$')
TRACKING_CODE = """
@ -66,6 +66,8 @@ class KissMetricsNode(Node):
"must be a string containing a 40-digit hexadecimal number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
commands = []
identity = get_identity(context, 'kiss_metrics')
if identity is not None:

View file

@ -4,9 +4,9 @@ Matomo template tags and filters.
from __future__ import absolute_import
import re
from collections import namedtuple
from itertools import chain
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
@ -14,7 +14,6 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import (is_internal_ip, disable_html,
get_required_setting, get_identity)
# domain name (characters separated by a dot), optional port, optional URI path, no slash
DOMAINPATH_RE = re.compile(r'^(([^./?#@:]+\.)*[^./?#@:]+)+(:[0-9]+)?(/[^/?#@:]+)*$')
@ -84,6 +83,8 @@ class MatomoNode(Node):
"must be a (string containing a) number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
custom_variables = context.get('matomo_vars', ())
complete_variables = (var if len(var) >= 4 else var + (DEFAULT_SCOPE,)

View file

@ -7,12 +7,12 @@ from __future__ import absolute_import
import json
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from django.utils.safestring import mark_safe
from analytical.utils import is_internal_ip, disable_html, get_identity, \
get_required_setting
get_required_setting
MIXPANEL_API_TOKEN_RE = re.compile(r'^[0-9a-f]{32}$')
TRACKING_CODE = """
@ -52,6 +52,8 @@ class MixpanelNode(Node):
"must be a string containing a 32-digit hexadecimal number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
commands = []
identity = get_identity(context, 'mixpanel')
if identity is not None:

View file

@ -7,11 +7,11 @@ 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 get_identity, get_required_setting
SITE_ID_RE = re.compile(r'^\d+-\d+-\d+-\d+$')
SETUP_CODE = """
<script type='text/javascript'>
@ -63,6 +63,8 @@ class OlarkNode(Node):
"must be a string looking like 'XXXX-XXX-XX-XXXX'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
extra_code = []
try:
extra_code.append(NICKNAME_CODE % context[NICKNAME_CONTEXT_KEY])

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
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
ACCOUNT_NUMBER_RE = re.compile(r'^\d+$')
SETUP_CODE = """<script src="//cdn.optimizely.com/js/%(account_number)s.js"></script>"""
@ -40,6 +40,8 @@ class OptimizelyNode(Node):
"must be a string looking like 'XXXXXXX'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = SETUP_CODE % {'account_number': self.account_number}
if is_internal_ip(context, 'OPTIMIZELY'):
html = disable_html(html, 'Optimizely')

View file

@ -6,12 +6,12 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from django.utils.safestring import mark_safe
from analytical.utils import is_internal_ip, disable_html, get_identity, \
get_required_setting
get_required_setting
API_KEY_RE = re.compile(r'^\w+$')
SETUP_CODE = """
@ -59,6 +59,8 @@ class PerformableNode(Node):
"must be a string looking like 'XXXXX'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = SETUP_CODE % {'api_key': self.api_key}
identity = get_identity(context, 'performable')
if identity is not None:

View file

@ -4,9 +4,10 @@ Piwik template tags and filters.
from __future__ import absolute_import
import re
import warnings
from collections import namedtuple
from itertools import chain
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
@ -14,7 +15,6 @@ from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import (is_internal_ip, disable_html,
get_required_setting, get_identity)
import warnings
warnings.warn('The Piwik module is deprecated; use the Matomo module.', DeprecationWarning)
# domain name (characters separated by a dot), optional port, optional URI path, no slash
@ -33,7 +33,7 @@ TRACKING_CODE = """
(function() {
var u="//%(url)s/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', %(siteid)s]);
_paq.push(['setSiteId', '%(siteid)s']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
@ -86,6 +86,8 @@ class PiwikNode(Node):
"must be a (string containing a) number")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
custom_variables = context.get('piwik_vars', ())
complete_variables = (var if len(var) >= 4 else var + (DEFAULT_SCOPE,)

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
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
get_required_setting
COUNTER_ID_RE = re.compile(r'^\d{7}$')
COUNTER_CODE = """
@ -56,6 +56,8 @@ class RatingMailruNode(Node):
"must be (a string containing) a number'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
html = COUNTER_CODE % {
'counter_id': self.counter_id,
}

View file

@ -73,6 +73,8 @@ class SnapEngageNode(Node):
"must be a string looking like this: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
settings_code = []
domain = self._get_setting(context, 'snapengage_domain',

View file

@ -6,11 +6,11 @@ from __future__ import absolute_import
import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_identity, is_internal_ip, disable_html, \
get_required_setting
get_required_setting
TRACKING_ID_RE = re.compile(r'^[0-9a-f]+$')
TRACKING_CODE = """
@ -56,6 +56,8 @@ class SpringMetricsNode(Node):
TRACKING_ID_RE, "must be a hexadecimal string")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
custom = {}
for dict_ in context:
for var, val in dict_.items():

View file

@ -9,8 +9,8 @@ import re
from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import get_required_setting, get_identity
from analytical.utils import get_required_setting, get_identity
WIDGET_KEY_RE = re.compile(r'^[a-zA-Z0-9]*$')
TRACKING_CODE = """
@ -53,6 +53,8 @@ class UserVoiceNode(Node):
'USERVOICE_WIDGET_KEY', WIDGET_KEY_RE, "must be an alphanumeric string")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
widget_key = context.get('uservoice_widget_key')
if not widget_key:
widget_key = self.default_widget_key

View file

@ -55,11 +55,13 @@ class WoopraNode(Node):
"must be a domain name")
def render(self, context):
settings = self._get_settings(context)
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
cfg = self._get_settings(context)
visitor = self._get_visitor(context)
html = TRACKING_CODE % {
'settings': json.dumps(settings, sort_keys=True),
'settings': json.dumps(cfg, sort_keys=True),
'visitor': json.dumps(visitor, sort_keys=True),
}
if is_internal_ip(context, 'WOOPRA'):

View file

@ -11,8 +11,7 @@ from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError
from analytical.utils import is_internal_ip, disable_html, \
get_required_setting
get_required_setting
COUNTER_ID_RE = re.compile(r'^\d{8}$')
COUNTER_CODE = """
@ -65,6 +64,8 @@ class YandexMetricaNode(Node):
"must be (a string containing) a number'")
def render(self, context):
if settings.get("DISABLE_TRACKING_CODE", False):
return ""
options = {
'id': int(self.counter_id),
'clickmap': True,

View file

@ -195,6 +195,8 @@ settings required to enable each service are listed here:
----
To disable the tracking code set DISABLE_TRACKING_CODE=True in settings (default=False).
The django-analytical application is now set-up to track visitors. For
information about identifying users, further configuration and
customization, see :doc:`features`.

View file

@ -25,12 +25,15 @@ The Matomo tracking code is inserted into templates using a template
tag. Load the :mod:`matomo` template tag library and insert the
:ttag:`matomo` 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 body as recommended by the
the tag at the bottom of the HEAD tag as recommended by the
`Matomo best practice for Integration Plugins`_::
{% load matomo %}
<html>
<head>
...
{% matomo %}
</head>
</body>
</html>