LW IT Solutions
« Blog Overview /Web Development / Comparing Two GTM Container Exports: Normalising Before...

Comparing Two GTM Container Exports: Normalising Before the Diff and What a Line Diff Cannot Show

Comparing Two GTM Container Exports: Normalising Before the Diff and What a Line Diff Cannot Show
Contents
  1. What Fills the Gap
  2. Normalise First, Compare Second
  3. Three Levels, Three Different Answers
  4. What No Level Can Show
  5. What to Compare Instead When the Answer Matters
  6. Sources

Comparing two exports of the same configuration is the fastest way to find out what someone changed, and the first attempt almost always produces a result that is useless. There are several hundred differing lines, of which one matters and the rest are the file format talking to itself.

Everything below is about the gap between those two numbers – what fills it, how to remove it, and what remains invisible even after it is gone.

The same one-word change shown at line, word and character level, plus a fourth pair of lines that differ only in key order and are the same object
Three levels for one change, and a fourth pair that a line comparison calls different and a parser calls identical.

What Fills the Gap

Exports are generated, and generators are not obliged to be stable. The same configuration exported twice can differ in the order of object keys, in identifiers assigned at export time, in a fingerprint that is a timestamp, and in whether the file ends with a newline. None of that is a change; all of it is a difference.

Source of noise What it looks like How it is removed
Key order whole blocks marked as changed jq -S . sorts keys recursively
Fingerprints, timestamps one changed line per object delete the fields before comparing
Export-time identifiers every reference differs the same – or compare by name instead
Indentation everything differs jq reformats both sides identically
Line endings every line differs, and looks identical dos2unix, or the diff tool’s own option
Minification one line differs and says nothing reformat, then compare

The line-endings row is the one that costs an hour, because the two lines look exactly the same on screen. A file that has been through a Windows editor differs from its origin in every single line, and every one of those differences is invisible.

Normalise First, Compare Second

The fix is a pipeline rather than a better diff tool. Both files go through the same normalisation, the volatile fields are removed, and only then are the results compared – at which point the diff contains what changed and nothing else.

norm() {
  jq -S 'walk(if type == "object"
              then del(.fingerprint, .accountId, .containerVersionId)
              else . end)' "$1"
}

diff <(norm alt.json) <(norm neu.json)

walk descends into every object, so the fields disappear wherever they occur rather than only at the top level. -S sorts the keys of every object, which removes the largest source of noise on its own. What survives both is a change someone made.

Three Levels, Three Different Answers

Line, word and character are not degrees of quality but different questions. A line comparison answers “which lines are not identical”, which is the right question for source code, where a line is roughly a statement. It is the wrong question for a JSON file with one object per line and entirely useless for a minified one, where the whole document is a single line.

Word level compares tokens and is what makes a one-value change readable. Character level is finer than anyone needs for reading, and it is exactly what is needed when the line is long: in a minified container export, only a character comparison can point at the single boolean that flipped.

What No Level Can Show

A text comparison sees text. Which means three kinds of change stay invisible no matter how fine the granularity gets. A moved block appears as a deletion in one place and an addition in another, with nothing connecting them. A renamed variable used in twelve places appears as twelve unrelated changes rather than one intention. And a value that changed type without changing appearance – "1" becoming 1 – is a two-character difference with consequences that no amount of highlighting will convey.

The opposite case is the one the fourth row of the diagram shows: two files that differ in every line and describe the same object. A comparison of text can only ever answer questions about text, and the question actually being asked – did the configuration change – is a question about structure.

What to Compare Instead When the Answer Matters

For anything with a schema, the honest comparison is between parsed objects rather than between files. jq can do it directly: two documents are equal or they are not, and the answer is a single boolean that is not affected by formatting, order or whitespace.

# are they the same object at all?
jq -e --slurpfile b neu.json '. == $b[0]' alt.json >/dev/null && echo "identical"

# which top-level keys differ?
jq -n --slurpfile a alt.json --slurpfile b neu.json \
  '($a[0] | keys) as $ka | ($b[0] | keys) as $kb
   | { nur_alt: ($ka - $kb), nur_neu: ($kb - $ka) }'

Which leaves the line comparison the job it is good at: showing a person what someone else did, in a form that reads like the file they will edit. It answers “what should I look at” very well and “is this the same” not at all, and most of the frustration with it comes from asking it the second question.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Write a comment

The email address is not published. Required fields are marked with an asterisk.

ALL ARTICLES & CATEGORIES

CCTV

Follow this category by RSS

Cloud & AI

Follow this category by RSS

Data Privacy

All 12 articles in this category Follow this category by RSS

Digital Analytics

All 47 articles in this category Follow this category by RSS

Digital Marketing

All 27 articles in this category Follow this category by RSS

IT & Networks

All 16 articles in this category Follow this category by RSS

Music Production

Follow this category by RSS

Raspberry PI

Follow this category by RSS

Smart Home

All 17 articles in this category Follow this category by RSS

Web Development

Follow this category by RSS

WordPress Plugins & Tricks

Follow this category by RSS