Web Analytics with Google Analytics 4Tagging with a tag manager · Lesson 9 of 20
QA, debugging and release discipline
Video lecture
QA, debugging and release discipline
The narrated lecture is in production
Every chapter is scripted and ready. Browse the chapters and read the full transcript now — the video will appear here when it’s published.
Chapters
Transcript of the narration, chapter by chapter.
0:00 QA and debugging
Here's a rule that will save your reputation as an analyst: assume every tracking implementation is broken until you've proven otherwise. Not because developers are careless, but because websites change constantly, and measurement is invisible when it breaks. In this lecture you'll learn the debugging toolkit, a step-by-step QA script, the most common bugs and how to spot them, how to reconcile G A four with your backend, and how to monitor automatically with the BigQuery export so you hear about problems before your stakeholders do.
0:37 Why QA is your job
Why is QA the analyst's job? Because bad data is worse than no data. People act on it. A key event that fires on a button click rather than on success makes a campaign look twice as good as it is. A missing currency makes revenue look tiny. And nobody notices, because the numbers still look like numbers. Every tracking change should pass a repeatable QA process before and after release, and the analyst is the person who knows what correct looks like.
1:13 The toolkit
Here's the toolkit. Tag manager preview mode, also called Tag Assistant, shows which tags fired on each action, which didn't, and variable values at that moment. G A four DebugView shows events arriving in G A four from debug-enabled devices, with parameters and user properties. The Realtime report is a sanity check that production events arrive at all. The browser's network tab lets you inspect requests to the collection endpoint. And a staging environment lets you test without polluting production data.
1:48 The parcel analogy
Think of it like a parcel delivery. Preview mode is the warehouse camera: did the parcel leave, with the right label? DebugView is the delivery confirmation: did it arrive at G A four, intact? Realtime is glancing out the window to see if any vans are arriving at all. And the reports, a day or two later, are the monthly statement. You need all four views, because a parcel can leave correctly and still arrive damaged, or arrive fine and be filed in the wrong place.
2:25 The QA script
Here's the QA script for each event in the plan. Trigger: perform the action as a user would, and the failure path too. Tag fired: preview shows it fired once, on the correct trigger. Values: variables resolved, no undefined, no personal data. Arrived: DebugView shows the right name and parameters. Consent: repeat with consent denied and check behavior matches your design. Devices: mobile and another browser. Reports: confirm a day or two later. And document: mark the row verified with the date and tester.
3:02 Common bugs
Now the most common bugs. Page views doubled: usually a hard-coded tag plus the tag manager, or single-page app double firing. Key events far above backend counts: a trigger on the click or attempt, or confirmation page reloads. Parameters showing not set: the variable was undefined at fire time, or the dimension isn't registered. Revenue in the wrong magnitude: missing currency, or values in minor units like cents or paisa. Paid traffic appearing as referral or direct: stripped UTMs or missing unwanted referrals. And a sudden drop to zero: an unpublished container, a blocking consent banner, or a release that removed the snippet.
3:47 Reconciliation
Then reconciliation. G A four key events will rarely match your backend exactly. Consent choices, ad blockers, network failures and browser restrictions all remove some hits. So establish a routine: compare weekly G A four purchases with orders from your system. Define an acceptable variance for your context. Here's the key idea: a stable gap is manageable, a changing gap signals breakage. Explain the gap to stakeholders rather than hiding it.
4:18 Example 1: missing Saudi orders
First example, a simple one. A G C C e-commerce brand notices G A four purchases from Saudi Arabia dropped sharply, while backend orders were steady. Realtime shows purchases from other countries, so the tag works in general. Preview mode on the Saudi storefront reveals the purchase tag doesn't fire: a new local payment method redirects to a different confirmation URL, not matched by the trigger. The fix: move the trigger to a data layer purchase push from the order confirmation logic, and add the new payment method to the QA script.
4:58 Example 2: Bristol subscriptions
Second example, a business case with illustrative numbers. A Bristol subscription company's weekly reconciliation shows G A four purchases about twelve percent below orders for months, which the team accepts as consent and ad-blocker loss. One week the gap jumps. Their automated health query shows purchases missing a transaction id rising right after a checkout update: a new payment step sent purchase without the id. The developer restored the field, and the gap returned to its usual level within a day.
5:33 Watch me do it, part 1
Watch me build that health query in BigQuery. For the last fourteen days, grouped by event date, I count page views and purchases. I count distinct transaction ids among purchases, which gives unique orders. I count purchases where the transaction id is null. And I count purchases missing a value. If purchases exceed unique orders, I have duplicates. Any missing ids or values are bugs. And a sudden drop in page views on one day points to a release or a consent change.
6:09 Watch me do it, part 2
Then I automate it. I save the query as a BigQuery scheduled query that runs every morning, and write results to a table that feeds a small sheet or a chat alert. I also create custom insights in G A four for sudden drops in key events or sessions. And whenever tracking changes, I add an annotation or change log entry, so future analysts can see when data behavior changed. Now problems find me, instead of my stakeholders finding them.
6:44 Common mistakes
Common mistakes. Testing only the happy path and never the failure path. Testing only on desktop Chrome with an ad blocker disabled. Declaring success because Realtime shows something. Not re-testing after site releases. And chasing a perfect match with backend data instead of a stable, explained variance.
7:04 Release checklist
And the release checklist. The QA script completed for every changed event. Consent-denied behavior verified. The version named and described, and the change log updated. Stakeholders told what changed and from which date. And an annotation added, so the next person knows when the data changed. It takes ten minutes and it's the difference between a trusted analytics function and one that's always explaining surprises.
7:32 Recap
Recap. Assume tracking is broken until a repeatable QA script proves otherwise. Use preview for tags, DebugView for arrival, Realtime for sanity and reports for final confirmation. Expect a stable gap with your backend, and investigate when it changes. Re-test after every release, and automate monitoring with a scheduled health query and alerts.
7:55 Try this now
Try this now. Write a QA script for three events on a site you know and run it in preview mode, including the failure path and a consent-denied pass. Record the results in a status column in your tracking plan. If you have the BigQuery export, run the health query from the lesson for the last fourteen days and note anything suspicious.
Why QA is the analyst's job
Bad data is worse than no data because people act on it. Every tracking change should pass a repeatable QA process before and after release. Assume every implementation is broken until proven otherwise.
The debugging toolkit
| Tool | Use it to |
|---|---|
| Tag manager preview mode (Tag Assistant) | See which tags fired on each action, which did not, and the variable values at that moment |
| GA4 DebugView | See events arriving in GA4 from debug-enabled devices, with parameters and user properties |
| GA4 Realtime report | Sanity-check that production events are arriving at all |
| Browser developer tools (Network tab) | Inspect requests to the GA4 collection endpoint and their parameters |
| Staging environment | Test changes without polluting production data |
DebugView data is excluded from standard reports when you use the developer traffic filter, so you can test on production without distortion if needed.
A step-by-step QA script
For each event in the tracking plan:
1. Trigger: Perform the action exactly as a user would (and the failure path).
2. Tag fired? Preview mode shows the tag fired ONCE on the correct trigger.
3. Values: Variables resolved to expected values (no "undefined", no PII).
4. Arrived? DebugView shows the event with correct name and parameters.
5. Consent: Repeat with consent denied - tag behavior matches consent design.
6. Devices: Repeat on mobile and at least one other browser.
7. Reports: 24-48 hours later, confirm data in standard reports/explorations.
8. Document: Mark row "verified" in the tracking plan with date and tester.The most common bugs and how to spot them
| Symptom | Likely cause | Where to look |
|---|---|---|
| Page views doubled | Hard-coded tag plus tag manager; SPA double firing | Network tab, preview mode |
| Key event count far above backend count | Trigger on click/attempt; confirmation page reloads | Trigger config, transaction_id |
| Parameters show "(not set)" | Variable undefined at fire time; not registered as custom dimension | Preview mode variables; custom definitions |
| Revenue in wrong magnitude | Currency missing; value sent in minor units (cents/paisa) | DebugView parameters |
| Paid traffic shows as referral or direct | UTMs stripped by redirects; unwanted referrals missing | Landing URLs, redirect chains |
| Sudden drop to zero | Container not published, consent banner blocking, site release removed snippet | Realtime, page source |
Reconciliation: how close is close enough?
GA4 key events will rarely match your backend exactly. Consent choices, ad blockers, network failures and browser restrictions all remove some hits. Establish a reconciliation routine: compare weekly GA4 purchases with orders from your system. Define an acceptable variance for your context, investigate when it widens suddenly, and explain the gap to stakeholders rather than hiding it. A stable gap is manageable; a changing gap signals breakage.
Monitoring after release
QA does not end at publish. Set up:
- Custom insights / alerts in GA4 for sudden drops in key events or sessions.
- A weekly smoke test of top journeys (for example: view product, add to cart, begin checkout).
- Release coordination: developers notify analytics before front-end deployments; analytics re-runs the QA script afterwards.
Worked example: the missing Saudi orders
An e-commerce brand selling across the GCC notices GA4 purchases from Saudi Arabia dropped sharply while backend orders were steady. QA steps:
- Realtime shows purchases from other countries — the tag works in general.
- Preview mode on the Saudi storefront reveals the
purchasetag does not fire: a new local payment method redirects to a different confirmation URL not matched by the trigger. - Fix: move the trigger to a data layer
purchasepush from the order-confirmation logic, independent of URL. - Add the new payment method to the QA script and unwanted referrals list.
The lesson: URL-based triggers break whenever the journey changes. Event-based triggers from the order logic are resilient.
Hands-on: automated monitoring with the BigQuery export
The interface shows problems late. With the BigQuery export (module 7) you can run a daily health query and alert on anomalies:
-- Daily tracking health for the last 14 days
SELECT
event_date,
COUNTIF(event_name = 'page_view') AS page_views,
COUNTIF(event_name = 'purchase') AS purchases,
COUNT(DISTINCT IF(event_name = 'purchase', ecommerce.transaction_id, NULL)) AS unique_orders,
COUNTIF(event_name = 'purchase' AND ecommerce.transaction_id IS NULL) AS purchases_missing_id,
COUNTIF(event_name = 'purchase'
AND (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'currency') IS NULL)
AS purchases_missing_currency,
COUNTIF(event_name = 'purchase' AND ecommerce.purchase_revenue IS NULL) AS purchases_missing_revenue
FROM `my-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 14 DAY))
AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
GROUP BY event_date
ORDER BY event_date;Watch for: purchases greater than unique_orders (duplicates), any missing ids, currencies or revenue, and sudden drops in page views on one day (a release or consent change). Schedule it as a BigQuery scheduled query and send results to a sheet or chat alert.
Custom insights and annotations
In the GA4 interface, create custom insights (alerts) for sudden drops in key events or sessions, and add an annotation or change-log entry whenever tracking changes so future analysts can see when data behavior changed.
Second worked example: a UK subscription box
A Bristol subscription company's weekly reconciliation shows GA4 purchases about 12% below orders (illustrative) for months, which the team accepts as consent and ad-blocker loss. One week the gap jumps sharply. The health query shows purchases_missing_id rising after a checkout update: a new payment step sent purchase without transaction_id, so duplicates and missing values appeared at once. The developer restored the field; the gap returned to its usual level within a day. A stable gap was fine; a changing gap was the signal.
Common mistakes
- Testing only the happy path and never the failure path.
- Testing only on desktop Chrome with an ad blocker disabled.
- Declaring success because "Realtime shows something".
- Not re-testing after site releases.
- Chasing a perfect match with backend data instead of a stable, explained variance.
Release checklist
Key takeaways
- Assume tracking is broken until a repeatable QA script proves otherwise.
- Use preview mode for tags, DebugView for arrival, Realtime for sanity, reports for final confirmation.
- Expect a stable gap between GA4 and backend data; investigate when it changes.
- Re-test after every site release and monitor with alerts.
Check your understanding
Quick questions to lock in the lesson. They don’t count towards your certificate.
Put it into practice
Write a QA script for three events on a site you know, run it in preview mode (or describe how you would), and record results in a tracking-plan status column.
Enrol for free to save your progress
Reading is always free. Enrol to keep your place, take the final assessment and earn a verifiable certificate.