{"id":16779,"date":"2026-09-09T12:40:52","date_gmt":"2026-09-09T10:40:52","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/ga4-measurement-protocol-json-validator\/"},"modified":"2026-09-09T13:09:32","modified_gmt":"2026-09-09T11:09:32","slug":"ga4-measurement-protocol-json-validator","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/","title":{"rendered":"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">Measurement Protocol odpowiada 2xx niemal na wszystko. \u0179le zbudowane zdarzenie, zastrze\u017cona nazwa parametru, warto\u015b\u0107 o jeden znak za d\u0142uga \u2014 \u017c\u0105danie zostaje przyj\u0119te, dane przepadaj\u0105, a raport po prostu pozostaje pusty. Serwer walidacyjny Google pomaga, ale zg\u0142asza tylko pierwszy znaleziony b\u0142\u0105d, a w trybie \u0142agodnym, kt\u00f3ry obowi\u0105zuje na produkcji, znacznie mniej ni\u017c to. Ta kontrola czyta \u0142adunek najpierw tutaj i wypisuje wszystko naraz, a obok pokazuje, co o tym samym tek\u015bcie m\u00f3wi serwer walidacyjny w obu trybach.<\/p>\n<div style=\"margin-bottom: 6px; display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline; justify-content: space-between;\">\n        <label for=\"mpv-json\" style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.85rem;\">\u0141adunek Measurement Protocol (tre\u015b\u0107 \u017c\u0105dania POST w JSON)<\/label><br \/>\n        <span style=\"display: flex; gap: 8px;\"><br \/>\n            <button type=\"button\" id=\"mpv-bsp1\" class=\"button\" style=\"background: transparent; color: var(--text-secondary, #a0a0b0); border: 1px solid var(--border, #2a2a35); padding: 5px 12px; border-radius: 6px; font-size: 0.78rem; cursor: pointer;\">Przyk\u0142ad z b\u0142\u0119dami<\/button><br \/>\n            <button type=\"button\" id=\"mpv-bsp2\" class=\"button\" style=\"background: transparent; color: var(--text-secondary, #a0a0b0); border: 1px solid var(--border, #2a2a35); padding: 5px 12px; border-radius: 6px; font-size: 0.78rem; cursor: pointer;\">Przyk\u0142ad poprawny<\/button><br \/>\n        <\/span>\n    <\/div>\n<p>    <textarea id=\"mpv-json\" rows=\"16\" spellcheck=\"false\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; box-sizing: border-box; font-family: monospace; font-size: 0.85rem; line-height: 1.5; resize: vertical;\"><\/textarea><\/p>\n<div style=\"display: flex; flex-wrap: wrap; gap: 18px; align-items: center; margin: 14px 0 6px;\">\n        <span><br \/>\n            <label for=\"mpv-strom\" style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; margin-right: 8px;\">Strumie\u0144 danych<\/label><br \/>\n            <select id=\"mpv-strom\" style=\"padding: 7px 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px;\"><option value=\"web\">Sie\u0107 (client_id)<\/option><option value=\"app\">Aplikacja (app_instance_id)<\/option><\/select><br \/>\n        <\/span><br \/>\n        <label style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; cursor: pointer;\"><br \/>\n            <input type=\"checkbox\" id=\"mpv-360\" style=\"vertical-align: middle; margin-right: 6px;\">Us\u0142uga Analytics 360 (warto\u015bci do 500 znak\u00f3w)<br \/>\n        <\/label><br \/>\n        <label style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; cursor: pointer;\"><br \/>\n            <input type=\"checkbox\" id=\"mpv-google\" checked style=\"vertical-align: middle; margin-right: 6px;\">Zapyta\u0107 dodatkowo serwer walidacyjny Google<br \/>\n        <\/label>\n    <\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.82rem; margin: 0 0 16px;\">\u017badne dane dost\u0119powe nie s\u0105 wymagane i nie s\u0105 potrzebne: serwer walidacyjny nie sprawdza ani measurement_id, ani api_secret, dlatego to narz\u0119dzie wysy\u0142a warto\u015bci zast\u0119pcze. Sam \u0142adunek nie jest zapisywany \u2014 w liczniku l\u0105duje wy\u0142\u0105cznie liczba bajt\u00f3w. Zdarzenia wys\u0142ane na serwer walidacyjny nie pojawiaj\u0105 si\u0119 w \u017cadnym raporcie.<\/p>\n<p>    <button id=\"mpv-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: var(--on-accent, #0b1114); border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Sprawd\u017a \u0142adunek<\/button><\/p>\n<div id=\"mpv-ausgabe\" style=\"margin-top: 22px;\"><\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.8rem; margin: 24px 0 0;\">Granice, kt\u00f3re warto zna\u0107: nazwy zastrze\u017cone, limity rozmiaru i parametry zalecane wynikaj\u0105 z opublikowanej dokumentacji i mog\u0105 zmieni\u0107 si\u0119 bez zapowiedzi. Listy parametr\u00f3w zalecanych s\u0105 kuratorowane dla popularnych zdarze\u0144; nieznana nazwa zdarzenia nie dostaje wi\u0119c \u017cadnej rekomendacji zamiast b\u0142\u0119dnej. To, czy us\u0142uga faktycznie zbiera dany parametr, zale\u017cy od jej wymiar\u00f3w niestandardowych, a tego nie poka\u017ce \u017caden \u0142adunek.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Measurement Protocol odpowiada 2xx niemal na wszystko. \u0179le zbudowane zdarzenie, zastrze\u017cona nazwa parametru, warto\u015b\u0107 o jeden znak za d\u0142uga \u2014 \u017c\u0105danie zostaje przyj\u0119te, dane przepadaj\u0105, a raport po prostu pozostaje pusty. Serwer walidacyjny Google pomaga, ale zg\u0142asza tylko pierwszy znaleziony b\u0142\u0105d, a w trybie \u0142agodnym, kt\u00f3ry obowi\u0105zuje na produkcji, znacznie mniej ni\u017c to. Ta kontrola czyta \u0142adunek najpierw tutaj i wypisuje wszystko naraz, a obok pokazuje, co o tym samym tek\u015bcie m\u00f3wi serwer walidacyjny w obu trybach.\",\"label_json\":\"\u0141adunek Measurement Protocol (tre\u015b\u0107 \u017c\u0105dania POST w JSON)\",\"label_strom\":\"Strumie\u0144 danych\",\"strom_web\":\"Sie\u0107 (client_id)\",\"strom_app\":\"Aplikacja (app_instance_id)\",\"label_360\":\"Us\u0142uga Analytics 360 (warto\u015bci do 500 znak\u00f3w)\",\"label_google\":\"Zapyta\u0107 dodatkowo serwer walidacyjny Google\",\"bsp_fehler\":\"Przyk\u0142ad z b\u0142\u0119dami\",\"bsp_sauber\":\"Przyk\u0142ad poprawny\",\"knopf\":\"Sprawd\u017a \u0142adunek\",\"laeuft\":\"Trwa odczyt \u0142adunku...\",\"datenschutz\":\"\u017badne dane dost\u0119powe nie s\u0105 wymagane i nie s\u0105 potrzebne: serwer walidacyjny nie sprawdza ani measurement_id, ani api_secret, dlatego to narz\u0119dzie wysy\u0142a warto\u015bci zast\u0119pcze. Sam \u0142adunek nie jest zapisywany \u2014 w liczniku l\u0105duje wy\u0142\u0105cznie liczba bajt\u00f3w. Zdarzenia wys\u0142ane na serwer walidacyjny nie pojawiaj\u0105 si\u0119 w \u017cadnym raporcie.\",\"grenze\":\"Granice, kt\u00f3re warto zna\u0107: nazwy zastrze\u017cone, limity rozmiaru i parametry zalecane wynikaj\u0105 z opublikowanej dokumentacji i mog\u0105 zmieni\u0107 si\u0119 bez zapowiedzi. Listy parametr\u00f3w zalecanych s\u0105 kuratorowane dla popularnych zdarze\u0144; nieznana nazwa zdarzenia nie dostaje wi\u0119c \u017cadnej rekomendacji zamiast b\u0142\u0119dnej. To, czy us\u0142uga faktycznie zbiera dany parametr, zale\u017cy od jej wymiar\u00f3w niestandardowych, a tego nie poka\u017ce \u017caden \u0142adunek.\",\"h_ereignisse\":\"Zdarzenia\",\"h_befunde\":\"Ustalenia\",\"h_google\":\"Serwer walidacyjny Google\",\"sp_nr\":\"Nr\",\"sp_name\":\"Nazwa zdarzenia\",\"sp_parameter\":\"Parametry\",\"sp_items\":\"Pozycje\",\"sp_urteil\":\"Ocena\",\"zeile_gut\":\"w porz\u0105dku\",\"zeile_warnung\":\"ostrze\u017cenie\",\"zeile_kritisch\":\"b\u0142\u0119dne\",\"wert_fehlt\":\"bez nazwy\",\"zeile_groesse\":\"Rozmiar \u0142adunku\",\"zeile_ereignisse\":\"Zdarzenia\",\"zeile_parameter\":\"Parametry\",\"zeile_items\":\"Pozycje\",\"zeile_up\":\"W\u0142a\u015bciwo\u015bci u\u017cytkownika\",\"zeile_dauer\":\"Czas\",\"zeile_limit\":\"Pozosta\u0142e kontrole w tej godzinie\",\"einheit_byte\":\"B\",\"tausendertrenner\":\"\u00a0\",\"stufe_hoch\":\"Wysoki\",\"stufe_mittel\":\"\u015aredni\",\"stufe_niedrig\":\"Niski\",\"stufe_info\":\"Informacja\",\"stufe_gut\":\"W porz\u0105dku\",\"keine_befunde\":\"Nie ma nic do zg\u0142oszenia.\",\"urteil_gut\":\"\u0141adunek odpowiada udokumentowanym regu\u0142om.\",\"urteil_warnung\":\"Zostanie przyj\u0119ty, ale cz\u0119\u015b\u0107 nie dotrze tak, jak zamierzono.\",\"urteil_kritisch\":\"Co\u015b w \u015brodku zostanie odrzucone lub po cichu porzucone.\",\"google_streng\":\"Z validation_behavior: ENFORCE_RECOMMENDATIONS\",\"google_locker\":\"Bez validation_behavior \u2014 tak traktuje go produkcja\",\"google_keine\":\"Brak komunikat\u00f3w. Ta kontrola znalaz\u0142a w tym samym tek\u015bcie {eigene} rzecz(y) warte zg\u0142oszenia.\",\"google_anzahl\":\"Komunikat\u00f3w: {n}. Ta kontrola znalaz\u0142a w tym samym tek\u015bcie {eigene} rzecz(y) warte zg\u0142oszenia.\",\"google_uebersprungen\":\"Nie pytano \u2014 \u0142adunku nie da si\u0119 odczyta\u0107 jako JSON, nie ma wi\u0119c czego wys\u0142a\u0107.\",\"google_aus\":\"Serwer walidacyjny nie zosta\u0142 zapytany w tym przebiegu.\",\"google_fehler\":\"Serwer walidacyjny by\u0142 nieosi\u0105galny.\",\"google_fehler_netz\":\"Serwer walidacyjny by\u0142 nieosi\u0105galny.\",\"google_fehler_status\":\"Serwer walidacyjny odpowiedzia\u0142 nieoczekiwanym statusem.\",\"google_fehler_antwort\":\"Odpowiedzi serwera walidacyjnego nie da\u0142o si\u0119 odczyta\u0107.\",\"google_fehler_kein_json\":\"Nic nie zosta\u0142o wys\u0142ane \u2014 \u0142adunku nie da si\u0119 odczyta\u0107 jako JSON.\",\"google_hinweis\":\"Serwer walidacyjny zatrzymuje si\u0119 na pierwszym znalezionym b\u0142\u0119dzie, a oba przebiegi nie zawsze zatrzymuj\u0105 si\u0119 na tym samym. Oba posz\u0142y z zast\u0119pczymi danymi dost\u0119powymi, poniewa\u017c serwer nie sprawdza ani measurement_id, ani api_secret.\",\"hinweis_komma\":\"Przed nawiasem zamykaj\u0105cym stoi przecinek \u2014 JSON nie dopuszcza przecinka ko\u0144cowego.\",\"hinweis_anfuehrung\":\"Wyst\u0119puj\u0105 apostrofy tam, gdzie JSON wymaga cudzys\u0142ow\u00f3w.\",\"hinweis_schluessel_ohne_anfuehrung\":\"Klucz stoi bez cudzys\u0142ow\u00f3w. JSON to nie JavaScript: ka\u017cdy klucz wymaga podw\u00f3jnych cudzys\u0142ow\u00f3w.\",\"hinweis_klammer\":\"Liczba otwieraj\u0105cych i zamykaj\u0105cych nawias\u00f3w klamrowych si\u0119 nie zgadza.\",\"hinweis_unbekannt\":\"Brak oczywistej przyczyny \u2014 pozycja z komunikatu jest punktem wyj\u015bcia.\",\"fehler_kein_token\":\"Kontroli nie da\u0142o si\u0119 uruchomi\u0107, poniewa\u017c reCAPTCHA si\u0119 nie za\u0142adowa\u0142a.\",\"fehler_captcha\":\"reCAPTCHA uzna\u0142a \u017c\u0105danie za zautomatyzowane. Prze\u0142adowanie strony zwykle pomaga.\",\"fehler_zu_viele\":\"Limit {limit} kontroli na godzin\u0119 dla tego adresu zosta\u0142 osi\u0105gni\u0119ty.\",\"fehler_zaehler\":\"Licznik jest nieosi\u0105galny, dlatego nic nie zosta\u0142o sprawdzone.\",\"fehler_pruefdienst\":\"Us\u0142uga reCAPTCHA by\u0142a nieosi\u0105galna.\",\"fehler_aufbau\":\"Us\u0142uga nie jest poprawnie skonfigurowana. B\u0142\u0105d le\u017cy po tej stronie.\",\"fehler_eingabe\":\"\u017b\u0105dania nie da\u0142o si\u0119 odczyta\u0107.\",\"fehler_methode\":\"Niew\u0142a\u015bciwa metoda \u017c\u0105dania.\",\"fehler_netz\":\"Us\u0142uga by\u0142a nieosi\u0105galna.\",\"fehler_antwort\":\"Odpowiedzi nie da\u0142o si\u0119 odczyta\u0107.\",\"fehler_zu_gross\":\"\u0141adunek jest d\u0142u\u017cszy ni\u017c {grenze} bajt\u00f3w i nie zosta\u0142 odczytany.\",\"fehler_nichts_eingegeben\":\"Nic nie zosta\u0142o wprowadzone.\",\"fehler_unbekannt\":\"Co\u015b posz\u0142o nie tak i nie ma na to osobnego komunikatu.\",\"befund_leer\":\"Pole jest puste || Nie ma czego sprawdza\u0107.\",\"befund_json_kaputt\":\"\u0141adunek nie jest poprawnym JSON-em || {meldung}. {rat} Dalej nic nie by\u0142o sprawdzane: co si\u0119 nie daje odczyta\u0107, nie dociera do Measurement Protocol w og\u00f3le.\",\"befund_kein_objekt\":\"\u0141adunek nie jest obiektem || Na samej g\u00f3rze stoi warto\u015b\u0107 typu {typ}. Measurement Protocol oczekuje obiektu JSON z client_id i events.\",\"befund_bom\":\"Tekst zaczyna si\u0119 znacznikiem kolejno\u015bci bajt\u00f3w || Niekt\u00f3re edytory dodaj\u0105 go niewidocznie. Rygorystyczne parsery JSON odrzucaj\u0105 przez to ca\u0142y dokument.\",\"befund_groesse_ueber_grenze\":\"\u0141adunek ma {bytes} bajt\u00f3w || Udokumentowany limit to {grenze}. Powy\u017cej \u017c\u0105danie jest odrzucane w ca\u0142o\u015bci, a nie skracane.\",\"befund_groesse\":\"Rozmiar \u0142adunku: {bytes} bajt\u00f3w || To {anteil}% limitu {grenze} bajt\u00f3w.\",\"befund_datalayer_statt_mp\":\"To wygl\u0105da na obiekt dataLayer, nie na \u0142adunek Measurement Protocol || Na g\u00f3rze stoi \\u0022event\\u0022: \\u0022{wert}\\u0022. W Measurement Protocol nazwa zdarzenia znajduje si\u0119 w events[].name, a na g\u00f3rze stoi client_id.\",\"befund_gtag_statt_mp\":\"To wygl\u0105da na wywo\u0142anie gtag, nie na \u0142adunek Measurement Protocol || Na g\u00f3rze stoi klucz event_name. Measurement Protocol oczekuje zamiast tego tablicy events.\",\"befund_zugangsdaten_im_rumpf\":\"Dane dost\u0119powe stoj\u0105 w tre\u015bci \u017c\u0105dania || measurement_id i api_secret nale\u017c\u0105 do ci\u0105gu zapytania, nie do JSON-a. W tre\u015bci s\u0105 nieznanymi polami, a nieznane pole sprawia, \u017ce Google odrzuca ca\u0142y \u0142adunek.\",\"befund_unbekannter_schluessel\":\"Nieznany klucz na najwy\u017cszym poziomie: {schluessel} || Measurement Protocol odrzuca z powodu jednego nieznanego pola ca\u0142y \u0142adunek, nie tylko to pole. Zmierzone na serwerze walidacyjnym: odpowiedzi\u0105 jest b\u0142\u0105d parsowania bez wskazania pola.\",\"befund_client_id_fehlt\":\"Brakuje client_id || Bez niego \u017cadnego zdarzenia nie da si\u0119 przypisa\u0107 do u\u017cytkownika, a serwer walidacyjny odpowiada VALUE_REQUIRED.\",\"befund_client_id_typ\":\"client_id jest typu {typ}, nie tekstem || Nawet czysto liczbowy client_id nale\u017cy uj\u0105\u0107 w cudzys\u0142\u00f3w. Bez niego Google nie odczyta ca\u0142ego \u0142adunku.\",\"befund_client_id_leer\":\"client_id jest pusty || Pusty ci\u0105g liczy si\u0119 jak brakuj\u0105cy.\",\"befund_client_id_gut\":\"client_id ma zalecan\u0105 posta\u0107 || {wert} \u2014 dwie liczby po\u0142\u0105czone kropk\u0105, dok\u0142adnie to, co wydaje gtag.\",\"befund_client_id_cookie\":\"client_id to pe\u0142na warto\u015b\u0107 ciasteczka || {wert}. Measurement Protocol j\u0105 przyjmuje i ta posta\u0107 jest wprost przewidziana. Kr\u00f3tsza, bez przedrostka GA1, to ta, kt\u00f3r\u0105 zg\u0142asza sam gtag.\",\"befund_client_id_form\":\"client_id ma nietypow\u0105 posta\u0107 || {wert}. Zostanie przyj\u0119ty, ale warto\u015b\u0107 spoza przegl\u0105darki tworzy przy ka\u017cdym \u017c\u0105daniu nowego u\u017cytkownika \u2014 tak w\u0142a\u015bnie raport zape\u0142nia si\u0119 sesjami z jednym zdarzeniem.\",\"befund_client_id_im_app\":\"client_id w \u0142adunku aplikacji || Strumienie aplikacji rozpoznaj\u0105 instalacj\u0119 po app_instance_id. client_id jest tu pomijany.\",\"befund_app_id_im_web\":\"app_instance_id w \u0142adunku sieciowym || Strumienie sieciowe rozpoznaj\u0105 przegl\u0105dark\u0119 po client_id. app_instance_id jest tu pomijany.\",\"befund_app_id_fehlt\":\"Brakuje app_instance_id || Strumienie aplikacji go potrzebuj\u0105; pochodzi z SDK Firebase i nie jest identyfikatorem client_id.\",\"befund_app_id_typ\":\"app_instance_id jest typu {typ}, nie tekstem || Warto\u015b\u0107 nale\u017cy uj\u0105\u0107 w cudzys\u0142\u00f3w.\",\"befund_app_id_gut\":\"app_instance_id ma oczekiwan\u0105 posta\u0107 || 32 znaki szesnastkowe.\",\"befund_app_id_form\":\"app_instance_id ma nietypow\u0105 posta\u0107 || {wert}, znak\u00f3w: {n}. SDK zwraca 32 znaki szesnastkowe; wszystko inne oznacza zwykle wklejony client_id.\",\"befund_user_id_typ\":\"user_id jest typu {typ}, nie tekstem || Warto\u015b\u0107 nale\u017cy uj\u0105\u0107 w cudzys\u0142\u00f3w.\",\"befund_user_id_lang\":\"user_id ma {n} znak\u00f3w || Udokumentowany limit to {grenze}.\",\"befund_user_id_pii\":\"user_id wygl\u0105da na dane osobowe ({art}) || Google Analytics zabrania wysy\u0142ania identyfikator\u00f3w osobowych. Pseudonimowy klucz z CRM robi to samo bez ryzyka usuni\u0119cia us\u0142ugi.\",\"befund_zeitstempel_typ\":\"timestamp_micros nie jest liczb\u0105 || {wert} typu {typ}. Oczekiwany jest znacznik czasu uniksowego w mikrosekundach.\",\"befund_zeitstempel_sekunden\":\"timestamp_micros podano w sekundach zamiast w mikrosekundach || {wert}. Warto\u015b\u0107 jest oko\u0142o milion razy za ma\u0142a i umieszcza zdarzenie w roku 1970. Serwer walidacyjny to zg\u0142asza, ale jako \u201eza daleko w przesz\u0142o\u015bci\u201d \u2014 komunikat, kt\u00f3ry kieruje poszukiwania na nieistniej\u0105cy problem z datowaniem wstecz.\",\"befund_zeitstempel_millisekunden\":\"timestamp_micros podano w milisekundach zamiast w mikrosekundach || {wert}. Date.now() zwraca milisekundy; Measurement Protocol oczekuje tej warto\u015bci razy 1000.\",\"befund_zeitstempel_zu_alt\":\"timestamp_micros wskazuje {stunden} godz. wstecz || Zdarzenia mo\u017cna datowa\u0107 wstecz najwy\u017cej o {grenze} godz. Starsze s\u0105 odrzucane.\",\"befund_zeitstempel_zukunft\":\"timestamp_micros wskazuje {minuten} min w przysz\u0142o\u015bci || Zwykle chodzi o rozstrojony zegar albo dwukrotnie doliczon\u0105 stref\u0119 czasow\u0105.\",\"befund_zeitstempel_gut\":\"timestamp_micros mie\u015bci si\u0119 w dopuszczalnym oknie || Oko\u0142o {stunden} godz. wstecz.\",\"befund_ereignis_zeit_typ\":\"Zdarzenie {nr}: timestamp_micros nie jest liczb\u0105 || {wert} typu {typ}.\",\"befund_ereignis_zeit_sekunden\":\"Zdarzenie {nr}: timestamp_micros podano w sekundach || {wert}. Tak\u017ce tutaj oczekiwane s\u0105 mikrosekundy.\",\"befund_ereignis_zeit_millisekunden\":\"Zdarzenie {nr}: timestamp_micros podano w milisekundach || {wert}. Warto\u015b\u0107 trzeba pomno\u017cy\u0107 przez 1000.\",\"befund_ereignis_zeit_zu_alt\":\"Zdarzenie {nr}: timestamp_micros wskazuje {stunden} godz. wstecz || Powy\u017cej {grenze} godz. zdarzenie jest odrzucane.\",\"befund_ereignis_zeit_zukunft\":\"Zdarzenie {nr}: timestamp_micros wskazuje {minuten} min w przysz\u0142o\u015bci || Zwykle chodzi o rozstrojony zegar.\",\"befund_ereignis_zeit_gut\":\"Zdarzenie {nr}: timestamp_micros mie\u015bci si\u0119 w dopuszczalnym oknie || Oko\u0142o {stunden} godz. wstecz.\",\"befund_consent_kein_objekt\":\"consent jest typu {typ}, nie obiektem || Oczekiwany jest obiekt z ad_user_data i ad_personalization.\",\"befund_consent_unbekannt\":\"Nieznany klucz w consent: {schluessel} || S\u0105 tu tylko ad_user_data i ad_personalization. analytics_storage oraz ad_storage nale\u017c\u0105 do Consent Mode w przegl\u0105darce, nie do Measurement Protocol \u2014 a nieznany klucz sprawia, \u017ce Google odrzuca ca\u0142y \u0142adunek.\",\"befund_consent_wert\":\"consent.{schluessel} niesie {wert} || Dopuszczalne s\u0105 wy\u0142\u0105cznie GRANTED i DENIED. Wszystko inne to nieznana warto\u015b\u0107 wyliczeniowa i \u0142adunek nie daje si\u0119 odczyta\u0107.\",\"befund_consent_gut\":\"consent jest ustawiony z {n} poprawn\u0105 warto\u015bci\u0105 || Bez consent Google si\u0119ga po stan z interakcji przegl\u0105darkowych tego samego klienta.\",\"befund_npa_veraltet\":\"non_personalized_ads jest wycofywane || Pole nadal dzia\u0142a, ale zast\u0119puje je ad_personalization wewn\u0105trz consent i to ono b\u0119dzie odczytywane dalej.\",\"befund_verhalten_streng\":\"validation_behavior ma warto\u015b\u0107 ENFORCE_RECOMMENDATIONS || Do testu w sam raz. Na produkcji lepiej pomin\u0105\u0107 to pole, poniewa\u017c rygorystyczna walidacja odrzuca zdarzenia, kt\u00f3re \u0142agodna jeszcze by zebra\u0142a.\",\"befund_verhalten_locker\":\"validation_behavior ma warto\u015b\u0107 RELAXED || To i tak jest ustawienie domy\u015blne. \u0141agodna walidacja pomija parametry przekraczaj\u0105ce limity zamiast je zg\u0142asza\u0107.\",\"befund_verhalten_unbekannt\":\"validation_behavior niesie {wert} || Istniej\u0105 tylko RELAXED i ENFORCE_RECOMMENDATIONS. Wszystko inne to nieznana warto\u015b\u0107 wyliczeniowa i ca\u0142y \u0142adunek nie daje si\u0119 odczyta\u0107.\",\"befund_up_kein_objekt\":\"user_properties jest typu {typ}, nie obiektem || Oczekiwany jest obiekt nazw, pod kt\u00f3rymi stoi obiekt z kluczem value.\",\"befund_up_zu_viele\":\"W\u0142a\u015bciwo\u015bci u\u017cytkownika: {n} || Na \u017c\u0105danie przyjmowanych jest najwy\u017cej {grenze}.\",\"befund_up_reserviert\":\"user_properties niesie zastrze\u017con\u0105 nazw\u0119 {name} || Nazwy zastrze\u017cone s\u0105 odrzucane. Identyfikator u\u017cytkownika nale\u017cy do najwy\u017cszego poziomu jako user_id, a nie do user_properties.\",\"befund_up_praefix\":\"Nazwa {name} w user_properties zaczyna si\u0119 od {praefix} || Ten przedrostek jest zastrze\u017cony.\",\"befund_up_name_lang\":\"Nazwa {name} w user_properties ma {n} znak\u00f3w || Limit wynosi tu {grenze} i jest cia\u015bniejszy ni\u017c dla parametr\u00f3w zdarze\u0144.\",\"befund_up_ohne_value\":\"user_properties {name} nie ma otoczki value || Oczekiwane jest {\\u0022value\\u0022: ...}. Go\u0142y ci\u0105g sprawia, \u017ce ca\u0142y \u0142adunek nie daje si\u0119 odczyta\u0107.\",\"befund_up_wert_typ\":\"user_properties {name} niesie warto\u015b\u0107 typu {typ} || Warto\u015bci w\u0142a\u015bciwo\u015bci u\u017cytkownika s\u0105 warto\u015bciami pojedynczymi, nie strukturami.\",\"befund_up_wert_lang\":\"Warto\u015b\u0107 {name} ma {n} znak\u00f3w || Limit wynosi tu {grenze} i jest cia\u015bniejszy ni\u017c dla parametr\u00f3w zdarze\u0144.\",\"befund_up_pii\":\"Warto\u015b\u0107 {name} wygl\u0105da na dane osobowe ({art}) || Google Analytics zabrania wysy\u0142ania identyfikator\u00f3w osobowych.\",\"befund_up_fremder_schluessel\":\"user_properties {name} niesie dodatkowy klucz: {schluessel} || Nale\u017cy tam wy\u0142\u0105cznie value.\",\"befund_up_gut\":\"Wszystkie w\u0142a\u015bciwo\u015bci u\u017cytkownika ({n}) mieszcz\u0105 si\u0119 w limitach || Nazwy do 24 znak\u00f3w, warto\u015bci do 36.\",\"befund_events_fehlt\":\"Brakuje events || Tablica jest wymagana. Serwer walidacyjny przyjmuje \u0142adunek bez niej bez s\u0142owa \u2014 zmierzone, nie domniemane \u2014 i nic nie zostaje zebrane.\",\"befund_events_kein_array\":\"events jest typu {typ}, nie tablic\u0105 || Nawet pojedyncze zdarzenie nale\u017cy do tablicy.\",\"befund_events_leer\":\"events jest puste || Pusta tablica nic nie niesie. Serwer walidacyjny nie zg\u0142asza problemu, a mimo to nic nie dociera.\",\"befund_events_zu_viele\":\"Zdarze\u0144 w jednym \u017c\u0105daniu: {n} || Udokumentowane jest najwy\u017cej {grenze}. W pomiarze na serwerze walidacyjnym 30 zdarze\u0144 przesz\u0142o bez s\u0142owa \u2014 nadmiar odpada wi\u0119c po cichu, zamiast zosta\u0107 zg\u0142oszony.\",\"befund_ereignis_kein_objekt\":\"Zdarzenie {nr} jest typu {typ}, nie obiektem || Ka\u017cdy wpis wymaga name i mo\u017ce nie\u015b\u0107 params.\",\"befund_ereignis_fremder_schluessel\":\"Zdarzenie {nr} niesie nieznany klucz: {schluessel} || Do zdarzenia nale\u017c\u0105 wy\u0142\u0105cznie name i params. Znacznik czasu trafia do params jako timestamp_micros.\",\"befund_ereignis_ohne_name\":\"Zdarzenie {nr} nie ma nazwy || Bez nazwy nie ma czego rejestrowa\u0107.\",\"befund_ereignis_name_typ\":\"Nazwa zdarzenia {nr} jest typu {typ} || Oczekiwany jest ci\u0105g znak\u00f3w.\",\"befund_ereignis_name_lang\":\"Nazwa zdarzenia {nr} ma {n} znak\u00f3w || {name}. Limit wynosi {grenze}.\",\"befund_ereignis_name_form\":\"Nazwa zdarzenia {nr} ma niedopuszczaln\u0105 posta\u0107 || {name}. Nazwy musz\u0105 zaczyna\u0107 si\u0119 od litery i mog\u0105 zawiera\u0107 wy\u0142\u0105cznie litery, cyfry i podkre\u015blenia. My\u015blniki, kropki i spacje s\u0105 odrzucane.\",\"befund_ereignis_name_gross\":\"Nazwa zdarzenia {nr} zawiera wielkie litery || {name}. Nazwy zdarze\u0144 rozr\u00f3\u017cniaj\u0105 wielko\u015b\u0107 liter: Purchase i purchase to dwa r\u00f3\u017cne zdarzenia, a raporty e-commerce zasila tylko to pisane ma\u0142ymi literami.\",\"befund_ereignis_name_reserviert\":\"Nazwa zdarzenia {nr} jest zastrze\u017cona || {name}. Google u\u017cywa tej nazwy samodzielnie; zdarzenie zostaje odrzucone.\",\"befund_ereignis_name_praefix\":\"Nazwa zdarzenia {nr} zaczyna si\u0119 od {praefix} || {name}. Ten przedrostek jest zastrze\u017cony.\",\"befund_ereignis_nur_app\":\"Zdarzenie {nr} jest dozwolone tylko w strumieniach aplikacji || {name}. W strumieniu sieciowym nie zostanie zebrane. Serwer walidacyjny nic o tym nie m\u00f3wi \u2014 zmierzone, nie domniemane.\",\"befund_ereignis_doppelt\":\"Nazwa zdarzenia {name} wyst\u0119puje {n} raz(y) || Dwa zdarzenia o tej samej nazwie w jednym \u017c\u0105daniu zostan\u0105 przyj\u0119te i policzone oba. Czy tak mia\u0142o by\u0107, warto sprawdzi\u0107, bo zwykle stoi za tym p\u0119tla wyzwalaj\u0105ca si\u0119 raz za du\u017co.\",\"befund_params_kein_objekt\":\"params zdarzenia {nr} jest typu {typ}, nie obiektem || Parametry to pary nazwy i warto\u015bci.\",\"befund_params_zu_viele\":\"Zdarzenie {nr} ma {n} parametr\u00f3w || Na zdarzenie przyjmowanych jest najwy\u017cej {grenze}, powy\u017cej rygorystyczna walidacja odrzuca \u017c\u0105danie.\",\"befund_param_reserviert\":\"Zdarzenie {nr} u\u017cywa zastrze\u017conej nazwy parametru {name} || Nazwa zostaje odrzucona.\",\"befund_param_praefix\":\"Zdarzenie {nr}: parametr {name} zaczyna si\u0119 od {praefix} || Zastrze\u017cone przedrostki to _, firebase_, ga_, google_ i gtag. Parametr zostaje odrzucony.\",\"befund_param_name_lang\":\"Zdarzenie {nr}: nazwa parametru {name} ma {n} znak\u00f3w || Limit wynosi {grenze}.\",\"befund_param_verschachtelt\":\"Zdarzenie {nr}: parametr {name} niesie warto\u015b\u0107 typu {typ} || Tylko items mo\u017ce by\u0107 tablic\u0105. Ka\u017cdy inny parametr przyjmuje warto\u015b\u0107 pojedyncz\u0105; struktura zagnie\u017cd\u017cona odpada.\",\"befund_param_null\":\"Zdarzenie {nr}: parametr {name} to null || Warto\u015b\u0107 pusta nie jest warto\u015bci\u0105. Pomini\u0119cie parametru m\u00f3wi to samo wyra\u017aniej.\",\"befund_param_leer\":\"Zdarzenie {nr}: parametr {name} jest pusty || Pusty ci\u0105g wygl\u0105da jak odpowied\u017a, a ni\u0105 nie jest. W raporcie pojawia si\u0119 jako pusta warto\u015b\u0107 wymiaru, a nie jako brak.\",\"befund_param_wert_lang\":\"Zdarzenie {nr}: warto\u015b\u0107 {name} ma {n} znak\u00f3w || Limit wynosi {grenze}. W trybie \u0142agodnym \u2014 domy\u015blnym, i tym z produkcji \u2014 warto\u015b\u0107 zostaje skr\u00f3cona lub porzucona bez s\u0142owa; zmierzone na serwerze walidacyjnym: ten sam \u0142adunek wr\u00f3ci\u0142 czysty.\",\"befund_param_typ\":\"Zdarzenie {nr}: {name} powinno by\u0107 {soll}, a jest {ist} || {wert}. Warto\u015bci niew\u0142a\u015bciwego typu s\u0105 przy znanych parametrach odrzucane.\",\"befund_param_pii\":\"Zdarzenie {nr}: {name} wygl\u0105da na dane osobowe ({art}) || Google Analytics zabrania wysy\u0142ania identyfikator\u00f3w osobowych, a us\u0142uga, kt\u00f3ra to robi, mo\u017ce zosta\u0107 usuni\u0119ta.\",\"befund_waehrung_form\":\"Zdarzenie {nr}: currency nie jest trzyliterowym kodem || {wert}. Oczekiwany jest ISO 4217 wielkimi literami, na przyk\u0142ad EUR albo USD.\",\"befund_wert_ohne_waehrung\":\"Zdarzenie {nr} ma value, ale nie ma currency || Przych\u00f3d bez waluty nie jest liczony w og\u00f3le. To najcz\u0119stszy pow\u00f3d, dla kt\u00f3rego raport e-commerce stoi na zerze, cho\u0107 zdarzenia docieraj\u0105.\",\"befund_waehrung_ohne_wert\":\"Zdarzenie {nr} ma currency, ale nie ma value || Sama waluta nie niesie przychodu.\",\"befund_session_id_fehlt\":\"\u017badne zdarzenie nie niesie session_id || Bez niego zdarzenia nie nale\u017c\u0105 do \u017cadnej sesji. W cz\u0119\u015bci raport\u00f3w i tak si\u0119 pojawi\u0105, ale sesje, sesje anga\u017cuj\u0105ce i widok w czasie rzeczywistym si\u0119 nie zgadzaj\u0105.\",\"befund_engagement_fehlt\":\"\u017badne zdarzenie nie niesie engagement_time_msec || Bez niego \u015bredni czas zaanga\u017cowania zostaje na zerze, a w czasie rzeczywistym zdarze\u0144 mo\u017ce zabrakn\u0105\u0107 zupe\u0142nie.\",\"befund_items_kein_array\":\"Zdarzenie {nr}: items jest typu {typ}, nie tablic\u0105 || Nawet pojedyncza pozycja nale\u017cy do tablicy.\",\"befund_items_leer\":\"Zdarzenie {nr}: items jest puste || Zdarzenie e-commerce bez pozycji nie zasila \u017cadnego raportu asortymentu.\",\"befund_items_zu_viele\":\"Zdarzenie {nr}: pozycji {n} || Udokumentowane jest najwy\u017cej {grenze} na zdarzenie.\",\"befund_item_kein_objekt\":\"Zdarzenie {nr}, pozycja {pos} jest typu {typ} || Ka\u017cda pozycja to obiekt z co najmniej item_id albo item_name.\",\"befund_item_ohne_kennung\":\"Zdarzenie {nr}, pozycja {pos} nie ma ani item_id, ani item_name || Jedno z dwojga jest wymagane; bez obu pozycji nie da si\u0119 pokaza\u0107.\",\"befund_item_typ\":\"Zdarzenie {nr}, pozycja {pos}: {feld} jest typu {ist} || {wert}. Oczekiwana jest liczba. Typy w pozycjach serwer walidacyjny faktycznie sprawdza \u2014 cena w cudzys\u0142owie wr\u00f3ci\u0142a jako VALUE_INVALID.\",\"befund_item_eigene_felder\":\"Zdarzenie {nr}, pozycja {pos} niesie {n} w\u0142asnych p\u00f3l || Na pozycj\u0119 odczytywanych jest najwy\u017cej {grenze} w\u0142asnych parametr\u00f3w.\",\"befund_summe_weicht_ab\":\"Zdarzenie {nr}: value wynosi {value}, pozycje daj\u0105 {summe} || Samo w sobie nie jest to b\u0142\u0119dem \u2014 wysy\u0142ka, podatek i rabaty t\u0142umacz\u0105 r\u00f3\u017cnic\u0119 s\u0142usznie. Tam, gdzie nie t\u0142umacz\u0105, jedna z dwu liczb jest b\u0142\u0119dna, a raport przeczy sklepowi.\",\"befund_summe_passt\":\"Zdarzenie {nr}: value zgadza si\u0119 z pozycjami || Cena razy ilo\u015b\u0107 daje {summe}.\",\"befund_items_fehlen\":\"Zdarzenie {nr} ({ereignis}) nie ma items || To zdarzenie zasila raporty asortymentu, a bez pozycji nie ma czym.\",\"befund_empfohlene_fehlen\":\"Zdarzeniu {nr} ({ereignis}) brakuje parametr\u00f3w zalecanych || {felder}. Zdarzenie zostanie zebrane i bez nich, ale oparte na nim raporty pozostan\u0105 puste.\",\"befund_empfohlene_da\":\"Zdarzenie {nr} ({ereignis}) niesie parametry zalecane || Dla tego zdarzenia nic nie brakuje.\",\"befund_zahlen\":\"Zdarze\u0144: {ereignisse}, parametr\u00f3w: {parameter}, pozycji: {items}, w\u0142a\u015bciwo\u015bci u\u017cytkownika: {user_properties} || Tyle niesie \u0142adunek.\"};<\/p>\n<p>    var ENDPUNKT = '\/lw-mpvalidate.php';\n    var SITEKEY = '6LcrPkEtAAAAAPo1QCOf-IIM2fCL0UfdJz4y2iSY';\n    var STUFEN = ['hoch', 'mittel', 'niedrig', 'info', 'gut'];\n    var NL = String.fromCharCode(10);<\/p>\n<p>    var BEISPIEL_FEHLER = [\n        '{',\n        '  \"client_id\": \"1234567890.1700000000\",',\n        '  \"timestamp_micros\": 1700000000,',\n        '  \"consent\": { \"ad_user_data\": \"yes\" },',\n        '  \"user_properties\": { \"user_id\": { \"value\": \"k-9910\" } },',\n        '  \"events\": [',\n        '    {',\n        '      \"name\": \"Purchase\",',\n        '      \"params\": {',\n        '        \"transaction_id\": \"T-8891\",',\n        '        \"value\": 25,',\n        '        \"ga_source\": \"newsletter\",',\n        '        \"customer_mail\": \"anna@example.com\",',\n        '        \"items\": [ { \"item_id\": \"A-1\", \"price\": 10, \"quantity\": 2 } ]',\n        '      }',\n        '    },',\n        '    { \"name\": \"screen_view\", \"params\": { \"screen_name\": \"Checkout\" } }',\n        '  ]',\n        '}'\n    ].join(NL);<\/p>\n<p>    var BEISPIEL_SAUBER = [\n        '{',\n        '  \"client_id\": \"1234567890.1700000000\",',\n        '  \"consent\": { \"ad_user_data\": \"GRANTED\", \"ad_personalization\": \"DENIED\" },',\n        '  \"user_properties\": { \"customer_tier\": { \"value\": \"gold\" } },',\n        '  \"events\": [',\n        '    {',\n        '      \"name\": \"purchase\",',\n        '      \"params\": {',\n        '        \"transaction_id\": \"T-8891\",',\n        '        \"currency\": \"EUR\",',\n        '        \"value\": 20,',\n        '        \"session_id\": \"1700000000\",',\n        '        \"engagement_time_msec\": 100,',\n        '        \"items\": [ { \"item_id\": \"A-1\", \"item_name\": \"Shirt\", \"price\": 10, \"quantity\": 2 } ]',\n        '      }',\n        '    }',\n        '  ]',\n        '}'\n    ].join(NL);<\/p>\n<p>    function liste(w) { return Array.isArray(w) ? w : []; }\n    function zahl(w) { return (typeof w === 'number' && isFinite(w)) ? w : null; }\n    function zeichen(w) { return (typeof w === 'string' && w !== '') ? w : null; }\n    function text(schluessel, daten) {\n        var t = T[schluessel];\n        if (typeof t !== 'string') { return null; }\n        return t.replace(\/\\{([a-z_0-9]+)\\}\/g, function (m, k) {\n            return (daten && daten[k] !== undefined && daten[k] !== null) ? String(daten[k]) : m;\n        });\n    }\n    \/** Zahl mit Tausenderpunkten in der Sprache der Seite. *\/\n    function tausend(n) {\n        return String(n).replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, T.tausendertrenner || ' ');\n    }\n    \/** Eine Meldung des Pruefservers auf Tabellenbreite kuerzen. *\/\n    function kurz(s, max) {\n        var t = String(s || '');\n        var m = max || 150;\n        return t.length <= m ? t : t.slice(0, m - 1) + '\u2026';\n    }\n\n    function meldungen(w) {\n        return liste(w).map(function (m) {\n            return { feld: String((m &#038;&#038; m.feld) || ''), code: String((m &#038;&#038; m.code) || ''), meldung: String((m &#038;&#038; m.meldung) || '') };\n        });\n    }\n\n    function bewerten(antwort) {\n        var a = antwort || {};\n        if (a.fehler) { return { fehler: String(a.fehler), limit: zahl(a.limit), grenze: zahl(a.grenze) }; }\n        var befunde = liste(a.befunde).map(function (f) {\n            return { key: String(f.key || ''), stufe: STUFEN.indexOf(f.stufe) === -1 ? 'info' : f.stufe, daten: (f.daten &#038;&#038; typeof f.daten === 'object') ? f.daten : {} };\n        });\n        var gruppen = {};\n        STUFEN.forEach(function (s) { gruppen[s] = befunde.filter(function (f) { return f.stufe === s; }); });\n        var ereignisse = liste(a.ereignisse).map(function (z) {\n            return {\n                nr: zahl(z.nr), name: zeichen(z.name), parameter: zahl(z.parameter), items: zahl(z.items),\n                urteil: (z.urteil === 'gut' || z.urteil === 'warnung') ? z.urteil : 'kritisch'\n            };\n        });\n        var g = (a.google &#038;&#038; typeof a.google === 'object') ? a.google : null;\n        var zahlen = (a.zahlen &#038;&#038; typeof a.zahlen === 'object') ? a.zahlen : {};\n        return {\n            fehler: null,\n            urteil: (a.urteil === 'gut' || a.urteil === 'warnung') ? a.urteil : 'kritisch',\n            bytes: zahl(a.bytes), strom: a.strom === 'app' ? 'app' : 'web',\n            befunde: befunde, gruppen: gruppen, ereignisse: ereignisse,\n            zahlen: {\n                ereignisse: zahl(zahlen.ereignisse) || 0, parameter: zahl(zahlen.parameter) || 0,\n                items: zahl(zahlen.items) || 0, user_properties: zahl(zahlen.user_properties) || 0\n            },\n            google: g ? {\n                streng: g.streng ? { fehler: g.streng.fehler || null, meldungen: meldungen(g.streng.meldungen), dauer: zahl(g.streng.dauer_ms) } : null,\n                locker: g.locker ? { fehler: g.locker.fehler || null, meldungen: meldungen(g.locker.meldungen), dauer: zahl(g.locker.dauer_ms) } : null\n            } : null,\n            dauer: zahl(a.dauer_ms), limitRest: zahl(a.limit_rest)\n        };\n    }\n\n    function skriptLaden() {\n        return new Promise(function (auf) {\n            if (window.grecaptcha) { auf(true); return; }\n            var s = document.createElement('script');\n            s.src = 'https:\/\/www.google.com\/recaptcha\/api.js?render=' + SITEKEY;\n            s.onload = function () { auf(true); }; s.onerror = function () { auf(false); };\n            document.head.appendChild(s);\n            setTimeout(function () { auf(!!window.grecaptcha); }, 8000);\n        });\n    }\n    function tokenHolen() {\n        return skriptLaden().then(function (da) {\n            if (!da || !window.grecaptcha || !window.grecaptcha.ready) { return null; }\n            return new Promise(function (auf) {\n                var fertig = false;\n                function einmal(w) { if (!fertig) { fertig = true; auf(w); } }\n                setTimeout(function () { einmal(null); }, 12000);\n                try {\n                    window.grecaptcha.ready(function () {\n                        if (fertig) { return; }\n                        if (!window.grecaptcha.execute) { einmal(null); return; }\n                        window.grecaptcha.execute(SITEKEY, { action: 'mpvalidate' }).then(function (t) { einmal(t || null); }, function () { einmal(null); });\n                    });\n                } catch (e) { einmal(null); }\n            });\n        }, function () { return null; });\n    }\n    function abfragen(eingabe) {\n        return tokenHolen().then(function (token) {\n            var rumpf = {\n                nutzdaten: eingabe.nutzdaten, strom: eingabe.strom, tarif: eingabe.tarif,\n                google: eingabe.google, token: token || ''\n            };\n            return fetch(ENDPUNKT, { method: 'POST', headers: { 'Content-Type': 'application\/json' }, body: JSON.stringify(rumpf) })\n                .then(function (r) { return r.json().then(function (j) { return j; }, function () { return { fehler: 'antwort' }; }); }, function () { return { fehler: 'netz' }; });\n        });\n    }\n\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.MPV = {\n        bewerten: bewerten, darstellen: null, text: text, kurz: kurz, tausend: tausend,\n        ENDPUNKT: ENDPUNKT, STUFEN: STUFEN, T: T,\n        BEISPIEL_FEHLER: BEISPIEL_FEHLER, BEISPIEL_SAUBER: BEISPIEL_SAUBER\n    };\n\n    var btn = document.getElementById('mpv-btn');\n    var out = document.getElementById('mpv-ausgabe');\n    var feld = document.getElementById('mpv-json');\n    if (!btn || !out || !feld) { return; }\n\n    function el(tag, stil, txt) { var e = document.createElement(tag); if (stil) { e.setAttribute('style', stil); } if (txt !== undefined &#038;&#038; txt !== null) { e.textContent = txt; } return e; }\n    var UEBERSCHRIFT = 'font-family: \"Nunito Sans\", sans-serif; font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 22px 0 8px;';\n    var ZELLE = 'padding: 5px 12px 5px 0; color: var(--text-secondary, #a0a0b0); font-size: 0.87rem;';\n    var ZELLE_WERT = 'padding: 5px 12px 5px 0; color: var(--text-primary, #e8e8ee); font-size: 0.87rem; font-family: monospace; word-break: break-all;';\n    var KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 14px 16px; margin: 0 0 10px;';\n    var GUT = ' color: #7ee787;', WARN = ' color: #ffa94d;', ROT = ' color: #ff7b72;', GRAU = ' color: #8a8a99;';\n    var FARBEN = { hoch: '#ff7b72', mittel: '#ffa94d', niedrig: '#e3b341', info: '#8a8a99', gut: '#7ee787' };\n    var URTEIL = { gut: GUT, warnung: WARN, kritisch: ROT };\n    function gitter(sp) { return el('div', 'display: grid; grid-template-columns: ' + sp + '; gap: 0 18px; align-items: baseline;'); }\n    function paar(g, n, w, stil) { g.appendChild(el('div', ZELLE, n)); g.appendChild(el('div', ZELLE_WERT + (stil || ''), w)); }\n\n    function tabelle(b) {\n        var huelle = el('div', 'overflow-x: auto; margin: 0 0 6px;');\n        var t = el('table', 'border-collapse: collapse; width: 100%; min-width: 520px; font-size: 0.84rem;');\n        var kopf = el('tr', '');\n        [T.sp_nr, T.sp_name, T.sp_parameter, T.sp_items, T.sp_urteil].forEach(function (n) {\n            kopf.appendChild(el('th', 'text-align: left; padding: 6px 12px 6px 0; color: #8a8a99; font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.4px; border-bottom: 1px solid var(--border, #2a2a35); white-space: nowrap;', n));\n        });\n        t.appendChild(kopf);\n        b.ereignisse.forEach(function (z) {\n            var r = el('tr', '');\n            function zelle(txt, stil) { r.appendChild(el('td', 'padding: 7px 12px 7px 0; border-bottom: 1px solid var(--border, #2a2a35); font-family: monospace; color: var(--text-primary, #e8e8ee);' + (stil || ''), txt)); }\n            zelle(String(z.nr !== null ? z.nr : '-'), GRAU);\n            zelle(z.name || T.wert_fehlt, z.name ? '' : ROT);\n            zelle(String(z.parameter !== null ? z.parameter : '-'), GRAU);\n            zelle(z.items === null ? '-' : String(z.items), GRAU);\n            zelle(T['zeile_' + z.urteil], URTEIL[z.urteil]);\n            t.appendChild(r);\n        });\n        huelle.appendChild(t);\n        return huelle;\n    }\n\n    function googleBlock(name, lauf, eigene) {\n        var kasten = el('div', KASTEN);\n        kasten.appendChild(el('div', 'color: var(--text-primary, #e8e8ee); font-size: 0.9rem; font-weight: 700;', name));\n        if (!lauf) { kasten.appendChild(el('div', ZELLE + ' padding: 6px 0 0;', T.google_uebersprungen)); return kasten; }\n        if (lauf.fehler) {\n            kasten.appendChild(el('div', ZELLE + WARN + ' padding: 6px 0 0;', T['google_fehler_' + lauf.fehler] || T.google_fehler));\n            return kasten;\n        }\n        if (!lauf.meldungen.length) {\n            kasten.appendChild(el('div', ZELLE + GUT + ' padding: 6px 0 0;', text('google_keine', { eigene: eigene })));\n            return kasten;\n        }\n        kasten.appendChild(el('div', ZELLE + ' padding: 6px 0 2px;', text('google_anzahl', { n: lauf.meldungen.length, eigene: eigene })));\n        lauf.meldungen.forEach(function (m) {\n            var z = el('div', 'margin: 8px 0 0; padding: 0 0 0 12px; border-left: 2px solid ' + FARBEN.mittel + ';');\n            z.appendChild(el('div', ZELLE_WERT + ' padding: 0;', m.code + (m.feld ? '  \u00b7  ' + m.feld : '')));\n            z.appendChild(el('div', ZELLE + ' padding: 2px 0 0; line-height: 1.5;', kurz(m.meldung, 320)));\n            kasten.appendChild(z);\n        });\n        return kasten;\n    }\n\n    function darstellen(b, ziel) {\n        ziel.innerHTML = '';\n        if (b.fehler) {\n            var txt = T['fehler_' + b.fehler] || T.fehler_unbekannt;\n            if (b.limit !== null) { txt = txt.replace('{limit}', String(b.limit)); }\n            if (b.grenze !== null) { txt = txt.replace('{grenze}', tausend(b.grenze)); }\n            ziel.appendChild(el('p', ZELLE + WARN + ' margin: 0;', txt));\n            return;\n        }\n        ziel.appendChild(el('div', 'font-size: 1.05rem; font-weight: 700; margin: 0 0 12px;' + URTEIL[b.urteil], T['urteil_' + b.urteil]));\n\n        var g = gitter('auto auto');\n        paar(g, T.zeile_groesse, tausend(b.bytes === null ? 0 : b.bytes) + ' ' + T.einheit_byte, GRAU);\n        paar(g, T.zeile_ereignisse, String(b.zahlen.ereignisse), GRAU);\n        paar(g, T.zeile_parameter, String(b.zahlen.parameter), GRAU);\n        if (b.zahlen.items) { paar(g, T.zeile_items, String(b.zahlen.items), GRAU); }\n        if (b.zahlen.user_properties) { paar(g, T.zeile_up, String(b.zahlen.user_properties), GRAU); }\n        if (b.dauer !== null) { paar(g, T.zeile_dauer, b.dauer + ' ms', GRAU); }\n        if (b.limitRest !== null) { paar(g, T.zeile_limit, String(b.limitRest), GRAU); }\n        ziel.appendChild(g);\n\n        if (b.ereignisse.length) {\n            ziel.appendChild(el('div', UEBERSCHRIFT, T.h_ereignisse));\n            ziel.appendChild(tabelle(b));\n        }\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        var irgendwas = false;\n        STUFEN.forEach(function (s) {\n            var gr = b.gruppen[s];\n            if (!gr.length) { return; }\n            irgendwas = true;\n            ziel.appendChild(el('div', 'font-weight: 700; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.5px; margin: 14px 0 6px; color: ' + FARBEN[s] + ';', T['stufe_' + s] + ' (' + gr.length + ')'));\n            gr.forEach(function (f) {\n                var k = el('div', KASTEN + ' border-left: 3px solid ' + FARBEN[s] + ';');\n                var daten = {};\n                Object.keys(f.daten).forEach(function (n) {\n                    daten[n] = (n === 'bytes' || n === 'grenze') ? tausend(f.daten[n]) : f.daten[n];\n                });\n                if (f.key === 'json_kaputt') { daten.rat = T['hinweis_' + f.daten.hinweis] || T.hinweis_unbekannt; }\n                var t = text('befund_' + f.key, daten) || f.key;\n                var teile = t.split(' || ');\n                k.appendChild(el('div', 'color: var(--text-primary, #e8e8ee); font-size: 0.9rem; font-weight: 700;', teile[0]));\n                if (teile[1]) { k.appendChild(el('div', ZELLE + ' padding: 6px 0 0; line-height: 1.55;', teile[1])); }\n                ziel.appendChild(k);\n            });\n        });\n        if (!irgendwas) { ziel.appendChild(el('p', ZELLE + ' margin: 0;', T.keine_befunde)); }\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_google));\n        if (!b.google) {\n            ziel.appendChild(el('p', ZELLE + ' margin: 0 0 10px;', T.google_aus));\n        } else {\n            var eigene = b.gruppen.hoch.length + b.gruppen.mittel.length;\n            ziel.appendChild(googleBlock(T.google_streng, b.google.streng, eigene));\n            ziel.appendChild(googleBlock(T.google_locker, b.google.locker, eigene));\n            ziel.appendChild(el('p', ZELLE + ' margin: 4px 0 0; line-height: 1.55;', T.google_hinweis));\n        }\n    }\n    window.LW_TEST.MPV.darstellen = darstellen;\n\n    function wert(id) { var e = document.getElementById(id); return e ? e.value : ''; }\n    function angehakt(id) { var e = document.getElementById(id); return !!(e &#038;&#038; e.checked); }\n\n    var b1 = document.getElementById('mpv-bsp1');\n    var b2 = document.getElementById('mpv-bsp2');\n    if (b1) { b1.addEventListener('click', function () { feld.value = BEISPIEL_FEHLER; }); }\n    if (b2) { b2.addEventListener('click', function () { feld.value = BEISPIEL_SAUBER; }); }\n    if (feld.value.trim() === '') { feld.value = BEISPIEL_FEHLER; }\n\n    var laeuft = false;\n    btn.addEventListener('click', function () {\n        if (laeuft) { return; }\n        laeuft = true; btn.disabled = true;\n        out.innerHTML = '';\n        out.appendChild(el('p', ZELLE + GRAU + ' margin: 0;', T.laeuft));\n        abfragen({\n            nutzdaten: feld.value, strom: wert('mpv-strom') === 'app' ? 'app' : 'web',\n            tarif: angehakt('mpv-360') ? '360' : 'standard', google: angehakt('mpv-google')\n        }).then(function (a) { darstellen(bewerten(a), out); laeuft = false; btn.disabled = false; },\n            function () { darstellen(bewerten({ fehler: 'netz' }), out); laeuft = false; btn.disabled = false; });\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Narz\u0119dzie czyta \u0142adunek Measurement Protocol wed\u0142ug udokumentowanych regu\u0142 i zg\u0142asza ka\u017cdy b\u0142\u0105d w jednym przebiegu: nazwy zastrze\u017cone, ciche limity d\u0142ugo\u015bci, znaczniki czasu w z\u0142ej jednostce, dane osobowe w parametrach, sumy pozycji niezgodne z value. Ten sam tekst trafia dwukrotnie na serwer walidacyjny Google \u2014 w trybie rygorystycznym i w tym, kt\u00f3ry obowi\u0105zuje na produkcji \u2014 wi\u0119c r\u00f3\u017cnica mi\u0119dzy trzema ocenami jest widoczna obok siebie.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9284,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92097,92100,92136],"class_list":["post-16779","page","type-page","status-publish","hentry","tag-data-quality-pl","tag-google-analytics-4-pl","tag-server-side-gtm-pl"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Narz\u0119dzie czyta \u0142adunek Measurement Protocol wed\u0142ug udokumentowanych regu\u0142 i zg\u0142asza ka\u017cdy b\u0142\u0105d w jednym przebiegu: nazwy zastrze\u017cone, ciche limity d\u0142ugo\u015bci, znaczniki czasu w z\u0142ej jednostce, dane osobowe w parametrach, sumy pozycji niezgodne z value. Ten sam tekst trafia dwukrotnie na serwer walidacyjny Google \u2014 w trybie rygorystycznym i w tym, kt\u00f3ry obowi\u0105zuje na produkcji \u2014 wi\u0119c r\u00f3\u017cnica mi\u0119dzy trzema ocenami jest widoczna obok siebie.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-09T11:09:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/ga4-measurement-protocol-json-validator\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/ga4-measurement-protocol-json-validator\\\/\",\"name\":\"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-09T10:40:52+00:00\",\"dateModified\":\"2026-09-09T11:09:32+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/ga4-measurement-protocol-json-validator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/ga4-measurement-protocol-json-validator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/ga4-measurement-protocol-json-validator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-3\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/","og_locale":"en_US","og_type":"article","og_title":"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog","og_description":"Narz\u0119dzie czyta \u0142adunek Measurement Protocol wed\u0142ug udokumentowanych regu\u0142 i zg\u0142asza ka\u017cdy b\u0142\u0105d w jednym przebiegu: nazwy zastrze\u017cone, ciche limity d\u0142ugo\u015bci, znaczniki czasu w z\u0142ej jednostce, dane osobowe w parametrach, sumy pozycji niezgodne z value. Ten sam tekst trafia dwukrotnie na serwer walidacyjny Google \u2014 w trybie rygorystycznym i w tym, kt\u00f3ry obowi\u0105zuje na produkcji \u2014 wi\u0119c r\u00f3\u017cnica mi\u0119dzy trzema ocenami jest widoczna obok siebie.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-09-09T11:09:32+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/","name":"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-09T10:40:52+00:00","dateModified":"2026-09-09T11:09:32+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-measurement-protocol-json-validator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-3\/"},{"@type":"ListItem","position":3,"name":"Walidator JSON dla Measurement Protocol w GA4: wszystkie b\u0142\u0119dy naraz"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/16779","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=16779"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/16779\/revisions"}],"predecessor-version":[{"id":17030,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/16779\/revisions\/17030"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9284"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=16779"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=16779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}