What we keep off the critical path
How we use select and depth in Payload CMS queries to reduce response times and improve TTFB across listing pages and sitemaps.
The Blog
A contact form is a lead capture pipeline, spam filtering, CMS audit trail, and CRM sync all need to work without the visitor noticing. We wire reCAPTCHA v3, Payload submissions, and HubSpot together through a single server action.
The problem
Every enquiry form has three responsibilities that most setups handle independently. Filter spam before it reaches anyone. Store the submission somewhere the team can access it. Route it to the sales pipeline so it gets followed up.
On a typical marketing site, these are patched together: a CAPTCHA widget on the front end, a form plugin that emails the submission, and a Zapier integration that maybe pushes it to the CRM. Each piece has its own failure mode. The CAPTCHA blocks legitimate users with low scores. The email goes to a shared inbox where submissions get lost. The Zapier integration breaks silently after an API change and nobody notices for weeks.
The result is a form that technically works but leaks leads at every seam. Spam gets through or real enquiries get blocked. Submissions exist in an inbox but not in the CRM. The sales team doesn't know about the enquiry until someone remembers to forward it.
The pipeline
We handle all three jobs in a single Next.js server action. The form submits to the server, no client-side API keys, no exposed endpoints. The server action runs three steps in sequence.
First, it verifies the reCAPTCHA v3 token. reCAPTCHA v3 is invisible, no checkbox, no image puzzles. Google assigns a score based on the visitor's behaviour. We verify the token server-side and reject submissions below a confidence threshold. The visitor never sees the verification happen.
Second, the action creates a submission entry in Payload CMS. This is the audit trail. Every enquiry is stored as structured content, name, email, message, source page, timestamp. The team can search, filter, and export submissions directly from the CMS admin.
Third, the action sends the same data to HubSpot via their form submission API. The enquiry lands in the CRM pipeline with context, which page the visitor was on, what they asked about. The sales team picks it up in HubSpot's workflow, not in a forwarded email.
If any step fails, the others still complete. A HubSpot API timeout doesn't prevent the Payload submission from being stored. The visitor sees a success message as long as the core submission was recorded.
Server-side
Client-side form handling exposes secrets. A reCAPTCHA secret key in browser JavaScript can be extracted. A HubSpot API key in a client-side fetch call is visible in the network tab. Form endpoints without server-side validation accept whatever the browser sends.
Server actions in Next.js run on the server. The reCAPTCHA secret key, the HubSpot portal ID, and the form GUID never reach the browser. The client sends form data to the server action endpoint. The server verifies, stores, and routes.
This also means validation runs where it can be trusted. Client-side validation is a UX convenience, it tells the visitor their email is malformed before they submit. Server-side validation is a security boundary, it ensures the data that reaches Payload and HubSpot meets the actual requirements regardless of what the browser sent.
Spam filtering
reCAPTCHA v3 scores every visitor on a scale from 0 (likely bot) to 1 (likely human). There's no interaction required, no checkboxes, no "select all traffic lights." The score is based on behavioural signals: how the visitor arrived, how they interact with the page, browser fingerprint patterns.
We set a threshold and reject submissions below it. The threshold is a tradeoff. Too aggressive and legitimate enquiries from visitors with unusual browsing patterns get blocked. Too lenient and spam gets through.
There's no universally correct threshold. We start with a reasonable default and adjust based on what actually arrives. If the team reports spam getting through, the threshold tightens. If legitimate enquiries are being blocked, it loosens. The submissions stored in Payload make this easy to audit, the team can see what was accepted and what was filtered.
Dual write
Storing submissions in both Payload and HubSpot serves different purposes.
Payload is the source of truth. Every submission is stored with full context, the form data, the page it came from, the timestamp. The team can search submissions, export them, and reference them months later. If HubSpot's sync breaks, the submissions are still in Payload. If someone needs to verify what a prospect actually asked, it's in the CMS.
HubSpot is the action layer. The submission enters a pipeline, triggers workflows, assigns a contact owner, and tracks follow-up. This is where sales engagement happens, not in the CMS.
The two systems serve different audiences. The development team and project managers reference Payload. The sales team works in HubSpot. Neither needs to switch tools to get what they need.
FAQs
HubSpot's embedded forms load external JavaScript, add their own styling, and send data directly to HubSpot's servers. This means less control over the experience, an additional third-party script affecting page speed, and no local audit trail in the CMS. Server-side submission gives you control over every step.
The Payload submission still completes. The enquiry is stored in the CMS. You can replay failed HubSpot submissions manually or build a retry mechanism. The visitor's submission is never lost.
The reCAPTCHA script does add a small amount of JavaScript. We load it only on pages that have forms, not site-wide. The verification itself happens server-side and doesn't add client-side latency to the submission.
Yes. Turnstile (Cloudflare), hCaptcha, and honeypot fields are alternatives. The server action pattern is the same, verify server-side, then store and route. reCAPTCHA v3 is our current default because of its invisible UX and Google's scoring model.
Check the Payload submissions collection. Spam entries are usually obvious, gibberish names, irrelevant messages, patterns in the email domains. If spam volume increases, tighten the reCAPTCHA threshold or add disposable-email filtering.