Skip to content

Commit

Permalink
Merge pull request #57 from uktrade/feature/ORPD-93-add-ga-script
Browse files Browse the repository at this point in the history
ORPD-93 - Add Google Analytics script and opt out/in options
  • Loading branch information
gdbarnes authored Nov 26, 2024
2 parents f3401c9 + 5c1e554 commit f3739b3
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 106 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ Navigate a browser to:
http://localhost:8081

## Local development environment

While the `docker-compose` configuration is the quickest way to get started, it
can also be useful to create a development environment on your local machine.
However, your mileage may vary depending on your operating system. The following
instructions are for OSX.

### Prerequisites

As we are using python package `psycopg-c`, you need the PostgreSQL client
development headers (e.g. the `libpq-dev` package) installed on your system.
On Mac you can run the following command to install `libpq`:
Expand All @@ -74,6 +76,7 @@ On Mac you can run the following command to install `libpq`:
you'll require including `engine`, `build` and `compose`.

### Install Poetry

We use [Poetry](https://python-poetry.org/) to manage dependencies. Follow the
guidance in the [official documentation](https://python-poetry.org/docs/). On
OSX, run the following commands to install Poetry:
Expand All @@ -99,7 +102,6 @@ With your Poetry shell active:
> Code quality checks are also performed when pushing your code to origin
> but pre-commit hooks catch issues early and will improve Developer Experience.

### Update database tables

> To update local database tables, you need to set the `DATABASE_URL` environment variable. You can set it in the terminal or in the `.env` file.
Expand All @@ -113,7 +115,3 @@ With your Poetry shell active:
> If you want to migrate a single app then navigate /orp/orp and use the following command:
$ poetry run python manage.py migrate <app_name>



poetry add boto3 awswrangler
3 changes: 3 additions & 0 deletions local.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ DJANGO_SECRET_KEY=orp-secret
DATABASE_URL=postgres://postgres:postgres@db:5432/orp # pragma: allowlist secret
DB_MAX_CONNS=1
POSTGRES_HOST_AUTH_METHOD=trust

# Google analytics
GOOGLE_ANALYTICS_TAG_MANAGER_ID=XXX-XXXXXXX # Check passman or ask a colleague
6 changes: 6 additions & 0 deletions orp/config/context_processors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf import settings


def google_tag_manager(request):
"""Context processor to add Google Tag Manager ID to all templates."""
return {"gtm_id": settings.GOOGLE_ANALYTICS_TAG_MANAGER_ID}
9 changes: 9 additions & 0 deletions orp/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"config.context_processors.google_tag_manager",
],
},
},
Expand Down Expand Up @@ -251,3 +252,11 @@
}

HOSTNAME = HOSTNAME_MAP.get(ENVIRONMENT.lower(), HOSTNAME_MAP["prod"])

# Google Analytics (GA)
# Note: please consult the performance team before changing these settings
COOKIE_PREFERENCES_SET_NAME: str = "cookie_preferences_set"
COOKIE_ACCEPTED_GA_NAME: str = "accepted_ga_cookies"
GOOGLE_ANALYTICS_TAG_MANAGER_ID = env(
"GOOGLE_ANALYTICS_TAG_MANAGER_ID", default=None
)
37 changes: 15 additions & 22 deletions orp/core/cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,28 @@
from django.http import HttpRequest, HttpResponse


def set_analytics_consent_cookie(
response: HttpResponse, analytics_consent: bool
) -> None:
"""Set analytics consent cookie.
def set_ga_cookie_policy(response: HttpResponse, preference: str) -> None:
"""Set Google Analytics (GA) policy.
Sets the analytics consent cookie on the response object.
Sets the cookies that are required for Google Tag Manager (GTM) to
function correctly.
"""
response.set_cookie(
settings.ANALYTICS_CONSENT_NAME,
value=str(analytics_consent),
key=settings.COOKIE_ACCEPTED_GA_NAME,
value=preference,
max_age=365 * 24 * 60 * 60,
)


def get_analytics_consent(request: HttpRequest) -> bool:
"""Get analytics consent.
Returns the analytics consent boolean value from the request object.
"""
analytics_consent = request.COOKIES.get(
settings.ANALYTICS_CONSENT_NAME, None
response.set_cookie(
key=settings.COOKIE_PREFERENCES_SET_NAME,
value="true",
max_age=365 * 24 * 60 * 60,
)
return True if analytics_consent == "True" else False


def analytics_form_initial_mapping(analytics_consent: bool) -> dict:
"""Analytics mapping.
def get_ga_cookie_preference(request: HttpRequest) -> str:
"""Get Google Analytics (GA) cookie preference.
Returns a dictionary with the analytics consent value, which is used to
initialise the analytics cookie form.
Returns value of the GA cookie preference if it exists, otherwise
returns "false".
"""
return {settings.ANALYTICS_CONSENT_NAME: analytics_consent}
return request.COOKIES.get(settings.COOKIE_ACCEPTED_GA_NAME, "false")
21 changes: 11 additions & 10 deletions orp/core/forms.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
from django import forms


class CookiePageConsentForm(forms.Form):
"""Consent Form.
class CookiePreferenceForm(forms.Form):
"""Cookie page preference form.
Radio Select Form for setting analytics cookie consent in the cookies page.
Radio Select Form for setting Google Analytics (GA) consent cookies. This
form is rendered in the cookies page.
Note: We want to set the value of the GA cookie to "true" or "false" rather
than a boolean values so that the GTM script can read the value correctly.
"""

ANALYTICS_CHOICES = [
(True, "Yes"),
(False, "No"),
]
analytics_consent = forms.ChoiceField(
choices=ANALYTICS_CHOICES,
cookie_preference = forms.ChoiceField(
label="Do you want to accept analytics cookies?",
widget=forms.RadioSelect(),
choices=(("true", "Yes"), ("false", "No")),
widget=forms.RadioSelect,
required=False,
)


Expand Down
6 changes: 3 additions & 3 deletions orp/core/templates/accessibility_statement.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ <h2 class="govuk-heading-m">Feedback and contact information</h2>
</a>
</li>
</ul>
<p>Well consider your request and get back to you in 5 days.</p>
<p>We'll consider your request and get back to you in 5 days.</p>
<h2 class="govuk-heading-m">Reporting accessibility problems with this service</h2>
<strong class="govuk-tag govuk-tag--yellow">TBD</strong>
<p>Were always looking to improve the accessibility of this service. If you find any
<p>We're always looking to improve the accessibility of this service. If you find any
problems that are not listed on this page or think we're not meeting accessibility
requirements:
</p>
Expand All @@ -97,7 +97,7 @@ <h2 class="govuk-heading-m">Enforcement procedure</h2>
Equality Advisory and Support Service (EASS).
</a>
</p>
<h2 class="govuk-heading-m">Technical information about this services accessibility</h2>
<h2 class="govuk-heading-m">Technical information about this service's accessibility</h2>
<strong class="govuk-tag govuk-tag--red">Verify content</strong>
<p>The Department of Business and Trade is committed to making this service accessible,
in accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2)
Expand Down
56 changes: 29 additions & 27 deletions orp/core/templates/cookies.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{% block body_content %}
<div class="govuk-width-container">
<main class="govuk-main-wrapper govuk-main-wrapper--l" id="main-content" role="main">
{% if analytics_cookie_name in request.GET %}
{% if cookie_preference_name in request.GET %}
<div class="govuk-notification-banner govuk-notification-banner--success" role="alert"
aria-labelledby="govuk-notification-banner-title" data-module="govuk-notification-banner">
<div class="govuk-notification-banner__header">
Expand Down Expand Up @@ -47,24 +47,22 @@ <h2 class="govuk-heading-l">Essential cookies</h2>
</thead>
<tbody class="govuk-table__body">
<tr class="govuk-table__row">
<th class="govuk-table__header govuk-!-width-one-quarter app-!-vertical-align-top"
scope="row">
{{analytics_cookie_name}}
<th class="govuk-table__header govuk-!-width-one-quarter app-!-vertical-align-top" scope="row">
accepted_ga_cookies
</th>
<td class="govuk-table__cell app-!-vertical-align-top">
Saves your analytics cookie consent settings
Saves your cookie consent settings.
</td>
<td class="govuk-table__cell app-!-vertical-align-top govuk-!-width-one-quarter">
1 year
</td>
</tr>
<tr class="govuk-table__row">
<th class="govuk-table__header govuk-!-width-one-quarter app-!-vertical-align-top"
scope="row">
csrftoken
<th class="govuk-table__header govuk-!-width-one-quarter app-!-vertical-align-top" scope="row">
cookie_preferences_set
</th>
<td class="govuk-table__cell app-!-vertical-align-top">
Helps prevent Cross-Site Request Forgery (CSRF) attacks
Lets us know that you've saved your cookie consent settings.
</td>
<td class="govuk-table__cell app-!-vertical-align-top govuk-!-width-one-quarter">
1 year
Expand All @@ -73,22 +71,21 @@ <h2 class="govuk-heading-l">Essential cookies</h2>
<tr class="govuk-table__row">
<th class="govuk-table__header govuk-!-width-one-quarter app-!-vertical-align-top"
scope="row">
session
csrftoken
</th>
<td class="govuk-table__cell app-!-vertical-align-top">
Used to keep you signed in when publishing a report
Helps prevent Cross-Site Request Forgery (CSRF) attacks
</td>
<td class="govuk-table__cell app-!-vertical-align-top govuk-!-width-one-quarter">
20 hours
1 year
</td>
</tr>
</tbody>
</table>

<h2 class="govuk-heading-l">Analytics cookies (optional)</h2>
<p class="govuk-body">
With your permission, we use Google Analytics to collect data about how you use Check when large
businesses pay their suppliers. This information helps us to improve our service.
With your permission, we use Google Analytics to collect data about how you use {{service_name}}. This information helps us to improve our service.
</p>
<div class="govuk-inset-text">
Google is not allowed to use or share our analytics data with anyone.
Expand Down Expand Up @@ -148,33 +145,38 @@ <h2 class="govuk-heading-l">Analytics cookies (optional)</h2>
</tr>
</tbody>
</table>

<h2 class="govuk-heading-l">Change your cookie settings</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="govuk-form-group">
<fieldset class="govuk-fieldset">
<legend class="govuk-fieldset__legend govuk-fieldset__legend--s">
{{ form.analytics_consent.label }}
{{ form.cookie_preference.label }}
</legend>
<div class="govuk-radios" data-module="govuk-radios">
{% for value, text in form.analytics_consent.field.choices %}
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="analytics-consent-{{ value }}"
name="{{ form.analytics_consent.name }}" type="radio" value="{{ value }}"
{% if form.analytics_consent.value == value %}checked{% endif %}>
<label class="govuk-label govuk-radios__label" for="analytics-consent-{{ value }}">
{{ text }}
</label>
</div>
{% endfor %}
<div class="govuk-radios govuk-radios--inline" data-module="govuk-radios">
{% with field=form.cookie_preference %}
{% for choice in field.field.widget.choices %}
<div class="govuk-radios__item">
<input class="govuk-radios__input"
id="cookie-preference-{{ forloop.counter }}"
name="{{ field.html_name }}"
type="radio"
value="{{ choice.0 }}"
{% if field.value == choice.0 %}checked{% endif %}>
<label class="govuk-label govuk-radios__label" for="cookie-preference-{{ forloop.counter }}">
{{ choice.1 }}
</label>
</div>
{% endfor %}
{% endwith %}
</div>
</fieldset>
</div>
<button type="submit" class="govuk-button" data-module="govuk-button">
Save cookie settings
</button>
</form>

</div>
</div>
</main>
Expand Down
10 changes: 6 additions & 4 deletions orp/core/templatetags/cookie_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,25 @@ def render_cookie_banner(context) -> str:
is not rendered.
"""
request = context["request"]
if settings.ANALYTICS_CONSENT_NAME not in request.COOKIES:
if settings.COOKIE_PREFERENCES_SET_NAME not in request.COOKIES:
return render_to_string(
"cookie_banner.html",
{
"service_name": settings.SERVICE_NAME,
"analytics_cookie_name": settings.ANALYTICS_CONSENT_NAME,
"cookie_preference_name": settings.COOKIE_ACCEPTED_GA_NAME,
"request": request,
"show_cookie_banner": True,
"show_confirmation_message": False,
},
)
elif "cookie_preferences" in request.GET:
elif "hide_banner" in request.GET:
return render_to_string(
"cookie_banner.html",
{
"service_name": settings.SERVICE_NAME,
"cookie_preferences": request.GET.get("cookie_preferences"),
"cookie_preference": request.GET.get(
settings.COOKIE_ACCEPTED_GA_NAME
),
"request": request,
"show_cookie_banner": False,
"show_confirmation_message": True,
Expand Down
Loading

0 comments on commit f3739b3

Please sign in to comment.