Skip to content
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ This is the repository for the BuildingSync Validator web application.
pyenv virtualenv 3.9.23 bsync-validator-3.9.23
pyenv local bsync-validator-3.9.23
```
1. Install PostgreSQL server for local development (if desired)
1. Install PostgreSQL server for local development (if desired) or run from docker
`docker compose -f docker-compose.yml -f docker-compose.dev.yml up`
- Once installed, create your local database and user:
```bash
psql -c 'DROP DATABASE bsync_validator;'
Expand Down
4 changes: 4 additions & 0 deletions bsyncviewer/settings/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

GOOGLE_ANALYTICS_MEASUREMENT_ID = os.environ.get(
"GOOGLE_ANALYTICS_MEASUREMENT_ID", "G-P8CNFE9GY2"
)

ALLOWED_HOSTS = [
"127.0.0.1",
"localhost",
Expand Down
1 change: 1 addition & 0 deletions bsyncviewer/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{% load static %}

{% block bootstrap_extra_head %}
{% google_analytics %}
{# Load CSS and JavaScript #}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
Expand Down
2 changes: 2 additions & 0 deletions bsyncviewer/templates/base2.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% load bootstrap4 %}

{% load navtags %}
{% load static %}

<!DOCTYPE html>
Expand All @@ -12,6 +13,7 @@
<!--[if gt IE 8]><!-->
<html class="no-js" lang="en"> <!--<![endif]-->
<head>
{% google_analytics %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

Expand Down
9 changes: 9 additions & 0 deletions bsyncviewer/templates/google_analytics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% if measurement_id %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ measurement_id|urlencode }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ measurement_id|escapejs }}');
</script>
{% endif %}
12 changes: 12 additions & 0 deletions bsyncviewer/templatetags/navtags.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
from django import template
from django.conf import settings
from django.urls import Resolver404, resolve

register = template.Library()


@register.inclusion_tag("google_analytics.html")
def google_analytics():
return {
"measurement_id": (
""
if settings.DEBUG
else getattr(settings, "GOOGLE_ANALYTICS_MEASUREMENT_ID", "")
)
}


@register.simple_tag
def active_page(request, *view_names):
if not request:
Expand Down
32 changes: 31 additions & 1 deletion bsyncviewer/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command
from django.test import Client, TestCase
from django.template.loader import render_to_string
from django.test import Client, SimpleTestCase, TestCase, override_settings
from django.urls import reverse

from bsyncviewer.models.attribute import Attribute
Expand All @@ -15,6 +16,35 @@
TEST_SCHEMA_VERSION = "0.0.1"


class GoogleAnalyticsTemplateTests(SimpleTestCase):
@override_settings(DEBUG=False, GOOGLE_ANALYTICS_MEASUREMENT_ID="G-P8CNFE9GY2")
def test_tracking_enabled_in_both_layouts(self):
for template_name in ("base.html", "base2.html"):
with self.subTest(template_name=template_name):
content = render_to_string(template_name)
self.assertEqual(
content.count(
"https://www.googletagmanager.com/gtag/js?id=G-P8CNFE9GY2"
),
1,
)
self.assertEqual(
content.count("gtag('config', 'G\\u002DP8CNFE9GY2');"), 1
)

@override_settings(DEBUG=True, GOOGLE_ANALYTICS_MEASUREMENT_ID="G-P8CNFE9GY2")
def test_tracking_disabled_in_development(self):
for template_name in ("base.html", "base2.html"):
with self.subTest(template_name=template_name):
self.assertNotIn("googletagmanager", render_to_string(template_name))

@override_settings(DEBUG=False, GOOGLE_ANALYTICS_MEASUREMENT_ID="")
def test_tracking_disabled_without_measurement_id(self):
for template_name in ("base.html", "base2.html"):
with self.subTest(template_name=template_name):
self.assertNotIn("googletagmanager", render_to_string(template_name))


class BsyncviewerViewTests(TestCase):
def test_index_ok(self):
response = self.client.get(reverse("index"))
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

services:
db-postgres:
ports:
- "127.0.0.1:5432:5432"
web:
command: python3 manage.py runserver 0.0.0.0:80
environment:
Expand Down
24 changes: 24 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ docker-compose -f docker-compose.prod.yml up -d --build

# Debugging

## Google Analytics

Production settings enable GA4 page-view tracking with Measurement ID `G-P8CNFE9GY2`.
Tracking is disabled when Django's `DEBUG` setting is true. The shared page layouts
include the tag; the Django admin does not.

To change or disable tracking, set `GOOGLE_ANALYTICS_MEASUREMENT_ID` in the web
container's environment. For example, add this entry under `web.environment` in
your Compose configuration to disable it:

```yaml
- GOOGLE_ANALYTICS_MEASUREMENT_ID=
```

Rebuild and redeploy to apply the template changes. Then visit the public site
with browser tracking blockers disabled and check GA4's Realtime report for the
visit. Data collection cannot be verified until the updated site is deployed.

The tag does not implement cookie consent. Confirm applicable consent and privacy
notice requirements before deploying; if consent is required, gate the tag on
consent before enabling collection.

## Container Logs

- Tail log

```bash
Expand Down
Loading