# Atrybucja leadów i zdarzenia konwersji

> Jak lead dostaje parametry kampanii bez cookies, co dokładnie wysyła strona po wysłaniu formularza, reguły strony podziękowania i punkty checklisty landingu.

Opublikowano: 2026-09-04 · Aktualizacja: 2026-09-16
Źródło: https://kompasfirm.pl/dokumentacja/atrybucja-leadow-i-zdarzenia-konwersji

---
## Parametry kampanii przy leadzie

Przy zapisie leada platforma zbiera dziewięć parametrów: `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`, `gclid`, `fbclid`, `msclkid`, `ttclid`. Dwa źródła, w tej kolejności:

1. **Ukryte pola formularza.** Krótki skrypt w nagłówku każdej strony tenanta czyta ciąg zapytania z adresu bieżącej strony i dopisuje znalezione parametry jako `input type="hidden"` do każdego formularza wysyłanego na `/__lead`. Nie używa cookies, `localStorage` ani `sessionStorage`, więc nie podlega zgodzie z banera i działa także dla osób, które ją odrzuciły.
2. **Nagłówek Referer.** Gdy pola nie przyszły (skrypt zablokowany, formularz osadzony inaczej), serwer parsuje ciąg zapytania z adresu strony, z której przyszło żądanie.

Wartości są przycinane do 200 znaków. Komplet ląduje w `leads.metadata.attribution`; `utm_medium` i `utm_campaign` dodatkowo w kolumnach `medium` i `campaign`, a `utm_source` w `metadata.utm_source`, jak dotąd. Pole `landing_page` nadal nie zawiera ciągu zapytania.

Świadome ograniczenie: brak trwałego zapisu oznacza, że atrybucja obejmuje tylko stronę, na której jest formularz. Wejście z reklamy na stronę A i wysłanie formularza ze strony B bez przeniesienia parametrów w linku gubi atrybucję. Zapis w `sessionStorage` rozwiązałby to kosztem zgody na przechowywanie na urządzeniu; wybieramy brak zgody.

## Gdzie parametry są widoczne

- karta leada w panelu (wiersz Kampania oraz surowe identyfikatory kliknięć),
- mail `LeadReceivedMail` (wiersz Kampania),
- payload webhooka: `lead.utm.{source,medium,campaign,term,content}` i `lead.click_ids.{gclid,fbclid,msclkid,ttclid}` (pusty obiekt, gdy brak).

Etykietę „google / cpc / wiosna” albo nazwę systemu reklamowego rozpoznaną po identyfikatorze buduje `LeadAttribution::label()`.

![Karta leada w panelu z atrybucją kampanii i identyfikatorem kliknięcia](/img/help/konwersje/04-lead-karta.jpg)

## Zdarzenia konwersji

Odpowiedź po wysyłce formularza to przekierowanie z parametrem `?sent=1`. Strona z tym parametrem omija cache i renderuje partial `tenant.partials.lead-conversion`, dołączany na końcu bloku integracji w `<head>`, po snippetach pikseli:

| Warunek | Skrypt |
| --- | --- |
| zawsze | `dataLayer.push({event:'kf_lead'})` |
| `ga4` | `gtag('event','generate_lead')` |
| `google_ads` + `google_ads_conversion_label` | `gtag('event','conversion',{send_to:'AW-x/ETYKIETA'})` |
| `meta_pixel` | `fbq('track','Lead')` |
| `tiktok_pixel` | `ttq.track('SubmitForm')` |
| `bing_uet` | `uetq.push('event','submit_lead_form')` |

Każdy skrypt dostaje te same atrybuty Klaro co piksel, którego dotyczy (`type="text/plain" data-name="analytics|marketing"`), więc wykonuje się dopiero po tej samej zgodzie. Przy włączonym Consent Mode v2 zdarzenia dla tagów Google są zwykłymi skryptami, bo tag ładuje się zawsze, a o zapisie decyduje sygnał zgody. Wpis do `dataLayer` nie jest bramkowany: sam nic nie wysyła.

Etykieta konwersji to nowe pole `integrations.google_ads_conversion_label` (regex `^[A-Za-z0-9_-]+$`, do 40 znaków), zapisywane razem z pozostałymi integracjami za flagą planu `analytics_integrations`.

## Strona podziękowania

Kolumna `forms.success_url` (do 500 znaków). Walidacja dopuszcza wyłącznie ścieżkę zaczynającą się od `/` albo adres `https://`; schematy `javascript:` i `data:` odpadają na poziomie FormRequest, bo wartość trafia do nagłówka Location.

Logika przekierowania w `CaptureLead::successUrl()`:

- puste pole: `{strona}?sent=1#kontakt`, jak dotąd,
- ścieżka: `{origin}{ścieżka}?sent=1` (parametr doklejany po `&`, gdy ścieżka już ma zapytanie), dzięki czemu zdarzenia konwersji odpalają się na stronie podziękowania,
- adres https: przekierowanie 1:1, bez `sent`, bo to obca strona.

## Checklista landingu

`LandingChecklist::for(Website)` liczy się przy każdym otwarciu ustawień landingu (`WebsiteController@edit`) i renderuje partial `builder.websites.partials.landing-checklist`. Strona sprawdzana to pierwsza podstrona najwyższego poziomu, z pierwszeństwem dla slugów `home`, `/` i pustego.

| Klucz | Waga | Warunek |
| --- | --- | --- |
| `published` | konieczne | `Page::isPublished()` |
| `hero` | konieczne | pierwsza widoczna sekcja to `lp_hero` |
| `lead` | konieczne | jest sekcja z listy `lp_form`, `lp_cta_two_step`, `lp_contact`, `lp_lead_magnet`, `lp_order`, `lp_booking`, `lp_quiz` |
| `phone` | konieczne | `settings.business.phone` niepuste |
| `consent` | konieczne | każda sekcja leadowa ma `consent_label` albo `privacy_note` (brak sekcji = zaliczone) |
| `proof` | ważne | `lp_testimonials`, `lp_proof`, `lp_logos`, `lp_case` albo `lp_before_after` |
| `objections` | ważne | `lp_faq`, `lp_guarantees` albo `lp_not_for` |
| `meta` | ważne | tytuł 20 do 70 znaków, opis 50 do 170 |
| `og_image` | warto | `settings.business.og_image` |
| `tracking` | konieczne | dowolna integracja analityczna lub reklamowa |
| `consent_mode` | ważne | gdy jest tag Google, `consent_mode` włączony |
| `ads_conversion` | ważne | gdy jest `google_ads`, jest też etykieta |
| `lead_routing` | warto | adresy powiadomień w którymś formularzu albo aktywny webhook |
| `domain` | warto | zweryfikowana domena główna |

Wagi nie blokują niczego; to komunikat, nie bramka. Testy: `tests/Feature/Leads/LeadAttributionAndConversionTest.php`.

![Checklista landingu w ustawieniach witryny](/img/help/konwersje/06-checklista.jpg)
