Web form tracking
Attribute every form submission back to the campaign, channel and landing page that brought the visitor in. No DOM rewriting needed.
Form tracking doesn’t need a pool or a swap zone - visitors hand you their email or phone in the form itself, so there’s no per-source address to provision. Funnelion.ai just needs to know when a submission happens and who submitted it (which session). One ingestion endpoint, two integration paths.
1. Dashboard setup
- Add a form at Forms → New. Give it a name and a CSS selector for the
<form>element (e.g.#contact-form,form.demo-form). - Configure capture rules. By default Funnelion.ai captures every named field except anything containing the word
password. To restrict, set capture_fields to a whitelist; to denylist specific fields (ssn,dob), use redact_fields. - Note the Form id once saved - backend integrators pass it through to link submissions to this Form row.
2. Frontend path (JS snippet)
With the snippet loaded, Funnelion.ai auto-binds a submit listener to every form matching a registered selector. On submit, the listener captures the field values (subject to your capture / redact rules), POSTs to /track/form-event, and your existing form handler proceeds untouched. The user-visible submit flow is unchanged.
<!-- Anywhere in <head>. Use the minified build in production; the
unminified track.js is the same code, easier to read in DevTools. -->
<script async src="https://dash.funnelion.ai/track.min.js?t=YOUR_SITE_TOKEN"></script>
<!-- <script async src="https://dash.funnelion.ai/track.js?t=YOUR_SITE_TOKEN"></script> -->
<!-- Your form, matching the selector you registered in the dashboard -->
<form id="contact-form" action="/submit" method="post">
<input name="email" required />
<input name="name" required />
<textarea name="message"></textarea>
<button type="submit">Send</button>
</form>Honeypots and Chrome autofill
3. Backend path (PHP SDK)
Server-side conversion tracking - your form handler validates the submission and does its real work (SMTP, CRM, whatever), then fires formEventOrNull() after the work succeeds. Funnelion.ai failures never break the form: if the API is down, the visitor still sees the success message.
use Funnelion\Client;
use Funnelion\Config;
use Funnelion\FormEvent\Request as FormEventRequest;
// ...after your existing send / persist logic succeeds:
$client = new Client(new Config(
siteToken: getenv('FUNNELION_SERVER_SIDE_TOKEN'),
timeoutSeconds: 0.5,
));
$client->formEventOrNull(new FormEventRequest(
ip: $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0',
fields: [
'name' => $name,
'email' => $email,
'phone' => $phone,
'company' => $company,
'message' => $message,
],
referrer: $_SERVER['HTTP_REFERER'] ?? null,
userAgent: $_SERVER['HTTP_USER_AGENT'] ?? null,
visitorId: $_COOKIE['funnelion_session'] ?? null,
formId: (int) getenv('FUNNELION_FORM_ID') ?: null,
formActionUrl: 'https://yoursite.com'.($_SERVER['REQUEST_URI'] ?? '/api/contact'),
language: 'en',
));Why formEventOrNull?
- Returns null on Funnelion.ai outages, slow networks, rate limits - never throws.
- Hard timeout (0.5 s default) so a stuck Funnelion.ai can’t hold your visitor’s success response hostage.
- visitor_id from the funnelion_session cookie attributes the submission back to the same session that resolved the page - turning the form into a fully-attributed conversion event.
Optional: form_id linking
Pass formId (the id of your Form row in the dashboard) so submissions land linked to that row instead of orphaned with form_id NULL. Read the id from an env var so dev / staging environments can leave it unset - the ingester silently ignores mismatched ids and the submission still attributes via the session cookie.
4. What the dashboard shows
Every submission lands as a lead event of kind form, joined to:
- The visitor’s session (UTMs, referrer, landing page, IP, device).
- The matched routing rule (so it lights up the right column on per-source dashboards).
- The Form row you set up in step 1 (when form_id is passed).
- The visitor identity (deduped by email or phone against previous lead events).
Submissions are visible immediately under Leads. If the visitor had no prior session (direct submission, deep-linked /api/contact hit), Funnelion.ai still records the lead event with attribution_status=no_match for incident debugging.