Skip to main content

GOV.UK GA4 annotations

The GOV.UK GA4 annotations report provides information on users of GOV.UK GA4 data to SPOCs.

The data provided includes:

  • the dates of changes to the GOV.UK GA4 data collection
  • the dates of external events which could impact use of GOV.UK

This report was first created in mid 2024 by the GOV.UK Insights and Analytics team to support users of the GOV.UK GA4 data.

Using the GOV.UK GA4 annotations report

### Get access to the GOV.UK GA4 annotations report

The report can be viewed by anyone with a GDS email address.

Those in the GOV.UK Insights and Analytics team Google group and in the GDS Performance Analysts Google group are automatically granted ‘Edit’ permissions.

GOV.UK GA4 annotations data definitions

Field name Definition Notes
start_date The date the issue happened or started on  
end_date If present, the date the issue was resolved or stopped occuring Only present for annotations pulled from the data_quality_notes table
category The type of annotation - for example, if the annotation provides ‘Information’ or tells you when something was ‘Changed’, ‘Created’ or ‘Broken’ Always ‘Information’ for the govuk_timeline and planning_message_calendar tables
issue_name The ‘title’ of the issue Calculated in the custom query for the govuk_timeline and planning_message_calendar tables
details A more detailed explanation of the issue Calculated in the custom query for the govuk_timeline and planning_message_calendar tables
duration The difference between the start and end dates A calculated field added to the data source
impacted_event_names The event_name value for the GOV.UK GA4 events that might be impacted by this issue - ‘null’ if all events or unknown Always ‘null’ for the govuk_timeline and planning_message_calendar tables
impacted_event_types The type value for the GOV.UK GA4 events that might be impacted by this issue - ‘null’ if all events or unknown Always ‘null’ for the govuk_timeline and planning_message_calendar tables
Record Count A count of the records (rows) in the table Default Looker Studio field

How the GOV.UK GA4 annotations report works

Data sources

The GOV.UK GA4 annotations reporting Looker Studio report uses the ‘GOV.UK GA4 annotations’ data source. This is a custom query which pulls together data from a few different data sources in the ga4_annotations dataset:

  • the data_quality_notes table, which pulls information on changes to the GA4 data collection from a Google Sheet
  • the govuk_timeline and planning_message_calendar tables, which pull information on external events from two Google Sheets

The custom query unions each of these tables together after adding in the ‘Category’ and ‘Issue name’ fields and ensuring that only appropriate rows (where events have specific dates) are pulled in.

Date range parameters are enabled and the whole data source (the result of the union of the above tables) is filtered by the Looker Studio date parameters.

The custom query is as follows:

SQL WITH dq_notes AS ( SELECT What_date_did_the_thing_start_ AS start_date, What_date_did_the_thing_end___if_relevant_ AS end_date, Category AS category, Issue_name AS issue_name, Details AS details, Impacted_event_name_s____comma_separated AS impacted_event_names, Impacted_event_type_s____comma_separated AS impacted_event_types FROM `ga4-analytics-352613.ga4_annotations.data_quality_notes` ), first_event_date AS ( SELECT event_name, type, first_date FROM `ga4-analytics-352613.ga4_annotations.event_first_recorded_date` ), govuk_timeline AS( SELECT PARSE_DATETIME("%A %e %B %Y", date) AS date, CASE WHEN other_events IS NOT NULL THEN "External event" WHEN covid_events IS NOT NULL THEN "Covid event" WHEN govuk_changes IS NOT NULL THEN "GOV.UK change" ELSE NULL END AS issue_name, other_events, covid_events, govuk_changes FROM `ga4-analytics-352613.ga4_annotations.govuk_timeline` ), message_calendar AS( SELECT PARSE_DATETIME("%e %B %Y", CONCAT(date, year)) AS date, CASE WHEN national_events IS NOT NULL THEN "National event" WHEN fixed_service_deadlines IS NOT NULL THEN "Fixed service deadline" WHEN government_announcements IS NOT NULL THEN "Government annonucement" WHEN political_calendar IS NOT NULL THEN "Political event" WHEN government_events IS NOT NULL THEN "Government event" WHEN external_events IS NOT NULL THEN "External event" WHEN emotional_calendar IS NOT NULL THEN "Emotional event" ELSE NULL END AS issue_name, national_events, fixed_service_deadlines, government_announcements, political_calendar, government_events, external_events, emotional_calendar FROM `ga4-analytics-352613.ga4_annotations.planning_message_calendar` WHERE REGEXP_CONTAINS(date, '^[0-9]{1,2}.[a-z]*') ), union_table AS ( SELECT start_date, end_date, category, issue_name, details, impacted_event_names, impacted_event_types FROM dq_notes UNION ALL SELECT first_date, NULL, 'Created', CONCAT(type, " ", event_name, " event added"), CONCAT("New event type added - name: ", CONCAT(event_name, CONCAT(", type: ", type))), event_name, type FROM first_event_date UNION ALL SELECT DATE(date), NULL, 'Information', govuk_timeline.issue_name, CONCAT(IFNULL(govuk_timeline.other_events,""), CONCAT(IFNULL(govuk_timeline.covid_events,""), IFNULL(govuk_timeline.govuk_changes, ""))) AS details, NULL, NULL FROM govuk_timeline WHERE govuk_timeline.issue_name IS NOT NULL UNION ALL SELECT DATE(date), NULL, 'Information', message_calendar.issue_name, CONCAT(IFNULL(message_calendar.national_events,""), CONCAT(IFNULL(message_calendar.fixed_service_deadlines,""), CONCAT(IFNULL(message_calendar.government_announcements, ""), CONCAT(IFNULL(message_calendar.political_calendar, ""), CONCAT(IFNULL(message_calendar.government_events, ""), CONCAT(IFNULL(message_calendar.external_events, ""), IFNULL(message_calendar.emotional_calendar, ""))))))) AS details, NULL, NULL FROM message_calendar WHERE message_calendar.issue_name IS NOT NULL) SELECT * FROM union_table WHERE (start_date BETWEEN PARSE_DATE('%Y%m%d', @DS_START_DATE) AND PARSE_DATE('%Y%m%d', @DS_END_DATE)) OR (end_date BETWEEN PARSE_DATE('%Y%m%d', @DS_START_DATE) AND PARSE_DATE('%Y%m%d', @DS_END_DATE)) OR ( --date in middle of issue range start_date <= PARSE_DATE('%Y%m%d', @DS_START_DATE) AND end_date >= PARSE_DATE('%Y%m%d', @DS_END_DATE) AND end_date IS NOT NULL) ORDER BY start_date

This page was last reviewed on 14 November 2024. It needs to be reviewed again on 14 May 2025 .