01 Tracking & consent — desktop jasny · persona: klient (owner) · 1440×1280 · linia zgięcia 810 · nad zgięciem: consent + guard + początek formularza
Szukaj widoku, rekordu, komendy… ⌘K

Tracking & consent

aion-marketing · singleton tracking_config · kanały: GA4, Meta wł. · LinkedIn, TikTok wył. · LIVE · 03:07

Consent Mode v2 default deny

LIVE · 03:07

Domyślne flagi pushowane przez defaultDenied() przed załadowaniem jakiegokolwiek tagu · wait_for_update: 500 · klucz storage aios-cookie-consent.

Guard ci:no-hardcode-analytics PASS LIVE · 02:58 exit 0 · skan apps/ + packages/ · 0 naruszeń
Tagi ładowane po zgodzie LIVE · 03:07 loadGa4() → hasAnalyticsConsent · loadMetaPixel() → hasAdConsent
ID tylko w Directus / env LIVE · 03:07 TrackingClientConfig z singletonu · zero literałów w kodzie
sGTM endpoint sgtm_endpoint brak UNVERIFIED upgrade path · pole puste w singletonie

Identyfikatory · singleton tracking_config

test event 03:04 · sent: ga4_mp, meta_capi LIVE · 03:07
GA4 Measurement ID ga4_measurement_idwł.
G-7Q4KX2M9PL
format G- + 10 znaków · zgodny
GA4 API secret ga4_api_secret
•••••••••••••••• pokaż 5 s
Measurement Protocol · special: conceal · zapis tylko przez Directus
Meta Pixel ID meta_pixel_idwł.
102938475612345
15–16 cyfr · zgodny
Meta CAPI token meta_capi_token
•••••••••••••••• pokaż 5 s
system user token · special: conceal · max 512 znaków
LinkedIn Partner ID linkedin_partner_idwył.
nie skonfigurowano
6–8 cyfr · kanał wyłączony
TikTok Pixel ID tiktok_pixel_idwył.
tt-9K3L2M4
Oczekiwano formatu C + 18 znaków alfanumerycznych — zapis zablokowany do poprawy
GTM container gtm_id
GTM-N7X4KQ2
format GTM- + 7 znaków · opcjonalny, client-side
Meta test_event_code test_event_code
TEST41872
Events Manager · tylko staging · dodawany do „Test event”
Zapis przez @directus/sdk do singletonu. Pola conceal nie wracają do klienta — „pokaż 5 s” pobiera wartość jednorazowo. Test event → /api/track Zapisz w Directus

Strumień /api/track

ostatnie 5 z 1 240 zdarzeń · 24 h · retencja 30 dni LIVE · 03:07 Filtr Eksport
event_idZdarzenie → MetaŹródłoUser-dataCAPI / Measurement ProtocolCzas
5f1c2a7e-9b3d-4e61-a8f0-2c7d9e4b1a35 page_view client — brak user_data skipped · meta_capi · ad_storage denied sent · ga4_mp 03:06:41
c0b7d3e1-4a52-4f8e-9c6b-7e1f2a3b4c5d generate_lead → Lead server sha256 · em, ph sent · meta_capi, ga4_mp 03:05:12
e7a1b2c3-d4e5-4f60-8a9b-0c1d2e3f4a5b generate_lead → Lead test server sha256 · em sent · meta_capi · test_event_code 03:04:02
sha256:a3f9c2e17b4d…5e8f · ord_1042 purchase → Purchase server sha256 · em, external_id sent · meta_capi · dedup event_id 03:01:55
9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d contact_form_submit → Contact server sha256 · em error meta_capi 400 · OAuthException 190 02:58:30
event_id współdzielony client/server — deduplikacja Pixel + CAPI · purchase = sha256(order_id + event) Pokaż wszystkie
02 Tracking & consent — desktop operator (ciemny) · persona: operator Aion · 1440×1280 · linia zgięcia 810 · tenant switcher · „rotuj” na sekretach · drawer zdarzenia z błędem · tooltip kill-gate
Szukaj widoku, rekordu, komendy… ⌘K

Tracking & consent

aion-marketing · singleton tracking_config · kanały: GA4, Meta wł. · LinkedIn, TikTok wył. · LIVE · 03:07

Consent Mode v2 default deny

LIVE · 03:07

Domyślne flagi pushowane przez defaultDenied() przed załadowaniem jakiegokolwiek tagu · wait_for_update: 500 · klucz storage aios-cookie-consent.

Guard ci:no-hardcode-analytics PASS LIVE · 02:58 exit 0 · skan apps/ + packages/ · 0 naruszeń
Tagi ładowane po zgodzie LIVE · 03:07 loadGa4() → hasAnalyticsConsent · loadMetaPixel() → hasAdConsent
ID tylko w Directus / env LIVE · 03:07 TrackingClientConfig z singletonu · zero literałów w kodzie
sGTM endpoint sgtm_endpoint brak UNVERIFIED upgrade path · pole puste w singletonie

Identyfikatory · singleton tracking_config

test event 03:04 · sent: ga4_mp, meta_capi LIVE · 03:07
GA4 Measurement ID ga4_measurement_idwł.
G-7Q4KX2M9PL
format G- + 10 znaków · zgodny
GA4 API secret ga4_api_secret
•••••••••••••••• pokaż 5 s rotuj
Measurement Protocol · special: conceal · zapis tylko przez Directus
Meta Pixel ID meta_pixel_idwł.
102938475612345
15–16 cyfr · zgodny
Meta CAPI token meta_capi_token
•••••••••••••••• pokaż 5 s rotuj
system user token · special: conceal · max 512 znaków
LinkedIn Partner ID linkedin_partner_idwył.
nie skonfigurowano
6–8 cyfr · kanał wyłączony
TikTok Pixel ID tiktok_pixel_idwył.
tt-9K3L2M4
Oczekiwano formatu C + 18 znaków alfanumerycznych — zapis zablokowany do poprawy
GTM container gtm_id
GTM-N7X4KQ2
format GTM- + 7 znaków · opcjonalny, client-side
Meta test_event_code test_event_code
TEST41872
Events Manager · tylko staging · dodawany do „Test event”
Zapis przez @directus/sdk do singletonu. Pola conceal nie wracają do klienta — „pokaż 5 s” pobiera wartość jednorazowo. Test event → /api/track Zapisz w Directus

Strumień /api/track

ostatnie 5 z 1 240 zdarzeń · 24 h · retencja 30 dni LIVE · 03:07 Filtr Eksport
event_idZdarzenie → MetaŹródłoUser-dataCAPI / Measurement ProtocolCzas
5f1c2a7e-9b3d-4e61-a8f0-2c7d9e4b1a35 page_view client — brak user_data skipped · meta_capi · ad_storage denied sent · ga4_mp 03:06:41
c0b7d3e1-4a52-4f8e-9c6b-7e1f2a3b4c5d generate_lead → Lead server sha256 · em, ph sent · meta_capi, ga4_mp 03:05:12
e7a1b2c3-d4e5-4f60-8a9b-0c1d2e3f4a5b generate_lead → Lead test server sha256 · em sent · meta_capi · test_event_code 03:04:02
sha256:a3f9c2e17b4d…5e8f · ord_1042 purchase → Purchase server sha256 · em, external_id sent · meta_capi · dedup event_id 03:01:55
9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d contact_form_submit → Contact server sha256 · em error meta_capi 400 · OAuthException 190 02:58:30
event_id współdzielony client/server — deduplikacja Pixel + CAPI · purchase = sha256(order_id + event) Pokaż wszystkie
03 Stany — loading · empty · error · blocked · 1440 × auto · jasny · każdy stan z akcją i etykietą wiarygodności
Loading · skeleton karty consent + formularza · shimmer = jedyne opacity
Empty · świeży tenant, singleton pusty · checklist runbooka, nie ilustracja

Tracking nie jest jeszcze skonfigurowany

Singleton tracking_config nie ma żadnego identyfikatora. Strona działa z Consent Mode v2 default deny — żaden tag się nie ładuje. Uzupełnij kroki po kolei; każdy weryfikujemy automatycznie.

Otwórz singleton w Directusrunbook §4 — tracking
  1. Consent Mode v2 default deny aktywnydefaultDenied() w site-header · LIVE · 03:07
  2. Wklej GA4 Measurement ID i API secretAdmin GA4 → Data streams → Measurement Protocol
  3. Meta Pixel ID + token CAPI (system user)Events Manager → Ustawienia → Conversions API
  4. Wyślij „Test event” z test_event_codeoczekiwane: sent: meta_capi, ga4_mp w strumieniu
  5. Uruchom guard npm run ci:no-hardcode-analyticsPASS = ID tylko w Directus / env
Error · /api/track nieosiągalny · retry + log, formularz nadal edytowalny
Strumień /api/track nie odpowiada 502 LIVE · 03:07

Trzy próby co 5 s zakończone 502 Bad Gateway z upstreamu Astro (marketing-aionflow-astro). Ostatnie poprawne odczytanie strumienia: 02:58. Konfiguracja identyfikatorów i consent pochodzą z Directus i są aktualne.

GET https://aion-marketing.pl/api/track?limit=8   502  1 204 ms
GET https://aion-marketing.pl/api/track?limit=8   502  1 189 ms
GET https://aion-marketing.pl/api/track?limit=8   502  1 211 ms
upstream: 127.0.0.1:3023 · pm2 marketing-aionflow-astro · status: online, restarts: 3 (10 min)
Ponów Build & Deploy → smokeZdarzenia po stronie serwera są buforowane — nie giną.
Blocked · rola member = read-only · brak uprawnień do sekretów · guard FAIL
Zapis zablokowany — rola member BLOCKED

Identyfikatory widoczne, sekrety ukryte bez „pokaż 5 s”. Zmianę zatwierdza owner lub operator Aion. To nie jest „partial done” — brak uprawnień to stan końcowy tego ekranu.

Poproś ownera
Guard ci:no-hardcode-analytics FAIL LIVE · 03:02 exit 1 · 2 naruszenia · build zablokowany do poprawy

Naruszenia file · match

apps/starter/src/layouts/Base.astro:41G-7Q4KX2M9PL
packages/tracking/src/analytics.ts:112fbq('init', '1029…')

Przenieś ID do tracking_config (Directus) lub env; kod czyta wyłącznie TrackingClientConfig.

05 Spec — decyzje · tekst · hierarchia · badge vs cisza · LIVE/UNVERIFIED · komponenty §5

Decyzje projektowe — Tracking & consent

  1. Consent przed identyfikatorami. Karta Consent Mode v2 stoi nad formularzem, bo bez default deny żaden ID nie ma prawa się załadować. Flagi pokazujemy 1:1 z DEFAULT_DENIED (7 kluczy, w tym functionality i security granted) — bez upraszczania do „cookies tak/nie”.
  2. Sekrety = ConcealField. ga4_api_secret i meta_capi_token zawsze jako ••••; „pokaż 5 s” dostępne dla ownera i operatora, „rotuj” tylko dla operatora (persona 02). Rola member nie widzi żadnej akcji na sekrecie (artboard 03 · blocked).
  3. Walidacja formatu jest blokująca, nie ostrzegawcza. Błędny tiktok_pixel_id zmienia obrys pola na krytyczny + ikona + zdanie z oczekiwanym wzorem; zapis czeka na poprawę. Puste pole to obrys kreskowany i etykieta „nie skonfigurowano” — nie kolor.
  4. Strumień zamiast licznika. /api/track to tabela zdarzeń z pełnym event_id w mono, źródłem client/server (ikona + słowo), hashem user-data (✓ sha256 + lista pól) i statusem CAPI/MP. OK = „sent · …” bez badge'a; badge tylko dla error i test.
  5. Guard CI jako StatusTile, nie baner. ci:no-hardcode-analytics ma PASS z dowodem (komenda + exit code + LIVE hh:mm). FAIL rozwija listę file · match. Zielony pojawia się wyłącznie z dowodem — pozostałe tile bez koloru („cisza”).
  6. Operator dostaje drawer, klient tabelę. Szczegóły zdarzenia z błędem (odpowiedź Graph API, kod 190) otwierają się w drawerze po prawej — tylko na planszy operatora; klient widzi błąd w wierszu i link do Events Managera.

Co jest badge'em, co ciszą

ElementSygnałKolor
Guard PASSikona check + „PASS” + LIVE hh:mm + dowód--ok (krawędź + tekst stanu)
Guard FAILikona x + „FAIL” + lista naruszeń--critical
Zdarzenie senttekst „sent · kanały” w monobrak (cisza)
Zdarzenie skippedikona minus + powód consent--muted
Zdarzenie errorbadge critical „error” + kod HTTP--critical
Test eventbadge info „test” + wynik--blue (informacja, nie stan)
Pole niepoprawneobrys + ikona + zdanie--critical na obrysie
Pole pusteobrys kreskowany + „nie skonfigurowano”brak
Kanał wył./wł.switch + słowo--text (nie akcent)
sGTM braktile unknown + UNVERIFIEDkreskowana krawędź

Dane LIVE / UNVERIFIED w mocku

DaneŹródłoEtykieta
Pola singletonu (7 ID + sgtm, test_event_code, enable_*)packages/tracking/schema/tracking_config.jsonLIVE
Flagi consent, wait_for_update: 500, klucz storagepackages/tracking/src/consent.tsLIVE
Dedup event_id, sha256(order_id + event)event-id.ts, hash-user-data.tsLIVE
Guard regex G-[A-Z0-9]{8,}, fbq('init','…')scripts/ci-no-hardcode-analytics.mjsLIVE
Wartości ID (G-7Q4K…, 1029…), zdarzenia, czasyprzykładowe dla tenanta aion-marketingUNVERIFIED (mock)
Kod 190 OAuthExceptionformat błędu Graph APIUNVERIFIED (przykład)

Mapowanie GA4 → Meta (GA4_TO_META) pokazujemy jako strzałkę w kolumnie zdarzenia; nazwy Meta pochodzą z kodu, nie z marketingu.

Komponenty użyte (BRIEF §5)

.status-tile (guard, tagi po zgodzie, sGTM unknown) · .conceal (2 sekrety) · .mode-badge (stopka menu) · .kill-lock (Commerce w menu + tooltip) · .event-stream (/api/track) · .empty-checklist (03) · .skeleton (03) · .blocked-banner (03 + drawer) · .drawer (02) · .tabs — nie użyte w tym widoku (brak grupowania) · .stat-card, .chart-bars, .gate-table, .diff-panel — nie dotyczą Trackingu.

Hierarchia i fold

Nad linią zgięcia (810): nagłówek + karta consent + kolumna 4 tile (guard na górze) + początek formularza. Formularz i strumień poniżej — operator po scrollu widzi całość bez zakładek. Poziomy zagnieżdżenia: karta → wnętrze (surface-2); nic głębiej.

Tokeny — role i test desaturacji

accent-cl (01)
accent-op (02)
ok
warn
critical
blue (link/info)
teal (nieużyty)
muted

Jasny motyw: --accent = --accent-cl (klient/team). Ciemny operator: --accent = --accent-op. Oba akcenty mają inną jasność niż --warn i --teal — primary CTA po desaturacji nie zlewa się z badge'em warn. --purple zadeklarowany, nieużyty.