TL;DR
Lead scoring to liczba lub etykieta (cold / warm / hot), która mówi handlowcowi, kogo dzwonić w pierwszej kolejności — na podstawie danych z formularza, zachowania na stronie i źródła kampanii. Formularz kontaktowy w Next.js to nie tylko mailto: — to Server Action zapisujący lead do PostgreSQL na Branchly Cloud, webhook do CRM i event generate_lead w GA4. Pipeline sprzedaży mapuje statusy (new → qualified → proposal → won) na reguły automatyczne: przypisanie opiekuna, task w CRM, Slack po score > 70. Poniżej: model danych, reguły scoringu, integracja z formularzem i anty-spam.
Dla kogo to jest
- Firm B2B, które dostają dziesiątki zapytań z formularza miesięcznie i tracą gorące leady w skrzynce „info@"
- Zespołów sprzedaży bez jasnych kryteriów „kto jest priorytetem" — każdy lead wygląda tak samo
- Developerów wdrażających formularze w Next.js 15 (Server Actions) z zapisem do bazy i CRM
- Marketingu, które chce połączyć UTM / GA4 z jakością leada, nie tylko liczbą submitów
- Właścicieli stron po wdrożeniu u DevStudio — rozszerzenie formularza o scoring bez przepisywania całej strony
Fraza (SEO)
lead scoring formularz, pipeline sprzedaży crm, formularz kontaktowy nextjs, server actions lead, integracja crm webhook, punktacja leadów b2b
Od formularza do deala — mapa procesu
Typowy przepływ w projekcie firmowym:
Strona (UTM w sesji) → Submit formularza → Walidacja server-side
→ Zapis Lead w Branchly (PostgreSQL)
→ Obliczenie score + segment
→ Webhook CRM (HubSpot / Pipedrive / custom)
→ Powiadomienie (email / Slack) jeśli hot
→ Pipeline: statusy i zadania handlowcaFormularz to wejście do systemu, nie koniec. Bez zapisu w bazie i CRM każdy submit to mail w skrzynce współdzielonej — niemierzalny w raportach i łatwy do zgubienia.
Model danych — Lead i Score
Prisma na Branchly (fragment ilustracyjny):
model Lead {
id String @id @default(cuid())
email String
company String?
budget String?
message String?
utmSource String?
utmCampaign String?
score Int @default(0)
segment LeadSegment @default(COLD)
status LeadStatus @default(NEW)
createdAt DateTime @default(now())
}
enum LeadSegment {
COLD
WARM
HOT
}
enum LeadStatus {
NEW
CONTACTED
QUALIFIED
PROPOSAL
WON
LOST
}Score może być sumą wag pól i zdarzeń. Segment ustawiasz progami: 0–39 cold, 40–69 warm, 70+ hot — progi kalibrujesz co kwartał na podstawie conversion rate do won.
Reguły lead scoring — co punktować
| Sygnał | Przykładowa waga | Uzasadnienie |
|---|---|---|
| Budżet „> 50 000 PLN" | +30 | Gotowość inwestycyjna |
| Firma wypełniona (nie gmail) | +20 | B2B vs konsument |
utm_medium=cpc |
+15 | Płatny ruch — intencja |
Strony /cennik, /case-studies w sesji |
+10 każda | Research phase |
| Wiadomość > 200 znaków | +10 | Konkretna potrzeba |
| Email darmowy (gmail, wp) | −15 | Niższa wartość B2B |
| Brak telefonu przy wymaganym polu | −10 | Trudniejszy kontakt |
Reguły trzymaj w kodzie (TypeScript) lub tabeli ScoringRule w bazie — drugie podejście pozwala marketingowi zmieniać wagi bez deployu, ale wymaga panelu admin.
Przykład funkcji scoringu:
function computeLeadScore(input: LeadInput, sessionPages: string[]): number {
let score = 0;
if (input.company && !isFreeEmail(input.email)) score += 20;
if (input.budget === '50000+') score += 30;
if (input.utmMedium === 'cpc') score += 15;
if (sessionPages.includes('/cennik')) score += 10;
if ((input.message?.length ?? 0) > 200) score += 10;
if (isFreeEmail(input.email)) score -= 15;
return Math.max(0, Math.min(100, score));
}Formularz Next.js — Server Action end-to-end
Server Action waliduje (Zod), liczy score, zapisuje, wysyła webhook:
'use server';
import { z } from 'zod';
import { prisma } from '@/lib/prisma';
import { computeLeadScore } from '@/lib/scoring';
const schema = z.object({
email: z.string().email(),
company: z.string().optional(),
budget: z.enum(['unknown', '10000', '50000+']).optional(),
message: z.string().max(5000),
utmSource: z.string().optional(),
utmMedium: z.string().optional(),
});
export async function submitContactForm(formData: FormData) {
const parsed = schema.safeParse(Object.fromEntries(formData));
if (!parsed.success) return { ok: false, errors: parsed.error.flatten() };
const score = computeLeadScore(parsed.data, []);
const segment = score >= 70 ? 'HOT' : score >= 40 ? 'WARM' : 'COLD';
const lead = await prisma.lead.create({
data: { ...parsed.data, score, segment: segment as any, status: 'NEW' },
});
await fetch(process.env.CRM_WEBHOOK_URL!, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ leadId: lead.id, score, segment }),
});
return { ok: true, leadId: lead.id };
}Formularz kliencki przekazuje UTM z sessionStorage lub hidden fields ustawionych po page_view. Hosting na DevStudioIT Cloud zapewnia stabilny runtime dla Server Actions i env z CRM_WEBHOOK_URL / DATABASE_URL do Branchly.
Pipeline sprzedaży w CRM
Pipeline to kolumny Kanban odpowiadające LeadStatus. Automatyzacje:
| Status | Akcja automatyczna |
|---|---|
| NEW + HOT | Przypisanie do senior AE, Slack w 15 min |
| NEW + COLD | Email nurturing, brak dzwonienia D0 |
| CONTACTED | Task „follow-up za 3 dni" |
| QUALIFIED | Utworzenie deala, szacunek wartości |
| PROPOSAL | Przypomnienie po 7 dniach bez odpowiedzi |
| WON / LOST | Zamknięcie, sync do GA4 offline conversion (opcjonalnie) |
CRM (HubSpot, Pipedrive, Salesforce) otrzymuje webhook z score i segment — mapuj na pola custom i listy „Hot leads this week". Jedna definicja segmentu w firmie — inaczej marketing i sales mówią innym językiem.
Anty-spam, RODO i jakość danych
- Honeypot + rate limit (IP / fingerprint) — mniej śmieci w scoringu
- Double opt-in dla newslettera vs single submit dla zapytania ofertowego — różne zgody w polityce prywatności
- Consent na przetwarzanie i kontakt handlowy — checkbox przed submit
- Logi zapisu leada w UE (Branchly) — audyt kto widział dane
Score oparty na botach zaniża jakość — filtruj leady z identycznym IP > 5/h.
GA4 i marketing feedback loop
Event generate_lead z parametrami lead_score, lead_segment (custom dimensions) pozwala porównać kampanie nie tylko po liczbie submitów, ale po średnim score. Kampania z tańszym CPC i niższym avg score może być gorsza niż droższa z hot leadami.
FAQ
Ile reguł scoringu na start?
Pięć do siedmiu sygnałów wystarczy. Zbyt skomplikowany model na day one — nikt nie weryfikuje wag. Po 90 dniach porównaj score hot leadów z conversion do won i skoryguj progi.
Czy lead scoring zastępuje rozmowę kwalifikacyjną?
Nie. Score priorytetyzuje kolejkę; kwalifikacja BANT/MEDDIC nadal po stronie handlowca. Automatyczne odrzucanie cold leadów bez polityki firmy to strata długiego taila.
HubSpot vs własna baza na Branchly?
Małe firmy: formularz → Branchly + webhook do HubSpot free. Większe: lead w PostgreSQL jako source of truth, sync dwukierunkowy do CRM. Next.js Server Action pasuje do obu — ważna spójność ID leada.
Jak testować pipeline bez spamowania CRM?
Staging na Branchly + CRM sandbox env (patrz staging z Branchly). Submit testowy z prefiksem [TEST] w company.
Chcesz formularz, który dowozi leady do sprzedaży?
- Skontaktuj się z nami — zaprojektujemy formularz, scoring, CRM i hosting w jednym wdrożeniu
- Next.js Server Actions — formularze kontaktowe — techniczna warstwa submita
- Strony WWW — strony firmowe z formularzem i analityką od początku
O autorze
Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.
Przydatne linki
Od teorii do produkcji — Branchly, hosting i realizacje.
