Jak jsem opravil SEO sitemapy a faviconu
Web d3arts.cz běží na WordPressu, na LiteSpeed serveru s využitím LiteSpeed Cache a QuickCloud/CDN. Použitá šablona je Oshine a favicony jsou řešené přes RealFaviconGenerator, který generuje kompletní sadu ikon, manifest a HTML tagy pro moderní prohlížeče i vyhledávače. O generování sitemap.xml se stará Yoast SEO. Problém s faviconem jsme už řešili v článku Favicona WordPress webu není vidět v SERP Google - ale v mém případě bylo řešení trochu komplikovanější, než by se mohlo zdát. Konfigurace webu tedy je:
CMS: WordPress
Server: LiteSpeed
Cache/CDN: LiteSpeed Cache + QuickCloud
Hosting: BEST-HOSTING.CZ
Favicon plugin: RealFaviconGenerator
SEO plugin: Yoast SEO
Klíčové poznatky
WordPress Site Icon a RealFaviconGenerator se mohou navzájem duplikovat.
Šablona Oshine sama o sobě nebyla hlavní problém, ale generuje hodně vlastního HTML/CSS.
LiteSpeed Cache a QuickCloud výrazně ovlivňují, co reálně dostane Googlebot.
Sitemapu je vhodné cachovat, ale neoptimalizovat/minifikovat.
Crawlerům není vhodné zbytečně vypínat cache přes „Do Not Cache User Agents“.
.webmanifest musí být validní JSON a ideálně se servírovat jako application/manifest+json.
Nejdůležitější zásah u favicon:
Původní problém favicony: duplicitní WordPress Site Icon + RealFaviconGenerator
Řešení favicony: odstranění WordPress Site Icon a ponechání RealFaviconGenerator sady
Původní problém sitemap: pomalé generování / no-cache pro crawlery
Řešení sitemap: cache pro sitemap povolena, optimalizace/minifikace pro sitemap vyloučena
Během kontroly jsme řešili dva problémy, které se na první pohled tvářily odděleně:
- Google Search Console hlásila chyby u sitemap, hlavně u
post-sitemap.xml. - Favicon se nezobrazovala správně ve výsledcích Google.
Nakonec se ukázalo, že problém nebyl v samotném XML ani v samotných obrázcích favicony. Šlo hlavně o to, jaké hlavičky server vrací crawlerům Googlu, jak funguje cache a zda v HTML nejsou duplicitní instrukce.
Důležité bylo hlavně to, že se na webu potkaly dvě různé favicon konfigurace:
- původní WordPress Site Icon
- nová sada z RealFaviconGeneratoru
WordPress Site Icon byla nastavená v administraci:
Vzhled → Přizpůsobit → Identita webu → Ikona webu
A právě tato původní WordPress ikona generovala staré favicon tagy, které kolidovaly s novou sadou z RealFaviconGeneratoru. Nebojte se ji v deffaultním nastavení Wordprees v ikoně webu úplně odstranit.
1. Problém se sitemapou v Google Search Console
Google Search Console ukazovala chyby typu u /post-sitemap.xml nebo /portfolio-sitemap.xml, což jsou v mém případě jedny z nejobsžnějších sitemap a hlavní sitemap index je sitemap_index.xml. Na první pohled to vypadalo, že problém může být v samotné sitemapě. Proto jsme začali testovat přímo z terminálu a Windows PowerShellu, co server reálně vrací.
Nelze načíst
Všeobecná chyba HTTP
1 chyba
Hlavní sitemap index byl https://d3arts.cz/sitemap_index.xml
Na první pohled to vypadalo, že problém může být v samotné sitemapě. Proto jsme začali testovat přímo z terminálu a Windows PowerShellu, co server reálně vrací. Podsitemapy v indexu obsahovaly například:
https://d3arts.cz/post-sitemap.xml
https://d3arts.cz/page-sitemap.xml
https://d3arts.cz/product-sitemap.xml
https://d3arts.cz/portfolio-sitemap.xml
https://d3arts.cz/category-sitemap.xml
https://d3arts.cz/video-sitemap.xml
...
Testy ukázaly, že sitemap index i jednotlivé podsitemapy vrací HTTP 200, správný XML content-type a nenulovou velikost. Sitemap tedy nebyla obsahově rozbitá. Problém byl jinde: v rychlosti odpovědi a cache.
Použité diagnostické příkazy pro Windows PowerShell a terminál
Během opravy jsme průběžně ověřovali, co web skutečně vrací crawlerům. Níže jsou příkazy ve dvou verzích: pro Windows PowerShell a pro běžný terminál.
Windows PowerShell
curl.exe --ssl-no-revoke -L -A "Googlebot" "https://d3arts.cz/sitemap_index.xml" -o sitemap-index.xml -w "`nHTTP: %{http_code}`nTime: %{time_total}s`nSize: %{size_download} bytes`nContent-Type: %{content_type}`nFinal URL: %{url_effective}`n" Terminál
curl -L -A "Googlebot" "https://d3arts.cz/sitemap_index.xml" -o sitemap-index.xml -w "\nHTTP: %{http_code}\nTime: %{time_total}s\nSize: %{size_download} bytes\nContent-Type: %{content_type}\nFinal URL: %{url_effective}\n"Vypsání všech podsitemap z indexu
Windows PowerShell
[xml]$xml = Get-Content .\sitemap-index.xml
$xml.sitemapindex.sitemap | ForEach-Object { $_.loc }Terminál
curl -L "https://d3arts.cz/sitemap_index.xml" | grep -oP '(?<=<loc>).*?(?=</loc>)'Pokud grep -P není dostupný, použít lze jednodušší variantu:
curl -L "https://d3arts.cz/sitemap_index.xml" | sed -n 's:.*<loc>\(.*\)</loc>.*:\1:p'Kontrola post-sitemap.xml
Obsažná sitemapa týkající se příspěvků wordpress - tedy článků na blogu. Pomalé generování post-sitemap.xml pomocí Yoast SEO. Soubor se původně načítal přibližně přes 5 sekund. To je na XML soubor o velikosti zhruba 141 kB příliš pomalé. To sice znamená, že soubor existoval a byl validně dostupný, ale pro Google Search Console mohl být takový fetch nestabilní. Pokud server nebo CDN v některých momentech odpověděly pomaleji, GSC mohla nahlásit obecnou HTTP chybu. V hlavičkách se objevovalo: x-qc-cache: miss, cache-control: no-cache, no-store, private
Windows PowerShell
curl.exe --ssl-no-revoke -L -A "Googlebot" "https://d3arts.cz/post-sitemap.xml" -o post-sitemap.xml -w "`nHTTP: %{http_code}`nTime: %{time_total}s`nSize: %{size_download} bytes`nContent-Type: %{content_type}`nFinal URL: %{url_effective}`n"Terminál
curl -L -A "Googlebot" "https://d3arts.cz/post-sitemap.xml" -o /dev/null -w "\nHTTP: %{http_code}\nTime: %{time_total}s\nSize: %{size_download} bytes\nContent-Type: %{content_type}\nFinal URL: %{url_effective}\n"Důležité hlavičky: x-qc-chache ukazuje, že cache lite speed serveru cachuje sitemapu (což je dobře), protože jinak je doba načítání přes pět vteřin, což Crawler Googlebot vyhodnotí jako nedostupné. To byl jeden z důvodů proč se nedařilo dostat sitemapy do Google Search Console.
HTTP/2 200
content-type: text/xml; charset=UTF-8
x-qc-cache: hit
Kontrola favicon tagů na homepage
Windows PowerShell
curl.exe --ssl-no-revoke -L -A "Googlebot" "https://d3arts.cz/" -o homepage.html
Select-String -Path .\homepage.html -Pattern '<link[^>]+rel="[^"]*icon|<link[^>]+rel="manifest|msapplication-TileImage'Terminal
curl -L -A "Googlebot" "https://d3arts.cz/" -o homepage.html
grep -Ei '<link[^>]+rel="[^"]*icon|<link[^>]+rel="manifest|msapplication-TileImage' homepage.htmlSprávně má zůstat jen sada z RealFaviconGeneratoru:
<link rel="icon" type="image/png" href="/wp-content/uploads/fbrfg/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/wp-content/uploads/fbrfg/favicon.svg" />
<link rel="shortcut icon" href="/wp-content/uploads/fbrfg/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/wp-content/uploads/fbrfg/apple-touch-icon.png" />
<link rel="manifest" href="/wp-content/uploads/fbrfg/site.webmanifest" />Kontrola favicon souborů pro Googlebot-Image
Windows PowerShell
curl.exe --ssl-no-revoke -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon-96x96.png"
curl.exe --ssl-no-revoke -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon.svg"
curl.exe --ssl-no-revoke -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon.ico"
curl.exe --ssl-no-revoke -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/apple-touch-icon.png" Terminál
curl -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon-96x96.png"
curl -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon.svg"
curl -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/favicon.ico"
curl -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/apple-touch-icon.png"
Správné výsledky:
HTTP/2 200
content-type: image/png
content-type: image/svg+xml
content-type: image/x-iconKontrola manifestu
Windows PowerShell
curl.exe --ssl-no-revoke -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest"Terminál
curl -L -A "Googlebot-Image" -I "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest"Správný výsledek:
HTTP/2 200
content-type: application/manifest+json
Vypsání obsahu manifestu
Windows PowerShell
curl.exe --ssl-no-revoke -L "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest"Terminál
curl -L "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest"Validace manifestu jako JSON
Tady byla zásadní chyba, protože server servíroval jako content-type: application/octet-stream a ne content-type: application/manifest+json - to změníte buď v .htaccess nebo nastavením serveru - kde je asi radnon zavolat si na podporu.
Oprava .htaccess
<IfModule mod_mime.c>
AddType application/manifest+json .webmanifest
</IfModule>Windows PowerShell
Přihlaste se do admin rozhraní: https://server-ip:7800
Virtuals Hosts - Mine Settings
Přidejte nový MINE typ: Suffix: webmanifest a MINE type: application/manifest+json
Uložit a restartovat
pokud toto nezabere, přihlaste se ke svému serveru
curl.exe --ssl-no-revoke -L "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest" -o site.webmanifest
Get-Content .\site.webmanifest | ConvertFrom-JsonTerminal
curl -L "https://d3arts.cz/wp-content/uploads/fbrfg/site.webmanifest" | jq .Správný výsledek:
{
"name": "d3arts.cz",
"short_name": "d3arts",
"icons": [
{
"src": "/wp-content/uploads/fbrfg/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/wp-content/uploads/fbrfg/web-app-manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}2. Skutečný problém: cache a pomalé generování sitemap
U post-sitemap.xml se původně objevoval čas načítání kolem pěti sekund. To je na soubor o velikosti zhruba 141 kB zbytečně moc. Z hlaviček bylo vidět, že QuickCloud vrací x-qc-cache: miss, případně že sitemapu server posílal s hlavičkami typu no-cache, no-store, private.
To znamenalo, že sitemapu pokaždé znovu generuje WordPress/Yoast místo toho, aby ji QuickCloud/LiteSpeed rychle servíroval z cache.
V LiteSpeed Cache byly sitemapy původně vyloučené z cachování v záložce Mezipaměť - (4) Excludes / Vyzaření:
/(.)sitemap(.).xml
/(.*)sitemap.xsl
/sitemap_index.xml
/wp-content/plugins/wordpress-seo/css/main-sitemap.xsl
To dávalo smysl z hlediska „vždy čerstvého XML“, ale v praxi to způsobovalo pomalé odpovědi crawlerům. Nastavení jsme proto upravili tak, aby se sitemapy nevylučovaly z cache, ale zároveň se vyloučily z optimalizací/minifikací.
Správná logika Sitemap XML:
neoptimalizovat jako HTML/CSS/JS
cachovat ano
minifikovat ne
lazyload ne
Po úpravě začala post-sitemap.xml vracet z QuickCloudu x-qc-cache: hit a rychlost se zlepšila přibližně z pěti sekund na méně než půl sekundy.
Další skrytý problém: „No cache user agents“
V .htaccess jsme objevili pravidlo, které vyřazovalo z cache různé crawlery. To znamenalo, že crawlerům se vypínala cache. Pro veřejné stránky, sitemapy a favicony to není žádoucí. Googlebot má dostávat rychlou veřejnou verzi webu, stejně jako běžný nepřihlášený návštěvník.
Googlebot-Video
Googlebot-News
Google-InspectionTool
AdsBot-Google
Mediapartners-Google
Bingbot
DuckDuckBot
SeznamBot
Applebot
…
Tohle nastavení mohlo způsobovat, že Googlebot nedostával rychlou cachovanou verzi, ale pomalejší dynamickou odpověď. Seznam jsme proto z LiteSpeed Cache odstranili. První požadavek po purge byl ještě MISS, což je normální, ale další požadavky už přešly na HIT. Tím se potvrdilo, že crawlerům už server servíruje sitemapu rychle z cache.
Favicon v Google SERPu: problém nebyl v obrázku, ale v duplicitních tazích
Druhý problém byl favicon. V Google výsledcích se nezobrazovala správně, nebo se přestala zobrazovat. Nejdřív jsme ověřili, jestli Googlebot vůbec vidí favicon tagy na homepage.
PowerShell test ukázal, že v HTML byly současně dvě různé sady favicon. Tohle byl hlavní konflikt. Google měl v HTML dvě různé instrukce, jakou faviconu má používat. Staré tagy generoval nativní WordPress přes funkci wp_site_icon(), protože v administraci byla stále nastavená stará „Ikona webu“.
Po odstranění WordPress Site Icon zůstala v HTML jen sada z RealFaviconGeneratoru. Poslední kontrola ukázala, že staré favicon-2 odkazy už ve výpisu nejsou a homepage obsahuje jen novou favicon sadu
RealFaviconGenerator a manifest
Použitý nástroj byl RealFaviconGenerator, který vytvořil složku /wp-content/uploads/fbrfg/
favicon-96x96.png
favicon.svg
favicon.ico
apple-touch-icon.png
site.webmanifest
web-app-manifest-192x192.png
web-app-manifest-512x512.png
Favicon soubory byly dostupné pro Googlebot-Image, vracely HTTP 200 a správné MIME typy, například image/png, image/svg+xml nebo image/x-icon.
U manifestu byl ale ještě jeden technický detail: server ho původně posílal jako:
content-type: application/octet-stream namísto content-type: application/manifest+json
Zde je nutná úprava serverového nastavení.
Máme opraveno a co dál
Teď už není vhodné dál měnit URL ikon, znovu generovat favicony nebo přepisovat sitemap pravidla. Naopak je potřeba nechat Google, aby si nové nastavení znovu načetl.
V Google Search Console je vhodné udělat:
Kontrola URL → https://d3arts.cz/ → Požádat o indexování
Tento krok trochu trvá, proto si vždy zkontrolujte rozkliknutím - položky Indexování stránek, kdy byla stránka naposledy prohledána.
a pro sitemapu nechat odeslanou pouze:
sitemap_index.xml
Jednotlivé podsitemapy jako post-sitemap.xml není potřeba do GSC vkládat ručně.
Pak už zbyde jen čekat co na to Google bot. A neděste se, že vám GSC hlásí, že soubor nejde načíst - pokud jste tam měli již ten soubor předtím pamatuje si starý stav. Bohužel tohle nijak neurychlíte.




