-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Analytics): add an analytics module (#773)
* feat(Analytics): add an analytics module * chore(analytics): Use a middleware instead of signals when setting user properties, better error handling, removing useless condition * fix tests --------- Co-authored-by: Quentin Gérôme <[email protected]>
- Loading branch information
1 parent
8298410
commit 7d9e098
Showing
20 changed files
with
140 additions
and
34 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
Empty file.
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,8 @@ | ||
from hexa.app import CoreAppConfig | ||
|
||
|
||
class AnalyticsConfig(CoreAppConfig): | ||
name = "hexa.analytics" | ||
label = "analytics" | ||
|
||
ANONYMOUS_URLS = ["analytics:track"] |
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,19 @@ | ||
from typing import Callable | ||
|
||
from django.http import HttpRequest, HttpResponse | ||
|
||
from hexa.analytics.api import set_user_properties | ||
|
||
|
||
def set_analytics_middleware( | ||
get_response: Callable[[HttpRequest], HttpResponse], | ||
) -> Callable[[HttpRequest], HttpResponse]: | ||
"""Send the user properties to the analytics service.""" | ||
|
||
def middleware(request: HttpRequest) -> HttpResponse: | ||
response = get_response(request) | ||
if getattr(request, "user") and request.user.is_authenticated: | ||
set_user_properties(request.user) | ||
return response | ||
|
||
return middleware |
Empty file.
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,54 @@ | ||
from unittest import mock | ||
|
||
from django.urls import reverse | ||
|
||
from hexa.core.test import TestCase | ||
from hexa.user_management.models import User | ||
|
||
|
||
class AnalyticsTests(TestCase): | ||
@classmethod | ||
def setUpTestData(cls): | ||
cls.USER = User.objects.create_user( | ||
"[email protected]", | ||
"user_password", | ||
) | ||
|
||
def test_track_event_bad_request(self): | ||
self.client.force_login(self.USER) | ||
r = self.client.post( | ||
reverse( | ||
"analytics:track", | ||
), | ||
{"properties": {}}, | ||
content_type="application/json", | ||
) | ||
self.assertEqual(r.status_code, 400) | ||
self.assertEqual(r.json(), {"Bad request": "event name is required."}) | ||
|
||
def test_track_event(self): | ||
self.client.force_login(self.USER) | ||
r = self.client.post( | ||
reverse( | ||
"analytics:track", | ||
), | ||
{"event": "page_viewed", "properties": {"page": "database"}}, | ||
content_type="application/json", | ||
) | ||
self.assertEqual(r.status_code, 200) | ||
|
||
@mock.patch("hexa.analytics.api.mixpanel") | ||
def test_track_event_analytics_not_enabled(self, mixpanel_mock): | ||
self.USER.analytics_enabled = False | ||
self.USER.save() | ||
self.client.force_login(self.USER) | ||
with self.settings(MIXPANEL_TOKEN="123"): | ||
r = self.client.post( | ||
reverse( | ||
"analytics:track", | ||
), | ||
{"event": "page_viewed", "properties": {"page": "database"}}, | ||
content_type="application/json", | ||
) | ||
self.assertEqual(r.status_code, 200) | ||
mixpanel_mock.track.assert_not_called() |
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,9 @@ | ||
from django.urls import path | ||
|
||
from . import views | ||
|
||
app_name = "analytics" | ||
|
||
urlpatterns = [ | ||
path("track", views.track_event, name="track"), | ||
] |
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,27 @@ | ||
import json | ||
|
||
from django.http import HttpRequest, HttpResponse, JsonResponse | ||
from django.views.decorators.csrf import csrf_exempt | ||
from django.views.decorators.http import require_POST | ||
|
||
from .api import track | ||
|
||
|
||
@csrf_exempt | ||
@require_POST | ||
def track_event(request: HttpRequest) -> HttpResponse: | ||
"""This API endpoint is called by the frontend to track events.""" | ||
try: | ||
payload = json.loads(request.body.decode("utf-8")) | ||
except json.JSONDecodeError: | ||
return JsonResponse({"Bad request": "Invalid JSON payload."}, status=400) | ||
|
||
if "event" not in payload: | ||
return JsonResponse({"Bad request": "event name is required."}, status=400) | ||
|
||
track( | ||
request, | ||
payload.get("event"), | ||
payload.get("properties", {}), | ||
) | ||
return JsonResponse({}, status=200) |
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
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
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 was deleted.
Oops, something went wrong.