---
title: "Capture UTM attribution"
description: "Store campaign parameters in hidden Fillo fields, keep them through product navigation, and treat them as respondent-supplied context."
order: 21
type: "guide"
topic: "Prefill recipes"
tags:
  - "UTM"
  - "attribution"
  - "hidden fields"
  - "prefill"
updated: "2026-07-15"
---

Hidden fields let you store campaign query parameters beside a response without asking anyone to type them.

## Add hidden fields

```ts
const acquisition = defineForm({
  id: "demo-request",
  title: "Request a demo",
  pages: [{
    id: "request",
    blocks: [
      { id: "email", kind: "email", label: "Work email", required: true },
      { id: "utm_source", kind: "hidden", label: "UTM source", paramName: "utm_source" },
      { id: "utm_medium", kind: "hidden", label: "UTM medium", paramName: "utm_medium" },
      { id: "utm_campaign", kind: "hidden", label: "UTM campaign", paramName: "utm_campaign" },
      { id: "landing_path", kind: "hidden", label: "Landing path", paramName: "landing_path" },
    ],
  }],
});
```

A hosted form reads those parameters directly. For an embed later in a multi-page product flow, capture the approved values on arrival and pass them through `initialData` when the form mounts.

```ts
const initialData = {
  utm_source: sessionStorage.getItem("utm_source") ?? "",
  utm_medium: sessionStorage.getItem("utm_medium") ?? "",
  utm_campaign: sessionStorage.getItem("utm_campaign") ?? "",
  landing_path: sessionStorage.getItem("landing_path") ?? location.pathname,
};
```

Decide when attribution expires and whether first-touch or last-touch wins. Don't collect arbitrary query parameters or personal data because they happen to be available.

## Interpret it correctly

Visitors, link shorteners, and referrers can change or strip UTM values. They're respondent-supplied analysis context, not proof — don't base commissions, billing, access, or security decisions on them. When the source is missing, use a documented `direct` or unknown bucket instead of inventing one.

## Try it

[Start with a prompt](/start?from=guide-capture-utm-attribution) and your coding agent builds the first form, staged for your review — or [open the editor](/new).

## Related

- [Beta access example](/examples#beta-access): See a signup form that carries hidden campaign context.
- [Hidden field](/docs/fields/hidden): Configure `paramName` and default values.
- [Prefill from URL parameters](/guides/prefill-from-url): Encode and validate query values.
- [Exports](/docs/exports): Analyze campaign columns in a filtered CSV.
