repos
/ analytics-django master

analytics-django

mirror archived upstream

Self-hostable website analytics on Django: a straightforward collector API, dashboards, a world map, and PDF reports.

analyticsdjangodockerhandcodedpythonself-hostedsqliteviteweb-analytics

3.1 KB · 91 lines · Python Raw History
 1import uuid
 2
 3from django.db import models
 4from django.utils import timezone
 5from django.contrib.auth import get_user_model
 6
 7
 8User = get_user_model()
 9
10
11class Property(models.Model):
12    """
13    A site that we attach all our analytics hits to and connect up to a user.
14    """
15    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
16    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='properties')
17    name = models.CharField(max_length=255)
18    custom_cards = models.JSONField(default=list, blank=True, null=True)
19    created_at = models.DateTimeField(auto_now_add=True, editable=False)
20    updated_at = models.DateTimeField(auto_now=True, editable=False)
21    is_protected = models.BooleanField(default=False, editable=False)
22    is_public = models.BooleanField(default=False, editable=False)
23
24    class Meta:
25        verbose_name = 'Property'
26        verbose_name_plural = 'Properties'
27
28    def __str__(self):
29        return self.name
30
31    @property
32    def is_active(self):
33        """
34        Returns True if we've recieved any events for this property in the last
35        7 days.
36        """
37        return self.events.filter(created_at__gte=timezone.now() - timezone.timedelta(days=7)).exists()
38
39    @property
40    def total_events(self):
41        return self.events.count()
42
43    @property
44    def total_session_starts(self):
45        return self.events.filter(event="session_start").count()
46
47    @property
48    def total_page_views(self):
49        return self.events.filter(event="page_view").count()
50
51    @property
52    def total_clicks(self):
53        return self.events.filter(event="click").count()
54
55    @property
56    def total_scrolls(self):
57        return self.events.filter(event="scroll").count()
58
59
60class Event(models.Model):
61    """
62    An event that is sent by a site that we want to collect. The most basic of
63    events is a "page_view" event. All events can have a variety of key-value
64    pairs sent along with them that we store in a JSONField.
65
66    As an example a "page_view" may contain the following key-value pairs:
67
68    - url: The URL of the page that was viewed
69    - title: The title of the page that was viewed
70    - referrer: The URL of the page that referred the user to the page that was viewed
71    - user_agent: The user agent of the user that viewed the page
72    - screen_width: The width of the screen of the user that viewed the page
73    - screen_height: The height of the screen of the user that viewed the page
74
75    Users are free to send any event with any key-value pairs they want.
76    """
77    created_at = models.DateTimeField(auto_now_add=True, editable=False)
78    property = models.ForeignKey(Property, on_delete=models.CASCADE, related_name="events", editable=False)
79    event = models.CharField(max_length=255, editable=False)
80    data = models.JSONField(editable=False)
81
82    def __str__(self):
83        return self.event
84
85    class Meta:
86        indexes = [
87            models.Index(fields=['created_at']),
88            models.Index(fields=['property', 'created_at']),
89            models.Index(fields=['property', 'event', 'created_at']),
90        ]