Vrací Google díky AI klíčová slova zpět do GA4?
Téměř ano, jen jsou to celé věty. Možná si myslíš, že éra „not provided“ v analytice je definitivně za námi. Možná taky ne.
Ale pak se objeví Google AI Overviews a začne do URL přidávat něco jako #:~:text=nějaký%20text… a najednou se probouzí naděje: co když nám AI konečně ukazuje, co přesně z našeho textu považuje za odpověď?
Tak pojďme rozebrat, co se vlastně děje, proč by tě to mělo zajímat, a jak to celé můžeš změřit v GA4.
Co jsou vlastně ty Fragment Text Directives?
V jednoduchosti: je to způsob, jak se dá v URL odkazovat přímo na konkrétní část textu.
Když přidáš do odkazu třeba:
prohlížeč zascrolluje na tuhle větu a zvýrazní ji.
Kouzlo? Ne. Jen staré dobré HTML5 s příchutí user-friendly magie.
Google tenhle trik se používá už od roku 2020, ale teprve s nástupem AI Overviews (GAIO) a AI Mode to začalo být zajímavé. AI totiž při citacích webů tenhle mechanismus používá, aby odkázala uživatele přesně na úsek, který považuje za relevantní.
Proč na tom záleží?
Protože tohle je něco jako návrat „klíčových slov“ do GA4.
Jen místo query z vyhledávání dostáváme konkrétní úryvek textu, kvůli kterému uživatel klikl.
To je pro analytika sen, zjistíš, co přesně z textu přivedlo návštěvu.
Dřív jsme měli „klíčové slov / frázi“ → dnes můžeme mít #:~:text=.
Získáš tak odpověď na otázku:
„Na kterou větu z mého webu / obsahu reagovala AI ve výsledcích vyhledávání?“
A to už není drobnost. To je nový analytický signál, který bude moci pomocí hlavně SEO.
Měření AI citací = nový SEO insight
Z mých testů (a taky pár experimentů u klientů, kde intenzivně sledujeme AI traffic už delší dobu) vychází, že GAIO používá fragmenty střídmě, zatímco AI Mode mnohem víc.
Pravděpodobně se snaží zvýšit přesnost při přechodu z AI odpovědi na web.
V praxi to znamená, že pokud uživatel klikne z AI výsledku, můžeš zachytit, na jaký úryvek se dostal a tedy i co Google AI považuje za „nejlepší odpověď“.
Co od toho čekat v číslech?
Z mých testů na několika projektech vychází ~1 % organického Google návštěvností s detekovatelným :~:text= v době testování , trend je spíš nahoru. AI Mode rollout v Česku může tuhle křivku zrychlit.
Bacha, tady se chybuje nejčastěji…
- Přisuzování dotazů: fragment ≠ dotaz uživatele. Je to odpovědní snippet dle AI.
- Pocitově se tento fragment požívá tak u 50% prokliků, změřit to nemám jak. To nechám na jiných.
- Google používal fragment text directives již před AI overviews a AI mode, takže to není jistota, ale spíše jen vyšší pravděpodobnost.
Jak to funguje technicky?
Fragment Text Directives (FTD) se přidávají do URL pomocí #:~:text=text.
Jenže háček je v tom, že tenhle fragment se nezobrazí v document.location
ani window.location
.
Takže v GTM proměnné ho prostě neuvidíš.
Jednoduché? Ani náhodou.
Ale existuje hack.
Použij performance API – přesněji performance.getEntriesByType('navigation')[0]["name"]
Tento trik totiž vrací kompletní URL, včetně fragmentu, který normálně v GTM neuvidíte, ikdyž se budete dívat na URL hash.
Jednoduchá verze měření AI fragment #:~:text
Jednoduchá verze která je implementovaná přes GTM tag, umí zachytávat jen fragment :~:text=a nemá fallbacky, nemá tak detailní data.
Kdy bych toto řešení použil?
Máte normální web, bez nějaké super komplexní analytiky. Vhodné v 98% případů.
Kód
1 2 | !function(){var n=performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(!n)return;var u=new URL(n.name),h=u.hash||"";if(-1===h.indexOf(":~:"))return;var match=h.match(/:~:text=([^&]+)/);var a=match?match[1]:"";if(a) window.dataLayer.push({event:"url_fragment_text",url_fragment_text:decodeURIComponent(a).replace(/\s+/g," ").trim().slice(0,100)})}(); |
Návod pro jednoduchou verzi
- Vytvoř HTML značku se skriptem
- GTM → Tags → New → Custom HTML
- Pojmenuj ho třeba „HTML url_fragment_text“
- Vlož kód výše. * (mezi značky <script></script>)
- Nastav Kontroly dalšího souhlasu – „Není požadován žádný další souhlas“
- Nastav Spouštění / trigger: All Pages (Page View).
- Ulož
- Vytvoř si v GTM proměnné, které budeš chtít používat.
- GTM → Tags → New → DataLayer variable
- Jméno dl.url_fragment_text
- Hodnota url_fragment_text
- Ulož
- Odešli data, které chceš do GA4 přes Event.
- Vytvoř GTM → Tags → New → GA4 event
- Nastav ID měření
- Nastav jméno eventu „url_fragment_text“
- Vlož proměnou – Přidat parametr url_fragment_text = {{dl.url_fragment_text}}
- Nastav souhlas > nevyžaduji další souhlas.
- Vytvoř trigger
- Vyber Custom Event
- Jmené EVENT url_fragment_text
- Event name: url_fragment_text
- Ulož
- Ulož
- Vytvoření custom dimenze
- GA4 Admin → Custom definitions → Create custom dimension
- Dimension name → url_fragment_text
- Event parameter → url_fragment_text
- Ulož
- Otestuje
- Při debugování v GTM přidej do URL #:~:text=test
- Dej znova načíst stránku > To odešle GA4 event
- Proveď kontrolu, že vše funguje
- Přes nějaké Rozšíření prohlížeče třeba Analytics Debugger
- GA4 → Report → Realtime overview
- Publikuj verzi kontejneru Google tag manageru.
- Sleduj, reportuj
Komplexní verze měření AI fragmentu #:~:text
Tuto šablonu používám pro generické GA4 eventy na odesílání dat. Vše řeší přímo ze skriptu a tak se při správně nastavené šabloně nemusí řešit další nastavení v GTM, tjs je potřeba méně custom nastavení v GTM. Vhodně pro velké projekty kde si detailně hrajete s daty.
Tato verze umí více typů fragmentu, má fallback na starší prohlížeče etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | function dec(v){ v = (v == null ? '' : String(v)); try { return decodeURIComponent(v.replace(/\+/g, '%20')); } catch(_){ return v; } } !function(){ try { var nav = (window.performance && performance.getEntriesByType) ? performance.getEntriesByType('navigation')[0] : null; var rawUrl = (nav && nav.name) ? nav.name : (typeof location !== 'undefined' && location.href ? location.href : ''); var source = (nav && nav.name) ? 'performance.name' : 'location.href'; var hash = ''; try { var url = rawUrl ? new URL(rawUrl) : null; hash = url && url.hash ? url.hash : ''; } catch(_){ } if (!hash && typeof location !== 'undefined') { hash = location.hash || ''; source = 'location.hash'; } if (!hash || hash.indexOf(':~:') === -1) return; var after = hash.split(':~:')[1] || ''; var parts = after.split('&'); var out = { text: [], textStart: null, textEnd: null, prefix: null, suffix: null }; for (var i = 0; i < parts.length; i++) { var p = parts[i]; if (p.indexOf('text=') === 0) { out.text.push(dec(p.slice(5))); } else if (p.indexOf('textStart=') === 0) { out.textStart = dec(p.slice(10)); } else if (p.indexOf('textEnd=') === 0) { out.textEnd = dec(p.slice(8)); } else if (p.indexOf('prefix=') === 0) { out.prefix = dec(p.slice(7)); } else if (p.indexOf('suffix=') === 0) { out.suffix = dec(p.slice(7)); } } var summary = [].concat(out.text).filter(Boolean).join(' | '); if (!summary && (out.textStart || out.textEnd)) { summary = [out.textStart, out.textEnd].filter(Boolean).join(' → '); } if (!summary && (out.prefix || out.suffix)) { summary = [ out.prefix ? ('…' + out.prefix) : '', out.suffix ? (out.suffix + '…') : '' ].filter(Boolean).join(' | '); } if (!summary) return; window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'url_fragment_text', hit: { url_fragment_text:summary.replace(/\s+/g,' ').trim().slice(0, 100), url_fragment_source: source, event_type: 'generic', event_endpoint: 'analytics', event_source: 'gtm_html_tag', action_type: 'seo_signal', action_name: 'ai_text_fragment', action_text: summary.replace(/\s+/g,' ').trim().slice(0, 100), action_value: summary.length, measure_note: 'Measuring AI fragments is a signal for SEO from Google AI mode', data: out }, _clear: true }); } catch(e) { window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: "error_url_fragment_text", hit: { event_type: "generic", event_endpoint: "analytics", event_source: "gtm_html_tag", action_type: "error_invisible", action_name: "error in gtm tag js", action_text: String(e && e.message ? e.message : e), measure_note: "error in tag url_fragment_text" }, _clear: true }); } }(); |
Minify komplexní verze
1 | function dec(e){e=null==e?"":String(e);try{return decodeURIComponent(e.replace(/\+/g,"%20"))}catch(t){return e}}!function(){try{var e=window.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null,t=e&&e.name?e.name:"undefined"!=typeof location&&location.href?location.href:"",n=e&&e.name?"performance.name":"location.href",a="";try{var r=t?new URL(t):null;a=r&&r.hash?r.hash:""}catch(i){}if(a||"undefined"==typeof location||(a=location.hash||"",n="location.hash"),!a||-1===a.indexOf(":~:"))return;for(var f=(a.split(":~:")[1]||"").split("&"),l={text:[],textStart:null,textEnd:null,prefix:null,suffix:null},c=0;c<f.length;c++){var s=f[c];0===s.indexOf("text=")?l.text.push(dec(s.slice(5))):0===s.indexOf("textStart=")?l.textStart=dec(s.slice(10)):0===s.indexOf("textEnd=")?l.textEnd=dec(s.slice(8)):0===s.indexOf("prefix=")?l.prefix=dec(s.slice(7)):0===s.indexOf("suffix=")&&(l.suffix=dec(s.slice(7)))}var o=[].concat(l.text).filter(Boolean).join(" | ");if(!o&&(l.textStart||l.textEnd)&&(o=[l.textStart,l.textEnd].filter(Boolean).join(" → ")),!o&&(l.prefix||l.suffix)&&(o=[l.prefix?"…"+l.prefix:"",l.suffix?l.suffix+"…":""].filter(Boolean).join(" | ")),!o)return;window.dataLayer=window.dataLayer||[],window.dataLayer.push({event:"url_fragment_text",hit:{url_fragment_text:o.replace(/\s+/g," ").trim().slice(0,100),event_type:"generic",event_endpoint:"analytics",event_source:"gtm_html_tag",action_type:"seo_signal",action_name:"ai_text_fragment",action_text:o.replace(/\s+/g," ").trim().slice(0,100),action_value:o.length,url_fragment_source:n,measure_note:"Measuring AI fragments is a signal for SEO from Google AI mode",data:l},_clear:!0})}catch(x){window.dataLayer=window.dataLayer||[],window.dataLayer.push({event:"error_url_fragment_text",hit:{event_type:"generic",event_endpoint:"analytics",event_source:"gtm_html_tag",action_type:"error_invisible",action_name:"error in gtm tag js",action_text:String(x&&x.message?x.message:x),measure_note:"error in tag url_fragment_text"},_clear:!0})}}(); |
Návod pro komplexní verzi
Pro pokročilé je stručný návod 🙂
- GTM → Tags → New → Custom HTML a vlož kód výše
- * (mezi značky <script></script>)
- Nastav trigger: All Pages (Page View).
- Vytvoř si v GTM proměnné, které budeš chtít používat.
- Odešli data, které chceš do GA4 přes Event.
- GA4 Admin → Custom definitions → Vytvoř vše potřebné
- Otestuje, publikuj GTM.
- Sleduj, reportuj
- Postav si report z GA4 dat v Google big query.
Jak bude vypadat výstup v dataLayeru?
Vstup:
#:~:prefix=Podle%20vědců%20%2C&textStart=černé%20díry&textEnd=jsou%20stále%20záhadou&suffix=%2C%20říká%20profesor
Výstup:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { event: "url_fragment_text", hit: { url_fragment_text: "černé díry → jsou stále záhadou", url_fragment_source: "performance.name", event_type: "generic", event_endpoint: "analytics", event_source: "gtm_html_tag", action_type: "seo_signal", action_name: "ai_text_fragment", action_text: "černé díry → jsou stále záhadou", action_value: 31, measure_note: "Measuring AI fragments is a signal for SEO from Google AI mode", data: { text: [], textStart: "černé díry", textEnd: "jsou stále záhadou", prefix: "Podle vědců ,", suffix: ", říká profesor" } }, _clear: true } |
Implementační nuance
- Pokrytí pro podporované prohlížeče je pro Fragment Text Directives cca 93,2 % uživatelů , ale problém může být čtením této hodnoty, protože některé prohlížeče se brání. Chromium-based prohlížeče jsou v pohodě.
- Firefox podporuje funkci, ale blokuje čtení této hodnoty z performance API. (Otestováno)
- Safari, to má podobně jako Firefox, ve starších verzích to funguje, v nových verzích Safari je to blokované. (Otestováno)
- Některé weby postavené na Javascriptu smažou z URL: #:~:text= , ale neudělají to dostatečně rychle, takže to většinou změříte.
- Bude to fungovat na věčné časy? Ne. Je dost možné, že kvuli soukromí možnost číst tyto data bloknou i ostatní prohlížeče.
- V hlavičkách a Server requestech tato hodnota není, takže se k tomu nedostane ServerGTM ani web server.
GA4 Limity
Consent a PII
- Fragment může obsahovat text, který nechceš posílat do GA (uživatelské jméno v UI, komentář).
- Zvaž deny-list slov, max length, případně hashování nebo local-only analýzu pro citlivé sekce a nebo v těchto sekcích neposílejte vůbec text, jen že se to stalo.
Co ještě zbývá vyřešit?
- Míra adopce AI fragmentů v jednotlivých zemích a vertikálách. Prakticky nevím. Dost záleží na Google.
- Korelace fragmentů s konverzemi vs. tradiční SERP. Bude zajímavé si to vyhodnotit.
- Stabilita citací v čase (drift AI odpovědí).
Shrnutí
- Text Fragments z AI výsledků do URL jsou nový analytický signál vyhodnocení SEO.
- Pomocí Performance API je dostaneš viditelnou URL i do GA4.
- Nechovej se k tomu jako „klíčového slovu“, ale je to prostě AI vybraný úryvek.
- Použij to k prioritizaci obsahu, UX úpravám a reportingu „co AI považuje za odpověď“.
Jak to vidíte vy? Kterou větu z vašeho webu by AI měla citovat jako první?
Poslední update kódů: 20. 10. 2025 11:23:36 – Zvýšil jsem komptabilitu se staršími prohlížeči.