Umów konsultację

Bezpłatna wycena w 24h

Migracja Sportywalki.com.pl – WordPress + Elementor → Headless Next.js. 202 trasy, zero downtime

Migracja Sportywalki.com.pl – WordPress + Elementor → Headless Next.js. 202 trasy, zero downtime

Case Study18 kwietnia 202612 min czytania

Największy polski portal o sportach walki — MMA, boks, kickboxing, freak fights — działał na współdzielonym hostingu z WordPressem, Elementorem Pro i wtyczką Seraphinite Accelerator. Ponad 120 artykułów, archiwa kategorii i autorów, lata pracy redakcyjnej nagromadzone w CMS-ie. I wydajność, która nie nadążała za rosnącym ruchem.

Zadanie: zmigrować cały portal do Next.js bez żadnego downtime'u i bez regresji SEO. Poniżej opisujemy dokładnie, co zrobiliśmy, jakie podejście przyjęliśmy i dlaczego — włącznie z technicznymi decyzjami, które sprawiają, że ten projekt różni się od typowej migracji headless.

Problem: Elementor + współdzielony hosting = sufit wydajnościowy

Seraphinite Accelerator z agresywnym cachowaniem robił co mógł, ale sufit był nieunikniony. Przy każdym żądaniu z niezakeszowanego IP serwer PHP musiał wygenerować stronę od zera — Elementor, baza danych, ładowanie motywu, wszystkie wtyczki. TTFB powyżej 600 ms dla zimnego cache'u był normą, nie wyjątkiem.

Dodatkowy problem: każda zmiana designu wymagała dostępu do panelu WP i znajomości Elementora. Brak kontroli nad frontendem oznaczał brak możliwości optymalizacji pod Core Web Vitals — Elementor generuje kilkadziesiąt kilobajtów własnego JavaScriptu i CSS-u, których nie można wyłączyć bez zepsucia layoutu.

Podejście — nie GraphQL API, ale static HTML export

Większość migracji headless WordPress wygląda tak: instalujemy WPGraphQL, budujemy Next.js pobierający dane przez GraphQL, deployujemy. To standardowe podejście.

W przypadku sportywalki.com.pl wybraliśmy inne rozwiązanie. Zamiast budować warstwę API GraphQL do istniejącego WP, wyeksportowaliśmy pełny rendering każdej podstrony do statycznych plików JSON — Next.js serwuje je jako dynamiczne strony z własną warstwą transformacji HTML.

Dlaczego? Elementor generuje specyficzną strukturę HTML z własnymi klasami, inline stylami i interakcjami JS. Próba odtworzenia tego przez GraphQL wymagałaby parsowania surowych danych WP i ręcznego rekonstruowania layoutu każdej podstrony — przy 202 trasach to nierealne. Static HTML export zachowuje oryginalny rendering jeden do jednego, a transformacja Cheerio nadpisuje tylko to, co potrzebne.

Aspekt Standard (WPGraphQL) Tu zastosowane
Źródło treściGraphQL API z WPStatic HTML export każdej podstrony
LayoutRekonstruowany w ReactOryginalny HTML + Cheerio transforms
Zależność od WP w runtimeWymaganaZero — WP odizolowany od użytkownika
Nowe treściPrzez GraphQL w runtimeRewalidacja przez ISR

Skala migracji — co zostało przeniesione

Typ zasobu Liczba / Rozmiar
Wpisy blogowe (artykuły)120
Strony statyczne28
Archiwa kategorii + paginacje10
Biblioteka mediów2 370 plików, 141 MB
Cache CSS (Seraphinite Accelerator)516 plików CSS
Assety wtyczek (Elementor, Cookie Law, Smush)Wszystkie w public/
XML sitemaps (Yoast standard)4 mapy + index

Kluczowy aspekt: wszystkie assety WordPress — CSS, JavaScript, obrazy — serwowane lokalnie z katalogu public/. Żadne żądanie przy renderowaniu strony nie trafia do serwera WP. WordPress jest całkowicie odizolowany od użytkownika końcowego.

Cheerio HTML Transform Pipeline — co robi i dlaczego jest konieczne

Wyeksportowany HTML z Elementora to nie gotowy, czysty kod. Zawiera martwy JavaScript, absolutne URL-e do starego hostingu i brakujące interakcje. Własny parser Cheerio przetwarza każdy wyeksportowany plik i wykonuje serię transformacji:

  • Usuwanie martwego JavaScriptu — skrypty Elementora, jQuery i wszystkie inline skrypty niepotrzebne po odizolowaniu od WP.
  • Normalizacja URL-i — wszystkie absolutne linki do starego hostingu zamieniane na relatywne lub nowe URL-e Vercel.
  • Iniekcja sekcji FAQ — do każdego artykułu dodawana jest sekcja FAQ z 5 pytaniami wygenerowanymi przez AI. Łącznie 600 par pytanie/odpowiedź dla 120 artykułów.
  • YouTube embeds — 10 filmów przypisanych do konkretnych artykułów osadzanych w odpowiednich miejscach, z youtube-nocookie.com i loading="lazy".
  • Dynamiczny TOC — nagłówki H2/H3 wyekstrahowane, budowany spis treści dla każdego artykułu.
  • Asset proxy fallback — trasy /wp-assets/[...assetPath] jako fallback dla dynamicznych URL-i Elementora.

Elementor bez Elementora — interakcje w czystym TypeScript

Popupy scroll-triggered, off-canvas panele, FAQ akordeony — wszystkie działały przez JavaScript Elementora, który wymagał jQuery. Łącznie ponad 200 KB JavaScriptu zbędnego w nowej architekturze.

Każda interakcja odtworzona od zera w czystym TypeScript: popupy przez własny hook z IntersectionObserver, off-canvas panel jako komponent React z animacją CSS, FAQ akordeony jako prosty useState — kilkanaście linii kodu zamiast 200 KB zewnętrznej biblioteki.

Efekt: 200 KB mniej JavaScriptu po stronie użytkownika, bezpośrednie przełożenie na LCP i TTI.

Max Mazurkiewicz

Max Mazurkiewicz

Founder

POTRZEBUJESZ SPERSONALIZOWANEJ WYCENY?

Chcesz się na coś zdecydować ale od nadmiaru możliwości boli głowa? Skontaktuj się z nami, dobierzemy rozwiązanie do potrzeb Twojej firmy.

Umów się na konsultację

Nowa implementacja to pełny Google Consent Mode v2 z granularnym systemem zgód w 5 kategoriach (niezbędne, funkcjonalne, personalizacja, analityczne, marketingowe) i synchroniczną inicjalizacją GA4 — brak okna wait_for_update, które przy błędnej implementacji powoduje nieprawidłowy stan zgód w raportach.

Zdarzenie GA4 Trigger
scroll_depthPrzewinięcie 50% i 90% artykułu
outbound_clickKliknięcie w link zewnętrzny (sklep, social media, partnerzy)
select_contentNawigacja między podstronami portalu
search + view_search_resultsWyszukiwanie wewnętrzne na portalu
file_downloadPobranie pliku (PDF, ZIP, MP4)
shareKliknięcie ikony udostępnienia (FB, X, WhatsApp)
generate_leadWysłanie dowolnego formularza kontaktowego

Każde zdarzenie zawiera kontekst strony: page_type (article/category/author), content_category (MMA/boks/kickboxing/freak), author. Dane w GA4 nie są płaskie — można filtrować po kategorii treści i zobaczyć, które sekcje portalu angażują użytkowników najgłębiej.

FAQ Schema — 600 par pytanie/odpowiedź wygenerowanych przez AI

Google Rich Results dla FAQ (FAQPage w JSON-LD) dają potencjalnie duże zwiększenie powierzchni w SERP. Przy 120 artykułach oznacza to ogromny potencjał, ale też ogromną ilość pracy — ręczne napisanie 5 pytań do każdego artykułu to 600 par.

Claude AI przeanalizował treść każdego z 120 artykułów i wygenerował 5 par pytanie/odpowiedź zgodnych z wytycznymi Google Rich Results — pytania w naturalnym języku polskim, odpowiedzi jako pełne zdania, bez powielania treści nagłówków. Cheerio pipeline wstrzykuje sekcję FAQ i odpowiadający JSON-LD do każdego artykułu automatycznie podczas buildowania.

SEO — zachowanie bez regresji

Migracja headless to ryzyko dla SEO. Błędne przekierowania, zaginięte meta tagi, zmieniona struktura URL — każdy z tych błędów może kosztować pozycje wypracowane przez lata.

  • Wszystkie meta tagi, opisy, canonical URL, OG/Twitter cards — zachowane 1:1 z oryginalnego HTML.
  • Robots.txt zachowany bez zmian — Next.js serwuje go ze statycznego pliku.
  • Pełny zestaw XML sitemaps w standardzie Yoast SEO: post-sitemap, page-sitemap, category-sitemap, author-sitemap, sitemap_index.
  • Brak regresji w Search Console po zmianie DNS — zero 404, zero zagubionych URL-i.

Wyniki wydajnościowe

Metryka Przed (WP + Elementor) Po (Next.js + Vercel)
TTFB>600 ms (PHP, zimny cache)<200 ms (Edge CDN)
Zewnętrzne żądania do WPKażde żądanie stronyZero
JavaScript Elementora~200 KB jQuery + Elementor JS0
FAQ Schema (artykuły)Brak600 par pytanie/odpowiedź
Regresja SEOBrak — zero 404 po migracji

Wnioski — kiedy static HTML export zamiast GraphQL

Podejście z static HTML export i Cheerio pipeline nie jest standardowe — i celowo. Jest optymalne gdy frontend jest zbudowany w Elementorze (rekonstrukcja layoutu przez GraphQL byłaby trudniejsza niż transformacja istniejącego HTML), gdy chcesz całkowicie odizolować WP od użytkownika, i gdy priorytetem jest brak regresji SEO — oryginalny HTML zachowuje wszystkie meta tagi i strukturę dokładnie tak jak były.

Dla nowych projektów, gdzie frontend jest budowany od zera, standardowe podejście WPGraphQL + Apollo Client jest prostsze i łatwiejsze w utrzymaniu. Ale dla migracji istniejącego serwisu z Elementorem — static HTML export bywa jedynym sensownym wyborem.

sportywalki.com.pl po migracji ma wydajność, której współdzielony hosting z WordPressem i Elementorem nigdy nie był w stanie zapewnić — i zachowany w 100% dorobek SEO wypracowany przez lata pracy redakcyjnej.

Najczęściej zadawane pytania

Kluczowe kroki: eksport całej treści, mapa przekierowań 301 dla wszystkich URL-i, odtworzenie meta tagów i Schema markup, przeniesienie plików mediów i walidacja indeksacji w GSC po migracji. W Sportywalki.com.pl przenieśliśmy 202 trasy bez spadku widoczności.

Cheerio to biblioteka Node.js do parsowania HTML — działa jak jQuery na serwerze. Przy migracji użyliśmy jej do automatycznej transformacji treści z WordPressa (czyszczenie shortcode Elementora, zamiana klas CSS, ekstrakcja struktury nagłówków) na czysty HTML kompatybilny z Next.js.

Tak — Google nie rozróżnia, kto napisał FAQ, liczy się jakość i trafność odpowiedzi. W Sportywalki wygenerowaliśmy 600 zestawów FAQ Schema AI, które przeszły ręczną weryfikację. Kluczowe: pytania muszą odpowiadać realnym zapytaniom użytkowników, nie być sztucznie napompowane.

Consent Mode v2 to mechanizm Google pozwalający dostosować działanie tagów (GA4, Google Ads) do zgody użytkownika na cookies. Od marca 2024 jest wymagany w UE do zbierania danych remarketingowych. Bez niego Google Ads nie będzie budować list odbiorców z Twojego ruchu.

Zależy od złożoności — portal informacyjny z artykułami to 4–8 tygodni. Jeśli dochodzą dynamiczne funkcjonalności (formularze, integracje API, system komentarzy), czas rośnie do 8–12 tygodni. Sportywalki z 202 trasami i pipeline transformacji treści zajęły ok. 7 tygodni.

Max Mazurkiewicz
Max Mazurkiewicz
Founder
Digital marketing expert