--- title: "Snippety SERP: statystyki (`getStatistics`)" source: https://docs.senuto.com/modules/rank_tracker/rt-snippets-getStatistics api: POST /api/rank_tracker/reports/snippets/getStatistics --- # Snippety SERP: statystyki (`getStatistics`) **`POST /api/rank_tracker/reports/snippets/getStatistics`** Zwraca statystyki elementów SERP (snippetów) wykrytych dla fraz projektu Rank Tracker. Dla każdego typu snippetu akcja porównuje dwa snapshoty — `date_min` (wartości `previous`) i `date_max` (wartości `recent`) — i raportuje, ile fraz projektu ma dany snippet w SERP (`all_keywords`) oraz w ilu z nich widoczna jest domena projektu (`visible_keywords`), wraz z różnicami bezwzględnymi i procentowymi oraz procentowym pokryciem SERP (`serp_coverage`). Powyższy przykład w playgroundzie został **skrócony do 4 typów snippetów** dla czytelności — pełną, zwalidowaną odpowiedź (14 typów) znajdziesz niżej w sekcji „Odpowiedź". --- ## Żądanie `POST` `/api/rank_tracker/reports/snippets/getStatistics` Nagłówki: `Authorization: Bearer `, `Content-Type: application/json`. ### Struktura żądania **Podstawowy** ```jsonc filename="żądanie-podstawowe.jsonc" { "project_id": null, "date_min": "2026-06-20", "date_max": "2026-06-29" } ``` **cURL** ```bash curl --location --request POST 'https://api.senuto.com/api/rank_tracker/reports/snippets/getStatistics' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer $YOUR_TOKEN_HERE' \ --data-raw '{ "project_id": null, "date_min": "2026-06-20", "date_max": "2026-06-29" }' ``` ### Parametry ```ts type GetSnippetsStatisticsRequest = { /** * **Wymagane**. ID projektu Rank Tracker (walidator `SnippetsValidator`). * Musi należeć do użytkownika, inaczej zwracane jest `418` z komunikatem `Unauthorized access`. * Realny `project_id` pobierzesz z `POST /api/rank_tracker/management/projects/getMyActiveProjects`. */ project_id: number; /** * **Wymagane**. Data początkowa zakresu w formacie `YYYY-MM-DD` — snapshot bazowy, * którego wartości trafiają do pól `previous`. */ date_min: string; /** * **Wymagane**. Data końcowa zakresu w formacie `YYYY-MM-DD` — snapshot bieżący, * którego wartości trafiają do pól `recent`. */ date_max: string; } export default GetSnippetsStatisticsRequest ``` > **Ostrzeżenie:** > Znany bug walidacji: gdy `date_min` jest **późniejsze** niż `date_max`, reguły `DateRangeRules` zwracają błąd z **odwróconym komunikatem** (treść sugeruje odwrotny kierunek naruszenia). Pilnuj poprawnej kolejności dat po swojej stronie. > **Ostrzeżenie:** > **Pułapki tego endpointu:** (1) `data` to **obiekt keyed by typ snippetu** (klucze dynamiczne, np. `image_thumbs`, `wiki_right`), a nie tablica — iteruj po kluczach, nie po indeksach. (2) `serp_coverage` to **string** (np. `"29.79"` = procent pokrycia SERP), nie liczba. (3) `diff_percent` bywa **liczbą `0` albo stringiem** (np. `"-24.32"`) — parsuj defensywnie. (4) Odpowiedź **nie ma paginacji**. (5) Zbiór typów snippetów w odpowiedzi może być **podzbiorem** wszystkich typów — siostrzana akcja `getHistory` dla tego samego projektu zwróciła dodatkowo m.in. `people_also_ask`, `related_searches`, `video_thumbs`, `videos_pack`, `featured_snippets` i `answer_box`; zbiór kluczy traktuj jako dynamiczny. ## Odpowiedź Po pomyślnym żądaniu otrzymujesz `data` — **obiekt**, którego kluczami są typy snippetów. Każdy wpis zawiera `serp_coverage` (string z procentem pokrycia SERP), powtórzoną nazwę typu w polu `snippet` oraz dwa bloki liczników: `all_keywords` (frazy projektu z danym snippetem w SERP) i `visible_keywords` (frazy, w których snippecie widoczna jest domena projektu). Każdy blok liczników ma `recent` (stan z `date_max`), `previous` (stan z `date_min`), `diff` oraz `diff_percent`. **Skrócona** ```json filename="przykładowa-odpowiedź (skrócona)" { "success": true, "data": { "image_thumbs": { "serp_coverage": "29.79", "snippet": "image_thumbs", "all_keywords": { "recent": 28, "previous": 37, "diff": -9, "diff_percent": "-24.32" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "wiki_right": { "serp_coverage": "12.77", "snippet": "wiki_right", "all_keywords": { "recent": 12, "previous": 9, "diff": 3, "diff_percent": "33.33" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } } } } ``` **Pełna** ```json filename="przykładowa-odpowiedź (200)" { "success": true, "data": { "news": { "serp_coverage": "0.00", "snippet": "news", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "image_thumbs": { "serp_coverage": "29.79", "snippet": "image_thumbs", "all_keywords": { "recent": 28, "previous": 37, "diff": -9, "diff_percent": "-24.32" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "wiki_right": { "serp_coverage": "12.77", "snippet": "wiki_right", "all_keywords": { "recent": 12, "previous": 9, "diff": 3, "diff_percent": "33.33" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "map": { "serp_coverage": "0.00", "snippet": "map", "all_keywords": { "recent": 0, "previous": 1, "diff": -1, "diff_percent": "-100.00" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_video": { "serp_coverage": "0.00", "snippet": "top_video", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "spell": { "serp_coverage": "3.19", "snippet": "spell", "all_keywords": { "recent": 3, "previous": 3, "diff": 0, "diff_percent": "0.00" }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_info": { "serp_coverage": "0.00", "snippet": "top_info", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_bar": { "serp_coverage": "0.00", "snippet": "top_bar", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_scholar": { "serp_coverage": "0.00", "snippet": "top_scholar", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_number_results": { "serp_coverage": "0.00", "snippet": "top_number_results", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "top_public_data": { "serp_coverage": "0.00", "snippet": "top_public_data", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "site_links": { "serp_coverage": "0.00", "snippet": "site_links", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "featured_answer": { "serp_coverage": "0.00", "snippet": "featured_answer", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } }, "adwords": { "serp_coverage": "0.00", "snippet": "adwords", "all_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 }, "visible_keywords": { "recent": 0, "previous": 0, "diff": 0, "diff_percent": 0 } } } } ``` ### Struktura odpowiedzi ```ts type GetSnippetsStatisticsResponse = { /** `true` przy powodzeniu; przy błędzie `false` i koperta z `error` */ success: boolean; /** * Obiekt keyed by typ snippetu (klucze dynamiczne, np. `image_thumbs`, `wiki_right`, `map`). * To NIE jest tablica. Zbiór kluczy może być podzbiorem wszystkich typów snippetów. */ data: Record; } type SnippetStatistics = { /** Procent pokrycia SERP jako STRING, np. "29.79" */ serp_coverage: string; /** Nazwa typu snippetu (powtórzenie klucza) */ snippet: string; /** Frazy projektu, dla których dany snippet występuje w SERP */ all_keywords: SnippetCounters; /** Frazy, w których snippecie widoczna jest domena projektu */ visible_keywords: SnippetCounters; } type SnippetCounters = { /** Stan ze snapshotu `date_max` */ recent: number; /** Stan ze snapshotu `date_min` */ previous: number; /** Różnica bezwzględna: recent - previous */ diff: number; /** Różnica procentowa — liczba `0` albo STRING, np. "-24.32" */ diff_percent: number | string; } export default GetSnippetsStatisticsResponse ``` ## Błędy ```ts type ErrorResponse = { success: false; data: { error: { /** np. invalid_data, unknown */ type: string; message: string; /** pole -> reguła -> komunikat (dla invalid_data) */ params?: Record>; }; }; } export default ErrorResponse ``` > **Błąd:** > Błędy walidacji zwracane są ze statusem **`418`**. Brak któregokolwiek z pól `project_id`, `date_min`, `date_max` → `invalid_data`. `project_id` nienależący do użytkownika → `Unauthorized access` (`418`), a nie `404`. Znany bug: przy `date_min` późniejszym niż `date_max` komunikat błędu z `DateRangeRules` jest odwrócony względem faktycznego naruszenia. ## Powiązane akcje - `getStatistics` — porównanie dwóch snapshotów per typ snippetu, z pokryciem SERP i widocznością domeny (ta strona) - `getHistory` — liczba fraz z danym typem snippetu w SERP, per data pomiaru (`POST`, `project_id` + `date_min` + `date_max`)