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

  1. 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).
  2. 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.
  3. 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.

HTML
<!-- 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

Chrome and Safari autofill happily fill hidden inputs, including honeypots. If you’re defending against bots, prefer reCAPTCHA v3 or an invisible challenge over a hidden honeypot field - otherwise legitimate submissions get silently dropped.

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.

PHP
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.