Skip to content

Lead source

The lead source tells you where the person who filled in a form came from. Each submission can show whether they arrived from a Google ad, from Google search, from Facebook or from another website, plus the campaign tags of the first page they opened. It is off by default.

This matters because campaign tags disappear as soon as someone clicks through your site. A visitor who lands on your home page from an ad and fills in the contact form three pages later would otherwise arrive without any trace of the ad.

Go to OctaForms → Settings → Privacy & security and tick Record where visitors came from. It is off on a fresh install and stays off after an update until you turn it on.

If your pages are cached, a change to the setting takes effect on those pages only after the cache is cleared.

Three things are added to the submission’s meta:

"meta": {
"url": "https://example.com/contact",
"referrer": "https://example.com/pricing",
"source": "Google Ads",
"campaign": { "utm_campaign": "spring", "gclid": "Cj0KCQ" }
}

referrer is the address of the page that led the visitor to the form page, without its query string and the part after #, at most 500 characters. It is always sent, also without consent, because nothing is stored on the device for it. On a direct entry, for example from a bookmark, it is an empty text "", which the submission keeps.

source is the first outside source of the whole visit:

You see When
Google Ads The visitor came from Google search, or from Google’s ad network, and the page they landed on has a gclid, gbraid or wbraid tag
Google Organic The visitor came from Google search without any of those tags
Facebook The visitor came from Facebook, fb.com, fb.me or Instagram
The address of the page The visitor came from any other website, including Gmail, Google Docs or a Google sign-in

Google sends only its domain as the referrer, without the search or the ad. That is why a paid click is recognised by the tag Google adds to the landing page: gclid, or gbraid and wbraid on part of the traffic from iPhones. A visit from Google’s ad network (googleadservices.com, googlesyndication.com, doubleclick.net) counts as Google Ads only with one of those tags. Without one it is recorded as the address.

The address of another website is kept without its query string and the part after #, for example https://forum.example.org/thread for https://forum.example.org/thread?email=jan@example.com. A referring page can carry an e-mail address or a token there, and that has no place in your leads.

Your own site is never a source. Pages on www.example.com and example.com count as one site, and so does a subdomain such as en.example.com.

campaign holds the campaign tags of the first page of the visit that had any: utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, gbraid, wbraid and fbclid. Other parameters are ignored. Each value is cut to 500 characters.

source and campaign follow the first touch. Moving around your site does not change them, and a later page with different tags does not overwrite them. A visit that starts with no outside source, for example from a bookmark, is remembered as a direct entry. A later return from a payment gateway or a sign-in page then does not become its source, and the submission has no source. The one exception is the page with the form itself: when its own address has campaign tags, those are sent instead of the stored ones, all of them together, so a form page opened from a campaign link always reports that campaign and never a mix of two.

The visit is remembered in the browser’s session storage, so it ends when the visitor closes the tab.

Remembering the source for the rest of the visit stores data on the visitor’s device, so it needs consent for statistics. The plugin reads consent the same way as for the visit path: your own window.octaFormsConsent.canTrack() hook first, then Google Consent Mode v2, then the WP Consent API. With no consent system on the page, nothing is stored by default.

Without consent there is no source, because it follows the visit across pages. The page with the form still sends its referrer and the tags in its own address, because nothing is stored on the device for those. The address of that page already travels with every submission as meta.url.

When a visitor declines, or later withdraws consent, the stored source is cleared from their device. A Consent Mode default of denied is not a refusal. It only waits for the visitor’s answer, as described for the visit path.

To store without a consent system, if you accept that responsibility yourself:

add_filter( 'octa_forms_lead_source_require_consent', '__return_false' );
  • Single submission page (admin). A Lead source section shows the source, the referring page and the campaign tags. A submission stored by a 1.5.0 test build, which kept the source in referrer, shows it as the source too.
  • CSV export. A source column, a referrer column and one column per campaign tag, added only when at least one exported submission has them.
  • Webhooks. Inside meta, like any other meta key.
  • Personal data export. Included, with the campaign tags as a JSON string.
  • Emails. Not included.

The three keys belong to the plugin and do not count toward the limit of 10 meta keys, so they can never make a submission fail. campaign is treated as the lead source only when it is an object, so a theme that already sends its own campaign text keeps it. While the feature is on, referrer and source are the plugin’s: an address in either keeps only http, https and android-app addresses, without the query string and fragment, and a label has its spaces collapsed, both cut to 500 characters. An empty source is not stored, an empty referrer is. While the feature is off, a referrer or source your theme sends is kept like any other meta key, as before, but it still does not count toward the 10.

Filter Purpose
octa_forms_lead_source_enabled Force collection on or off in code (default: the setting). Read by the page and by the server.
octa_forms_lead_source_require_consent Whether a consent signal is required before the source is stored (default: true).