Automatyczne testy regresji SEO w GitHub Actions — noindex, link kanoniczny i redirecty pod kontrolą CI/CD
Jeden przypadkowy noindex i tracisz tygodnie pozycji. Jak CI/CD i Playwright blokują regresje SEO zanim w ogóle trafią na produkcję.
Maciej Sala
Founder StriveLab
6 min czytaniaOpublikowano 30 maja 2026 (Aktualizacja 6 lipca 2026)
Dlaczego techniczne SEO zasługuje na testy regresji
W praktyce testujemy logikę biznesową, komponenty, ścieżki użytkownika — a metadane SEO traktujemy często tak, jakby były odporne na zmiany. Tymczasem to właśnie one są wyjątkowo kruche, ponieważ zależą od konfiguracji, która może się łatwo wymknąć spod kontroli przy refaktorze. Przykładowo, ktoś zmienia komponent layoutu i niechcący usuwa tag linku kanonicznego; ktoś inny dodaje noindex na środowisku staging i zapomina go zdjąć przed mergem do głównej gałęzi. Migracja routingu podmienia 301 na 302, przez co Google przestaje przekazywać moc linków. Scenariuszy jest mnóstwo i nieuwaga może drogo kosztować.
Wspólnym mianownikiem tych błędów jest to, że żaden z nich nie wywoła awarii widocznej dla użytkownika. Aplikacja działa sobie bez zarzutu, testy funkcjonalne są zielone, a problem ujawnia się dopiero, gdy ruch organiczny zaczyna spadać — czyli z perspektywy biznesu o wiele za późno. Test regresji SEO domyka tę lukę, bo sprawdza dokładnie te rzeczy, których nie widać gołym okiem, ale które decydują o tym, jak stronę traktuje wyszukiwarka.
Co testować w automatycznych testach SEO
Zanim napiszemy kod, warto ustalić zakres. Dobry zestaw testów SEO koncentruje się na kilku obszarach, które najczęściej ulegają regresji.
Pierwszy to — najważniejsza asercja w całym zestawie. Strony, które mają się indeksować, nie mogą zawierać noindex. Drugi to — musi istnieć, być bezwzględnym adresem i wskazywać właściwą wersję strony. Trzeci to podstawowe metadane, czyli tytuł i meta description, których brak albo pustka oznacza utratę kontroli nad tym, jak strona prezentuje się w wynikach.
Na stronach wielojęzycznych dochodzą tagi , których spójność łatwo zepsuć przy zmianach w i18n. Wreszcie przekierowania — kluczowe redirecty muszą zwracać 301, a nie 302 czy, co gorsza, prowadzić przez łańcuch pośrednich adresów. Każdy z tych obszarów to jedna albo dwie proste asercje, a razem tworzą siatkę, przez którą typowe regresje SEO po prostu nie przejdą.
Testy metadanych SEO w Playwright
Zacznijmy od najważniejszego — sprawdzenia zawartości <head> na kluczowych typach stron. Poniższy test weryfikuje, że strona produktowa indeksuje się poprawnie i ma komplet metadanych.
Code
// tests/seo/metadata.spec.tsimport { test, expect } from '@playwright/test'test.describe('Regresja SEO — metadane', () => { test('strona produktu ma poprawne metadane i nie jest noindex', async ({ page, }) => { await page.goto('/produkty/przykladowy-produkt') // Najważniejsze: brak przypadkowego noindex const robots = await page .locator('meta[name="robots"]') .getAttribute('content') expect(robots ?? '').not.toContain('noindex') // Canonical istnieje, jest bezwzględny i wskazuje właściwy adres const canonical = await page .locator('link[rel="canonical"]') .getAttribute('href') expect(canonical).toMatch(/^https:\/\//) expect(canonical).toContain('/produkty/przykladowy-produkt') // Tytuł i description są obecne i niepuste await expect(page).toHaveTitle(/.+/) const description = await page .locator('meta[name="description"]') .getAttribute('content') expect(description?.length ?? 0).toBeGreaterThan(0) })})
Logika jest prosta i czytelna, ale dokładnie ta prostota jest zaletą — każdy w zespole rozumie, co test sprawdza i dlaczego jego niepowodzenie blokuje merge. Asercja na noindex jest tu celowo postawiona jako pierwsza, bo to ona chroni przed najkosztowniejszym scenariuszem.
Testy przekierowań 301 i 302 w regresji SEO
Drugi filar to przekierowania. Tutaj kluczowy jest jeden szczegół: żeby sprawdzić status redirectu, nie wolno za nim automatycznie podążać, bo wtedy zobaczysz dopiero stronę docelową, a nie samo przekierowanie. W Playwright wykonujemy więc surowe żądanie z wyłączonym podążaniem za redirectami.
Code
// tests/seo/redirects.spec.tsimport { test, expect } from '@playwright/test'test.describe('Regresja SEO — przekierowania', () => { test('stary adres przekierowuje 301 na nowy, bez łańcucha', async ({ request, }) => { const response = await request.get('/stary-adres-produktu', { maxRedirects: 0, }) // Status musi być 301 (trwałe), nie 302 (tymczasowe) expect(response.status()).toBe(301) // Location wskazuje docelowy, kanoniczny adres expect(response.headers()['location']).toBe('/nowy-adres-produktu') })})
Ten test wyłapuje trzy typowe regresje naraz: podmianę trwałego 301 na tymczasowy 302 (przez co Google nie przenosi pozycji na nowy adres), zerwanie przekierowania, które zaczyna zwracać 404, oraz pojawienie się łańcucha pośrednich redirectów. Wybór między Playwright a Cypress to tylko jeden z kontekstów, w których te dwa narzędzia się różnią — jeśli prowadzisz projekt Next.js i chcesz zobaczyć pełniejsze porównanie pod kątem CI i component testingu, mam je w zestawieniu Cypress vs Playwright dla projektów Next.js. Każdy z tych przypadków potrafi po cichu kosztować pozycje wypracowane latami, a tutaj kończy się czerwonym testem w pull requeście. Jeśli prowadzisz większą migrację adresów, warto połączyć to z wiedzą z artykułu o migracji treści i redirectach 301 przy przejściu z WordPressa na Next.js.
Jak wpiąć testy regresji SEO w GitHub Actions
Same testy nie chronią niczego, dopóki nie uruchamiają się automatycznie przy każdej zmianie. Centralną częścią automatyzacji jest , gdzie definiujemy workflow uruchamiany na każdy pull request.
Code
# .github/workflows/seo-regression.ymlname: Regresja SEOon: pull_request: branches: [main]jobs: seo-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npx playwright install --with-deps chromium # Build i start aplikacji w tle - run: npm run build - run: npm start & - run: npx wait-on http://localhost:3000 # Tylko testy SEO — szybko i celowo - run: npx playwright test tests/seo
Po dodaniu tego workflow każdy pull request automatycznie buduje aplikację i uruchamia na niej zestaw testów SEO. Jeśli któryś nie przejdzie — bo ktoś zostawił noindex albo zepsuł link kanoniczny — GitHub oznaczy sprawdzenie jako nieudane i zablokuje merge. Aby ta blokada faktycznie działała, ustaw ten workflow jako wymagane sprawdzenie statusu w regułach ochrony gałęzi main. Dopiero wtedy zielony test staje się warunkiem wejścia kodu na produkcję, a nie tylko informacją, którą można zignorować.
Dlaczego warto testować SEO automatycznie, skoro mam Search Console?
Bo Search Console informuje o problemie po fakcie — często z kilkudniowym opóźnieniem, gdy regresja jest już na produkcji i zdążyła zaszkodzić. Przypadkowy noindex albo zepsuty link kanoniczny potrafi wyciąć stronę z indeksu na tygodnie, zanim w ogóle zauważysz spadek ruchu. Test automatyczny w CI/CD wyłapuje taki błąd, zanim kod zostanie zmergowany — przesuwa wykrycie z „klient dzwoni, że ruch spadł" na „pull request nie przeszedł".
Playwright czy Cypress do testów SEO?
Oba narzędzia poradzą sobie z tym zadaniem, bo testy SEO sprowadzają się do sprawdzenia zawartości <head> i zachowania przy przekierowaniach. W 2026 dla zestawów regresyjnych częściej rekomenduje się Playwright — ma wyższą stabilność testów, natywną integrację z GitHub Actions i wygodną obsługę wielu przeglądarek. Cypress świetnie sprawdza się przy szybkim testowaniu komponentów w trakcie developmentu. Jeśli zaczynasz od zera pod kątem regresji SEO w CI, postaw na Playwright.
Co konkretnie powinien sprawdzać test regresji SEO?
Minimum to: brak przypadkowego noindex na stronach, które mają się indeksować; poprawny i bezwzględny tag linku kanonicznego; obecność tytułu i meta description; poprawność tagów hreflang na stronach wielojęzycznych; oraz to, czy kluczowe przekierowania zwracają status 301, a nie 302 czy łańcuch redirectów. Dla stron z danymi strukturalnymi warto dodać walidację obecności i poprawności JSON-LD.
Czy takie testy spowalniają pipeline CI/CD?
Minimalnie. Testy SEO są lekkie — sprawdzają zawartość HTML i nagłówki odpowiedzi, nie wymagają klikania przez całą aplikację. Zestaw kilkunastu asercji na kluczowych typach stron wykonuje się w kilkanaście sekund. To nieporównywalnie mniej niż koszt naprawy deindeksacji wykrytej dopiero na produkcji. Jeśli zależy Ci na czasie, możesz uruchamiać je równolegle z resztą testów albo tylko na zmienionych ścieżkach.
Jak testować redirecty 301 w Playwright?
Najpewniej przez wykonanie żądania bez automatycznego podążania za przekierowaniem i sprawdzenie statusu oraz nagłówka Location pierwszej odpowiedzi. W Playwright użyjesz do tego request.get(url, { maxRedirects: 0 }) i zweryfikujesz, że status to 301, a Location wskazuje docelowy, kanoniczny adres. To wyłapie zarówno podmianę 301 na 302, jak i przypadkowe zerwanie przekierowania.
O autorze
Maciej Sala
Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwijam własne projekty.
Najbardziej kosztowne błędy SEO uderzają cicho i niepostrzeżenie. Strona bezproblemowo się ładuje, formularz dalej działa, a użytkownik normalnie z niej korzysta. Jednocześnie Google zaczyna dostawać nieprawidłowy link kanoniczny, brakujący hreflang albo nadany przypadkowo noindex . QA w SEO polega na wyraźnych regułach w kodzie, testach i walidacji danych.
Maciej Sala
Founder StriveLab
Dogłębne porównanie Cypress i Playwright w kontekście projektów Next.js. doświadczenie deweloperskie, szybkość, wsparcie dla SSR i React – który framework testowy wybrać?
Maciej Sala
Founder StriveLab
Ten sam błąd może kosztować dwie minuty czasu pracy albo kilka tygodni braku ruchu organicznego. Przypadkowy noindex zatrzyma test w CI, poprawiasz jedną linijkę kodu i sytuacja jest pod kontrolą. Jeśli jednak przejdzie na produkcję, strona może wypaść z Google, przychody spadną po cichu, a po naprawie nadal trzeba czekać na ponowne crawlowanie i indeksację. Technicznie to ta sama poprawka, ale opóźnienie w jej wdrożeniu, może drogo kosztować.