Jak optymalizacja przycisku „Dodaj do koszyka” oszczędza crawl budget
W zaawansowanym SEO wygrywają ci, którzy zwracają uwagę na detale. Podczas gdy konkurencja skupia się na kolejnym artykule blogowym, prawdziwa przewaga często leży w kodzie – w miejscach, w które mało kto zagląda. Mowa o niepozornym przycisku „Dodaj do koszyka”, który często jest linkiem ustylizowanym na przycisk. Zanim jednak sięgniesz po plik robots.txt, pokażę Ci znacznie lepsze, bardziej eleganckie i fundamentalnie poprawne rozwiązanie, które rozwiązuje problem u źródła i przynosi szereg dodatkowych korzyści dla SEO, UX i dostępności sklepu.

Kod, od którego wszystko się zaczyna
Po wprowadzeniu poniższego kodu do functions.php sklep zyska szereg pozytywnych aspektów, bo Googlebot nie klika w przyciski1
- Crawl budget jest lepiej wykorzystywany
- Oszczędza całkiem dużo render budget Googlebota gdy „Dodaj do koszyka” ma włączony AJAX
- Do kolejki nie trafiają zbędne linki (?add-to-cart), więc zmniejsza się liczba zbędnych adresów, które Googlebot musi sprawdzić
- Strona działa identycznie dla użytkownika końcowego
- Przyciski lepiej spełniają swoją rolę pod kątem WCAG
- Działania AJAX typu szybkie dodawanie do koszyka pozostaje w pełni aktywne
function seekio_add_to_cart_button( $button_html, $product, $args ) {
if ( $product->is_type( 'simple' ) ) {
$product_id = $product->get_id();
$button_text = $product->add_to_cart_text();
$button_class = esc_attr( isset( $args['class'] ) ? $args['class'] : 'button' );
$quantity = esc_attr( isset( $args['quantity'] ) ? $args['quantity'] : 1 );
$new_button_html = sprintf(
'<button type="submit" data-quantity="%s" class="%s" data-product_id="%s" data-product_sku="%s" aria-label="%s">%s</button>',
$quantity,
$button_class . ' product_type_simple add_to_cart_button ajax_add_to_cart',
$product_id,
esc_attr( $product->get_sku() ),
esc_attr( sprintf( __( 'Add to cart: “%s”', 'woocommerce' ), $product->get_name() ) ),
esc_html( $button_text )
);
return $new_button_html;
}
return $button_html;
}
add_filter( 'woocommerce_loop_add_to_cart_link', 'seekio_add_to_cart_button', 10, 3 );Powyższy kod zamienia domyślny link <a> na semantyczny przycisk <button> dla produktów prostych.
3 powody dla których ta zmiana jest dobra dla SEO
1. Semantyczny HTML
Roboty Google są coraz mądrzejsze. Analizują treść i strukturę HTML, aby zrozumieć, czym jest dany element i jakie jest jego przeznaczenie oceniając przy tym cały dokument.
- Znacznik
<a>jako typowy link – służy do nawigacji. Jego celem jest przeniesienie użytkownika na inną stronę lub do innej części tej samej strony - Znacznik
<button>jako przycisk – służy do wykonania akcji na bieżącej stronie, np. wysłania formularza, otwarcia okna modalnego lub w celu dodania produktu do koszyka bez przeładowania strony
Użycie <button> zamiast <a> do akcji „Dodaj do koszyka” jest semantycznie poprawne. To jest sygnał dla Googlebota: „Hej, ten element nie prowadzi do nowej treści, on wykonuje konkretną funkcję„. Strony zbudowane zgodnie ze standardami i logiką HTML są postrzegane jako strony wyższej jakości, co jest pozytywnym sygnałem rankingowym.
Zapraszam do artykułu „Odległość semantyczna między terminami w dokumencie HTML” gdzie szczegółowo opisuję czym jest Ranking Component składający się z 3 modułów (Page Analyzer, Distance Component i Relevance Component) oraz tego jak Googlebot ocenia stronę.
2. Lepsze doświadczenie użytkownika (UX) i sygnały behawioralne
User Experience to ważny ale też pośredni czynnik rankingowych. Dlaczego? zadowolony użytkownik spędza na stronie więcej czasu, chętniej na nią wraca i rzadziej ją opuszcza zaraz po wejściu.
Użycie odpowiednich znaczników HTML poprawia interakcję ze stroną. Prawidłowe ostylowanie przycisków i ich zachowanie (np. stan :focus czy :disabled) jest łatwiejsze i bardziej naturalne dla <button>
Chociaż jest to subtelna różnica, suma takich drobnych ulepszeń buduje pozytywne doświadczenie, które Google potrafi zmierzyć, ocenić i docenić.
O czynnikach behawioralnych, które trafiają do Google pisałem w artykule „Wielowymiarowa rola kliknięć w ocenie i rankingu„. Opisałem zaawansowane systemy śledzenia, modelowania zachowań i wewnętrzne metryki ewaluacyjne, których ostatecznym celem jest próba zmierzenia satysfakcji użytkownika z treści zawartych na stronie.
3. Dostępność (Accessibility) – niedoceniany aspekt SEO
To jest absolutnie najważniejszy punkt w moim kodzie. Zwróć uwagę na ten fragment: aria-label="%s", który dynamicznie generuje opis dla czytników ekranu.
aria-label to atrybut, który dostarcza tekst alternatywny dla elementów, które nie mają widocznej etykiety. Jest on odczytywany przez czytniki ekranu używane przez osoby z niepełnosprawnością wzroku. Dzięki temu czytniki ekranu używane przez osoby niedowidzące, precyzyjnie informują o akcji, jaką wykonuje przycisk. To jest sygnał wysokiej jakości technicznej witryny.
Dlaczego to jest ważne dla SEO?
- Strony dostępne dla wszystkich użytkowników są uznawane za bardziej wartościowe. Google w swoich wytycznych2 i narzędziach (np. Lighthouse) coraz mocniej podkreśla znaczenie dostępności, np. alty w obrazach, to nie miły dodatek dla Googlebota, a realna pomoc dla dostępności
- Dodatkowe, opisowe atrybuty pomagają robotom lepiej zrozumieć czego dotyczy dany element i w jakim kontekście występuje (podobnie jak schema)
- Dbałość o dostępność świadczy o wysokiej jakości technicznej witryny
W skrócie dlaczego tak uważam? Strona przyjazna dla osób z niepełnosprawnościami, to strona o lepszym UX dla wszystkich, a lepszy UX to lepsze SEO i zrozumienie kontekstu dla robotów.
Co z linkowaniem wewnętrznym?
Można by argumentować, że zamiana <a> na <button> pozbawia nas linku wewnętrznego i z tym się zgadzam ale… link „Dodaj do koszyka” w WooCommerce nie jest linkiem kanonicznym do strony produktu (zawiera parametr ?add-to-cart=ID-PRODUKTU), a przynajmniej nie powinien nim być. Główne linki wewnętrzne, które przekazują „moc SEO„, to link na zdjęciu produktu oraz w tytule / nazwie. Zatem utrata takiego „linku” na przycisku akcji jest całkowicie niezauważalna i w porównaniu do korzyści płynących z poprawy semantyki, UX i dostępności zdecydowanie lepsza.
W tej kwestii nic więcej nie mam do dodania jednak…
Co z disallow w robots?
Moje rozwiązanie i robots.txt częściowo rozwiązują ten sam problem ale działają na zupełnie innych poziomach.
User-agent: * Disallow: /*?add-to-cart=
To polecenie blokuje robotom dostęp do adresu, który zawiera parametr ?add-to-cart= i to spełnia swoje zadanie, bo roboty nie zobaczą żadnej treści ALE.. zmiana kodu na <button> jest rozwiązaniem fundamentalnie lepszym pod praktycznie każdym względem.
- Rozwiązanie z robots.txt – Googlebot wchodzi na stronę, widzi wszystkie XXX linków z parametrem ?add-to-cart i dla każdego z nich musi:
- Zarejestrować istnienie linku i dodać do kolejki
- Sprawdzić w pliku robots.txt, czy może go odwiedzić
- Zobaczyć dyrektywę
Disallowi zrezygnować z crawlowania. To jest mikro-operacja, ale pomnożona przez tysiące produktów i setki wizyt robota, może zużywać zasoby i czas, które Googlebot mógłby przeznaczyć na coś innego
- Rozwiązanie ze zmianą kodu na
<button>– Googlebot wchodzi na stronę i nie widzi linków z?add-to-cart=. Zamiast tego widzi elementy<button>, które z definicji nie są linkami i nie mają atrybutuhref, więc Googlebot:- Nie ma żadnego URL do przetworzenia
- Nie ma potrzeby sprawdzania
robots.txt - Nie ma marnowania nawet jednego cyklu procesora na analizę bezwartościowego linku
Problem został rozwiązany u samego źródła – zamiast mówić Google „te drzwi są zamknięte”, po prostu nie pokazuję mu tych drzwi 🙂
| Cecha | Disallow w robots.txt | <button> |
|---|---|---|
| Sposób działania | Reaktywny – blokuje robotom linki, które już istnieją na stronie | Proaktywny – eliminuje zbędne linki u źródła, więc roboty ich nie zobaczą |
| Crawl budget | Oszczędza ale wciąż wymaga od Google przetworzenia linku i sprawdzenia reguły | Maksymalnie oszczędza, ponieważ URL w ogóle nie jest widoczny dla robota |
| Semantyka i jakość | Praktycznie nie ma tu żadnej semantyki i jakości, a zwykłe blokowanie dostępu | Sygnał wysokiej jakości technicznej typu: „cześć, używam HTML zgodnie z jego przeznaczeniem„ |
| User Experience (UX) | Brak | Poprawia doświadczenie użytkownika. Przyciski są stworzone do akcji AJAX. Działanie jest płynniejsze i bardziej przewidywalne dla użytkownika |
| Dostępność (A11y) | Nie ma wpływu. Link zostaje linkiem, często bez dobrego kontekstu dla czytników ekranu. Chociaż można dodać aria-label, to nie jest zalecaną praktyką w tym konkretnym przypadku | Moje rozwiązanie automatycznie dodaje aria-label, co drastycznie poprawia dostępność i jest pozytywnym sygnałem jakościowym |
| Reasumując | Rozwiązanie dobre ale nie idealne | Idealne, fundamentalnie i czysto techniczne rozwiązanie |
Googlebot nadal odwiedza stare adresy
Jeśli sklep istnieje od dłuższego czasu, to z ogromnym prawdopodobieństwem Googlebot zapisał adresy z ?add-to-cart do swojej pamięci i globalnej kolejki stron do odwiedzenia (tzw. Crawl Queue). Nawet jeśli te linki zostały usunięte ze strony, to nadal istnieją w tej kolejce. Mając zapisane takie URLe, to Googlebot będzie wracał do znanych mu adresów, aby sprawdzić ich status (kod http).
Najbezpieczniejszym rozwiązaniem jest wprowadzić <button>, bo gdy do sklepu dojdą nowe produkty, to Googlebot już nie będzie odwiedzał adresów z parametrem ?add-to-cart, a przy tym warto ustawić disallow w robots.txt dla starszych adresów. Gdyby ktoś w internecie (jakimś cudem) linkował bezpośrednio do produktu z „Dodaj do koszyka”, to i tak powinien być ustawiony canonical na URL bez parametru. Takie rozwiązanie jest najlepszym wyjściem.
Teoretycznie można pokosić się o zwracanie innego statusu http, np. 404, 410 albo 403 tylko dla adresów zawierających parametr, jednak uważam że to jest ryzykowna strategia i nieprzewidywalna. Biorąc to pod uwagę kompletnie nieopłacalna.
Polecana przeze mnie strategia „hybrydowa” jest moim zdaniem najlepszym rozwiązaniem:
- Wdróż kod – zmień linki
<a>na przyciski<button>, aby rozwiązać problem u źródła dla wszystkich nowych i istniejących produktów - Dodaj regułę w robots.txt lub upewnij się, że taka istnieje – użyj dyrektywy
Disallow: /*?add-to-cart=, która zablokuje Googlebota przed marnowaniem zasobów na stare adresy, które wciąż ma w swojej kolejce - Sprawdź canonical – upewnij się, że strony produktów mają poprawnie ustawione linki kanoniczne na wersje URL bez parametrów. To ostateczne zabezpieczenie na wypadek, gdyby ktoś z zewnątrz (jakimś cudem) linkował do URL z parametrem
Podsumowanie, czyli mała zmiana i wielkie korzyści
Jak widać, zmiana jednego elementu na stronie, tj. linku na semantyczny przycisk – uruchamia lawinę korzyści dla SEO:
- Optymalizuje budżet crawlowania pozwalając Googlebotowi skupić się na tym co jest ważne
- Poprawia semantykę HTML wysyłając sygnał o wysokiej jakości technicznej strony
- Podnosi jakość User Experience i dostępność, co przekłada się na pozytywne sygnały behawioralne
W nowoczesnym SEO diabeł tkwi w szczegółach. Wierzę, że dbanie o takie fundamenty to inwestycja, która procentuje w długoterminowej walce o najwyższe pozycje w wynikach wyszukiwania 😉
- Googlebot nie klika w przyciski – wypowiedzi Martina Splitta z Google podczas JavaScript SEO Office Hours [youtube] ↩︎
- Podstawowe aspekty a11y, które zwiększają dostępność witryny dla różnych grup osób [support.google.com] ↩︎
