Skip to content

Commit

Permalink
Add Cookie banner and Google Tag Manager snippet (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
kacperpONS authored Nov 12, 2024
1 parent 65563ea commit 4fac1fb
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 43 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,11 @@ make megalint
Wagtail is built on [Django](https://djangoproject.com/) and changes to its models may require generating and
running schema migrations. For full details see the [Django documentation on migrations](https://docs.djangoproject.com/en/5.1/topics/migrations/)

Below are the commands you will most commonly use:
Below are the commands you will most commonly use, note that these have to be run inside the container.

```bash
# Check if you need to generate any new migrations after changes to the model
poetru run django-admin makemigrations --check
poetry run django-admin makemigrations --check
# Generate migrations
poetry run django-admin makemigrations
Expand Down
8 changes: 4 additions & 4 deletions cms/core/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

from django.conf import settings

from cms.core.models import Tracking

if TYPE_CHECKING:
from django.http import HttpRequest


def global_vars(request: "HttpRequest") -> dict[str, str | bool | None]:
"""Set our global variables to use in templates."""
tracking = Tracking.for_request(request)
return {
"GOOGLE_TAG_MANAGER_ID": getattr(tracking, "google_tag_manager_id", None),
"GOOGLE_TAG_MANAGER_CONTAINER_ID": settings.GOOGLE_TAG_MANAGER_CONTAINER_ID,
# Cookie banner settings
"ONS_COOKIE_BANNER_SERVICE_NAME": settings.ONS_COOKIE_BANNER_SERVICE_NAME,
"MANAGE_COOKIE_SETTINGS_URL": settings.MANAGE_COOKIE_SETTINGS_URL,
"SEO_NOINDEX": settings.SEO_NOINDEX,
"LANGUAGE_CODE": settings.LANGUAGE_CODE,
"IS_EXTERNAL_ENV": settings.IS_EXTERNAL_ENV,
Expand Down
15 changes: 15 additions & 0 deletions cms/core/migrations/0003_delete_tracking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generated by Django 5.1.3 on 2024-11-08 15:42

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("core", "0002_contactdetails"),
]

operations = [
migrations.DeleteModel(
name="Tracking",
),
]
12 changes: 0 additions & 12 deletions cms/core/models/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class BaseSiteSetting(_BaseSiteSetting, models.Model):
__all__ = [
"SocialMediaSettings",
"SystemMessagesSettings",
"Tracking",
]


Expand Down Expand Up @@ -64,14 +63,3 @@ class Meta:
panels: ClassVar[list[FieldPanel]] = [
MultiFieldPanel([FieldPanel("title_404"), FieldPanel("body_404")], "404 page")
]


@register_setting(icon="view")
class Tracking(BaseSiteSetting):
"""Settings class for various trackers."""

google_tag_manager_id = models.CharField(
max_length=255,
blank=True,
help_text="Your Google Tag Manager ID",
)
28 changes: 7 additions & 21 deletions cms/core/tests/test_context_processors.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
from django.conf import settings
from django.test import RequestFactory, TestCase
from wagtail.models import Site

from cms.core.context_processors import global_vars
from cms.core.models import Tracking


class ContextProcessorTestCase(TestCase):
"""Tests for context processors."""

def setUp(self):
request_factory = RequestFactory()

# Request is created with each test to avoid mutation side-effects
self.request = request_factory.get("/")

def test_when_no_tracking_settings_defined(self):
"""Check the global vars include sensible defaults when no Tracking settings defined."""
self.assertEqual(
global_vars(self.request),
{
"GOOGLE_TAG_MANAGER_ID": "",
"SEO_NOINDEX": False,
"LANGUAGE_CODE": "en-gb",
"IS_EXTERNAL_ENV": False,
},
)

def test_when_tracking_settings_defined(self):
"""Confirm the global vars include Tracking settings when defined."""
Tracking.objects.create(
site=Site.objects.get(is_default_site=True),
google_tag_manager_id="GTM-123456",
)
def test_context_processor_picks_up_variables_from_env(self):
"""Check that the context processor correctly picks up environment variables."""
self.assertEqual(
global_vars(self.request),
{
"GOOGLE_TAG_MANAGER_ID": "GTM-123456",
"GOOGLE_TAG_MANAGER_CONTAINER_ID": settings.GOOGLE_TAG_MANAGER_CONTAINER_ID,
"ONS_COOKIE_BANNER_SERVICE_NAME": settings.ONS_COOKIE_BANNER_SERVICE_NAME,
"MANAGE_COOKIE_SETTINGS_URL": settings.MANAGE_COOKIE_SETTINGS_URL,
"SEO_NOINDEX": False,
"LANGUAGE_CODE": "en-gb",
"IS_EXTERNAL_ENV": False,
Expand Down
15 changes: 15 additions & 0 deletions cms/core/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import logging

from django.conf import settings
from django.test import Client, TestCase


class CSRFTestCase(TestCase):
"""Tests for CSRF enforcement."""

def setUp(self):
# Client is created with each test to avoid mutation side-effects
self.client = Client(enforce_csrf_checks=True)
Expand All @@ -17,3 +19,16 @@ def test_csrf_token_mismatch_logs_an_error(self):
self.client.post("/admin/login/", {})

self.assertIn("CSRF Failure: CSRF cookie", logs.output[0])


class TestGoogleTagManagerTestCase(TestCase):
"""Tests for the Google Tag Manager."""

def test_google_tag_manager_script_present(self):
"""Check that the Google Tag Manager script and ID are present on the page.
Note: this doesn't check the functionality, only presence.
"""
response = self.client.get("/")

self.assertIn("https://www.googletagmanager.com/gtm.js?id=", response.rendered_content)
self.assertIn(settings.GOOGLE_TAG_MANAGER_CONTAINER_ID, response.rendered_content)
57 changes: 55 additions & 2 deletions cms/jinja2/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends "layout/_template.njk" %}
{% from "components/cookies-banner/_macro.njk" import onsCookiesBanner %}

{% set page_title %}
{% if current_site and page.pk == current_site.root_page.pk and current_site.site_name %}{{ current_site.site_name }} | {% endif %}{% block title %}{% if page.seo_title %}{{ page.seo_title }}{% else %}{{ page.title}}{% endif %}{% endblock %}{% block title_suffix %}{% if current_site and page.pk != current_site.root_page.pk and current_site.site_name %} | {{ current_site.site_name }}{% endif %}{% endblock %}
Expand Down Expand Up @@ -56,10 +57,42 @@
}
}
%}

{# fmt:on #}
{% block head %}
<link rel="stylesheet" href="{{ static('css/main.css') }}">
{% endblock %}
<link rel="stylesheet" href="{{ static ('css/main.css') }}">

{% if GOOGLE_TAG_MANAGER_CONTAINER_ID and not request.is_preview %}
<script>
function loadGTM(){
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({
'gtm.start': new Date().getTime(),
event:'gtm.js'
});
var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
j.async=true;
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
f.parentNode.insertBefore(j,f);
})
(window,document,'script','dataLayer', "{{ GOOGLE_TAG_MANAGER_CONTAINER_ID|escape }}");
}

function isUsageCookieAllowed(){
var re = /^(.*)?\s*'usage':true\s*[^;]+(.*)?$/;
return document.cookie.match(re);
}

if (isUsageCookieAllowed()) {
loadGTM();
}
</script>
{% endif %}

{% endblock %}


{% block preMain %}
{% if not IS_EXTERNAL_ENV %}
Expand All @@ -70,3 +103,23 @@
{% block scripts %}
<script src="{{ static('js/main.js') }}"></script>
{% endblock %}

{% block preHeader %}

{#
NOTE:
the "settingsLinkTextURL" setting currently doesn't match what's in the guidelines
that's because we're on version 70.0.17 and it has been renamed to "settingsLinkUrl" in 72.0.0
See: https://github.com/ONSdigital/design-system/pull/3300
#}
{# fmt:off #}
{{
onsCookiesBanner({
'lang': "cy" if LANGUAGE_CODE == "cy" else "en",
'serviceName': COOKIE_BANNER_SERVICE_NAME,
'settingsLinkTextURL': MANAGE_COOKIE_SETTINGS_URL,
})
}}
{# fmt:on #}

{% endblock %}
7 changes: 5 additions & 2 deletions cms/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,7 @@
DEFAULT_PER_PAGE = 20

# Google Tag Manager ID from env
GOOGLE_TAG_MANAGER_ID = env.get("GOOGLE_TAG_MANAGER_ID")

GOOGLE_TAG_MANAGER_CONTAINER_ID = env.get("GOOGLE_TAG_MANAGER_CONTAINER_ID", "")

# Allows us to toggle search indexing via an environment variable.
SEO_NOINDEX = env.get("SEO_NOINDEX", "false").lower() == "true"
Expand Down Expand Up @@ -778,3 +777,7 @@
DATETIME_FORMAT = "j F Y g:ia" # 1 November 2024, 1 p.m.

ONS_EMBED_PREFIX = env.get("ONS_EMBED_PREFIX", "https://www.ons.gov.uk/visualisations/")

# ONS Cookie banner settings
ONS_COOKIE_BANNER_SERVICE_NAME = env.get("ONS_COOKIE_BANNER_SERVICE_NAME", "www.ons.gov.uk")
MANAGE_COOKIE_SETTINGS_URL = env.get("MANAGE_COOKIE_SETTINGS_URL", "https://www.ons.gov.uk/cookies")
6 changes: 6 additions & 0 deletions cms/settings/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
# Wagtail
WAGTAILADMIN_BASE_URL = "http://testserver"

# Google Tag Manager
GOOGLE_TAG_MANAGER_CONTAINER_ID = "GTM-123456789"

# Cookie banner config
ONS_COOKIE_BANNER_SERVICE_NAME = "example.ons.gov.uk"
MANAGE_COOKIE_SETTINGS_URL = "example.ons.gov.uk/cookies"

# #############
# Performance
Expand Down

0 comments on commit 4fac1fb

Please sign in to comment.