SEO przy zmianie domeny bloga

To ostatni wpis nawiązujący do Blox, przynajmniej techniczny, bo być może pojawi się jeszcze jeden o tym, jak Agora ma w głębokim poważaniu wolność słowa (określając to górnolotnie) i że ważniejsze jest parę złotych.

Po przeniesieniu bloga, o którym nieco pisałem, przyszedł czas na przeniesienie pozycjonowania w Google w nowe miejsce, czyli zabawę z SEO po zmianie domeny, aby ludzie wchodząc z wyszukiwarki trafiali w nowe miejsce. Przyznaję, że motywację miałem nikłą – nie zarabiam na wejściach, bo ani nie służy on do sprzedaży produktu, ani nawet nie ma podpiętych innych, pośrednich form zarobku.

Po przeniesieniu treści postanowiłem poczekać. Zwyczajnie i po prostu, nie robiąc nic, poza daniem informacji Google, że blog jest i jak interpretować zawarte na nim dane. Zresztą akurat miałem co innego na głowie. Znaczy ograniczyłem się do wypełnienia Data HighliterWebmaster Tools. Stan taki trwał jakiś miesiąc albo dwa.

Z braku kontroli nad nagłówkami pomysł przekierowania w nowe miejsce przy pomocy kodu odpowiedzi 301 odpadł w przedbiegach, choć to najprostsza, automatyczna i zalecana – także z punktu widzenia SEO – forma przekierowania ruchu w nowe miejsce.

Trochę czasu minęło, ilość wejść na nową lokalizację była szczątkowa, choć miałem nadzieję, że Google zacznie ogarniać sytuację samodzielnie. Niestety tak się nie stało, więc postanowiłem zacząć działać, choć miałem świadomość, że to praca, która się nie automatyzuje. Pierwsze co przyszło mi do głowy, to ustawienie link canonical dla wybranych, najczęściej odwiedzanych wpisów z nową lokalizacją jako celem. I tu okazało się, że Blox przewidział sytuację i… stosowne elementy HTML znikają po dodaniu ich w edycji źródła[1].

Z braku lepszych pomysłów dodałem w najpopularniejszych wpisach namiar na nowe miejsce, poprawiłem też linki do bloga w większości miejsc, gdzie były one umieszczone i… postanowiłem jeszcze poczekać. Poczekałem kwartał, ale nie wydarzyło się nic specjalnego. Statystyki wg Webmaster Tools wyglądały na koniec kwartału następująco:

ostanie 28 dni: impr: 2250, CTR 0,84%, avg pos 33,7. 130 wizyt

Delikatnie mówiąc szału nie ma.

Postanowiłem więc podziałać inaczej. Skoro nie mogę przekierować wyszukiwarki Google, to postanowiłem przekierować przynajmniej żywych ludzi, licząc, że Google w jakiś sposób to zauważy i odpowiednio zinterpretuje. Skoro nic nie działa, to co zadziała na pewno i czego nie można zablokować? Oczywiście JavaScript. Malware korzystający z niego ma się dobrze dzięki obfuskacji, zablokować całkowicie wykorzystania JS na stornie nie bardzo można, bo masa funkcjonalności z niego korzysta. Użyłem następującej wersji przekierowania z jednej lokalizacji na drugą (dla najpopularniejszych wpisów):

<script>
window.location.replace('https://zakr.es/blog/2017/09/goodbye-yanosik/');
</script>

Oczywiście powyższy JS był tylko w odpowiadającym wpisie na starym blogu, a URL w skrypcie to URL na nowym blogu.

Zadziałało nadspodziewanie dobrze. Nadspodziewanie, bo przy wejściu na URL kategorii zawierającej wyświetlany wpis z przekierowaniem, także przekierowywało. Co gorsza przekierowywało przy wejściu na stronę główną, bo także znalazł się tam wpis z przekierowaniem. Może i więcej ruchu przez to, ale niezupełnie o to chodziło i mało to precyzyjne… Dla wpisów z głównej dokonałem więc stosownej korekty w stylu:

<script>
var stringPathName = window.location.pathname;
if (stringPathName == "/2018/02/Waze-jako-nawigacja.html") {
  window.location.replace('https://zakr.es/blog/2018/02/waze-jako-nawigacja/');
}
</script>

Poczekałem miesiąc, wyniki w statystykach były zauważalne, zacząłem więc dodawać tego typu przekierowania dla kolejnych, popularnych linków. Po dwóch miesiącach od dodania przekierowań w JS, wyniki wyglądały następująco:

28 dni: impr: 10450, CTR 4,46%, avg pos 18.8, 490 wizyt

Jak widać wzrost wszędzie. Uznałem, że jest sukces, zacząłem – dla pewności – usuwać większość treści wpisów na starym blogu. Nie było negatywnego wpływu, nastąpił nawet dalszy, równie znaczący wzrost wskaźników. Choć zakładam, że wynika on po prostu z upływu czasu.

Największym zaskoczeniem jest dla mnie, że Google przy pozycjonowaniu uwzględnia JS do tego stopnia. Wiedziałem, że radzi sobie z treścią w JS i umie odczytać URLe. Ale w tym przypadku wygląda, że poprawnie interpretowany jest fakt przekierowania.

Co można było zrobić lepiej lub inaczej? Całość działań można było zamknąć w mniej niż dwa miesiące, gdybym od razu wiedział co robić i działał zdecydowanie. Oczywiście lepsze efekty byłyby, gdyby zmiany dotyczyły wszystkich wpisów. Jest to jednak żmudna, ręczna praca, której poświęcałem kilka minut dziennie przy porannej kawie. Powyższy sposób przekierowania nie jest jedynym dostępnym w JS. Miałem w planach sprawdzenie różnych, ale ten sprawdziłem jako pierwszy i zadziałał powyżej oczekiwań, więc nie testowałem innych.

Na koniec jeszcze garść cyferek. Ingerowałem ręcznie w ww. sposób w 40 wpisów. Wg Matomo nowy blog ma obecnie ok. 4-5 razy większą ilość wizyt, niż stary. Czyli ładny podział zgodnie z zasadą Pareto.

Co dalej? Dodawanie przekierowań w kolejnych wpisach i usuwanie z nich treści. Ostatecznie pewnie usuwanie przekierowanych wpisów, ale póki co nie mam na to ciśnienia.

[1] Tu zniknęła moja wątpliwość w celowość działań Blox w celu przywiązania użytkowników do swojej platformy. Przypominam: technicznie mają kontrolę nad nagłówkami i domeną – to jakby naturalne i cena za korzystanie ze współdzielonej platformy. Do tego wyłączyli parę lat temu – rzekomo tymczasowo – API. Ale jak widać dodatkowo jeszcze celowo ingerują w treść HTML.

UPDATE: Wersja ultimate, czyli przekierowująca – w założeniu – wszystkie wpisy, a dodawana prosto w jednym miejscu (Własny HTML pod każdym wpisem). Sprawdza, czy URL kończy się ciągiem „.html”. Jeśli tak, do URLa bazowego nowej lokalizacji (koniecznie bez / na końcu!) dodaje ścieżkę. Działa dla schematu URLi w WordPress zgodnego z Blox. Wyżej opisane wpisy szczegółowe mają pierwszeństwo.

<script>
var stringPathNameBlog = window.location.pathname;
myRegexp = /(.*?)\.html/;
myBase = "https://zakr.es/blog";
if (stringPathNameBlog.match(myRegexp)){
var match = myRegexp.exec(stringPathNameBlog);
var newLoc = myBase + match[1] + "/";
window.location.replace(newLoc);
}
</script>

UPDATE: Warto jeszcze w ramach dbania o SEO po zmienie domeny poprawić URLe do innych wpisów na blogu tak, by kierowały na nową lokalizację. Jak to zrobić dla WordPressa opisałem w aktualizacji wpisu o migracji z Blox na WordPress.

UPDATE 2: Zmiana domeny na WordPress i dbanie o SEO po niej mogą wyglądać podobnie. Zatem wnioski można nieco uogólnić, choć skrypty JS raczej nie będą konieczne. WordPress zapewne daje lepsze, natywne mechanizmy,

Switchover

Stało się, stało się, to co miało się stać

troszeczkę nieplanowo, noż…

Planowałem najpierw przenieść blog o BKS, poćwiczyć przepięcie ruchu i dopiero wziąć się za ten. Ponieważ z czasem i motywacją było słabo, parę wpisów chodziło mi po głowie, a pisać nie było gdzie, poszedłem na łatwiznę. Stwierdziłem, że albo przeniosę teraz i dopieszczę później, albo nigdy tego nie zrobię. Zatem blog został zamrożony i przeniesiony w nowe miejsce dla Pomiędzy Bitami.

Poszedłem na łatwiznę i przeniosłem się z Blox na WordPressa. Jednak. Z rzeczy związanych z migracją – na razie zmieniłem licencję, za moment pojawi się info we wpisach skąd pochodzą. W najbliższym czasie zmienię źródło feeda RSS (jeśli ktoś czyta via RSS i nie korzysta jeszcze z RSS w wersji opartej o Feedburner, to polecam przepięcie się) i linki z ważniejszych miejsc.

TBH rozważałem mirror statyczny i zaczęcie pisania od nowa, po prostu, ale ostatecznie wykonałem eksport. Wpisy są wszystkie, komentarze być może nie, stron nie ma, bo ani nie mam na to skryptu, ani nie chcę przenosić wszystkiego – przydadzą się tam gruntowne porządki, zresztą to proste copy & paste…

Stoi to wszystko na niezbyt fortunnej lokalizacji, bo arubacloud w czeskim DC szybkością sieci nie grzeszy, ale i tak jest sporo lżej i szybciej, niż na Blox, mimo możliwie tych samych ustawień.

GTtmetrix - blox.pl

GTmetrix - zakr.es

OK, dla jasności, tu są jakieś drobiazgi, których nie ma (przynajmniej na razie) w nowym miejscu, typu LinkWithin itp. ale nie robią one takiej różnicy. No i gdyby było więcej grafik, to wynik wyglądałby gorzej, ale to już kwestia wspomnianej sieci w czeskim DC.

Oczywiście wszystko lata bezpiecznie i wydajnie po SSL i HTTP/2 i mam możliwość pełnej kontroli nad tym, co się dzieje.

Blox pożegnał mnie w stylu, w jakim go zapamiętam – wyłączyłem możliwość komentowania na blogach, zapisałem ustawienia i co? Po napisaniu tego wpisu, czyli kilkanaście minut później, nadal mogłem dodać testowy komentarz.

(Not so) fun fact: uciekłem z Joggera z powodu cenzury i autorytaryzmu administratorów. Doczekałem się cenzury i autorytaryzmu ze strony Agory (ale o tym to już w nowym miejscu więcej napiszę).

UPDATE: Wygląda na to, że ustawienie dot. komentarzy działa wyłącznie dla nowych wpisów, w starych nie ma możliwości wyłączenia możliwości komentowania (pewnie można uprzykrzać życie przy pomocy zepsutej CAPTCHA i moderowania, zamierzam, ale później, może się coś jeszcze przeładuje). Wot usability!

Migracja z Blox na WordPressa – HOWTO

Jak pisałem poprzednio, na pierwszy rzut do migracji poszedł blog o kapeli Bez Krótkich Spodni. Z migracją zeszło mi nieco dłużej, niż planowałem, głównie za sprawą hostingu, który się kończy, a którego nie przedłużam. Zamiast dedyka w Kimsufi zdecydowałem się na dwa VPSy w arubacloud.pl. Zaleta: taniej i SSD. Wada: potrzebuję dwie maszyny, co wiązało się z podziałem usług. I niestety, mimo konteneryzacji część usług jest od siebie zależna, głównie za sprawą domeny. W każdym razie zeszło więcej czasu, niż planowałem, ale jest to sensowniej podzielone.

Sama migracja na WordPress jest prosta. Najpierw instalujemy WordPressa. Long story short:

wget https://wordpress.org/latest.tar.gz
tar -zxf latest.tar.gz
chown www-data:www-data katalog

Pozostaje utworzenie bazy i użytkownika:

CREATE DATABASE wordpress_db;
GRANT ALL PRIVILEGES ON wordpress_db.* TO "wordpress_db_user"@"localhost" IDENTIFIED BY "VeryStrongPassword";

W przypadku instalacji opartej o serwer nginx i WordPressa trzeba jeszcze dodać jedno ustawienie w konfiguracji tego pierwszego:

location /bks/ {
    try_files $uri $uri/ /bks/index.php?$args;
}

Następnie uruchamiamy instalator WordPressa przez WWW i logujemy się. Warto usunąć przykładowy wpis i strony, z których nie korzystamy, można wybrać szablon (cóż, domyślny robi robotę jak dla mnie) i zrobić porządek w pluginach.

Niestety Blox wyciął użytkownikom możliwość eksportu wpisów, więc w tym miejscu musiałem posiłkować się autorskim skryptem, by zdobyć treść bloga z Blox w formacie wordpressowym. Potem szybkie dopieszczenie szablonu, zwłaszcza zdjęcia z nagłówka i… w zasadzie jest. Niestety, obrazki w takim rozwiązaniu są serwowane nadal z serwerów Blox, więc nie mamy pełnej niezależności i będziemy dostawać komunikat ostrzegawczy przy HTTPS, bo nie wszystkie treści są serwowane w sposób bezpieczny.

Jest jednak na to sposób. Okazuje się, że istnieje plugin Download External Images In Posts, który robi dokładnie to, na co wskazuje nazwa – pobiera obrazki ze zdalnego serwera, zapisuje je lokalnie i podmienia linki we wszystkich wpisach, także już istniejących. Działa zadziwiająco dobrze, choć jedna rzecz mi się w nim nie podoba: musi pozostać aktywny po zrobieniu roboty, bo linki nie są podmienione w treści. Ale z tym jestem w stanie żyć.

Ostatni szlif to dodanie statystyk Matomo (dawniej Piwik). Skorzystałem z pluginu Insert Headers and Footers, następnie wkleiłem tam stosowny JS.

Efekt finalny migracji na WordPress widać w pierwszym linku. Jak widać zachowana została treść wpisów, ich daty, komentarze, ich autorzy oraz daty. Działają także tagi i kategorie (tych ostatnich akurat nie używam na blogu BKS). Wszystko jest serwowane po HTTPS (i dodatkowo HTTP/2, ale to już zaleta nginx z odpowiednią konfiguracją), czyli szybko, bezpiecznie i SEO friendly. Tak, jak powinno być. 🙂

Zostało posprzątanie na starym blogu i przekierowanie w nowe miejsce, ale to już bez pośpiechu…

Dodam jeszcze, że WordPress spodobał mi się na tyle, że rozważam migrację tego bloga także na WP, zamiast statycznego Pelicana. Ale nad tym jeszcze chwilę pomyślę.

UPDATE Aby działały poprawnie wszystkie ustawienia dla bezpośrednich odnośników, trzeba podać katalog w konfiguracji, zgodnie z tym opisem.

UPDATE2 Warto zaktualizować URLe w treści postów, żeby kierowały na aktualny blog. Na szczęście można to zrobić automatycznie w prosty sposób. Na Blox schemat URLa posta to http://adresbloga.blox.pl/YYYY/MM/Tytul-wpisu.html
Zakładając, że nasz WordPress używa podobnego schematu, korzystamy z HTTPS i przenieśliśmy się na example.com, czyli mamy https://example.com/YYYY/MM/Tytul-wpisu należy… Zrobić backup bazy (lub całego bloga, polecam wpis o dodatkach do WordPressa). Opisany sposób działa dla MariaDB, goły MySQL podobno może mieć problemy, więc lepiej mieć do czego wrócić. Jak już mamy backup i wiemy co z nim robić, wydajemy polecenie:

update wp_posts set post_content = regexp_replace(post_content, 'http://adresbloga.blox.pl/20(.*?).html', 'https://example.com/20\\1');

W przypadku mojego bloga było to dokładnie:

update wp_posts set post_content = regexp_replace(post_content, 'http://rozie.blox.pl/20(.*?).html', 'https://zakr.es/blog/20\\1');