A small plugin loads the snippet with your site ID and lets Contact Form 7, WPForms, Gravity Forms and Elementor Pro forms carry the attribution. It reads no form values and stores nothing on your server: the snippet does the same work it does on any other site, in the visitor's browser, after consent.
Download: tracelead-wordpress.zip. Source: adapters/wordpress/tracelead in the TraceLead repository.
What is tested: the plugin's PHP (settings, the script tag, the Gravity Forms, WPForms and Elementor hooks) has unit tests, and the snippet is run on every release against each builder's rendered markup (tests/e2e/fixtures/wordpress-*.html). The plugin has not yet been exercised on a live WordPress install by the TraceLead team; if something differs on yours, tell us.
1. Install the plugin
Plugins → Add New → Upload Plugin → choose the zip → Activate. Then open Settings → TraceLead:
- Site ID: from the site page in your dashboard (
tl_…). Leaving it empty disables the snippet. - Snippet URL: leave as is unless your dashboard shows a different address.
- Consent signal: see step 3.
The plugin prints the one-line tag (async, in the footer) with the stub that queues calls made before the snippet loads. If your theme already includes the tag, remove one of the two.
2. Add hidden fields to your form
Contact Form 7
Add the fields to the form template with CF7's own hidden tag, named tl_<field>:
[hidden tl_channel]
[hidden tl_source]
[hidden tl_utm_campaign]
[hidden tl_gclid]
[hidden tl_landing_page]
[hidden tl_first_touch_at]
Use the matching mail tags ([tl_channel], [tl_utm_campaign], …) in the mail template, or map them in whichever CRM add-on your form posts to. Nothing else is needed: CF7 renders them as <input type="hidden" name="tl_channel">, which the default mappings fill.
WPForms
WPForms chooses its own input names, so the plugin marks the input instead. Add a Hidden Field per value and, under Advanced → CSS Classes, enter tracelead-<field>: tracelead-channel, tracelead-utm_campaign, tracelead-gclid, and so on. The plugin adds data-tracelead="channel" to that input and the snippet fills it. The value lands in the entry and in any CRM integration like any other hidden field.
Gravity Forms
Add a Hidden field per value, tick Advanced → Allow field to be populated dynamically and set the parameter name to tl_<field> (tl_channel, tl_utm_campaign, tl_gclid, …). The plugin adds data-tracelead="channel" to that input and the snippet fills it. Dynamic population itself is not used; it is simply where Gravity Forms lets you name a hidden field.
Elementor Pro forms
Elementor names its inputs form_fields[<ID>], so the plugin marks the input instead. In the Form widget, add a field of type Hidden per value and, under Advanced → ID, enter tl_<field>: tl_channel, tl_utm_campaign, tl_gclid, and so on. The plugin (1.1.0 or later) adds data-tracelead="channel" to that input through Elementor's elementor_pro/forms/render/item/hidden hook and the snippet fills it. The value appears in Elementor's form submissions and in any action after submit (email, webhook, CRM) under that ID. Leave the field's default value empty.
Any other builder
If the builder lets you set a custom attribute on the input, add data-tracelead="<field>" yourself; the snippet fills any input carrying it, no mapping needed. If it only lets you set the input's name, use tl_<field>. Field names: see Installing the snippet.
3. Signal consent
Nothing is stored or filled until the page says consent was given (unless the TraceLead site is set to assumed consent). Pick one in Settings → TraceLead:
- My site calls
tracelead('consent', true)itself. Wire your banner as described in Consent integration, for example from a Cookiebot or OneTrust callback. - Follow the WordPress Consent API. Consent plugins that implement the API (Complianz, among others) expose
wp_has_consent()and firewp_listen_for_consent_change. The plugin bridges them to the snippet for the category you choose (marketing or statistics), on load and on every change.
4. Check the install
Open a page of your site with ?utm_source=test&utm_medium=cpc, grant consent, submit a test entry and check that the hidden values arrived. For a closer look, run tracelead.diagnostics() in the browser console: attributedInputs counts the inputs marked by the plugin and mappings shows the tl_* inputs found.
Caching and page builders
- Full-page caches are fine: the snippet reads the URL in the browser, not on the server.
- Forms loaded into the page later (pop-ups, AJAX reloads after a validation error) are filled when they appear.
- A form embedded in an iframe is not reachable; see Typeform, Jotform and other embedded forms.