{"id":325,"date":"2025-09-05T13:25:24","date_gmt":"2025-09-05T11:25:24","guid":{"rendered":"https:\/\/www.sabatka.net\/cs\/?page_id=325"},"modified":"2025-09-05T15:21:28","modified_gmt":"2025-09-05T13:21:28","slug":"data-quality-monitor-for-ga4","status":"publish","type":"page","link":"https:\/\/www.sabatka.net\/en\/data-quality-monitor-for-ga4\/","title":{"rendered":"Automated website testing for GA4 &#038; BigQuery"},"content":{"rendered":"\n<p>We automatically run a set of tests on your data once a day. If something is wrong (events, e-commerce, export to BigQuery, consent, UTM\u2026), you will receive an email notification. You know that the measurements are correct \u2014 and your Google Ads \/ P-Max are not running blindly.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"800\" height=\"533\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/bad-data-no-data.png\" alt=\"\" class=\"wp-image-337 lazyload\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/bad-data-no-data.png 800w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/bad-data-no-data-300x200.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/bad-data-no-data-768x512.png 768w\" data-sizes=\"(max-width: 800px) 100vw, 800px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 800px; --smush-placeholder-aspect-ratio: 800\/533;\" \/><\/figure>\n\n\n\n<style>\n  .waitlist-card{\n    --accent: var(--wp--preset--color--accent, #4f46e5);\n    --accent-ink: #fff;\n    --ring: rgba(79,70,229,.25);\n    --ink: var(--wp--preset--color--contrast, #111);\n    --muted: #6b7280;\n    --bg: var(--wp--preset--color--base, #fff);\n    max-width: 640px; margin: 1.5rem auto; padding: 1.5rem;\n    background: var(--bg); border: 1px solid rgba(17,24,39,.06);\n    border-radius: 16px; box-shadow: 0 10px 20px rgba(2,6,23,.04);\n  }\n  .waitlist-head{display:flex; align-items:center; gap:.75rem; margin-bottom:.75rem;}\n  .waitlist-head h3{margin:0; font-size:1.35rem; line-height:1.2; color:var(--ink);}\n  .waitlist-head p{margin:.15rem 0 0; color:var(--muted); font-size:.95rem;}\n  .waitlist-icon{flex:0 0 auto; width:40px; height:40px; border-radius:10px;\n    background: radial-gradient(120% 120% at 10% 10%, rgba(79,70,229,.25), transparent 60%),\n                rgba(79,70,229,.08);\n    display:grid; place-items:center; color:var(--accent);\n  }\n  .waitlist-fields{display:flex; gap:.5rem; margin-top:.75rem;}\n  .waitlist-fields input[type=\"email\"]{\n    flex:1 1 auto; font:inherit; padding:.9rem 1rem; border-radius:12px;\n    border:1px solid rgba(17,24,39,.12); background:#fff; color:var(--ink);\n    outline: none;\n  }\n  .waitlist-fields input[type=\"email\"]::placeholder{color:#9ca3af;}\n  .waitlist-fields input[type=\"email\"]:focus{\n    border-color: var(--accent); box-shadow: 0 0 0 8px var(--ring);\n  }\n  .waitlist-fields button{\n    flex:0 0 auto; padding:.9rem 1.1rem; border-radius:12px; border:0;\n    background: var(--accent); color: var(--accent-ink); font-weight:600; cursor:pointer;\n    transition: transform .04s ease, filter .2s ease;\n  }\n  .waitlist-fields button:hover{filter:brightness(1.05)}\n  .waitlist-fields button:active{transform: translateY(1px)}\n  .waitlist-micro{margin:.6rem 0 0; font-size:.9rem; color:var(--muted);}\n  .sr-only{position:absolute!important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}\n  @media (max-width:640px){ .waitlist-fields{flex-direction:column;} }\n<\/style>\n\n<form\n  class=\"waitlist-card\"\n  action=\"https:\/\/docs.google.com\/forms\/d\/1ITIAZy6dWt_5WXx3QsbvPm8tJZ1KQfooHnqv041ES0o\/formResponse\"\n  method=\"POST\" target=\"_self\" novalidate>\n\n\n  <div class=\"waitlist-head\">\n    <div class=\"waitlist-icon\" aria-hidden=\"true\">\n      <!-- jednoduch\u00e1 ob\u00e1lka jako ikona -->\n      <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"currentColor\" role=\"img\">\n        <path d=\"M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2Zm0 4.236-7.555 4.722a1 1 0 0 1-1.062 0L4 8.236V6l8 5 8-5v2.236Z\"\/>\n      <\/svg>\n    <\/div>\n    <div>\n      <h3>Join the waitlist<\/h3>\n      <p>I&#8217;ll send the info as soon as it&#8217;s released.<\/p>\n    <\/div>\n  <\/div>\n\n  <label class=\"sr-only\" for=\"email\">Email<\/label>\n  <div class=\"waitlist-fields\">\n    <input id=\"email\" name=\"entry.863651229\" type=\"email\" required\n           placeholder=\"vas@email.cz\" autocomplete=\"email\" inputmode=\"email\" \/>\n    <button type=\"submit\">I want to be at the release<\/button>\n  <\/div>\n\n  <p class=\"waitlist-micro\">No spam. Just a one-time launch notification.<\/p>\n\n  <!-- voliteln\u00e9: technick\u00e9 parametry Google Forms (v\u011bt\u0161inou nen\u00ed nutn\u00e9) -->\n  <input type=\"hidden\" name=\"fvv\" value=\"1\">\n  <input type=\"hidden\" name=\"pageHistory\" value=\"0\">\n<\/form>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>A minor change in the code, a missing event, or an export failure is enough to cause data to go missing. GA4 diverges from reality, e-commerce sales in reports plummet, P-Max loses conversion signals and starts &#8220;hunting&#8221; blindly.<\/p>\n\n\n\n<p><strong>Solution: Automatic data testing<\/strong>\u2014every morning, we check key parts of the measurement, and if we find an error or anomaly, you will receive a clear email. Before it starts to hurt your budget.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Where do measurement errors come from?<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Human errors (developer\/analyst)<\/strong><br>renamed\/duplicate events, missing parameters, incorrect currency, changes in GTM\/GA4 without QA, incorrectly set conversions\/events<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Technical errors and script conflicts<\/strong><br>asynchronous loading and race conditions, library collisions, shadow DOM, blocking\/incompatibility with cookie bar, CSP\/CORS, deployment errors<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Changes in measurement technologies<\/strong><br>new privacy policies, Consent Mode adjustments, changes in browsers (ITP\/ETP), SDK\/library versions, schema\/limit changes (GA4\/BigQuery)<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>External influences<\/strong><br>bots and scraping, measurement attacks (spam\/ghost hits), in-app browsers, adblockers, non-standard proxy\/VPN traffic<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"800\" height=\"533\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/it-happends-fix-it-fast.png\" alt=\"\" class=\"wp-image-336 lazyload\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/it-happends-fix-it-fast.png 800w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/it-happends-fix-it-fast-300x200.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/it-happends-fix-it-fast-768x512.png 768w\" data-sizes=\"(max-width: 800px) 100vw, 800px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 800px; --smush-placeholder-aspect-ratio: 800\/533;\" \/><\/figure>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What exactly do we monitor (selection)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GA4 events &#038; e-commerce<\/strong>: presence of key events (page_view, view_item, add_to_cart, purchase), correct parameters, currency\/price consistency.<\/li>\n\n\n\n<li><strong>BigQuery export<\/strong>: table freshness, number of events compared to yesterday\/7-day average, missing partition.<\/li>\n\n\n\n<li><strong>Consent Mode &#038; opt-in rate<\/strong>: sharp drops\/steps, unexpected differences between consent dialog views vs. allow all.<\/li>\n\n\n\n<li><strong>UTM &#038; traffic sources<\/strong>: increase (not set), self-referrals, campaign breakdown, unexpected channels.<\/li>\n\n\n\n<li><strong>Conversions for GAds\/P-Max<\/strong>: changes in number\/conversion value, shifts in attribution window, noticeable anomalies.<\/li>\n\n\n\n<li><strong>Technical signals<\/strong>: anomalous jumps in bot traffic, unusually short sessions, atypical device\/OS resolution.<\/li>\n<\/ul>\n\n\n\n<p>And much more.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">How it works (3 steps)<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Connect GA4 + BigQuery <\/strong>(read-only).<\/li>\n\n\n\n<li><strong>Daily tests run <\/strong>automatically every morning.<\/li>\n\n\n\n<li><strong>Email with results<\/strong>: overview of errors\/anomalies found + recommendations for next steps.<\/li>\n<\/ol>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Email example<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"800\" height=\"450\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/test_report_demo_en.png\" alt=\"\" class=\"wp-image-342 lazyload\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/test_report_demo_en.png 800w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/test_report_demo_en-300x169.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/test_report_demo_en-768x432.png 768w\" data-sizes=\"(max-width: 800px) 100vw, 800px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 800px; --smush-placeholder-aspect-ratio: 800\/450;\" \/><\/figure>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">I want to be at the release<\/h2>\n\n\n\n<style>\n  .waitlist-card{\n    --accent: var(--wp--preset--color--accent, #4f46e5);\n    --accent-ink: #fff;\n    --ring: rgba(79,70,229,.25);\n    --ink: var(--wp--preset--color--contrast, #111);\n    --muted: #6b7280;\n    --bg: var(--wp--preset--color--base, #fff);\n    max-width: 640px; margin: 1.5rem auto; padding: 1.5rem;\n    background: var(--bg); border: 1px solid rgba(17,24,39,.06);\n    border-radius: 16px; box-shadow: 0 10px 20px rgba(2,6,23,.04);\n  }\n  .waitlist-head{display:flex; align-items:center; gap:.75rem; margin-bottom:.75rem;}\n  .waitlist-head h3{margin:0; font-size:1.35rem; line-height:1.2; color:var(--ink);}\n  .waitlist-head p{margin:.15rem 0 0; color:var(--muted); font-size:.95rem;}\n  .waitlist-icon{flex:0 0 auto; width:40px; height:40px; border-radius:10px;\n    background: radial-gradient(120% 120% at 10% 10%, rgba(79,70,229,.25), transparent 60%),\n                rgba(79,70,229,.08);\n    display:grid; place-items:center; color:var(--accent);\n  }\n  .waitlist-fields{display:flex; gap:.5rem; margin-top:.75rem;}\n  .waitlist-fields input[type=\"email\"]{\n    flex:1 1 auto; font:inherit; padding:.9rem 1rem; border-radius:12px;\n    border:1px solid rgba(17,24,39,.12); background:#fff; color:var(--ink);\n    outline: none;\n  }\n  .waitlist-fields input[type=\"email\"]::placeholder{color:#9ca3af;}\n  .waitlist-fields input[type=\"email\"]:focus{\n    border-color: var(--accent); box-shadow: 0 0 0 8px var(--ring);\n  }\n  .waitlist-fields button{\n    flex:0 0 auto; padding:.9rem 1.1rem; border-radius:12px; border:0;\n    background: var(--accent); color: var(--accent-ink); font-weight:600; cursor:pointer;\n    transition: transform .04s ease, filter .2s ease;\n  }\n  .waitlist-fields button:hover{filter:brightness(1.05)}\n  .waitlist-fields button:active{transform: translateY(1px)}\n  .waitlist-micro{margin:.6rem 0 0; font-size:.9rem; color:var(--muted);}\n  .sr-only{position:absolute!important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}\n  @media (max-width:640px){ .waitlist-fields{flex-direction:column;} }\n<\/style>\n\n<form\n  class=\"waitlist-card\"\n  action=\"https:\/\/docs.google.com\/forms\/d\/1ITIAZy6dWt_5WXx3QsbvPm8tJZ1KQfooHnqv041ES0o\/formResponse\"\n  method=\"POST\" target=\"_self\" novalidate>\n\n\n  <div class=\"waitlist-head\">\n    <div class=\"waitlist-icon\" aria-hidden=\"true\">\n      <!-- jednoduch\u00e1 ob\u00e1lka jako ikona -->\n      <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"currentColor\" role=\"img\">\n        <path d=\"M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2Zm0 4.236-7.555 4.722a1 1 0 0 1-1.062 0L4 8.236V6l8 5 8-5v2.236Z\"\/>\n      <\/svg>\n    <\/div>\n    <div>\n      <h3>Join the waitlist<\/h3>\n      <p>I&#8217;ll send the info as soon as it&#8217;s released.<\/p>\n    <\/div>\n  <\/div>\n\n  <label class=\"sr-only\" for=\"email\">Email<\/label>\n  <div class=\"waitlist-fields\">\n    <input id=\"email\" name=\"entry.863651229\" type=\"email\" required\n           placeholder=\"vas@email.cz\" autocomplete=\"email\" inputmode=\"email\" \/>\n    <button type=\"submit\">I want to be at the release<\/button>\n  <\/div>\n\n  <p class=\"waitlist-micro\">No spam. Just a one-time launch notification.<\/p>\n\n  <!-- voliteln\u00e9: technick\u00e9 parametry Google Forms (v\u011bt\u0161inou nen\u00ed nutn\u00e9) -->\n  <input type=\"hidden\" name=\"fvv\" value=\"1\">\n  <input type=\"hidden\" name=\"pageHistory\" value=\"0\">\n<\/form>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Who already uses the tests?<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"294\" height=\"294\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/knihy-dobrovsky.png\" alt=\"\" class=\"wp-image-167 lazyload\" style=\"--smush-placeholder-width: 294px; --smush-placeholder-aspect-ratio: 294\/294;object-fit:cover\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/knihy-dobrovsky.png 294w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/knihy-dobrovsky-150x150.png 150w\" data-sizes=\"(max-width: 294px) 100vw, 294px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"300\" height=\"300\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/konica-minolta-3.png\" alt=\"\" class=\"wp-image-172 lazyload\" style=\"--smush-placeholder-width: 300px; --smush-placeholder-aspect-ratio: 300\/300;object-fit:cover\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/konica-minolta-3.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/07\/konica-minolta-3-150x150.png 150w\" data-sizes=\"(max-width: 300px) 100vw, 300px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"300\" height=\"300\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/lectura.png\" alt=\"\" class=\"wp-image-353 lazyload\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/lectura.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2025\/09\/lectura-150x150.png 150w\" data-sizes=\"(max-width: 300px) 100vw, 300px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 300px; --smush-placeholder-aspect-ratio: 300\/300;\" \/><\/figure>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>We automatically run a set of tests on your data once a day. If something is wrong (events, e-commerce, export to BigQuery, consent, UTM\u2026), you will receive an email notification. You know that the measurements are correct \u2014 and your Google Ads \/ P-Max are not running blindly. Join the waitlist I&#8217;ll send the info [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-325","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/pages\/325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/comments?post=325"}],"version-history":[{"count":18,"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/pages\/325\/revisions"}],"predecessor-version":[{"id":369,"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/pages\/325\/revisions\/369"}],"wp:attachment":[{"href":"https:\/\/www.sabatka.net\/en\/wp-json\/wp\/v2\/media?parent=325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}