Przejdź do głównej zawartości

Meta Pixel i Conversions API

Pomiar konwersji reklamowych Meta (Facebook / Instagram): rejestracja konta oraz opłacona transakcja są raportowane jednocześnie z przeglądarki (Meta Pixel) i z serwera (Conversions API), z tym samym identyfikatorem zdarzenia — dzięki czemu Meta widzi jedną konwersję, a nie dwie.

Integracja jest włączana i konfigurowana z panelu administratora: Panel administratora → Marketing — Meta (/dashboard/marketing-settings). Domyślnie jest wyłączona; identyfikator zbioru danych 1222907778063897 jest wpisany wstępnie, token dostępu trzeba wkleić.

👤 Instrukcja dla marketingu

Co jest mierzone

ZdarzenieKiedy się wysyłaWartość
PageViewprzy wejściu na stronę i przy każdej zmianie widoku w aplikacji
CompleteRegistrationdopiero po utworzeniu konta potwierdzonym przez backend
Purchasedopiero po potwierdzeniu płatności przez Przelewy24rzeczywista kwota transakcji, PLN

Czego nie zobaczysz w Menedżerze zdarzeń — i tak ma być:

  • kliknięcie „Zarejestruj się", wysłanie formularza, wpisanie kodu SMS bez powodzenia — rejestracja nieudana nie jest konwersją,
  • powrót ze strony płatności, dopóki operator nie potwierdzi przelewu,
  • odświeżenie strony potwierdzenia płatności — jedna płatność to jedna konwersja,
  • ruch z dev.klient.acepark.pl, panel.acepark.pl i ze środowisk lokalnych — do zbioru danych trafia wyłącznie produkcyjny portal klienta klient.acepark.pl,
  • ruch użytkownika, który nie zaakceptował banera cookies.

Włączenie integracji

  1. Menedżer zdarzeń Meta → Ustawienia zbioru danych → Wygeneruj token dostępu.
  2. Panel administratora → Marketing — Meta: wklej identyfikator zbioru danych i token, przełącz Integracja aktywna, zapisz.
  3. Token jest zapisywany po stronie serwera i nigdy nie wraca do przeglądarki — formularz pokazuje tylko cztery ostatnie znaki. Puste pole przy kolejnym zapisie zostawia zapisany token bez zmian; przycisk „Usuń zapisany token" go kasuje.
  4. Włączenie bez kompletu danych jest odrzucane — panel nie pozwoli twierdzić, że integracja działa, gdy nie miałaby czego wysłać.
  5. Testuj połączenie — przycisk w panelu wysyła pojedyncze PageView zapisanym tokenem i pokazuje odpowiedź Meta. Działa również przy wyłączonej integracji, więc dane dostępowe można sprawdzić przed jej włączeniem. Wymaga wypełnionego kodu zdarzeń testowych: bez niego ping trafiłby do zbioru produkcyjnego, więc akcja się na to nie zgadza.

Zgody

Pixel nie ładuje się w ogóle, dopóki odwiedzający nie zaakceptuje banera cookies. Ta sama odpowiedź steruje wysyłką serwerową: bez zgody nie powstaje żaden event — ani przeglądarkowy, ani z Conversions API.

Baner nie pojawia się w widoku kalendarza rezerwacji /book osadzanym na stronie klubu w iframe — tam o zgodę pyta strona nadrzędna, a ruch z widgetu nie jest raportowany.

Weryfikacja w Menedżerze zdarzeń

  1. Otwórz https://klient.acepark.pl, zaakceptuj baner cookies.
  2. W Events Managerze zakładka Testuj zdarzenia pokaże PageView.
  3. Rejestracja testowa → jedno zdarzenie CompleteRegistration opisane jako „Przeglądarka i serwer" (deduplikacja zadziałała). Dwa osobne wiersze oznaczają, że identyfikatory się rozjechały.

Aby serwer wysyłał do zakładki testowej zamiast do zbioru produkcyjnego, wpisz tymczasowo kod z tej zakładki w polu Kod zdarzeń testowych w panelu.

🔧 Dokumentacja techniczna

Przepływ

Moduły

PlikRola
lib/meta/config.tswersja Graph API i nazwy ciasteczek _fbp / _fbc
lib/analytics/config.tslista hostów produkcyjnych i stałe zgody, wspólne dla Meta i Google Ads
lib/meta/settings.tsodczyt ustawień: konfiguracja publiczna (cache) i dane dostępowe CAPI
lib/actions/meta-tracking-settings.tszapis ustawień z panelu (tylko ADMIN)
lib/meta/hash.tsnormalizacja i SHA-256 dla em, ph, external_id
lib/meta/events.tsnazwy zdarzeń i budowa event_id wspólna dla obu stron
lib/analytics/consent.tsodczyt zgody i mirror do ciasteczka cookie-consent (wspólny z Google Ads)
lib/meta/server-context.ts_fbp, _fbc, IP, User-Agent, event_source_url z żądania
lib/meta/capi.tswysyłka POST /v21.0/<pixel_id>/events
lib/meta/registration.tsCompleteRegistration po utworzeniu konta
lib/meta/purchase.tszapis kontekstu przy inicjalizacji płatności i Purchase z webhooka
lib/meta/pixel-client.tswysyłka zdarzeń przeglądarkowych + kolejka i blokada powtórek
components/analytics/meta-pixel.tsxkod bazowy Pixela i PageView przy zmianie trasy
components/analytics/meta-purchase-tracker.tsxPurchase na stronie potwierdzenia

Dwie bramki

Zdarzenie powstaje tylko wtedy, gdy oba warunki są spełnione:

  1. Ustawieniemeta_tracking_settings.enabled = 1 z identyfikatorem zbioru danych i tokenem (panel administratora). Ustawienie jest per tenant.
  2. HostisTrackingHost() przepuszcza wyłącznie klient.acepark.pl (lib/analytics/config.ts, wspólny z Google Ads). NODE_ENV się do tego nie nadaje: worker deweloperski to również build produkcyjny. Środowisko deweloperskie korzysta z osobnej bazy D1, więc włączenie integracji na devie i tak nie dotyka produkcji — bramka hosta jest drugim zabezpieczeniem, nie jedynym.

Do zgody odwiedzającego dochodzi więc trzeci warunek, sprawdzany przy każdym żądaniu (readMetaRequestContext).

Tabela meta_tracking_settings

Migracja 0230_create_meta_tracking_settings.sql, jeden wiersz na tenant: enabled, pixel_id, access_token, test_event_code, updated_at, updated_by.

Konfiguracja publiczna (enabled, pixel_id) jest czytana przy każdym renderze strony, więc trzyma się w cache KV (meta-tracking, TTL 300 s, unieważniany przy zapisie). Token nie trafia do cache — czyta się go z D1 dopiero w momencie wysyłki zdarzenia, czyli kilkanaście razy dziennie.

Deduplikacja

Zdarzenieevent_idŹródło identyfikatora
CompleteRegistrationregistration_<userId>id konta utworzonego przez backend, zwrócone do przeglądarki jako conversionEventId
Purchasepurchase_<sessionId>session_id transakcji (uuid), znany obu stronom

Identyfikatory są deterministyczne, więc powtórka po stronie przeglądarki lub ponowione powiadomienie od operatora nie tworzą drugiej konwersji.

_fbp / _fbc w evencie serwerowym

Oba identyfikatory to ciasteczka pierwszej strony na domenie klient.acepark.pl, więc każde żądanie do naszego workera niesie je samo z siebie — front nie musi ich przekazywać. Wyjątkiem jest Purchase: webhook przychodzi z serwerów Przelewy24, bez ciasteczek i z ich adresem IP. Dlatego saveMetaEventContext() zapisuje _fbp, _fbc, IP i User-Agent płatnika do tabeli meta_event_context w momencie inicjalizacji płatności — czyli wtedy, gdy żądanie robi jeszcze przeglądarka płatnika.

_fbc nigdy nie jest generowane sztucznie: brak ciasteczka oznacza brak pola.

Tabela meta_event_context

Migracja 0229_create_meta_event_context.sql.

KolumnaZnaczenie
session_idsession_id transakcji (klucz główny)
fbp, fbcidentyfikatory przeglądarki płatnika
client_ip, user_agentdane dopasowania
event_source_urlstrona, z której ruszyła płatność
purchase_sent_atznacznik wysyłki — ustawiany warunkowym UPDATE … WHERE purchase_sent_at IS NULL, co gwarantuje jedną wysyłkę mimo ponowień webhooka

Wiersz powstaje wyłącznie dla płatnika ze zgodą na produkcji — jego brak jest równoznaczny z „nie raportujemy tej transakcji".

Strona potwierdzenia płatności

MetaPurchaseTracker odpytuje /api/public/meta/purchase-event?sessionId=… (co 2 s, maksymalnie 10 prób), bo płatnik wraca z Przelewy24 zwykle chwilę przed webhookiem. Endpoint odpowiada completed dopiero wtedy, gdy transakcja jest rozliczona i serwer wysłał już swoje zdarzenie (purchase_sent_at), więc przeglądarka nigdy nie raportuje konwersji, której nie ma po stronie serwera. Wysłane zdarzenie jest zapamiętywane w localStorage, co blokuje powtórkę przy odświeżeniu strony.

Czego nie raportujemy

  • Transakcji opłaconych w całości z portfela klubowego oraz kodem rabatowym na 100% — pieniądze nie przeszły przez operatora, a saldo portfela jest przyznawane przez klub. Zaraportowanie takiej płatności zawyżałoby przychód przypisany reklamom.
  • Rejestracji, w których konto już istniało (powracający opiekun potwierdzający numer telefonu) — provisionAccountForDraft() zwraca createdAccount: null.

Wdrożenie

Migracje 0229 (kontekst przeglądarki płatnika) i 0230 (ustawienia) — yarn db:update. Żadnych zmiennych środowiskowych ani sekretów workera: dane dostępowe wpisuje administrator w panelu. Bez tokenu Pixel się nie ładuje, a zdarzenia serwerowe są pomijane z ostrzeżeniem w logach (meta/capi).