Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create session-based user tracking ID #1648

Merged
merged 6 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions iogt/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@
# Matomo tracking server and site information

MATOMO_ADDITIONAL_SITE_ID = int(os.getenv('MATOMO_ADDITIONAL_SITE_ID', '0'))
MATOMO_CREATE_VISITOR_ID = os.getenv('MATOMO_CREATE_VISITOR_ID', 'disable') == 'enable'
MATOMO_SERVER_URL = os.getenv('MATOMO_SERVER_URL', '')
MATOMO_SITE_ID = int(os.getenv('MATOMO_SITE_ID', '') or '0')
MATOMO_TRACKING = os.getenv('MATOMO_TRACKING', 'disable') == 'enable'
Expand Down
9 changes: 4 additions & 5 deletions matomo/templates/matomo_tracking_tags.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
{% if tracking_enabled %}
<script type="text/javascript">
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
Expand All @@ -17,10 +16,10 @@
})();
</script>
<noscript>
<img src="{{ matomo_server_url }}matomo.php?idsite={{ matomo_site_id }}&rec=1" style="border:0" alt="" />
{% if matomo_additional_site_id %}
<img src="{{ matomo_server_url }}matomo.php?idsite={{ matomo_additional_site_id }}&rec=1" style="border:0" alt="" />
{% endif %}
<img src="{{ matomo_image_tracker_url }}" style="border:0" alt="" />
{% if matomo_additional_image_tracker_url %}
<img src="{{ matomo_additional_image_tracker_url }}" style="border:0" alt="" />
{% endif %}
</noscript>
{% endif %}
<!-- End Matomo Code -->
95 changes: 84 additions & 11 deletions matomo/templatetags/matomo_tags.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,99 @@
from uuid import uuid4
from hashlib import sha1
from datetime import datetime

from django import template
from django.conf import settings


VISITOR_ID_KEY = "vid"
register = template.Library()


@register.inclusion_tag("matomo_tracking_tags.html", takes_context=True)
def matomo_tracking_tags(context):
enabled = is_enabled()

if not enabled:
return context.update({"tracking_enabled": enabled})

server_url = settings.MATOMO_SERVER_URL
site_id = settings.MATOMO_SITE_ID
vid = create_visitor_id(context)

context.update(
{
"tracking_enabled": (
settings.MATOMO_TRACKING
and settings.MATOMO_SERVER_URL
and settings.MATOMO_SITE_ID
),
"matomo_site_id": settings.MATOMO_SITE_ID,
"matomo_server_url": settings.MATOMO_SERVER_URL,
"tracking_enabled": enabled,
"matomo_site_id": site_id,
"matomo_server_url": server_url,
"matomo_image_tracker_url": image_tracker(server_url, site_id, vid),
}
)

additional_site_id = settings.MATOMO_ADDITIONAL_SITE_ID
if type(additional_site_id) is int and additional_site_id > 0:
context.update({"matomo_additional_site_id": additional_site_id})
context.update(additional_site_id(server_url, vid))

return context


def is_enabled():
try:
return (
settings.MATOMO_TRACKING
and settings.MATOMO_SERVER_URL
and settings.MATOMO_SITE_ID
)
except AttributeError:
return False


def create_visitor_id(context):
try:
if settings.MATOMO_CREATE_VISITOR_ID:
return visitor_id(context["request"])
except AttributeError:
return None


def additional_site_id(server_url, vid=None):
try:
site_id = settings.MATOMO_ADDITIONAL_SITE_ID
except AttributeError:
return {}

if type(site_id) is int and site_id > 0:
return {
"matomo_additional_site_id": site_id,
"matomo_additional_image_tracker_url": image_tracker(
server_url, site_id, vid
),
}
else:
return {}


def visitor_id(request):
session = request.session

if not session.get(VISITOR_ID_KEY):
session[VISITOR_ID_KEY] = generate_random_id()

return session[VISITOR_ID_KEY]


def generate_random_id():
return sha1(
"".join(
[
datetime.now().isoformat(),
str(uuid4()),
]
).encode("utf-8")
).hexdigest()[0:16]


def image_tracker(server_url, site_id, vid=None):
url = f"{server_url}matomo.php?idsite={site_id}&rec=1"

if vid:
url += f"&_id={vid}"

return url
42 changes: 30 additions & 12 deletions matomo/tests/test_matomo_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,44 @@
)
class MatomoTagsTests(TestCase):
def test_only_enabled_when_required_settings_are_set(self):
self.assertTrue(matomo_tracking_tags(dict()).get("tracking_enabled"))
self.assertTrue(matomo_tracking_tags(create_context()).get("tracking_enabled"))

def test_additional_site_id_must_be_positive_integer(self):
with override_settings(MATOMO_ADDITIONAL_SITE_ID=567):
context = matomo_tracking_tags(create_context())
self.assertEqual(context.get("matomo_additional_site_id"), 567)
self.assertEqual(
matomo_tracking_tags(dict()).get("matomo_additional_site_id"),
567,
context.get("matomo_additional_image_tracker_url"),
"https://example.com/matomo.php?idsite=567&rec=1",
)

with override_settings(MATOMO_ADDITIONAL_SITE_ID=0):
self.assertFalse(
"matomo_additional_site_id" in matomo_tracking_tags(dict())
)
context = matomo_tracking_tags(create_context())
self.assertFalse("matomo_additional_site_id" in context)
self.assertFalse("matomo_additional_image_tracker_url" in context)

with override_settings(MATOMO_ADDITIONAL_SITE_ID=None):
self.assertFalse(
"matomo_additional_site_id" in matomo_tracking_tags(dict())
)
context = matomo_tracking_tags(create_context())
self.assertFalse("matomo_additional_site_id" in context)
self.assertFalse("matomo_additional_image_tracker_url" in context)

with override_settings(MATOMO_ADDITIONAL_SITE_ID='123'):
self.assertFalse(
"matomo_additional_site_id" in matomo_tracking_tags(dict())
with override_settings(MATOMO_ADDITIONAL_SITE_ID="123"):
context = matomo_tracking_tags(create_context())
self.assertFalse("matomo_additional_site_id" in context)
self.assertFalse("matomo_additional_image_tracker_url" in context)

def test_visitor_id_is_created_for_clients_without_javascript(self):
with override_settings(MATOMO_CREATE_VISITOR_ID=True):
self.assertRegexpMatches(
matomo_tracking_tags(create_context()).get("matomo_image_tracker_url"),
r"_id=[a-f0-9]{16}",
)


class MockRequest:
def __init__(self):
self.session = dict()


def create_context():
return {"request": MockRequest()}