Free reference · yours to keep
Symptom, cause, and the one-line fix for each. These are the defaults you get from wiring GA4 to a dashboard without a model in between — quiet, because the numbers still look plausible.
Totals rise by a fixed multiple; the trend still looks right, so it survives every review.
Fix: join traffic to pages at the grain it was measured at. Aggregate before the join, not after.
Query strings, tracking parameters and casing split a single page into many URLs; the dataset balloons.
Fix: normalise the URL at ingest — strip query strings, lowercase, drop trailing slashes.
Someone exports to Excel and fixes numbers by hand; now last quarter has two versions.
Fix: one source measure, published once. Everything downstream reads it; nobody re-derives.
You can't state last month's sessions without exporting first.
Fix: the aggregation belongs in DAX, not in the export. Move it into a measure.
History breaks every time a page moves, because the key is the URL.
Fix: key on a stable page id and map redirects into it, so the series survives the move.
Traffic drops after a rewrite and nobody can say if it's the content or the demand.
Fix: join a content-change log (crawl history works) to the traffic table.
You can't say how many published pages got zero visits last quarter.
Fix: full page inventory from a crawl, left-joined to traffic. The nulls are the answer.
A non-analyst changes the range and a total breaks.
Fix: the measure depends on filter context it shouldn't. Rewrite it with the right context.
You optimise queries when the dataset is simply too big.
Fix: normalise keys first, index second. Row count usually beats query complexity as the cause.
Impressions live apart from page traffic, so you never see the content gap.
Fix: join on a cleaned page key. Impressions without traffic is your gap list.
Evening viewers see tomorrow's date because TODAY() runs on UTC.
Fix: pin the boundary to your reporting timezone in one hidden measure; derive captions from it.
A report with a hand-edit every month has an expiry date the day its author leaves.
Fix: written documentation and no manual steps. If there's a monthly hand-edit, it will break.
visualContainerObjects at the root of visual.json renders nothing, silently.
Fix: it must sit inside the visual object — for every visual type, including textboxes.
Property 'description' is unknown on load.
Fix: never use /// comments before a relationship — they create a description property relationships don't allow. Use //.
TMDL won't parse; the error points at a comment line.
Fix: tabs only, never spaces — including inside multi-line DAX and before /// comments.
Knowing the bugs is half of it; finding which ones are live in your numbers, and by how much, is the other half. The $400 Count Audit does exactly that on your data and hands you a written finding — and it credits against a pilot.
See the audit & pilot