Kontrola před spuštěním webu

kvě 29 2019

Lukáš nám v Tritonu připravil checklist nejběžnějších chyb, které je překontrolovat před každým předáním nového webu. Protože se ale stále rozrůstáme a jednu větu v checklistu jde interpretovat různými způsoby, rozhodl jsem se vytvořit tento blogový zápisek, který to rozepisuje trochu podrobněji.

Nahrazuji starý web? Nastavil jsem přesměrování všech původních URL?

Důležitou součástí spuštění nového webu je bezproblémový přechod návštěvníků na novou verzi. Zejména v případech, kdy měníme platformu, tj. při přechodu na jiný CMS nebo u nové implementace webu, musíme ověřit, že ze všech původních URL se dostaneme na odpovídající sekci nového webu.

Nedodržení tohoto pravidla má dva zásadní dopady:

  • Oslabení vlivu zpětných odkazů, které nyní povedou na chybovou stránku.
  • Ztráta návštěvnosti a zákazníků. Stejně jako vyhledávače, i lidé neradi přicházejí na chybovou stránku - frustrace a zmatenost z neohlášené změny webu může poškodit značku. Například u e-shopů si zákaznící rádi ukládají záložky na produktové stránky.

Fungují všechny stránky webu? Fungují všechny formuláře? A co další funkce?

Před spuštěním je bezpodmínečně nutné projít každou stránku webu a ověřit, že skutečně funguje, stejně tak i interaktivní prvky, formuláře apod.

Není nic horšího, než zjistit, že nám týden nechodily objednávky od zákazníků, protože formulář byl špatně nastaven.

Je web optimalizovaný pro vyhledávače, tj. má dobré on-page SEO?

Základní meta informace

Každá stránka webu musí obsahovat tag title a description. Title stránky odpovídá skutečnému názvu, doplňujeme ho navíc také o název webu nebo nadřazené sekce za oddělovacím znakem. U titulní stránky obvykle dáváme název webu na první místo a za oddělovač přidáváme podtitulek nebo velmi krátký popis. Pokud stránka nemá vlastní popis, který by mělo smysl použít, pak description bude obsahovat alespoň obecný popis uvedený na titulní stránce webu.

Příklad:

<title>Rychlý networking | Net Forest</title>
<meta name="description" content="Děláme rychlý networking nejen pro start-upy. Na akcích Net Forest se seznamují lidé, kteří aktivně rozvíjejí své podnikání i profesní kariéru a těší se na nové příležitosti..">

Informační architektura stránek

Každá stránka musí dodržovat logický tok HTML elementů. Nevkládáme blokové (block) prvky dovnitř řádkových (inline), každá stránka má právě jeden nadpis úrovně h1, který je obvykle shodný s obsahem title tagu bez zmínění názvu webu. Jednotlivé obsahové sekce mají svůj vlastní příslušný nadpis nižší úrovně.

Každý obrázek vložený prostřednictvím img tagu by měl mít nastaven argument alt a v něm svůj krátký textový popis.

Příklad: https://www.netforest.cz/jak-to-funguje

URL stránek

Název stránky v URL by měl kopírovat název v title a h1. Jednotlivá slova oddělujeme pomlčkou, písmena měníme na malá a odstraňujeme interpunkci, háčky a čárky.

Příklad: https://www.hlinikova-strecha.info/vite-proc-je-plechova-strecha-lepsi-volbou-nez-tasky/

Sdílení odkazů na web

Většina webů přizpůsobených pro uživatelské sdílení odkazů dnes vytváří náhled odkazovaného webu. Protože vykreslovat celý skutečný snímek obrazovky je nepraktické, sestavovaly se podobné náhledy dříve pomocí triku - stáhl se title stránky a byl doplněn o první velký obrázek a souvislý text na stránce. Dnes si ale optimalizaci sdílení můžeme zjednodušit použitím OpenGraph meta tagů. U OpenGraph jde náhled sdílení dokonfigurovat vlastními informacemi. Každý web by měl obsahovat všechny meta tagy z příkladu. Náhledový obrázek by měl být alespoň jeden.

Pro testování náhledů lze využít Facebook sharing debugger: https://developers.facebook.com/tools/debug/sharing/

Příklad: https://www.netforest.cz/

    <meta property="og:url" content="https://www.netforest.cz">
    <meta property="og:type" content="website">
    <meta property="og:title" content="Rychlý networking | Net Forest">
    <meta property="og:description" content="Děláme rychlý networking nejen pro start-upy. Na akcích Net Forest se seznamují lidé, kteří aktivně rozvíjejí své podnikání i profesní kariéru a těší se na nové příležitosti..">
    <meta property="og:image" content="https://www.netforest.cz/images/netforest-photo1.jpg">
    <meta property="og:image" content="https://www.netforest.cz/images/netforest-photo2.jpg">
    <meta property="og:image" content="https://www.netforest.cz/images/netforest-photo3.jpg">
    <meta property="og:image" content="https://www.netforest.cz/images/netforest-photo4.jpg">
    <meta property="og:image" content="https://www.netforest.cz/images/netforest-photo5.jpg">

Nastavení pro roboty, vyhledávače a odkazy vedoucí ven z webu

U každého webu jde nastavit doporučení, jak by se měly chovat programy, které jej automatizovaně procházejí. Tato pravidla fungují pouze jako přání - nejde jimi vynutit dodržování. Pravidla pro roboty jde nastavit na třech základních místech:

  • Soubor robots.txt, který je uložen ve web root složce - povolení a zákaz přístupu k dalším souborům.
  • Meta tag robots HTML dokumentu: nastavení ukládání odkazů a indexování webů.
  • Atribut rel u odkazů uvnitř HTML dokumentu: chová se stejně jako u meta tagu, ale platí jen pro tento konkrétní odkaz.

Nastavení u odkazů se týkají cílové URL ve vztahu k současné stránce, nastavení uvnitř meta tagu robots se vztahuje ke všem odkazům na současné stránce. Nastavení v robots.txt umožňuje vytvářet pravidla pro celý web nebo jeho části.

Po finálním spuštění webu je potřeba ověřit, že na žádné veřejně dostupné stránce není nastaven zákaz indexování nebo crawlingu.

Příklad meta tagu - zákaz indexování stránky a následování jejích odkazů:

<meta name="“robots“" content="“noindex,nofollow“">

Příklad robots.txt - povolení crawlingu všem robotům na celém webu s vyjímkou složky admin a jejího obsahu:

User-agent: *
Disallow: /admin

Rychlost načítání

Od moderního webu, který se zobrazuje ve vyhledávačích, se o čekává rychlé a pohodlné načítání. Všechny obrázky na webu minifikujeme tak, aby zabíraly co nejméně místa a při jejich stahování se tak přenášelo co nejméně dat. Stejně jako obrázky, minifikujeme také CSS a JS odstraněním funkčně zbytečného formátování a zkrácením názvu proměnných.

Pro minifikaci jpg, png a gif obrázků lze využít web TinyPNG: https://tinypng.com/, v CMS systémech jsou dostupné minifikační pluginy.

Pro minifikaci skriptů a grafických stylů lze použít https://www.minifier.org/, lepší je ale nastavit si automatickou minifikaci ve vývojovém prostředí.

Pro testování rychlosti lze využít Google PageSpeed Insights: https://developers.google.com/speed/pagespeed/insights/?hl=cs

Je web zabezpečený? Chrání před spamem?

Nastavení HTTPS

Všechny weby, které spouštíme pro klienty, musí mít na finální doméně nastaven přístup přes HTTPS na portu 443. Verze bez šifrování na portu 80 musí na šifrovanou verzi přesměrovávat a to tak, že mění protokol a zachová zbytek původní URL.

Na našem serveru nastavujeme přesměrování pomocí konfigurace web serveru NGINX. Na externím hostingu většinou běží Apache HTTP server, který můžeme dokonfigurovat souborem .htaccess ve web root složce webu (tečka na začátku značí skrytý soubor v Linux / Unix systémech).

Příklad - pravidlo pro vynucení www a https před názvem domény:

RewriteEngine On

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{ENV:HTTPS} !^.*on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

HTTPS certifikát u webů citlivých na utajení dat nakupujeme a nebo používáme certifikáty vystavené certifikační autoritou Let's Encrypt. K nasazení certifikátů od Let's encrypt používáme automatizační nástroj certbot a jeho plugin pro webový server NGINX python-certbot-nginx.

Pokud nasazujeme Let's encrypt certifikát někam, kde nejde použít certbot, musíme ručně sestavit žádost (CSR) a odeslat ji na servery Let's encrypt, ručně provést ověření domén a pak hotový certifikát nasadit. Proces jde usnadnit použítím webové aplikace jako jako zerossl.com.

Obfuskace e-mailů

Všechny veřejně viditelné emailové adresy na webu musí být upraveny, aby je spamboti nemohli jednodušše přečíst Nejjednodušší metoda, jak toho docílit, je sestavení finálního textového řetězce (klikatelného) emailu pomocí javascriptu. Nejběžnější webové scrapery neumí javascript interpretovat.

Příklad obfuskace kontaktního emailu z webu tritonit.cz:

<script type="text/javascript"><!--
    var ivntlhw = ['t', 'i', 'e', 't', 'a', 'c', '"', 't', 's', '@', 't', ' ', '<', 'a', '"', '@', 'r', 'o', 'm', 't', 'i', ':', 'o', 'r', 'c', 'o', '<', ' ', 'i', 'i', '.', 'z', 't', 't', 'c', 'a', '=', 's', 'l', 'n', 'i', 'z', 'n', '/', 'o', 'f', 'f', 'e', '>', '>', 'n', 'm', 'i', 'o', 'n', 'h', 'l', 'a', 'i', 'l', 'i', '.', '=', 'f', '"', 'r', 'a', '"'];
    var schidlm = [60, 55, 41, 13, 36, 30, 8, 56, 37, 20, 53, 2, 64, 66, 40, 52, 4, 57, 42, 21, 16, 15, 14, 54, 34, 25, 0, 33, 23, 59, 29, 63, 28, 24, 62, 1, 39, 38, 12, 49, 48, 31, 17, 65, 19, 50, 18, 5, 47, 67, 26, 9, 11, 51, 58, 3, 35, 43, 27, 45, 44, 61, 7, 6, 32, 22, 10, 46];
    var bwmotom = new Array();
    for (var i = 0; i < schidlm.length; i++) {
        bwmotom[schidlm[i]] = ivntlhw[i];
    }
    for (var i = 0; i < bwmotom.length; i++) {
        document.write(bwmotom[i]);
    }
    // -->
</script>
<noscript>
  Pro zobrazení emailové adresy, prosíme, zapněte JavaScript.
</noscript>

Ochrana formulářů

Všechny veřejně dostupné formuláře potřebují antispamovou ochranu. V případě použití CMS systému (Wordpress) můžeme ochranu svěřit pluginu pro vytváření těchto formulářů. V případě tvorby webu od začátku je potřeba alespoň nějakou ochranu vytvořit ručně.

Nejjednodušší metoda ochrany je přidání skrytých polí do formuláře tak, že je robot nedovede rozeznat od zbytku.

Nastavil jsem měření návštěv?

Až na naprosté výjimky měříme u všech webů návštěvnost uživatelů. Tyto informace jsou v internetovém marketingu velmi důležité neboť nám umožňují přízpůsobit web na základě chování návštěvníků, analyzovat, co nám přináší nejvíce peněz, nebo zacílit na určitou skupinu podrobnější reklamu.

Google Tag Manager & Google Analytics

Na všech webech nasazujeme kód Google Tag Manager. Ten nám dovoluje spravovat kódy ostatních služeb přehledně z jednoho místa ve webovém prohlížeči, aniž bychom museli zasahovat do zdrojového kódu webu. Společně s Google Tag Managerem automaticky nasazujeme i základní měření Google Analytics, a to prostřednictvím tagu Universal Analytics s nastaveným měřením Page View.

Měření konverzí

Pokud vytváříme web, vždy tím sledujeme nějaký cíl nebo úkol, který bude web vykonávat. K ověřování plnění tohoto cíle slouží konverze. Rozplánování konverzí bychom měli řešit už při designové fázi webu. Během vývoje pak musíme zajistit, že jsou jednotlivé cíle měřitelné - tzn., že existuje způsob, kterým web dá vědět, že uživatel právě splnil vytyčený cíl.

Konverze si pomyslně dělíme na měkké a tvrdé. Tvrdou konverzí rozumíme úplné splnění úkolu webu - například dokončení prodeje zboží v e-shopu, odeslání poptávkového formuláře, nebo využití mzdové kalkulačky. Měkkou konverzí rozumíme buď splnění vedlejšího úkolu webu (přečtení celého článku, prohlédnutí kontaktních osob firmy), nebo dokončení významného kroku na cestě ke tvrdé konverzi, například ověření dostupnosti internetu, začátek vyplňování kontaktního formuláře, apod.

Měkké konverze obvykle využíváme k rozhodování, jak budeme s návštěvníkem nebo zákazníkem dále pracovat. Pokud někdo přidal zboží do košíku, mohl by nákup ještě dokončit, pokud si ověřil dostupnost služby, mohl by si ji ještě objednat.

Je všecho v pořádku s obsahem webu?

Na úplný závěr je potřeba sebekriticky znovu projít web. Skutečně vše vypadá dobře a na 100% funguje? Vypadá web tak, abych na něj mohl být hrdý? Nezapoměl jsem na žádnou funkci?

Odstranění testovacích dat

Odstranil jsem všechna testovací data a stránky? Co debugové výpisy do logu nebo konzole prohlížeče? Přepnul jsem web na produkční režim? Co databáze a číselníky v ní - jsou zde nahrána správná data?

Korektura textu

Jsou všechny texty gramaticky správně - bez hrubek a překlepů? Nezarovnává se někde podivně text na více řádků? Dávají všechny texty smysl? Kolik lidí si web pročetlo - můžu opravu věřit jen sobě nebo jedné další osobě? Odkazují se stránky na webu jedna na druhou v rozumné míře? Jsou odkazy vedeny z důležitých slov pro web - například běžných nákupních frází z vyhledávání?

Ošklivá grafika

Odpovídá grafika původnímu záměru designera? Skutečně se web zobrazuje správně na všech typech zařízení a v různých prohlížečích? Co dočasné fotografie a obrázky - vypadají dobře? Mám zajištěný termín dodání finálních fotografií od klienta?

Uživatelé, role a firmy na Facebooku

kvě 10 2019

Aktualizace: Tento článek dnes již není zcela přesný. Důvodem jsou změny v propojení Facebook a Instagram účtů, zavedení prodeje produktů na Instagram a také plynulý přechod od rozhraní Facebook business na novou podobu Facebook business suite.

Administrace a oprávnění na Facebooku nejsou úplně triviální, zvlášť dokud si nesáhnete úplně na každou situaci a roli. Tento zápisek je pokusem o co nejstručnější vysvětlení principů.

Certbot fails renewal with http-01 challenge on NGINX: Connection refused

dub 14 2019

The problem

This has been bothering me for more than half of a year. You might be unable to automatically renew certificates if the following conditions are true:

  • You're using the python-certbot-nginx plugin to install certificates and handle their renewal on your webserver.
  • You're using different location for acme-challenge than the actual folder inside installation root - this is most likely if you're using NGINX as a proxy for a different service.

During the renewal process you will most likely receive the following error:

Attempting to renew cert (example.com) from /etc/letsencrypt/renewal/example.com.conf produced an unexpected error: Failed authorization procedure. example.com (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching https://www.example.com/.well-known/acme-challenge/1hDMJJfjSOPJENxVmuXdDiphrVlEgRGXfHWB7Z8: Connection refused

However testing the connection with curl or wget from any location predictably gives just a 404 error. To fix it, I had to delete the old certificate configuration and reinstall it with the certbot-nginx plugin each time. This would allow http-01 challenge to pass successfully.

After pulling my hair for a while and playing with the --dry-run option, I've finally noticed the following message:

Plugins selected: Authenticator webroot, Installer nginx

This is wrong. It should be:

Plugins selected: Authenticator nginx, Installer nginx

The reason for the failure appears to be the alternate acme-challenge folder location. Webroot authenticator doesn't handle it and it will attempt to verify using regular sub-folder in webroot.

The solution

Open /etc/cron.d/certbot file and add --nginx option to the renew command, the python-certbot-nginx should be adding it automatically but it doesn't.

Přátelské upozornění od Facebook

dub 05 2019

S Facebookem obecně nerad sdílím jakékoliv informace v míře větší, než je minimum nutné pro fungování. Jednou z takových neposkytnutých informací bylo do nedávna moje telefonní číslo. Nicméně už objevili metodu, jak mě donutit prozradit jim ho:

Kamarád Facebook

A k čemu vlastně potřebuje Facebook tak přesně poznat, že jsem to skutečně já (a kde se nacházím)? To je vedlejší, je to prostě v zájmu veřejného blaha. Teď si určitě můžou být jisti, že mi nějaký hacker nezcizil účet :)

Cassandra Reaper

bře 18 2019

Do WebMedea jsme letos zapojili nové datacentrum. Udržovat Cassandru synchronizovanou pro nás ale s jeho přidáním znamená lineární nárůst práce. Kontroly logů, zda některá tabulka či schéma neprošly opravou, už nejsou časově únosné. Opravy databáze jsme se proto rozhodli automatizovat. Při rešerši možných řešení Pepa objevil aplikaci Cassandra Reaper, jejíž popis nádherně plní všechny naše potřeby:

  • periodické spouštění oprav
  • segmentované běhy oprav
  • historie a výsledek jednotlivých běhů.

Po menších obtížích s konfigurací webového UI jsme ji úspěšně nasadili k testování v následujících týdnech.

Změna schéma WebMedea databáze

led 27 2019

WebMedea již eviduje přes miliardu odkazů mezi weby. Tato data v naší Cassandra databázi zabírají již přes 110 GB. Společně s rostoucím množstvím dat jsme narazili na neustále se zvyšující vytížení RAM, CPU a diskové IO našich serverů právě od Cassandry. Její požadavky se zdá, že nejde ukojit. To nás přivedlo k zamyšlení se nad naším současným datovým modelem. Zhodnotili jsme, že nám nezbývá nic jiného než upravit způsob, jakým WebMedea ukládá odkazy mezi weby.

Cassandra, stejně jako relační databáze, umožňuje ukládat jako primární klíč tabulky skupinu více sloupců. Takový primární klíč se u Cassandry nazývá kompozitní (Composite key) a rozlišuje se na dvě důležité části - oddílový (Partition key) a třídící klíč (Clustering key). Oddílový klíč říká Cassandře do jakých celků (oddílů) ukládat bloky dat - tyto oddíly jsou vytvářeny na základě hodnoty sloupců, které jsou součástí klíče a cílem je vyhnout se příliš malým (stovky záznamů) nebo naopak příliš velkým oddílům (stovky MB dat). Třídící klíč, jak můj pokus o překlad napovídá, pak slouží ke třídění dat v rámci jednoho oddílu.

Při ukládání odkazů ve WebMedea jsme preventivně rozdělili cílové domény odkazů na jednotlivé úrovně oddělené tečkou a v oddílovém klíči je vedeme jako samostatné sloupce. Ukazuje se nám ale, že to nestačí. Největší české weby jako Heuréka.cz a Nova.cz jsou schopny vytvářet v naší databázi oddíly do velikosti až několika GB. Jejich "mikrostránky" jako produktroku.cz pak nejsou daleko pozadu.

Abychom předešli tomuto problému upravujeme náš oddílový klíč aby obsahoval také údaje o datumu nalezení odkazu. Tato změna má navíc benefit v tom, že urychlí zobrazování nejnovějších odkazů na výstupu z WebMedea. Jak ale provést takový zásah do 110 GB dat, která jsou neustále upravována, rozšiřována a čtena našimi klienty?

Pro tento úkol jsme přidali do WebMedea dva nové servery, které sídlí v datacentru Wedosu v Hluboké nad Vltavou. Tyto servery na svých instancích Cassandry replikují pouze nově vytvořené databázové schéma a s ním i novou strukturu uložení odkazů. Původní formát odkazů je postupně překládán na nový persistentní službou. Tím se zvedá zátěž na naše servery v ostrém provozu jen minimálně, protože nemusí zapisovat novou strukturu dat. Paralelně k tomu upravujeme naši těžbu odkazů tak, aby ukládala do obou formátů naráz. Posledním krokem pak bude přepnutí schématu v klientských aplikacích a změna replikačního faktoru nového schématu, aby se nový formát dat rozšířil do celé sítě WebMedea.

Aktualizace Echo pro Bludit

pro 19 2018

Bludit je super CMS systém pro blog, zápisník nebo i velmi jednoduché webové stránky. Nepotřebuje žádný databázový systém, vše ukládá do struktury textových souborů. Oslovil mě natolik, že jsem se stal sponzorem a vydávám pro něj sám grafickou šablonu, kterou jsem během pár posledních večerů opět aktualizoval. Ke stažení (a zkritizování) je dostupná (zatím ještě) na GitHub.

Teď jen najít chvíli a aktualizovat ji tady u sebe na blogu :)

Degustace ve Wine Bar

pro 12 2018

Protože jsem chtěl poznat vinárnu Wine Bar i z druhé strany, a porozumět tak více vínům, rozhodl jsem se navštívit degustaci vín, která se ve vinárně pravidelně koná. Degustace se tentokrát zaměřovala na vína oceněná českou soutěží Prague Wine Trophy, kde nabídka Wine Baru získala hned několik medailí a dokonce i titul šampióna ve dvou kategoriích. Degustace byla super akce - přestože jsem naprostý laik, necítil jsem se méněcenně. Sommeliér Petr Mikeska vysvětloval i pojmy, které jsou pro zkušené samozřejmostí. Ochutnávka každého vína byla doplněna názornou prezentací fotografií, mapou lokality, odkud pochází hrozny, i zajímavostmi ze zákulisí vinařství.

Spodní patro vinárny Wine Bar Spodní patro vinárny Wine Bar