{"id":459,"date":"2026-09-11T08:30:00","date_gmt":"2026-09-11T06:30:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/?p=459"},"modified":"2026-10-26T11:59:00","modified_gmt":"2026-10-26T10:59:00","slug":"automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/","title":{"rendered":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery"},"content":{"rendered":"<p>A tracking failure can remain unnoticed while the website still works. A daily volume check provides a clue: how many events were exported, and how far does the count differ from a comparable weekday? BigQuery calculates the comparison; Looker Studio displays it. Notifications require a separately configured alert rule.<\/p>\n<p>The example checks four event names. It does not validate every parameter or the entire measurement pipeline. Campaigns, holidays and consent changes can also explain a flagged result.<\/p>\n<h2>1. Data availability before event volume<\/h2>\n<p>The target is four days ago, compared with the same weekday in the previous eight weeks. The target is excluded from the reference mean. This delay allows time for late exports but does not certify completeness. GA4 has no universally guaranteed daily export time; 05:30 UTC is not a safe completion boundary.<\/p>\n<p>A missing daily table remains an unknown value. An absent event becomes zero only when its daily table exists. An existing table can still be incomplete. Here, <code>session_start<\/code> counts that event; it does not recreate the GA4 sessions metric.<\/p>\n<figure class=\"lw-diagram\"><img decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/dia-459-alerts-20261024-en.png\" alt=\"Availability, comparison and delivery need separate checks. A change from a constant baseline must not pass as an unremarkable result.\" width=\"1120\" height=\"580\" loading=\"lazy\"><figcaption>Availability, comparison and delivery need separate checks. A change from a constant baseline must not pass as an unremarkable result.<\/figcaption><\/figure>\n<h2>2. SQL example with separate failure states<\/h2>\n<p>The project, dataset and every occurrence of the reporting timezone need replacement with the intended settings. The query expects GA4 daily tables with compatible schemas. If all matching tables or access permissions are missing, the job fails; separate operational monitoring must cover that case. A BigQuery trial run and cost estimate are required before scheduling.<\/p>\n<pre><code class=\"language-sql\">-- GoogleSQL; replace project, dataset and reporting timezone.\nWITH dates AS (\n  SELECT d AS metric_date,\n    DATE_SUB(CURRENT_DATE(&#x27;Europe\/Warsaw&#x27;), INTERVAL 4 DAY) AS target_date\n  FROM UNNEST(GENERATE_DATE_ARRAY(\n    DATE_SUB(CURRENT_DATE(&#x27;Europe\/Warsaw&#x27;), INTERVAL 60 DAY),\n    DATE_SUB(CURRENT_DATE(&#x27;Europe\/Warsaw&#x27;), INTERVAL 4 DAY),\n    INTERVAL 7 DAY)) AS d\n),\navailable AS (\n  SELECT table_name\n  FROM `project_id.analytics_XXXXXXXXX.INFORMATION_SCHEMA.TABLES`\n  WHERE table_type = &#x27;BASE TABLE&#x27;\n),\ncounts AS (\n  SELECT PARSE_DATE(&#x27;%Y%m%d&#x27;, event_date) AS metric_date,\n    event_name, COUNT(*) AS event_count\n  FROM `project_id.analytics_XXXXXXXXX.events_*`\n  WHERE _TABLE_SUFFIX BETWEEN\n    FORMAT_DATE(&#x27;%Y%m%d&#x27;, DATE_SUB(CURRENT_DATE(&#x27;Europe\/Warsaw&#x27;), INTERVAL 60 DAY))\n    AND FORMAT_DATE(&#x27;%Y%m%d&#x27;, DATE_SUB(CURRENT_DATE(&#x27;Europe\/Warsaw&#x27;), INTERVAL 4 DAY))\n    AND event_name IN (&#x27;purchase&#x27;, &#x27;add_to_cart&#x27;, &#x27;begin_checkout&#x27;, &#x27;session_start&#x27;)\n  GROUP BY 1, 2\n),\ngrid AS (\n  SELECT d.metric_date, d.target_date, n AS event_name,\n    IF(a.table_name IS NULL, NULL, COALESCE(c.event_count, 0)) AS event_count\n  FROM dates AS d\n  CROSS JOIN UNNEST([&#x27;purchase&#x27;, &#x27;add_to_cart&#x27;, &#x27;begin_checkout&#x27;, &#x27;session_start&#x27;]) AS n\n  LEFT JOIN available AS a\n    ON a.table_name = CONCAT(&#x27;events_&#x27;, FORMAT_DATE(&#x27;%Y%m%d&#x27;, d.metric_date))\n  LEFT JOIN counts AS c ON c.metric_date = d.metric_date AND c.event_name = n\n),\nstats AS (\n  SELECT target_date AS metric_date, event_name,\n    MAX(IF(metric_date = target_date, event_count, NULL)) AS event_count,\n    COUNT(IF(metric_date &lt; target_date, event_count, NULL)) AS reference_days,\n    AVG(IF(metric_date &lt; target_date, event_count, NULL)) AS expected_avg,\n    STDDEV_SAMP(IF(metric_date &lt; target_date, event_count, NULL)) AS reference_sd\n  FROM grid\n  GROUP BY target_date, event_name\n),\nscored AS (\n  SELECT *,\n    IF(reference_days = 8,\n      SAFE_DIVIDE(event_count - expected_avg, reference_sd), NULL) AS z_score\n  FROM stats\n),\nclassified AS (\n  SELECT *,\n    CASE\n      WHEN event_count IS NULL THEN &#x27;MISSING_EXPORT&#x27;\n      WHEN reference_days != 8 THEN &#x27;INCOMPLETE_BASELINE&#x27;\n      WHEN reference_sd = 0 AND event_count != expected_avg THEN &#x27;CONSTANT_BASELINE_CHANGE&#x27;\n      WHEN reference_sd = 0 THEN &#x27;NO_CHANGE&#x27;\n      WHEN z_score &lt; -2.0 THEN &#x27;DROP&#x27;\n      WHEN z_score &gt; 3.0 THEN &#x27;SPIKE&#x27;\n      ELSE &#x27;WITHIN_RULE&#x27;\n    END AS quality_status\n  FROM scored\n)\nSELECT *, CURRENT_TIMESTAMP() AS evaluated_at,\n  IF(quality_status IN (&#x27;NO_CHANGE&#x27;, &#x27;WITHIN_RULE&#x27;), 0, 1) AS alert_flag\nFROM classified\nORDER BY event_name;\n<\/code><\/pre>\n<p><code>reference_days<\/code> must equal eight. A missing reference produces <code>INCOMPLETE_BASELINE<\/code>; a missing target produces <code>MISSING_EXPORT<\/code>. A constant baseline cannot support division by its standard deviation: eight values of 100 followed by zero therefore produce <code>CONSTANT_BASELINE_CHANGE<\/code>. Eight values of 100 followed by 100 produce <code>NO_CHANGE<\/code>.<\/p>\n<p>With a varying baseline, the z-score describes distance from the mean relative to the variation in the eight reference values. For example, a mean of 100, a sample standard deviation of 10 and a new value of 70 give (70 \u2212 100) \/ 10 = \u22123. The standard deviation measures how spread out the reference values are. The \u22122 and +3 thresholds are investigation rules, not calibrated significance tests. Eight observations provide limited evidence; multiple checks and low event volumes can produce misleading flags. <code>WITHIN_RULE<\/code> only means that this rule did not trigger.<\/p>\n<h2>3. Result storage and alert delivery<\/h2>\n<ol>\n<li>A monitoring dataset is created in a suitable BigQuery region. The account running the query needs checked read and write permissions.<\/li>\n<li>A manual first run is expected to return four rows including <code>evaluated_at<\/code> and <code>alert_flag<\/code>. The cost estimate needs review: the table range spans 57 days even though only nine comparison dates are needed.<\/li>\n<li>Scheduling follows observed export availability. The current-result destination table can be replaced after each successful run. A separate history requires run identifiers and a retry-deduplication rule; blind appends create duplicates.<\/li>\n<li>Looker Studio displays target date, event, count, reference mean, status and evaluation time. Pro chart alerts support email notifications and use default filters. Sending a report to Google Chat is a different feature from a conditional data alert.<\/li>\n<li>Cloud Monitoring uses a separate query returning only alert rows. The automatic <code>bigquerydatatransfer.googleapis.com\/transfer_config\/last_execution_job_rows<\/code> metric counts result rows, not z-scores. The rule filters to the correct <code>config_id<\/code> and alerts above zero.<\/li>\n<\/ol>\n<p>The alert query must follow a successful calculation and check freshness, the expected target date and all four result rows. An old healthy table must not conceal a failed new run. Job failures and missing runs need separate monitoring: the last row-count value can persist after a failure. Notification channels need verification with controlled cases before delivery can be relied on.<\/p>\n<h2>4. Acceptance checks before daily operation<\/h2>\n<ul>\n<li>Constant baseline followed by total loss: a change is flagged, not a false normal result.<\/li>\n<li>Missing daily table: missing export, not an invented event zero.<\/li>\n<li>Missing reference week: comparison withheld.<\/li>\n<li>Unchanged constant baseline: no change.<\/li>\n<li>Failed job or stale results: operational warning independent of the data-quality status.<\/li>\n<\/ul>\n<p>The status decision was checked in isolation with synthetic cases. This does not demonstrate a working BigQuery, Pro or Cloud Monitoring installation. Daily checks with a four-day delay explicitly cannot deliver instant outage alerts. Faster detection needs a separate assessment of provisional data.<\/p>\n<div class=\"lw-faq\">\n<h2>Questions and answers<\/h2>\n<h3>Why is filling missing counts with zero insufficient?<\/h3>\n<p>Without a date grid, days without events disappear. Filling every gap with zero, however, confuses a missing export with an observed zero day. The example also checks whether the table exists.<\/p>\n<h3>Does a flag prove a tracking failure?<\/h3>\n<p>No. Investigation needs additional evidence: releases, CMP changes, campaigns, server errors and export state. A volume rule cannot identify the cause or validate individual parameter values.<\/p>\n<\/div>\n<p><!-- lw-anomaly-weekday:start --><\/p>\n<h2>Practical check: a weekday baseline without the inspected day<\/h2>\n<p>The <a href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-anomaly-detector\/\">GA4 Anomaly Detector<\/a> now compares a selected reporting day with the same weekday from each of the eight previous weeks. A Thursday is compared with eight Thursdays. The inspected day is excluded from the reference mean and sample standard deviation, so a sharp drop cannot pull its own baseline down.<\/p>\n<p>The tool reads sessions, total users, page\/screen views, key events, event count, total revenue and engagement rate through the read-only Data API. The default date is four days ago to leave time for processing, but that delay does not certify that the report is complete. The property&#8217;s reporting timezone and the returned metadata remain relevant.<\/p>\n<ol>\n<li>The selected day must have ended; the eight reference dates shown in the result need checking.<\/li>\n<li>If a required date is absent from the response, the comparison is withheld. Missing rows are not silently replaced with zeros; a reported zero remains zero.<\/li>\n<li>The descriptive z-score is compared with the chosen threshold. With a constant baseline, the tool reports either no change or a change from that constant value, without dividing by zero.<\/li>\n<li>The nine comparison dates can be downloaded as CSV. Any flagged change is compared with releases, campaigns, holidays and other evidence.<\/li>\n<\/ol>\n<p>Eight observations are a small reference set. These flags are not calibrated significance tests, and seven concurrent metric checks can generate chance findings. Weekday matching does not remove trends, special events, consent changes or processing delays. No flag proves complete tracking, and a flag does not establish the cause. This is a manual investigation tool, not a scheduled alert service.<\/p>\n<p>Sources: <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/reporting\/data\/v1\/rest\/v1beta\/properties\/runReport\">Google runReport reference<\/a>, <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/reporting\/data\/v1\/api-schema\">metric definitions<\/a> and <a href=\"https:\/\/www.itl.nist.gov\/div898\/handbook\/eda\/section3\/eda35h.htm\">NIST guidance on outlier detection and its assumptions<\/a>.<\/p>\n<p><!-- lw-anomaly-weekday:end --><\/p>\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/support.google.com\/analytics\/answer\/9358801?hl=en\">GA4 export timing and limitations<\/a><\/li>\n<li><a href=\"https:\/\/support.google.com\/analytics\/answer\/7029846\">GA4 export schema<\/a><\/li>\n<li><a href=\"https:\/\/docs.cloud.google.com\/bigquery\/docs\/information-schema-tables\">Table inventory<\/a><\/li>\n<li><a href=\"https:\/\/docs.cloud.google.com\/bigquery\/docs\/reference\/standard-sql\/statistical_aggregate_functions\">Sample standard deviation<\/a><\/li>\n<li><a href=\"https:\/\/docs.cloud.google.com\/bigquery\/docs\/scheduling-queries\">Scheduled query configuration<\/a><\/li>\n<li><a href=\"https:\/\/docs.cloud.google.com\/bigquery\/docs\/create-alert-scheduled-query\">Row-count alert metric and operational limits<\/a><\/li>\n<li><a href=\"https:\/\/docs.cloud.google.com\/data-studio\/create-alerts-on-a-chart\">Pro chart alerts<\/a><\/li>\n<li><a href=\"https:\/\/www.itl.nist.gov\/div898\/handbook\/eda\/section3\/eda35h.htm\">Outliers and distributional assumptions<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A BigQuery example compares GA4 event counts with eight matching weekdays and separates missing exports from zero counts. Looker Studio displays the results; scheduled alerts require additional configuration and tests.<\/p>\n","protected":false},"author":1,"featured_media":14019,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[113],"tags":[91333,91297,91258,91353,91294,91219],"class_list":["post-459","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-bigquery","tag-data-quality","tag-google-analytics-4","tag-looker-studio","tag-monitoring","tag-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-11T06:30:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-26T10:59:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery\",\"datePublished\":\"2026-09-11T06:30:00+00:00\",\"dateModified\":\"2026-10-26T10:59:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/\"},\"wordCount\":1076,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-459-automated-data-quality-alerts-ga4-lo-g.png\",\"keywords\":[\"BigQuery\",\"Data Quality\",\"Google Analytics 4\",\"Looker Studio\",\"Monitoring\",\"Tutorial\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/\",\"name\":\"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-459-automated-data-quality-alerts-ga4-lo-g.png\",\"datePublished\":\"2026-09-11T06:30:00+00:00\",\"dateModified\":\"2026-10-26T10:59:00+00:00\",\"description\":\"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-459-automated-data-quality-alerts-ga4-lo-g.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/hero-459-automated-data-quality-alerts-ga4-lo-g.png\",\"width\":1200,\"height\":630,\"caption\":\"Automated Data Quality Alerts for GA4 with Looker Studio & BigQuery\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik","description":"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/","og_locale":"en_US","og_type":"article","og_title":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik","og_description":"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-09-11T06:30:00+00:00","article_modified_time":"2026-10-26T10:59:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery","datePublished":"2026-09-11T06:30:00+00:00","dateModified":"2026-10-26T10:59:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/"},"wordCount":1076,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png","keywords":["BigQuery","Data Quality","Google Analytics 4","Looker Studio","Monitoring","Tutorial"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/","name":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png","datePublished":"2026-09-11T06:30:00+00:00","dateModified":"2026-10-26T10:59:00+00:00","description":"Monitor GA4 data quality: BigQuery anomaly queries, scheduled checks and Looker Studio with weekday-based comparisons.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-459-automated-data-quality-alerts-ga4-lo-g.png","width":1200,"height":630,"caption":"Automated Data Quality Alerts for GA4 with Looker Studio & BigQuery"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/automated-data-quality-alerts-for-ga4-with-looker-studio-bigquery\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Automated Data Quality Alerts for GA4 with Looker Studio &amp; BigQuery"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=459"}],"version-history":[{"count":9,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions"}],"predecessor-version":[{"id":26736,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/459\/revisions\/26736"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/14019"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}