// SEO

NawiSEO 3 - inspekcja URL w GSC

▸ // rozdziały lekcji

NawiSEO 3 - Wolniś z lupą sprawdza, czy strona jest zaindeksowana

Narzędzie „Sprawdzanie adresu URL" w Search Console przyjmuje jeden adres naraz. Wklejasz, czekasz, czytasz wynik, przepisujesz. Przy 300 podstronach to cały dzień przeklikiwania, a po tygodniu dane są nieaktualne.

Ten workflow robi to samo przez API. Bierze adresy z tabeli nawiseo_adresy, pyta Google o stan indeksowania każdego z nich i wpisuje odpowiedź obok adresu: werdykt, stan pokrycia i datę ostatniej wizyty Googlebota.

To trzecia lekcja serii NawiSEO. Adresy pochodzą z NawiSEO 1.

Co robi ten workflow

  1. Uruchom recznie - start kliknięciem.
  2. Ustawienia - dwa pola: ile_na_raz (20) i wlasciwosc, czyli właściwość w Search Console.
  3. Przygotuj tabele - zakłada nawiseo_adresy albo używa istniejącej (opcja Reuse Existing Tables).
  4. Adresy bez inspekcji - pobiera wiersze z pustą kolumną gsc_status, najwyżej ile_na_raz sztuk.
  5. Inspekcja URL - HTTP Request wysyła POST do URL Inspection API, jeden adres co 1,1 sekundy.
  6. Wynik inspekcji - Edit Fields składa z odpowiedzi gsc_status i gsc_ostatni_crawl.
  7. Zapisz status - aktualizuje wiersz w tabeli, dopasowując go po url.

Kanwa workflow, siedem węzłów w jednej linii

Czego potrzebujesz

  • tabeli nawiseo_adresy z adresami z NawiSEO 1,
  • dostępu do właściwości w Search Console na koncie Google, którym podłączysz n8n,
  • projektu w Google Cloud z włączonym Search Console API,
  • poświadczenia w n8n typu Google OAuth2 API ze scope https://www.googleapis.com/auth/webmasters.readonly.

Poświadczenie zakładasz w Overview > zakładka Credentials. Jak działają poświadczenia i gdzie n8n je trzyma, pokazuję w lekcji Poświadczenia. Do Google OAuth2 potrzebujesz identyfikatora i sekretu klienta OAuth z Google Cloud. Całą konfigurację krok po kroku pokazuję w lekcji Credentials Google OAuth2 na komputerze. Scope webmasters.readonly daje tylko odczyt, więc workflow niczego w Search Console nie zmieni.

Okno poświadczenia Google OAuth2 API w n8n z wpisanym scope webmasters.readonly

Jak uruchomić

  1. Zaimportuj plik z tej lekcji.
  2. W węźle Ustawienia wpisz w wlasciwosc swoją właściwość (szczegóły niżej).
  3. W węźle Inspekcja URL wybierz swoje poświadczenie Google OAuth2 API.
  4. Kliknij Execute workflow.
  5. Otwórz tabelę nawiseo_adresy i sprawdź kolumny gsc_status i gsc_ostatni_crawl.
  6. Uruchamiaj ponownie, aż wszystkie adresy mają status.

Właściwość musi się zgadzać co do znaku

Pole wlasciwosc idzie do API jako siteUrl. Musi wyglądać dokładnie tak jak właściwość w Search Console:

  • prefiks URL - pełny adres z protokołem i ukośnikiem na końcu, na przykład https://twojadomena.pl/,
  • domena - zapis sc-domain:twojadomena.pl.

W pliku stoi https://damianslimak.pl/. Brak ukośnika, inne www albo http zamiast https i API odmówi.

Haczyk. Stara wersja tej lekcji składała siteUrl z adresu strony. Działało to tylko przy właściwości typu prefiks URL z tym samym protokołem i tym samym www. Teraz wpisujesz właściwość raz, ręcznie, i obsłużysz też właściwość domenową.

Zapytanie do API

Inspekcja URL wysyła POST na:

https://searchconsole.googleapis.com/v1/urlInspection/index:inspect

Treść zapytania składa wyrażenie:

{{ JSON.stringify({ inspectionUrl: $json.url, siteUrl: $('Ustawienia').item.json.wlasciwosc, languageCode: 'pl' }) }}

inspectionUrl to adres z tabeli, siteUrl to właściwość z Ustawień, a languageCode: 'pl' prosi o komunikaty po polsku.

Batching ustawiony jest na 1 zapytanie co 1100 milisekund. Według dokumentacji Google inspekcja ma limit 2000 zapytań dziennie i 600 na minutę na właściwość. Tych limitów nie sprawdzałem na żywo. Przy jednym zapytaniu co 1,1 sekundy zostajesz daleko pod limitem minutowym, a z porcją po 20 dzienny limit wyczerpiesz dopiero po 100 uruchomieniach.

Węzeł Inspekcja URL - metoda POST, poświadczenie Google OAuth2 API i opcja Batching

Co trafia do tabeli

Wynik inspekcji wyciąga z odpowiedzi dwa pola z inspectionResult.indexStatusResult:

  • gsc_status - werdykt i stan pokrycia sklejone dywizem, na przykład „PASS - Strona przesłana i zindeksowana". Stan pokrycia przychodzi w języku twojego konta Google, więc u ciebie może być po angielsku: „PASS - Submitted and indexed",
  • gsc_ostatni_crawl - wartość lastCrawlTime, czyli kiedy Googlebot był na stronie ostatni raz.

Adres bierze z węzła Adresy bez inspekcji, a nie z odpowiedzi API. Dzięki temu zapis trafia dokładnie w ten wiersz, z którego adres wyszedł.

Tabela nawiseo_adresy po przebiegu - adresy z damianslimak.pl, gsc_status z werdyktami PASS i NEUTRAL oraz data ostatniego crawla, pozostałe kolumny ukryte na zrzucie

Na moim przebiegu z 20 adresów zindeksowanych było tylko 6. Reszta ma „NEUTRAL - Strona wykryta - obecnie niezindeksowana" albo „Adres URL jest Google nieznany". Dokładnie po to jest ten workflow: w minutę widzisz, które podstrony Google pominął, zamiast klikać je po kolei w Search Console.

Błędy nie zatrzymują przebiegu

Węzeł Inspekcja URL ma ustawione kontynuowanie po błędzie. Jeśli API odmówi, na przykład przez złą właściwość, workflow idzie dalej, a do gsc_status trafia „BLAD - " i komunikat błędu.

Haczyk. Adres z błędem ma wypełnione gsc_status, więc przy kolejnym uruchomieniu nie wróci do kolejki. To celowe: zepsuty adres nie blokuje reszty. Żeby spróbować jeszcze raz, wyczyść jego komórkę gsc_status w tabeli.

Pro-tip. Zanim puścisz 20 adresów, ustaw ile_na_raz na 1. Jedno zapytanie powie ci, czy poświadczenie i właściwość są dobre. Jeśli w tabeli pojawi się „BLAD", poprawiasz jeden wiersz, a nie dwadzieścia.

Co z tym zrobić

Przejrzyj tabelę pod kątem gsc_status. Adresy, które Google zna, ale nie zaindeksował, to lista do przejrzenia: cienka treść, duplikaty, słabe linkowanie wewnętrzne. Stara data w gsc_ostatni_crawl mówi, że Googlebot rzadko zagląda na tę podstronę.

API inspekcji tylko czyta stan. Niczego nie zgłasza do indeksu.

Podsumowanie

Masz przy każdym adresie z mapy stan indeksowania wprost od Google, porcjami po 20 i daleko pod limitami. Właściwość w Ustawieniach wpisujesz dokładnie jak w Search Console, a błędy lądują w tabeli jako „BLAD", zamiast zatrzymywać workflow. Pamiętaj, że połączenie z żywym kontem Google opisuję według dokumentacji.

W NawiSEO 4 - analiza miesiąca z Search Console pobierzemy kliknięcia, wyświetlenia i pozycje każdej podstrony za poprzedni miesiąc.

Pokaż JSON do skopiowania - nawiseo-3-search-console-inspekcja-url.json
{
  "name": "NawiSEO 3 - Search Console, inspekcja adresow",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "id": "f66720b4-32a5-4323-be16-f575b9ae00ae",
      "name": "Uruchom recznie"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "27a107b9-23d3-7e35-6f46-207a8bf341fc",
              "name": "ile_na_raz",
              "value": "20",
              "type": "number"
            },
            {
              "id": "6136f01d-22a4-779d-6d09-d9161c3fe252",
              "name": "wlasciwosc",
              "value": "https://damianslimak.pl/",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ],
      "id": "bb693597-f992-b5f1-1882-54e901531fc3",
      "name": "Ustawienia"
    },
    {
      "parameters": {
        "resource": "table",
        "operation": "create",
        "tableName": "nawiseo_adresy",
        "columns": {
          "column": [
            {
              "name": "url",
              "type": "string"
            },
            {
              "name": "domena",
              "type": "string"
            },
            {
              "name": "sitemap",
              "type": "string"
            },
            {
              "name": "status_http",
              "type": "number"
            },
            {
              "name": "title",
              "type": "string"
            },
            {
              "name": "title_dl",
              "type": "number"
            },
            {
              "name": "description",
              "type": "string"
            },
            {
              "name": "description_dl",
              "type": "number"
            },
            {
              "name": "h1",
              "type": "string"
            },
            {
              "name": "h1_ilosc",
              "type": "number"
            },
            {
              "name": "sprawdzono",
              "type": "date"
            },
            {
              "name": "nowy_title",
              "type": "string"
            },
            {
              "name": "nowy_description",
              "type": "string"
            },
            {
              "name": "nowy_h1",
              "type": "string"
            },
            {
              "name": "gsc_status",
              "type": "string"
            },
            {
              "name": "gsc_ostatni_crawl",
              "type": "string"
            },
            {
              "name": "psi_mobile",
              "type": "number"
            },
            {
              "name": "psi_desktop",
              "type": "number"
            }
          ]
        },
        "options": {
          "createIfNotExists": true
        }
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        440,
        0
      ],
      "id": "294e722c-bedd-276d-8c66-e0140d7d3839",
      "name": "Przygotuj tabele"
    },
    {
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "value": "nawiseo_adresy",
          "mode": "name"
        },
        "returnAll": false,
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "gsc_status",
              "condition": "isEmpty"
            }
          ]
        },
        "limit": "={{ $('Ustawienia').item.json.ile_na_raz }}"
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        660,
        0
      ],
      "id": "8c7626c0-8171-564e-40a2-5c5116ce2c58",
      "name": "Adresy bez inspekcji"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://searchconsole.googleapis.com/v1/urlInspection/index:inspect",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleOAuth2Api",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ inspectionUrl: $json.url, siteUrl: $('Ustawienia').item.json.wlasciwosc, languageCode: 'pl' }) }}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 1,
              "batchInterval": 1100
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        880,
        0
      ],
      "id": "0201491b-cfdd-f8d0-4f17-586791f5164a",
      "name": "Inspekcja URL",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "6f4622b5-9290-9656-815d-e8d4aa355f55",
              "name": "url",
              "value": "={{ $('Adresy bez inspekcji').item.json.url }}",
              "type": "string"
            },
            {
              "id": "c11a59c5-be8d-d002-2bce-5ba9e324d964",
              "name": "gsc_status",
              "value": "={{ $json.inspectionResult ? $json.inspectionResult.indexStatusResult.verdict + ' - ' + $json.inspectionResult.indexStatusResult.coverageState : 'BLAD - ' + ($json.error?.message || 'brak odpowiedzi') }}",
              "type": "string"
            },
            {
              "id": "460ba058-1949-6343-f9a4-258fddce6cf8",
              "name": "gsc_ostatni_crawl",
              "value": "={{ $json.inspectionResult?.indexStatusResult?.lastCrawlTime || '' }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1100,
        0
      ],
      "id": "1edfa0bd-b7b5-ae41-28b0-172628fd8441",
      "name": "Wynik inspekcji"
    },
    {
      "parameters": {
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "value": "nawiseo_adresy",
          "mode": "name"
        },
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "url",
              "condition": "eq",
              "keyValue": "={{ $json.url }}"
            }
          ]
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "gsc_status": "={{ $json.gsc_status }}",
            "gsc_ostatni_crawl": "={{ $json.gsc_ostatni_crawl }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "url",
              "displayName": "url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "domena",
              "displayName": "domena",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "sitemap",
              "displayName": "sitemap",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "status_http",
              "displayName": "status_http",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "title",
              "displayName": "title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "title_dl",
              "displayName": "title_dl",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "description",
              "displayName": "description",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "description_dl",
              "displayName": "description_dl",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "h1",
              "displayName": "h1",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "h1_ilosc",
              "displayName": "h1_ilosc",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "sprawdzono",
              "displayName": "sprawdzono",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "date",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "nowy_title",
              "displayName": "nowy_title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "nowy_description",
              "displayName": "nowy_description",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "nowy_h1",
              "displayName": "nowy_h1",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "gsc_status",
              "displayName": "gsc_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "gsc_ostatni_crawl",
              "displayName": "gsc_ostatni_crawl",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "psi_mobile",
              "displayName": "psi_mobile",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "psi_desktop",
              "displayName": "psi_desktop",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "readOnly": false,
              "removed": true
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        1320,
        0
      ],
      "id": "43f708a9-4c3c-6bfd-82bc-e0aa08a1be41",
      "name": "Zapisz status"
    }
  ],
  "connections": {
    "Uruchom recznie": {
      "main": [
        [
          {
            "node": "Ustawienia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ustawienia": {
      "main": [
        [
          {
            "node": "Przygotuj tabele",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Przygotuj tabele": {
      "main": [
        [
          {
            "node": "Adresy bez inspekcji",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Adresy bez inspekcji": {
      "main": [
        [
          {
            "node": "Inspekcja URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Inspekcja URL": {
      "main": [
        [
          {
            "node": "Wynik inspekcji",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wynik inspekcji": {
      "main": [
        [
          {
            "node": "Zapisz status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}