Modelowane listy odbiorców nie zawierają konkretnych osób, tylko prawdopodobieństwa. Wyjaśniam, jak powstają, gdzie ich szukać w panelu i jak czytać ich raporty.
Linkowanie wewnętrzne to obszar, w którym najczęściej widzę rozdźwięk między tym, co ktoś sobie zaplanował, a tym, co faktycznie jest w kodzie strony. Na wizytówce z dwudziestoma podstronami można to trzymać w głowie. Na portalu, który publikuje kilkanaście tekstów dziennie i ma za sobą dziesięć lat archiwum, nikt tego nie ogarnia — ani redakcja, ani specjalista SEO wynajęty na kilka dni w miesiącu.
Od kilkunastu miesięcy do tego zadania używam modeli językowych i wektorowych reprezentacji tekstu. Nie dlatego, że to modne, ale dlatego, że problem szukania podobieństwa znaczeniowego między tysiącami dokumentów jest dokładnie tym, do czego te narzędzia się nadają. Ważne jest jednak, gdzie postawić granicę: model podpowiada kandydatów, decyzję i odpowiedzialność zostawiam ludziom.
Opisuję poniżej proces, którego używam, razem z miejscami, w których się potykałem.
Duży serwis nie ma jednego problemu z linkowaniem, ma trzy różne i każdy wymaga innej reakcji.
Pierwszy to archiwum bez linków wchodzących. Tekst z 2019 roku dostał kilka linków w tygodniu publikacji i od tego czasu nic. Nowe artykuły na ten sam temat linkują do siebie, a stary materiał wisi na końcu paginacji kategorii, praktycznie odcięty od reszty serwisu.
Drugi to linkowanie odwrotne do wartości biznesowej. Najwięcej linków dostają teksty, które akurat były na stronie głównej, a nie te, które faktycznie zarabiają. Podstrony ofertowe czy przewodniki zakupowe bywają w tej hierarchii na szarym końcu.
Trzeci to rozproszenie tematyczne. Serwis ma trzysta tekstów o kredytach, ale nie ma ani jednego miejsca, w którym te trzysta tekstów spina się w spójną grupę. Linki są, tylko prowadzą przypadkowo — bo redaktor pamiętał ten jeden artykuł, który sam pisał w marcu.
Ręczny audyt takiego serwisu potrafi zająć tygodnie, a jego efekt starzeje się w miesiąc, bo w tym czasie doszło kolejnych trzysta publikacji. To zadanie z definicji nadaje się do automatyzacji.
Rozdzielam dwie rzeczy, które w rozmowach o „AI do linkowania” wrzuca się do jednego worka.
Pierwsza to wyszukiwanie podobieństwa semantycznego przy użyciu embeddingów. Zamieniam treść każdej podstrony na wektor i mogę pytać: które dokumenty mówią o tym samym, choć nie używają tych samych słów. To działa dobrze, jest tanie i powtarzalne. Klasyczne wyszukiwanie po frazie tego nie da — „leasing operacyjny” i „wynajem długoterminowy dla firm” leksykalnie nie mają nic wspólnego, a czytelnik jednego tekstu jest naturalnym odbiorcą drugiego.
Druga to ocena, czy dane połączenie ma sens dla użytkownika. Tu model językowy jest tylko przybliżeniem. Umie ocenić, że dwa teksty są pokrewne, ale nie wie, że jeden z nich jest nieaktualny po zmianie przepisów, że drugi jest przygotowywany do usunięcia, a trzeci to materiał sponsorowany, którego nie chcemy promować z całego serwisu.
Dlatego traktuję model jako narzędzie do zawężenia miliona możliwych par URL-i do kilkuset sensownych propozycji. Wybór z tych kilkuset to nadal praca człowieka — tylko wykonalna w rozsądnym czasie.
Jakość podpowiedzi zależy od danych wejściowych bardziej niż od użytego modelu i to jest najczęstszy powód rozczarowań.
Crawl i raporty zbieram w jednym pliku roboczym i to on jest podstawą dalszej pracy. Nie wysyłam do modelu całych stron w kółko — kosztuje, jest wolne i niepotrzebne.
Kolejność zawężania ma znaczenie, bo każdy kolejny etap jest droższy niż poprzedni.
Zaczynam od podobieństwa wektorowego i biorę dla każdego adresu kilkanaście najbliższych dokumentów. Potem odrzucam pary, które już są połączone, adresy z parametrami, paginacje, tagi i wszystko, co nie jest treścią. Następnie nakładam reguły kierunku: chcę, żeby linki płynęły z tekstów mających ruch do tekstów, które mają go za mało, a nie odwrotnie.
Na tym etapie mam listę par i dopiero wtedy sięgam po model językowy — z konkretnym pytaniem, czy w tekście źródłowym istnieje fragment, w którym taki link byłby naturalny, i który to fragment. Odpowiedź musi wskazywać istniejące zdanie, nie propozycję dopisania nowego akapitu.
Ostatni filtr jest arytmetyczny. Ustalam limit linków dodawanych do jednego tekstu w jednym przebiegu i limit linków wchodzących na jeden adres docelowy. Bez tych dwóch liczb dostaniesz kilkanaście linków w jednym artykule i podstronę z tysiącem identycznych odnośników, co jest gorsze niż stan wyjściowy.
Podobieństwo tematyczne modele wyznaczają porządnie. Z tekstem anchora mam z nimi stały kłopot.
Typowe generowane propozycje wyglądają jak fragment materiału reklamowego: „sprawdź nasz kompleksowy przewodnik”, „dowiedz się więcej o najlepszych rozwiązaniach”. Do treści redakcyjnej to nie pasuje, a przy skali kilku tysięcy linków tworzy rozpoznawalny, powtarzalny wzorzec w całym serwisie.
Druga pułapka to anchory dokładnie zgodne z frazą docelową, powtórzone setki razy. Wygląda to jak optymalizacja pod jedno słowo i tak też pewnie jest oceniane.
Trzymam się więc prostej zasady: anchor musi być fragmentem zdania, które już istnieje w tekście. Model ma go wskazać, nie wymyślić. Jeśli w akapicie nie ma nic, co da się podlinkować bez przeredagowania, ta para po prostu wypada z listy. Dodatkowo pilnuję, żeby ten sam adres docelowy nie zbierał w całym serwisie identycznych anchorów — różnorodność bierze się tu sama z siebie, jeśli anchory pochodzą z realnych zdań.
Największa różnica między projektem, który działa, a takim, który po pół roku trzeba odkręcać, leży nie w modelu, a w sposobie wdrożenia.
Robię to tak, że wynik procesu trafia do redakcji jako lista propozycji — najlepiej wprost w panelu CMS, przy konkretnym akapicie, z przyciskiem przyjęcia albo odrzucenia. Link po zatwierdzeniu jest zwykłym elementem treści, zapisanym w bazie razem z artykułem. Nikt później nie musi wiedzieć, że powstał automatycznie.
Alternatywa, czyli moduł dolepiający linki w locie na podstawie reguł, jest wygodniejsza do wdrożenia i gorsza w każdym innym wymiarze. Traci się kontrolę nad tym, co dokładnie widzi wyszukiwarka w danym dniu, ciężko odtworzyć historię zmian, a przy awarii lub zmianie szablonu potrafi zniknąć całe piętro linkowania naraz.
Zostawiam też ślad w bazie: skąd wzięła się propozycja, kto ją zaakceptował i kiedy. Przy portalu z wieloma redaktorami to jedyny sposób, żeby po pół roku dało się cokolwiek zrekonstruować.
Nie oczekuję, że po takim projekcie coś skoczy w tydzień. Patrzę na wskaźniki pośrednie i daję im czas.
Najpierw liczę liczbę podstron bez linków wewnętrznych i głębokość kliknięcia od strony głównej. To dwie metryki, które zmieniają się od razu po wdrożeniu i pokazują, czy proces w ogóle zadziałał technicznie.
Potem obserwuję statystyki indeksowania w Search Console — czy roboty częściej odwiedzają sekcje, które wcześniej były odcięte. Dopiero na końcu, po kilku tygodniach, porównuję liczbę wyświetleń dla grup adresów, które dostały linki, z grupą, która ich nie dostała. Jeśli mam taką możliwość, wdrażam etapami właśnie po to, żeby mieć grupę odniesienia.
Nie próbuję przypisywać zmian pozycji pojedynczym linkom, bo w tym samym czasie dzieje się w serwisie i w wyszukiwarce zbyt wiele. Realny efekt tej pracy widzę raczej w tym, że archiwum przestaje umierać, a nowe teksty od pierwszego dnia mają sensowne otoczenie.
Używamy plików cookies, aby ułatwić Ci nawigację oraz wykonywanie określonych funkcji. Szczegółowe informacje o wszystkich plikach cookies znajdziesz w każdej kategorii zgody poniżej.
Pliki cookies oznaczone jako "Niezbędne" są przechowywane w Twojej przeglądarce, ponieważ są one kluczowe dla zapewnienia podstawowych funkcji strony.
Używamy również plików cookies firm trzecich, które pomagają nam analizować, w jaki sposób korzystasz z tej strony, zapamiętują Twoje preferencje oraz dostarczają treści i reklamy odpowiednie dla Ciebie. Te pliki cookies będą przechowywane w Twojej przeglądarce tylko za Twoją uprzednią zgodą.
Możesz zdecydować, czy chcesz włączyć lub wyłączyć niektóre bądź wszystkie te pliki cookies, jednak wyłączenie niektórych z nich może wpłynąć na Twoje doświadczenia podczas przeglądania strony.
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| __cf_bm | 13 minutes | Cloudflare bot management — distinguishes humans from bots. |
| rc::* | Persistent | Google reCAPTCHA — localStorage holding anti-bot challenge state. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| wpEmojiSettingsSupports | Session | WordPress — sessionStorage flag caching whether the browser can render emoji (feature detection). |
| ytidb* | Persistent | YouTube — IndexedDB storing playback/search state for embedded videos. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| _ga_* | 400 days | Google Analytics 4 — persists session state per property. |
| _ga | 400 days | Google Analytics — distinguishes unique users via a client id. |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| NID | 183 days | Google — stores preferences for personalized ads. |
| fr | 90 days | Meta — encrypted Facebook id and browser id for ads. |
| _gcl_au | 90 days | Google AdSense/Ads — experiments with advertising efficiency (conversion linker). |
| Cookie | Czas przechowywania | Opis |
|---|---|---|
| __Secure-YNID | 180 days | |
| YSC | Session | |
| __Secure-ROLLOUT_TOKEN | 180 days | |
| VISITOR_INFO1_LIVE | 180 days | |
| VISITOR_PRIVACY_METADATA | 180 days | |
| datr | 400 days | |
| sb | 400 days | |
| wd | 7 days |