Tutorial: Doppelt kodierte UTM-Parameter erkennen und korrigieren

Management Summary
UTM-Parameter sind Linkzusätze, mit denen Analysesysteme Besuche einer Kampagne zuordnen. Werden solche Angaben häufiger als vorgesehen in eine linktaugliche Schreibweise umgewandelt, kann dieselbe Kampagne unter mehreren Namen erscheinen und Vergleiche verzerren. Der Fehler kann beim Erstellen oder Weiterleiten von Links entstehen. Eine Korrektur an der Ursache vereinheitlicht künftige Berichte; ältere Namensvarianten lassen sich unter Erhalt der Originalwerte zusammenfassen. Auffällige Prozentzeichen allein beweisen noch keinen Fehler.
Inhalt
Eine als Sommer Aktion erwartete Kampagne erscheint als Sommer%20Aktion. Doppelte Kodierung ist eine mögliche Ursache. Der Bericht allein verrät jedoch weder die fehlerhafte Stelle noch die Richtigkeit der übrigen Zuordnung. Eine wörtliche Prozentfolge, ein fehlender Dekodierungsschritt oder ein ausdrücklich gesetzter Kampagnenwert können ähnlich aussehen.
Eine belastbare Diagnose vergleicht beabsichtigten Rohwert, erzeugten Link, Weiterleitungsziele und tatsächlich erfassten Wert. Korrekte Verschachtelung einer Adresse in einer anderen muss von unbeabsichtigter Mehrfachkodierung desselben Feldes getrennt werden.

Eine Ebene der Prozentkodierung
Prozentkodierung stellt Bytes durch % und zwei Hexadezimalziffern dar. Innerhalb eines Abfragewertes kann ein Leerzeichen als %20, ein Kaufmannsund als %26 und UTF-8-ü als %C3%BC erscheinen. Ein Kaufmannsund zwischen Abfrageparametern hat dagegen eine strukturelle Aufgabe und bleibt Trennzeichen.
encodeURIComponent macht aus dem Prozentzeichen eines bereits kodierten Textes %25. Bei bekanntem Rohwert und genau einem anschließenden Dekodierungsschritt ist das Ergebnis vorhersehbar:
| Endgültiger Abfragewert | Nach einem Dekodierungsschritt |
|---|---|
Sommer%20Aktion | Sommer Aktion |
Sommer%2520Aktion | Sommer%20Aktion |
Sommer%252520Aktion | Sommer%2520Aktion |
Das sind kontrollierte Beispiele, keine Methode zum Zählen sämtlicher Verarbeitungsschritte einer Tracking-Kette. Ein korrekt gelesener äußerer Parameter entfernt die eigene Kodierungsebene. Ein Prozentzeichen im Bericht ist ein Prüfhinweis, kein Fehlerbeweis.
Eine korrekt verschachtelte Tracking-Adresse
Ein Klicktracker kann eine vollständige Zieladresse in einem Parameter wie u speichern. Dafür ist eine Kodierung der Zieladresse erforderlich, auch wenn darin bereits kodierte Abfragewerte stehen. Der Parser der äußeren Adresse stellt vor der Weiterleitung das ursprüngliche Ziel wieder her:
const destination = "https://shop.example/?utm_campaign=Sommer%20Aktion";
const tracker = new URL("https://click.example/r");
tracker.searchParams.set("u", destination);
const restored = tracker.searchParams.get("u");
console.log(restored === destination); // true
console.log(new URL(restored).searchParams.get("utm_campaign"));
// Sommer AktionDie äußere Adresse enthält Sommer%2520Aktion, das wiederhergestellte Ziel aber weiterhin das richtige Sommer%20Aktion. Der abschließend gelesene Kampagnenwert lautet Sommer Aktion. Ein Fehler entsteht erst bei einer Kodierung oder Dekodierung entgegen dem vereinbarten Format. Auch %26utm_source%3D innerhalb eines verschachtelten Parameters beweist deshalb keinen defekten Link.
Eine Zieladresse aus Rohwerten bauen
Die URL-API berücksichtigt Trennzeichen, vorhandene Parameter und das Fragment. Die folgenden Eingaben sind Rohwerte, keine bereits mit encodeURIComponent bearbeiteten Zeichenketten:
const url = new URL("https://shop.example/sommer?lang=de#details");
url.searchParams.set("utm_source", "newsletter");
url.searchParams.set("utm_medium", "email");
url.searchParams.set("utm_campaign", "Sommer Aktion");
url.searchParams.set("utm_content", "header & title");
console.log(url.href);
// https://shop.example/sommer?lang=de&utm_source=newsletter&utm_medium=email&utm_campaign=Sommer+Aktion&utm_content=header+%26+title#detailsURLSearchParams schreibt Leerzeichen als +. Ein echtes Plus wird als %2B geschrieben; A B und A+B bleiben unterscheidbar. Beim Lesen gelten die entsprechenden Formularregeln. Dagegen lässt decodeURIComponent("A+B") das Plus unverändert.
encodeURIComponent eignet sich für einzelne Bestandteile und maskiert Abfragetrenner wie & und =. Einige Satzzeichen einschließlich ! bleiben erhalten; die Funktion beschränkt unmaskierte Zeichen nicht streng auf die unreservierte Menge aus RFC 3986. encodeURI erhält strukturelle Trennzeichen und eignet sich nicht zum Kodieren eines beliebigen Parameterwertes. Um bereits durch URLSearchParams serialisierte Werte gehört keine zusätzliche Kodierung.
Die fehlerhafte Übergabestelle finden
Eine nachvollziehbare Prüfung protokolliert Rohwert, Ausgabe des Linkbauers, verschachteltes Ziel nach dem Lesen des äußeren Parameters, alle HTTP-Location-Header und die endgültige Zieladresse. Die ausgehende Analytics-Anfrage und deren dekodierte Parameter zeigen anschließend den tatsächlich gesendeten Wert. Browser-Netzwerkwerkzeuge erfassen zusätzlich JavaScript-Weiterleitungen, die curl nicht ausführt.
Bei einer freigegebenen Testadresse folgt curl -sS -L -D - -o /dev/null 'https://shop.example/test?utm_campaign=Sommer%20Aktion' den HTTP-Weiterleitungen per GET und zeigt Antwortheader. Das Beispiel gilt für eine Unix-Shell. -I würde HEAD verwenden, mit möglicherweise anderem Verhalten. Da ein Tracking-Link beim Test einen Klick erfassen kann, eignet sich eine Testkampagne.
Linkbauer, Klicktracker, CMS-Ausgabe und Serverweiterleitung sind mögliche Übergabestellen. HTML-Maskierung, etwa & in einem Attribut, ist eine andere Ebene als Prozentkodierung. Ein Filter auf % findet nur Verdachtsfälle; fehlende Parameter, echte Pluszeichen und bereits zusammengeführte Namen können unentdeckt bleiben.
Einen bestätigten Fall korrigieren
Die erste Korrektur gehört an die fehlerhafte Quelle oder Übergabestelle. Automatisches wiederholtes Dekodieren ist ungeeignet: Aus einem absichtlichen wörtlichen %20 kann ein Leerzeichen werden, und ein kodierter Trenner kann strukturelle Bedeutung bekommen. Ungültige Fluchtfolgen können außerdem in decodeURIComponent eine Ausnahme auslösen.
Eine vorübergehende GTM-Zuordnung kann auf exakt bestätigte Eingabewerte begrenzt werden. Das Beispiel setzt voraus, dass die Vorschau den Rückgabewert von URL - utm_campaign beim gewählten Ereignis bestätigt und beide aufgeführten Schreibweisen nachweislich dieselbe Kampagne bezeichnen:
function () {
var value = {{URL - utm_campaign}};
var approved = {
"Sommer%20Aktion": "Sommer Aktion",
"Sommer%2520Aktion": "Sommer Aktion"
};
if (typeof value !== "string") { return undefined; }
return Object.prototype.hasOwnProperty.call(approved, value)
? approved[value] : value;
}Die Variable liefert lediglich Text. Die Anwendung braucht eine ausdrückliche Erfassungskonfiguration, beispielsweise das dokumentierte Feld campaign_name, bevor das relevante Google-Tag Kampagnendaten erfasst. Dieses Feld überschreibt utm_campaign; ein später gesendetes Tag repariert keine Sitzung rückwirkend. Kampagnenbezug, automatisches Tagging und weitere Herkunftsfelder müssen zusammenpassen. GA4-Regeln zur Ereignisänderung sind kein allgemeiner rekursiver URL-Dekodierer und ändern keine historischen Daten.
Historische Korrekturen umkehrbar halten
Eine dokumentierte Zuordnung in einer Auswertungsansicht erhält Rohwerte und gruppiert bestätigte Varianten. Das SQL-Beispiel benötigt eine vorbereitete Tabelle mit genau einer Zeile je Sitzung sowie geprüfter Quelle, Medium, Kampagne und Sitzungsdatum. Zeitraum und Schreibweisen sind Beispiele und müssen zum nachgewiesenen Vorfall passen:
SELECT
CASE
WHEN source = 'newsletter' AND medium = 'email'
AND campaign IN ('Sommer%20Aktion', 'Sommer%2520Aktion')
THEN 'Sommer Aktion'
ELSE campaign
END AS campaign_clean,
COUNT(*) AS session_rows
FROM `project.dataset.verified_sessions`
WHERE session_date BETWEEN DATE '2026-07-01' AND DATE '2026-08-31'
GROUP BY campaign_clean
ORDER BY session_rows DESC;COUNT(*) zählt Zeilen. Direkt auf einem GA4-Ereignisexport würde dasselbe Muster Ereignisse statt Sitzungen zählen. Ein Vergleich oder Segment kann Varianten auswählen, ohne die ursprüngliche Dimension umzubenennen. Korrigierte Auswertungsnamen sollten von erfassten Werten unterscheidbar bleiben.
Fragen und Antworten
Sind echte Prozent- oder Pluszeichen in Kampagnennamen zulässig?
Ja. Rohwerte wie 20%-rabatt und A+B lassen sich korrekt kodieren. Auch ein wörtliches %20 kann beabsichtigt sein. Eine dokumentierte Namenskonvention vereinfacht die Verarbeitung, ersetzt aber keine korrekte Kodierung und beweist keinen Fehler in einem historischen Namen.
Behebt das Apache-Flag NE den Fehler immer?
Nein. Apache kann bei einer externen Weiterleitung die Ersetzung maskieren, einschließlich bereits vorhandener Prozentzeichen. [NE] unterdrückt diese Maskierung, kann aber auch Zeichen wie # mit struktureller Bedeutung freigeben. Query-Übernahme, Ersetzung, Rückverweise und Flags gehören gemeinsam geprüft. Eine Weiterleitung kann Abfragewerte erhalten, ersetzen oder verwerfen; die tatsächlichen Location-Header liefern den Nachweis. Produktionsregeln sollten NE nicht pauschal erhalten.
Verstehen durch Ausprobieren
Was passiert beim zweiten Kodieren?
Wähle einen Kampagnenwert und die Zahl der Kodierungen. Vergleiche den URL-Wert mit dem Ergebnis nach genau einem Dekodierschritt.
- Original
- Wert in der URL
- Nach einem Dekodierschritt
Gezeigt wird Prozentkodierung eines einzelnen Werts, nicht einer ganzen URL. Formularkodierung wie bei URLSearchParams kann Leerzeichen als + darstellen. Echte Prozentzeichen sind erlaubt; % im Namen beweist allein keinen Fehler.
Dieses Modul rechnet im Browser und sendet oder speichert Deine Eingaben nicht.
Verstehen durch Ausprobieren
Eine Minute: Findest Du den Denkfehler?
Aus Sommer Aktion wird Sommer%2520Aktion in der URL. Was bleibt nach einmaligem Dekodieren?
%25 wird zu einem echten Prozentzeichen. Der Text %20 bleibt stehen. Ein weiterer Dekodierschritt ergäbe ein Leerzeichen; besser ist es, den unnötigen Kodierdurchgang beim Erzeugen des Links zu entfernen.