Guides

Capture UTM parameters and ad click IDs in form submissions

Keep the campaign that brought a visitor, even after they’ve browsed three pages before filling in your form, and store it on the lead.

Updated

Your ad sends people to /pallets/48x40?utm_source=google&utm_campaign=ohio-pallet-buyers&gclid=Cj0K…. The visitor reads that page, clicks through to pricing, then to the contact page, and fills in the form. By then the address bar says /contact and the campaign is gone. The lead arrives with no idea where it came from.

The fix is to save the tracking values on the visitor’s first page, then send them with the form, whatever page it’s on.

What to keep

ValueWhere it comes fromWhy it matters
utm_source, utm_medium, utm_campaign, utm_term, utm_contentYour tagged linksWhich campaign, ad and keyword
gclid, gbraid, wbraidGoogle AdsSending conversions back to Google
msclkidMicrosoft AdsThe same, for Bing
fbclidMeta adsThe same, for Facebook and Instagram
ttclidTikTok adsThe same, for TikTok
Referrerdocument.referrerOrganic search and links from other sites
Landing pageThe first URL of the visitWhich page did the persuading

Keep the first values you see and don’t overwrite them as the visitor moves around. That’s first-touch attribution: the campaign that started the visit gets the credit.

Save them on the first page

Put this in your site’s layout so it runs on every page. It only writes when nothing is saved yet, so later pages don’t wipe the landing values.

// attribution.js
const KEYS = [
  "utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content",
  "gclid", "gbraid", "wbraid", "msclkid", "fbclid", "ttclid",
];

(function saveFirstTouch() {
  if (sessionStorage.getItem("attribution")) return;
  const params = new URLSearchParams(location.search);
  const saved = {
    landing_page: location.pathname + location.search,
    referrer: document.referrer || undefined,
  };
  for (const key of KEYS) {
    const value = params.get(key);
    if (value) saved[key] = value;
  }
  sessionStorage.setItem("attribution", JSON.stringify(saved));
})();

export function attributionFields() {
  const saved = JSON.parse(sessionStorage.getItem("attribution") || "{}");
  const fields = { _1db_current_page: location.pathname };
  for (const [key, value] of Object.entries(saved)) {
    fields[`_1db_${key}`] = value;
  }
  return fields;
}

sessionStorage lasts for the browser tab’s visit. If your buyers often leave and come back days later before filling in the form, use localStorage with a date and expire it after 30 or 90 days, matching your ad platform’s attribution window.

Send them with the form

Add the saved values to the body you post. The _1db_ prefix tells 1DB these are attribution, not answers from the visitor.

import { attributionFields } from "./attribution.js";

const body = {
  formSlug: "quote-request",
  submission_id: submissionId,
  ...Object.fromEntries(new FormData(form)),
  ...attributionFields(),
};

If your form posts to your own server route first, have the browser include these fields and pass them through unchanged.

What 1DB does with them

1DB recognizes these fields:

FieldStored as
_1db_utm_source … _1db_utm_contentThe lead’s UTM values
_1db_referrerReferrer
_1db_landing_pageLanding page
_1db_current_pageThe page the form was sent from
_1db_gclid, _1db_gbraid, _1db_wbraid, _1db_msclkid, _1db_fbclid, _1db_ttclidClick IDs
_1db_ga_client_idYour Google Analytics client ID

They’re kept on the lead, shown in the dashboard, and can go along when the lead is forwarded to a partner, so whoever works the lead knows which campaign it came from. 1DB also records the visitor’s device, browser and approximate location from the request itself, so you don’t need to send those.

Check it works

Open your site with made-up tags, like /?utm_source=test&utm_campaign=attribution-check, click to another page, and send the form. The lead in the dashboard should show test and attribution-check, with your home page as the landing page.

Want the form itself? Start with the Next.js contact form or a backend for a static site.