Tutorial: Rozpoznawanie i naprawa podwójnie zakodowanych parametrów UTM

Management Summary
Parametry UTM to oznaczenia dodawane do linków, dzięki którym analityka rozpoznaje kampanię stojącą za wizytą. Zbyt wielokrotne przekształcenie zapisu na format odpowiedni dla linku może rozbić jedną kampanię na kilka nazw i zniekształcić porównania. Problem bywa skutkiem budowy linków lub przekierowań. Naprawa przyczyny porządkuje przyszłe raporty, a starsze warianty można połączyć z zachowaniem oryginalnych danych. Same nietypowe znaki procentowe nie dowodzą błędu.
Przejdź do interaktywnego przykładu ↓
Spis treści
Kampania oczekiwana jako Sommer Aktion pojawia się jako Sommer%20Aktion. Podwójne kodowanie jest możliwą przyczyną, lecz sam raport nie wskazuje wadliwego etapu ani nie dowodzi poprawnej atrybucji. Podobny wynik może dać dosłowna sekwencja procentowa, brak dekodowania albo jawnie ustawiona wartość kampanii.
Wiarygodna diagnoza porównuje zamierzoną wartość surową, wygenerowany link, cele przekierowań i faktycznie zebraną wartość. Poprawne zagnieżdżenie adresu w innym adresie wymaga odróżnienia od niezamierzonego wielokrotnego kodowania tego samego pola.

Jedna warstwa kodowania procentowego
Kodowanie procentowe zapisuje bajty jako % i dwie cyfry szesnastkowe. W wartości parametru spacja może wystąpić jako %20, ampersand jako %26, a ü w UTF-8 jako %C3%BC. Ampersand między parametrami pełni natomiast funkcję strukturalną i pozostaje separatorem.
Użycie encodeURIComponent na już zakodowanym tekście zmienia znak procentu w %25. Przy znanej wartości surowej i dokładnie jednym późniejszym dekodowaniu wynik jest przewidywalny:
| Końcowa wartość parametru | Po jednym dekodowaniu |
|---|---|
Sommer%20Aktion | Sommer Aktion |
Sommer%2520Aktion | Sommer%20Aktion |
Sommer%252520Aktion | Sommer%2520Aktion |
To kontrolowane przykłady, a nie metoda liczenia wszystkich operacji w łańcuchu pomiarowym. Poprawnie odczytany parametr zewnętrzny usuwa własną warstwę kodowania. Znak procentu w raporcie jest wskazówką do kontroli, nie dowodem błędu.
Poprawnie zagnieżdżony adres pomiarowy
System pomiaru kliknięć może przechowywać pełny adres docelowy w parametrze takim jak u. Zakodowanie tego adresu jest konieczne również wtedy, gdy adres zawiera już zakodowane wartości parametrów. Parser adresu zewnętrznego przywraca oryginalny cel przed przekierowaniem:
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 AktionAdres zewnętrzny zawiera Sommer%2520Aktion, lecz przywrócony cel nadal zawiera poprawne Sommer%20Aktion. Końcowa wartość kampanii to Sommer Aktion. Błąd powstaje dopiero przy kodowaniu lub dekodowaniu niezgodnym z ustalonym formatem. Obecność %26utm_source%3D wewnątrz zagnieżdżonego parametru nie dowodzi więc uszkodzenia linku.
Budowa adresu docelowego z surowych wartości
API URL obsługuje separatory, istniejące parametry i fragment. Poniższe dane wejściowe są wartościami surowymi, a nie tekstem wcześniej przetworzonym przez encodeURIComponent:
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 zapisuje spacje jako +. Dosłowny plus zostaje zapisany jako %2B, dlatego A B i A+B pozostają rozróżnialne. Odczyt stosuje odpowiadające reguły formularzowe. Natomiast decodeURIComponent("A+B") pozostawia plus bez zmian.
encodeURIComponent nadaje się do pojedynczych składników i koduje separatory takie jak & oraz =. Część znaków, w tym !, pozostaje niezakodowana; funkcja nie ogranicza takich znaków ściśle do zbioru niezastrzeżonego z RFC 3986. encodeURI zachowuje separatory strukturalne i nie nadaje się do kodowania dowolnej wartości parametru. Wartości zserializowane przez URLSearchParams nie wymagają dodatkowego kodowania.
Odnalezienie wadliwego etapu
Praktyczna kontrola zapisuje wartość surową, wynik kreatora linków, zagnieżdżony cel po odczycie parametru zewnętrznego, wszystkie nagłówki HTTP Location oraz końcowy adres docelowy. Wychodzące żądanie Analytics i zdekodowane parametry pokazują następnie faktycznie wysłaną wartość. Narzędzia sieciowe przeglądarki uwzględniają też przekierowania JavaScript, których curl nie wykonuje.
Dla zatwierdzonego adresu testowego polecenie curl -sS -L -D - -o /dev/null 'https://shop.example/test?utm_campaign=Sommer%20Aktion' śledzi przekierowania HTTP metodą GET i pokazuje nagłówki odpowiedzi. To przykład dla powłoki Unix. Opcja -I używałaby HEAD, co może dać inne zachowanie. Test linku pomiarowego może rejestrować kliknięcie, dlatego odpowiednia jest kampania testowa.
Kreator linków, system pomiaru kliknięć, wyjście CMS i przekierowanie serwera są możliwymi miejscami błędu. Maskowanie HTML, na przykład & w atrybucie, stanowi oddzielną warstwę względem kodowania procentowego. Filtr % wskazuje tylko podejrzane wartości; brakujące parametry, dosłowne plusy i już połączone nazwy mogą pozostać niewidoczne.
Naprawa potwierdzonego przypadku
Pierwsza poprawka powinna trafić do wadliwego źródła lub etapu przekazania danych. Automatyczne wielokrotne dekodowanie jest niewłaściwe: zamierzone dosłowne %20 może stać się spacją, a zakodowany separator uzyskać znaczenie strukturalne. Błędne sekwencje mogą też wywołać wyjątek w decodeURIComponent.
Tymczasowe mapowanie GTM można ograniczyć do dokładnych, potwierdzonych wartości wejściowych. Przykład zakłada, że podgląd potwierdził wynik URL - utm_campaign dla wybranego zdarzenia, a obie podane pisownie rzeczywiście oznaczają tę samą kampanię:
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;
}Zmienna zwraca tylko tekst. Zastosowanie wyniku wymaga jawnej konfiguracji zbierania, na przykład udokumentowanego pola campaign_name, zanim odpowiedni tag Google zbierze dane kampanii. To pole nadpisuje utm_campaign; późniejszy tag nie naprawia sesji wstecznie. Zakres kampanii, automatyczne tagowanie i pozostałe pola pozyskania muszą być spójne. Reguły modyfikacji zdarzeń GA4 nie są uniwersalnym rekurencyjnym dekoderem URL i nie zmieniają danych historycznych.
Odwracalne poprawki danych historycznych
Udokumentowane mapowanie w widoku analitycznym zachowuje surowe wartości i grupuje potwierdzone warianty. Przykład SQL wymaga przygotowanej tabeli z dokładnie jednym wierszem na sesję oraz sprawdzonym źródłem, medium, kampanią i datą sesji. Zakres dat i pisownie są przykładowe i muszą odpowiadać potwierdzonemu incydentowi:
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(*) liczy wiersze. Ten sam wzorzec użyty bezpośrednio na eksporcie zdarzeń GA4 liczyłby zdarzenia, nie sesje. Porównanie lub segment może wybrać warianty bez zmiany nazwy oryginalnego wymiaru. Poprawione etykiety analityczne powinny pozostać odróżnialne od wartości zebranych.
Pytania i odpowiedzi
Czy rzeczywisty procent lub plus jest dozwolony w nazwie kampanii?
Tak. Surowe 20%-taniej i A+B można poprawnie zakodować. Nawet dosłowne %20 może być zamierzone. Udokumentowana konwencja nazewnicza upraszcza obsługę, ale nie zastępuje poprawnego kodowania ani nie dowodzi błędu historycznej nazwy.
Czy flaga Apache NE zawsze naprawia problem?
Nie. Apache może maskować wynik podstawienia dla przekierowania zewnętrznego, włącznie z obecnymi znakami procentu. [NE] wyłącza to maskowanie, ale może również odsłonić znaki takie jak # o znaczeniu strukturalnym. Kopiowanie zapytania, podstawienia, odwołania wsteczne i flagi wymagają wspólnej oceny. Przekierowanie może zachować, zastąpić albo usunąć zapytanie; dowód zapewniają rzeczywiste nagłówki Location. Reguły produkcyjne nie powinny otrzymywać NE bez analizy.
Zrozum przez eksperyment
Co się dzieje przy ponownym kodowaniu?
Wybierz wartość kampanii i liczbę kodowań. Porównaj wartość w URL z wynikiem dokładnie jednego dekodowania.
- Oryginał
- Wartość w URL
- Po jednym dekodowaniu
Przykład kodowania procentowego jednej wartości, nie całego URL. Kodowanie formularzy, np. URLSearchParams, może zapisywać spacje jako +. Znak % może być częścią nazwy i sam nie dowodzi błędu.
Ten moduł działa w przeglądarce i nie wysyła ani nie zapisuje wpisanych danych.
Zrozum przez eksperyment
Jedna minuta: znajdziesz błąd?
Letnia akcja zmienia się w Letnia%2520akcja w URL. Co zostaje po jednym dekodowaniu?
%25 staje się znakiem procentu. Tekst %20 pozostaje. Kolejne dekodowanie dałoby spację; lepiej usunąć zbędne kodowanie podczas tworzenia odnośnika.