{"id":10232,"date":"2026-08-15T00:13:10","date_gmt":"2026-08-14T22:13:10","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/toolbox\/ga4-channel-grouping-debugger\/"},"modified":"2026-08-15T00:13:10","modified_gmt":"2026-08-14T22:13:10","slug":"ga4-channel-grouping-debugger","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/","title":{"rendered":"GA4 Channel Grouping &#038; Unassigned Debugger"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">GA4 walks eighteen rules from top to bottom and takes the first one that matches. This tool runs the same chain on a landing page URL or on hand-typed values and marks the rule that decided the outcome.<\/p>\n<p>    <label for=\"cg-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Landing page URL (optional, fills the fields below)<\/label><br \/>\n    <input type=\"text\" id=\"cg-url\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; font-size: 0.85rem; box-sizing: border-box;\" placeholder=\"https:\/\/example.com\/page?utm_source=newsletter&amp;utm_medium=email\"><\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 15px;\">\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"cg-quelle\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">utm_source<\/label><br \/>\n            <input type=\"text\" id=\"cg-quelle\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" placeholder=\"google\">\n        <\/div>\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"cg-medium\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">utm_medium<\/label><br \/>\n            <input type=\"text\" id=\"cg-medium\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" placeholder=\"cpc\">\n        <\/div>\n<div style=\"flex: 1; min-width: 170px;\">\n            <label for=\"cg-kampagne\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">utm_campaign<\/label><br \/>\n            <input type=\"text\" id=\"cg-kampagne\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" placeholder=\"summer_sale\">\n        <\/div>\n<div style=\"flex: 1; min-width: 200px;\">\n            <label for=\"cg-kategorie\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Source category<\/label><br \/>\n            <select id=\"cg-kategorie\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\"><option value=\"auto\">detect automatically<\/option><option value=\"none\">none or unknown source<\/option><option value=\"SEARCH\">search site<\/option><option value=\"SOCIAL\">social site<\/option><option value=\"VIDEO\">video site<\/option><option value=\"SHOPPING\">shopping site<\/option><\/select>\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 0;\">\n        <button id=\"cg-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Determine channel<\/button><br \/>\n        <button id=\"cg-beispiel\" class=\"button\" type=\"button\" style=\"background: transparent; color: var(--text-primary, #e8e8ee); border: 1px solid var(--border, #2a2a35); padding: 12px 20px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Load example<\/button>\n    <\/div>\n<div id=\"cg-ergebnis\" style=\"margin-top: 22px;\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"GA4 walks eighteen rules from top to bottom and takes the first one that matches. This tool runs the same chain on a landing page URL or on hand-typed values and marks the rule that decided the outcome.\",\"label_url\":\"Landing page URL (optional, fills the fields below)\",\"ph_url\":\"https:\\\/\\\/example.com\\\/page?utm_source=newsletter\\u0026utm_medium=email\",\"label_quelle\":\"utm_source\",\"label_medium\":\"utm_medium\",\"label_kampagne\":\"utm_campaign\",\"label_kategorie\":\"Source category\",\"kat_auto\":\"detect automatically\",\"kat_keine\":\"none or unknown source\",\"kat_suche\":\"search site\",\"kat_social\":\"social site\",\"kat_video\":\"video site\",\"kat_shopping\":\"shopping site\",\"knopf\":\"Determine channel\",\"beispiel\":\"Load example\",\"fehler_url_leer\":\"No URL was entered.\",\"fehler_keine_parameter\":\"The URL carries no query string, so there is nothing to read.\",\"ergebnis_kopf\":\"Default channel group\",\"ergebnis_stelle\":\"Decided by rule %s - the first match wins, the rules below it are never evaluated.\",\"grund_unassigned\":\"Not one of the eighteen rules matched, so the session lands in Unassigned.\",\"h_werte\":\"Values used\",\"h_hinweise\":\"Findings\",\"h_regeln\":\"Rule chain\",\"regeln_erklaerung\":\"Plus marks a rule that matches. The highlighted row is the one GA4 stops at.\",\"l_kategorie\":\"Source category\",\"r_direct\":\"Source is (direct) and medium is (none) or (not set).\",\"r_crossnetwork\":\"The campaign name contains cross-network.\",\"r_paidshopping\":\"Source is a shopping site or the campaign name looks like shopping, and the medium is a paid one.\",\"r_paidsearch\":\"Source is a search site and the medium is a paid one.\",\"r_paidsocial\":\"Source is a social site and the medium is a paid one.\",\"r_paidvideo\":\"Source is a video site and the medium is a paid one.\",\"r_display\":\"Medium is display, banner, expandable, interstitial or cpm.\",\"r_paidother\":\"The medium matches the paid pattern: anything containing cp, plus ppc, retargeting and everything starting with paid.\",\"r_orgshopping\":\"Source is a shopping site or the campaign name looks like shopping.\",\"r_orgsocial\":\"Source is a social site or the medium is social, social-network, social-media or sm.\",\"r_orgvideo\":\"Source is a video site or the medium contains video.\",\"r_orgsearch\":\"Source is a search site or the medium is organic.\",\"r_referral\":\"Medium is referral, app or link.\",\"r_email\":\"Source or medium is email, e-mail, e_mail or e mail.\",\"r_affiliate\":\"Medium is affiliate.\",\"r_audio\":\"Medium is audio.\",\"r_sms\":\"Source or medium is sms.\",\"r_push\":\"Medium ends in push or contains mobile or notification, or the source is firebase.\",\"h_gclid\":\"gclid, gbraid or wbraid is present: with auto-tagging switched on GA4 derives google \\\/ cpc even without utm parameters.\",\"h_msclkid\":\"msclkid is present: auto-tagging in Microsoft Advertising leads to bing \\\/ cpc.\",\"h_fbclid\":\"fbclid is only a click identifier of Meta. GA4 derives no source from it, so the session stays a referral from facebook.com or falls back to direct.\",\"h_utmid\":\"utm_id without utm_source: the identifier alone creates no source and never reaches the channel grouping.\",\"h_leerzeichen\":\"%s carries a leading or trailing space, which becomes part of the stored value.\",\"h_grossbuchstaben\":\"%s contains capital letters. GA4 stores them unchanged, so Email and email end up as two separate rows.\",\"h_medium_fehlt\":\"utm_medium is missing while utm_source is set. That is the most frequent cause of Unassigned.\",\"h_quelle_fehlt\":\"utm_source is missing. Without a source the medium alone rarely produces a channel.\",\"h_tippfehler\":\"The medium %s is not a value GA4 recognises, which usually means a typing error.\",\"hinweis_namen\":\"Channel names appear as the Data API and the BigQuery export return them. The GA4 interface translates them into the report language. The source categories held here are an excerpt of the list Google publishes - for a source that is missing, the category can be set by hand.\"};<\/p>\n<p>    \/\/ --- reine Auswertung, ohne Zugriff auf das Dokument ---<\/p>\n<p>    \/\/ Auszug aus den Quellkategorien von Google. Die vollstaendige Liste hat\n    \/\/ ueber tausend Eintraege; wer eine fehlende Quelle pruefen will, stellt\n    \/\/ die Kategorie von Hand ein.\n    const KATEGORIEN = {\n        SEARCH: ['google', 'bing', 'yahoo', 'duckduckgo', 'baidu', 'yandex', 'ecosia', 'ask',\n            'aol', 'brave', 'startpage', 'seznam', 'naver', 'qwant', 'sogou', 'msn', 'lycos',\n            'search.google.com', 'google.com', 'bing.com', 'duckduckgo.com', 'yandex.ru'],\n        SOCIAL: ['facebook', 'instagram', 'twitter', 't.co', 'linkedin', 'pinterest', 'reddit',\n            'tiktok', 'snapchat', 'vk.com', 'weibo', 'quora', 'tumblr', 'threads', 'xing',\n            'facebook.com', 'instagram.com', 'linkedin.com', 'l.facebook.com', 'lm.facebook.com',\n            'm.facebook.com', 'pinterest.com', 'tiktok.com', 'reddit.com'],\n        VIDEO: ['youtube', 'vimeo', 'dailymotion', 'twitch', 'youtube.com', 'm.youtube.com', 'vimeo.com', 'twitch.tv'],\n        SHOPPING: ['amazon', 'ebay', 'etsy', 'alibaba', 'aliexpress', 'walmart', 'shopify',\n            'allegro', 'otto', 'amazon.com', 'amazon.de', 'ebay.com', 'ebay.de', 'etsy.com', 'allegro.pl']\n    };<\/p>\n<p>    \/\/ Die bezahlten Medien nach der Regel von Google: alles mit \"cp\" darin,\n    \/\/ dazu ppc, retargeting und alles, was mit paid beginnt.\n    const BEZAHLT = \/^(.*cp.*|ppc|retargeting|paid.*)$\/;\n    const EINKAUF_KAMPAGNE = \/^(.*(([^a-df-z]|^)shop|shopping).*)$\/;\n    const ANZEIGE = ['display', 'banner', 'expandable', 'interstitial', 'cpm'];\n    const SOZIAL_MEDIUM = ['social', 'social-network', 'social-media', 'sm', 'social network', 'social media'];\n    const EMPFEHLUNG = ['referral', 'app', 'link'];\n    const POST = ['email', 'e-mail', 'e_mail', 'e mail'];<\/p>\n<p>    function klein(wert) {\n        return String(wert === undefined || wert === null ? '' : wert).trim().toLowerCase();\n    }<\/p>\n<p>    function kategorieVon(quelle) {\n        const q = klein(quelle);\n        if (q === '') { return ''; }\n        const namen = Object.keys(KATEGORIEN);\n        for (let i = 0; i < namen.length; i++) {\n            const liste = KATEGORIEN[namen[i]];\n            for (let j = 0; j < liste.length; j++) {\n                const eintrag = liste[j];\n                \/\/ Treffer bei genauer Gleichheit oder wenn die Quelle den\n                \/\/ Namen als Wortbestandteil einer Domain traegt.\n                if (q === eintrag || q === eintrag + '.com' || q.indexOf(eintrag + '.') === 0 || q.indexOf('.' + eintrag + '.') !== -1) {\n                    return namen[i];\n                }\n            }\n        }\n        return '';\n    }\n\n    \/**\n     * Die Reihenfolge ist die eigentliche Aussage: GA4 nimmt die erste Regel,\n     * die zutrifft, und hoert dann auf. Deshalb steht hier jede Regel als\n     * eigener Eintrag mit ihrer Bedingung.\n     *\/\n    function regeln(quelle, medium, kampagne, kategorie) {\n        const q = klein(quelle);\n        const m = klein(medium);\n        const k = klein(kampagne);\n        const kat = kategorie || kategorieVon(q);\n        const bezahlt = BEZAHLT.test(m);\n\n        return [\n            { name: 'Direct', bedingung: T.r_direct,\n              trifft: (q === '(direct)' || q === 'direct' || q === '') &#038;&#038; (m === '(none)' || m === '(not set)' || m === 'none' || m === '') },\n            { name: 'Cross-network', bedingung: T.r_crossnetwork,\n              trifft: k.indexOf('cross-network') !== -1 },\n            { name: 'Paid Shopping', bedingung: T.r_paidshopping,\n              trifft: (kat === 'SHOPPING' || EINKAUF_KAMPAGNE.test(k)) &#038;&#038; bezahlt },\n            { name: 'Paid Search', bedingung: T.r_paidsearch,\n              trifft: kat === 'SEARCH' &#038;&#038; bezahlt },\n            { name: 'Paid Social', bedingung: T.r_paidsocial,\n              trifft: kat === 'SOCIAL' &#038;&#038; bezahlt },\n            { name: 'Paid Video', bedingung: T.r_paidvideo,\n              trifft: kat === 'VIDEO' &#038;&#038; bezahlt },\n            { name: 'Display', bedingung: T.r_display,\n              trifft: ANZEIGE.indexOf(m) !== -1 },\n            { name: 'Paid Other', bedingung: T.r_paidother,\n              trifft: bezahlt },\n            { name: 'Organic Shopping', bedingung: T.r_orgshopping,\n              trifft: kat === 'SHOPPING' || EINKAUF_KAMPAGNE.test(k) },\n            { name: 'Organic Social', bedingung: T.r_orgsocial,\n              trifft: kat === 'SOCIAL' || SOZIAL_MEDIUM.indexOf(m) !== -1 },\n            { name: 'Organic Video', bedingung: T.r_orgvideo,\n              trifft: kat === 'VIDEO' || \/video\/.test(m) },\n            { name: 'Organic Search', bedingung: T.r_orgsearch,\n              trifft: kat === 'SEARCH' || m === 'organic' },\n            { name: 'Referral', bedingung: T.r_referral,\n              trifft: EMPFEHLUNG.indexOf(m) !== -1 },\n            { name: 'Email', bedingung: T.r_email,\n              trifft: POST.indexOf(q) !== -1 || POST.indexOf(m) !== -1 },\n            { name: 'Affiliates', bedingung: T.r_affiliate,\n              trifft: m === 'affiliate' },\n            { name: 'Audio', bedingung: T.r_audio,\n              trifft: m === 'audio' },\n            { name: 'SMS', bedingung: T.r_sms,\n              trifft: q === 'sms' || m === 'sms' },\n            { name: 'Mobile Push Notifications', bedingung: T.r_push,\n              trifft: m.length >= 4 && m.slice(-4) === 'push' || m.indexOf('mobile') !== -1 || m.indexOf('notification') !== -1 || q === 'firebase' }\n        ];\n    }<\/p>\n<p>    function ausUrl(url) {\n        const raus = { ok: false, fehler: '', parameter: {}, quelle: '', medium: '', kampagne: '', hinweise: [] };\n        const roh = String(url === undefined || url === null ? '' : url).trim();\n        if (roh === '') { raus.fehler = T.fehler_url_leer; return raus; }<\/p>\n<p>        let abfrage = '';\n        const fragezeichen = roh.indexOf('?');\n        if (fragezeichen !== -1) {\n            abfrage = roh.slice(fragezeichen + 1);\n            const raute = abfrage.indexOf('#');\n            if (raute !== -1) { abfrage = abfrage.slice(0, raute); }\n        }\n        if (abfrage === '') { raus.fehler = T.fehler_keine_parameter; return raus; }<\/p>\n<p>        abfrage.split('&').forEach(function (paar) {\n            if (paar === '') { return; }\n            const teil = paar.split('=');\n            const name = decodeURIComponent(teil[0].replace(\/\\+\/g, ' '));\n            const wert = teil.length > 1 ? decodeURIComponent(teil.slice(1).join('=').replace(\/\\+\/g, ' ')) : '';\n            raus.parameter[name] = wert;\n        });<\/p>\n<p>        const p = raus.parameter;\n        raus.quelle = p.utm_source || '';\n        raus.medium = p.utm_medium || '';\n        raus.kampagne = p.utm_campaign || '';<\/p>\n<p>        \/\/ Automatische Kennzeichnung: die Klickkennungen setzen Quelle und\n        \/\/ Medium, ohne dass utm-Parameter noetig waeren.\n        if (!raus.quelle && (p.gclid || p.gbraid || p.wbraid)) {\n            raus.quelle = 'google';\n            raus.medium = raus.medium || 'cpc';\n            raus.hinweise.push(T.h_gclid);\n        }\n        if (!raus.quelle && p.msclkid) {\n            raus.quelle = 'bing';\n            raus.medium = raus.medium || 'cpc';\n            raus.hinweise.push(T.h_msclkid);\n        }\n        if (p.fbclid && !p.utm_source) {\n            raus.hinweise.push(T.h_fbclid);\n        }\n        if (p.utm_id && !p.utm_source) {\n            raus.hinweise.push(T.h_utmid);\n        }\n        raus.ok = true;\n        return raus;\n    }<\/p>\n<p>    function pruefeWerte(quelle, medium, kampagne) {\n        const hinweise = [];\n        const roh = { quelle: String(quelle || ''), medium: String(medium || ''), kampagne: String(kampagne || '') };<\/p>\n<p>        Object.keys(roh).forEach(function (feld) {\n            const wert = roh[feld];\n            if (wert !== wert.trim()) {\n                hinweise.push(T.h_leerzeichen.replace('%s', feld === 'quelle' ? 'utm_source' : (feld === 'medium' ? 'utm_medium' : 'utm_campaign')));\n            }\n            if (wert.trim() !== '' && wert !== wert.toLowerCase()) {\n                hinweise.push(T.h_grossbuchstaben.replace('%s', feld === 'quelle' ? 'utm_source' : (feld === 'medium' ? 'utm_medium' : 'utm_campaign')));\n            }\n        });<\/p>\n<p>        const q = klein(quelle);\n        const m = klein(medium);\n        if (q !== '' && m === '') { hinweise.push(T.h_medium_fehlt); }\n        if (q === '' && m !== '') { hinweise.push(T.h_quelle_fehlt); }\n        if (m === 'referal' || m === 'referrer') { hinweise.push(T.h_tippfehler.replace('%s', m)); }\n        if (m === 'cpc ' || m === 'ppc.') { hinweise.push(T.h_tippfehler.replace('%s', m)); }\n        if (m === 'social' && q === '') { hinweise.push(T.h_quelle_fehlt); }\n        if (m === 'email' && q === '') { hinweise.push(T.h_quelle_fehlt); }\n        return hinweise;\n    }<\/p>\n<p>    function bestimmen(quelle, medium, kampagne, kategorie) {\n        const liste = regeln(quelle, medium, kampagne, kategorie === 'auto' || !kategorie ? '' : (kategorie === 'none' ? 'KEINE' : kategorie));\n        let kanal = 'Unassigned';\n        let grund = T.grund_unassigned;\n        let stelle = -1;\n        for (let i = 0; i < liste.length; i++) {\n            if (liste[i].trifft) {\n                kanal = liste[i].name;\n                grund = liste[i].bedingung;\n                stelle = i;\n                break;\n            }\n        }\n        return {\n            kanal: kanal,\n            grund: grund,\n            stelle: stelle,\n            regeln: liste,\n            kategorie: kategorie === 'auto' || !kategorie ? kategorieVon(quelle) : (kategorie === 'none' ? '' : kategorie),\n            hinweise: pruefeWerte(quelle, medium, kampagne)\n        };\n    }\n\n    if (typeof window !== 'undefined') {\n        window.LW_TEST = window.LW_TEST || {};\n        window.LW_TEST.CG = {\n            bestimmen: bestimmen,\n            ausUrl: ausUrl,\n            kategorieVon: kategorieVon,\n            regeln: regeln\n        };\n    }\n\n    \/\/ --- Anbindung an das Dokument ---\n\n    const btn = document.getElementById('cg-btn');\n    const out = document.getElementById('cg-ergebnis');\n    const urlFeld = document.getElementById('cg-url');\n    const quelleFeld = document.getElementById('cg-quelle');\n    const mediumFeld = document.getElementById('cg-medium');\n    const kampagneFeld = document.getElementById('cg-kampagne');\n    const katFeld = document.getElementById('cg-kategorie');\n    const beispielBtn = document.getElementById('cg-beispiel');\n    if (!btn || !out || !urlFeld || !quelleFeld || !mediumFeld || !kampagneFeld || !katFeld || !beispielBtn) { return; }\n\n    const KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 14px; margin-bottom: 18px;';\n    const UEBERSCHRIFT = 'color: var(--text-primary, #e8e8ee); font-weight: 700; margin-bottom: 8px;';\n\n    function el(tag, css, text) {\n        const knoten = document.createElement(tag);\n        if (css) { knoten.setAttribute('style', css); }\n        if (text !== undefined &#038;&#038; text !== null) { knoten.textContent = text; }\n        return knoten;\n    }\n\n    function zeile(kasten, name, wert) {\n        const z = el('div', 'display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; padding: 5px 0;');\n        z.appendChild(el('span', 'color: var(--text-secondary, #a0a0b0);', name));\n        z.appendChild(el('span', 'color: var(--text-primary, #e8e8ee); font-family: monospace; text-align: right; word-break: break-all;', wert));\n        kasten.appendChild(z);\n    }\n\n    function zeigen(erg, quelle, medium, kampagne) {\n        out.textContent = '';\n\n        const treffer = erg.kanal !== 'Unassigned';\n        const kopf = el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid ' + (treffer ? 'var(--accent, #7ee787)' : '#ffb86c') + '; border-radius: 6px; padding: 18px; margin-bottom: 18px;');\n        kopf.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.85rem;', T.ergebnis_kopf));\n        kopf.appendChild(el('div', 'color: ' + (treffer ? 'var(--accent, #7ee787)' : '#ffb86c') + '; font-size: 1.5rem; font-weight: 700; font-family: monospace; margin: 4px 0 8px;', erg.kanal));\n        kopf.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.9rem;', erg.grund));\n        if (erg.stelle >= 0) {\n            kopf.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; margin-top: 6px;', T.ergebnis_stelle.replace('%s', String(erg.stelle + 1))));\n        }\n        out.appendChild(kopf);<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_werte));\n        const werte = el('div', KASTEN);\n        zeile(werte, 'utm_source', quelle === '' ? '(not set)' : quelle);\n        zeile(werte, 'utm_medium', medium === '' ? '(not set)' : medium);\n        zeile(werte, 'utm_campaign', kampagne === '' ? '(not set)' : kampagne);\n        zeile(werte, T.l_kategorie, erg.kategorie === '' ? T.kat_keine : erg.kategorie);\n        out.appendChild(werte);<\/p>\n<p>        if (erg.hinweise.length) {\n            out.appendChild(el('div', UEBERSCHRIFT, T.h_hinweise));\n            const kasten = el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid #ffb86c; border-radius: 6px; padding: 14px; margin-bottom: 18px;');\n            erg.hinweise.forEach(function (h) {\n                kasten.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); padding: 4px 0; font-size: 0.9rem;', h));\n            });\n            out.appendChild(kasten);\n        }<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_regeln));\n        out.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; margin-bottom: 10px;', T.regeln_erklaerung));\n        const tabelle = el('div', KASTEN);\n        erg.regeln.forEach(function (r, i) {\n            const genommen = i === erg.stelle;\n            const z = el('div', 'display: flex; gap: 12px; align-items: flex-start; padding: 7px 0; border-bottom: 1px solid var(--border, #2a2a35);' + (genommen ? ' background: rgba(126, 231, 135, 0.07);' : ''));\n            z.appendChild(el('span', 'width: 26px; color: var(--text-secondary, #a0a0b0); font-family: monospace; font-size: 0.8rem;', String(i + 1)));\n            z.appendChild(el('span', 'width: 22px; color: ' + (r.trifft ? 'var(--accent, #7ee787)' : 'var(--text-secondary, #a0a0b0)') + '; font-family: monospace;', r.trifft ? '+' : '-'));\n            const text = el('span', 'flex: 1;');\n            text.appendChild(el('div', 'color: ' + (genommen ? 'var(--accent, #7ee787)' : 'var(--text-primary, #e8e8ee)') + '; font-weight: ' + (genommen ? '700' : '400') + '; font-family: monospace; font-size: 0.88rem;', r.name));\n            text.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.82rem; line-height: 1.5;', r.bedingung));\n            z.appendChild(text);\n            tabelle.appendChild(z);\n        });\n        out.appendChild(tabelle);<\/p>\n<p>        out.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.85rem;', T.hinweis_namen));\n    }<\/p>\n<p>    function auswerten() {\n        let quelle = quelleFeld.value;\n        let medium = mediumFeld.value;\n        let kampagne = kampagneFeld.value;\n        let zusatz = [];<\/p>\n<p>        if (urlFeld.value.trim() !== '') {\n            const zerlegt = ausUrl(urlFeld.value);\n            if (!zerlegt.ok) {\n                out.textContent = '';\n                out.appendChild(el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid var(--accent, #7ee787); color: var(--text-secondary, #a0a0b0); padding: 14px; border-radius: 6px;', zerlegt.fehler));\n                return;\n            }\n            quelle = zerlegt.quelle;\n            medium = zerlegt.medium;\n            kampagne = zerlegt.kampagne;\n            quelleFeld.value = quelle;\n            mediumFeld.value = medium;\n            kampagneFeld.value = kampagne;\n            zusatz = zerlegt.hinweise;\n        }<\/p>\n<p>        const erg = bestimmen(quelle, medium, kampagne, katFeld.value);\n        erg.hinweise = zusatz.concat(erg.hinweise);\n        zeigen(erg, quelle, medium, kampagne);\n    }<\/p>\n<p>    btn.addEventListener('click', auswerten);<\/p>\n<p>    beispielBtn.addEventListener('click', function () {\n        urlFeld.value = 'https:\/\/www.example.com\/landing?utm_source=newsletter&utm_campaign=august';\n        quelleFeld.value = '';\n        mediumFeld.value = '';\n        kampagneFeld.value = '';\n        katFeld.value = 'auto';\n        auswerten();\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Shows which default channel group GA4 assigns to a source, medium and campaign, which of the eighteen rules matched, and why a session ends up in Unassigned.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[91297,91386,91258],"class_list":["post-10232","page","type-page","status-publish","hentry","tag-data-quality","tag-marketing-cyfrowy-pl","tag-google-analytics-4"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GA4 Channel Grouping &amp; Unassigned Debugger - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GA4 Channel Grouping &amp; Unassigned Debugger - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Shows which default channel group GA4 assigns to a source, medium and campaign, which of the eighteen rules matched, and why a session ends up in Unassigned.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/ga4-channel-grouping-debugger\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/ga4-channel-grouping-debugger\\\/\",\"name\":\"GA4 Channel Grouping & Unassigned Debugger - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-14T22:13:10+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/ga4-channel-grouping-debugger\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/ga4-channel-grouping-debugger\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/ga4-channel-grouping-debugger\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"GA4 Channel Grouping &#038; Unassigned Debugger\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GA4 Channel Grouping & Unassigned Debugger - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/","og_locale":"en_US","og_type":"article","og_title":"GA4 Channel Grouping & Unassigned Debugger - Lukas Wojcik - Blog","og_description":"Shows which default channel group GA4 assigns to a source, medium and campaign, which of the eighteen rules matched, and why a session ends up in Unassigned.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/","og_site_name":"Lukas Wojcik - Blog","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/","name":"GA4 Channel Grouping & Unassigned Debugger - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-14T22:13:10+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-channel-grouping-debugger\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"GA4 Channel Grouping &#038; Unassigned Debugger"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10232","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=10232"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10232\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=10232"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=10232"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}